/* ============================================================
   "Tierra Fertil" - Premium Agricultural SaaS Theme
   Cuaderno de Campo by SBSoftware
   ============================================================ */

/* -- Google Fonts: Plus Jakarta Sans (display) + Inter Tight (body) + JetBrains Mono (mono).
   Stack legacy (DM Sans / Fraunces / Source Sans 3) se mantiene cargado por compatibilidad
   pero los tokens del design system enterprise apuntan a Plus Jakarta Sans / Inter Tight. -- */
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400;1,500&family=Inter+Tight:wght@400;500;600;700&family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700&family=Source+Sans+3:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');

/* ============================================================
   CSS CUSTOM PROPERTIES
   ============================================================ */

:root {
    /* -- Tierra Fertil palette · Enterprise edition -- */
    --tf-primary: #15803D;            /* emerald-700 — agro green */
    --tf-primary-hover: #166534;      /* emerald-800 */
    --tf-primary-light: rgba(21, 128, 61, 0.12);
    --tf-primary-rgb: 21, 128, 61;

    /* Sidebar dark slate (no marrón) */
    --tf-sidebar-bg: #0F172A;                          /* slate-900 */
    --tf-sidebar-header-start: #15803D;
    --tf-sidebar-header-end: #166534;
    --tf-sidebar-hover: rgba(255, 255, 255, 0.06);
    --tf-sidebar-active-bg: rgba(21, 128, 61, 0.18);
    --tf-sidebar-active-border: #22C55E;

    --tf-menu-text: rgba(226, 232, 240, 0.7);          /* slate-200 @ 70 */
    --tf-menu-text-hover: rgba(241, 245, 249, 0.92);   /* slate-100 */
    --tf-menu-text-active: #ffffff;
    --tf-menu-section-text: rgba(148, 163, 184, 0.55); /* slate-400 */

    --tf-page-bg: #F7F8FA;
    --tf-white: #ffffff;
    --tf-card-shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 1px 3px rgba(15, 23, 42, 0.04);
    --tf-card-shadow-hover: 0 4px 12px rgba(15, 23, 42, 0.07), 0 8px 24px -4px rgba(15, 23, 42, 0.08);
    --tf-card-radius: 12px;

    --tf-accent-warm: #2563EB;        /* cobalt enterprise CTA */
    --tf-accent-warm-light: rgba(37, 99, 235, 0.10);
    --tf-danger: #B91C1C;             /* red-700 */
    --tf-danger-light: rgba(185, 28, 28, 0.08);
    --tf-success: #15803D;
    --tf-info: #2563EB;               /* cobalt */
    --tf-info-light: rgba(37, 99, 235, 0.10);

    --tf-text-primary: #0F172A;       /* slate-900 */
    --tf-text-secondary: #475569;     /* slate-600 */
    --tf-text-muted: #94A3B8;         /* slate-400 */
    --tf-border-color: #E2E8F0;       /* slate-200 */

    /* -- Layout dimensions --
       El menu son dos piezas desde el rediseno del 2026-09-11: rail de areas
       (76 px, siempre visible) + panel del area (252 px). "Expanded" es la suma
       de las dos y "collapsed" es solo el rail, que es lo que queda cuando se
       pliega con el boton de la cabecera y lo que reserva la tableta.
       Todo el desplazamiento del contenido (#page-wrapper, .app-header,
       .rz-header, .rz-body) cuelga de estas dos variables: cambiarlas aqui mueve
       el layout entero, sin tocar ninguna regla mas. */
    --sidebar-width-expanded: 340px;   /* 88 rail + 252 panel */
    --sidebar-width-collapsed: 88px;   /* solo el rail */
    --header-height: 60px;

    /* -- Typography · Plus Jakarta Sans + Inter Tight -- */
    --tf-font-display: 'Plus Jakarta Sans', 'Inter Tight', system-ui, -apple-system, sans-serif;
    --tf-font-body: 'Inter Tight', 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
    --tf-font-nav: 'Plus Jakarta Sans', 'Inter Tight', system-ui, -apple-system, sans-serif;

    /* -- Transitions -- */
    --tf-transition-fast: 200ms ease;
    --tf-transition-normal: 300ms ease;
    --tf-transition-slow: 400ms ease;

    /* -- Override Radzen defaults · Enterprise palette -- */
    --rz-primary: #15803D;            /* emerald-700 */
    --rz-primary-lighter: #16A34A;
    --rz-primary-light: #22C55E;
    --rz-primary-dark: #166534;
    --rz-primary-darker: #14532D;
    --rz-secondary: #475569;          /* slate-600 */
    --rz-info: #2563EB;               /* blue-600 */
    --rz-success: #15803D;
    --rz-warning: #B45309;            /* amber-700 */
    --rz-danger: #B91C1C;              /* red-700 */
    --rz-base-background-color: #F7F8FA;

    /* -- Responsive breakpoints (v13.0 DS-02) -- */
    --tf-bp-mobile: 375px;
    --tf-bp-tablet: 768px;
    --tf-bp-desktop: 1024px;
    --tf-bp-wide: 1440px;
    --tf-bp-ultrawide: 1920px;

    /* -- Spacing scale 4/8dp (v13.0 DS-02) -- */
    --tf-space-3xs: 2px;
    --tf-space-2xs: 4px;
    --tf-space-xs: 8px;
    --tf-space-sm: 12px;
    --tf-space-md: 16px;
    --tf-space-lg: 24px;
    --tf-space-xl: 32px;
    --tf-space-2xl: 48px;
    --tf-space-3xl: 64px;

    /* -- Shadow scale (v13.0 DS-01) -- */
    --tf-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --tf-shadow-md: 0 4px 8px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.04);
    --tf-shadow-lg: 0 10px 20px rgba(0, 0, 0, 0.08), 0 4px 8px rgba(0, 0, 0, 0.05);
    --tf-shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.10), 0 8px 16px rgba(0, 0, 0, 0.06);

    /* -- Border radius scale (v13.0 DS-01) -- */
    --tf-radius-sm: 4px;
    --tf-radius-md: 8px;
    --tf-radius-lg: 12px;
    --tf-radius-xl: 16px;
    --tf-radius-pill: 999px;

    /* -- Fluid typography scale (v13.0 DS-01) -- */
    --tf-font-size-xs: clamp(11px, 0.7rem + 0.1vw, 12px);
    --tf-font-size-sm: clamp(12px, 0.75rem + 0.15vw, 13px);
    --tf-font-size-body: clamp(14px, 0.875rem + 0.15vw, 16px);
    --tf-font-size-lg: clamp(16px, 1rem + 0.2vw, 18px);
    --tf-font-size-h6: clamp(14px, 0.875rem + 0.2vw, 16px);
    --tf-font-size-h5: clamp(16px, 1rem + 0.3vw, 18px);
    --tf-font-size-h4: clamp(18px, 1.125rem + 0.4vw, 22px);
    --tf-font-size-h3: clamp(20px, 1.25rem + 0.6vw, 26px);
    --tf-font-size-h2: clamp(24px, 1.5rem + 0.8vw, 32px);
    --tf-font-size-h1: clamp(28px, 1.75rem + 1.2vw, 40px);

    /* -- Line-height scale (v13.0 DS-01) -- */
    --tf-line-tight: 1.2;
    --tf-line-snug: 1.35;
    --tf-line-normal: 1.5;
    --tf-line-relaxed: 1.6;

    /* -- Font-weight scale (v13.0 DS-01) -- */
    --tf-weight-regular: 400;
    --tf-weight-medium: 500;
    --tf-weight-semibold: 600;
    --tf-weight-bold: 700;
}

/* ============================================================
   RESPONSIVE TOKEN ADJUSTMENTS (v13.0 DS-02)
   Spacing scale adapts per breakpoint. Typography already
   scales fluidly via clamp() and needs no media queries.
   ============================================================ */

/* Tablet (>=768px): loosen spacing by ~15% for comfort */
@media (min-width: 768px) {
    :root {
        --tf-space-md: 18px;
        --tf-space-lg: 28px;
        --tf-space-xl: 36px;
        --tf-space-2xl: 56px;
        --tf-space-3xl: 72px;
    }
}

/* Desktop (>=1024px): loosen further for power-user density */
@media (min-width: 1024px) {
    :root {
        --tf-space-md: 20px;
        --tf-space-lg: 32px;
        --tf-space-xl: 40px;
        --tf-space-2xl: 64px;
        --tf-space-3xl: 80px;
    }
}

/* Wide desktop (>=1440px): maximum comfort spacing */
@media (min-width: 1440px) {
    :root {
        --tf-space-lg: 36px;
        --tf-space-xl: 48px;
        --tf-space-2xl: 72px;
        --tf-space-3xl: 96px;
    }
}

/* ============================================================
   GLOBAL RESET & TYPOGRAPHY
   ============================================================ */

*, *::before, *::after {
    box-sizing: border-box;
}

html, body {
    font-family: var(--tf-font-body);
    font-size: 15px;                       /* base enterprise */
    line-height: 1.5;
    color: var(--tf-text-primary);
    background-color: var(--tf-page-bg);
    margin: 0;
    padding: 0;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--tf-font-display);
    font-weight: 600;
    color: var(--tf-text-primary);
    line-height: 1.25;
    letter-spacing: -0.015em;
    margin-top: 0;
}
h1 { font-weight: 700; letter-spacing: -0.025em; }
h2 { font-weight: 700; letter-spacing: -0.02em; }

p {
    color: var(--tf-text-secondary);
    line-height: 1.55;
}

/* Anchors textuales (links de contenido, NO chrome de navegacion).
   Excluimos sidebar/header/nav/menu para que sus items hereden el color
   del nav slate, no el cobalt de los links de prosa.
   Las clases excluidas son las que envuelven los anchors del chrome. */
a {
    color: var(--tf-info);                 /* cobalt enterprise para links */
    text-decoration: none;
    transition: color var(--tf-transition-fast);
}

a:hover {
    color: var(--tf-primary);              /* hover a verde agro */
}

/* Reset · anchors del chrome de navegacion heredan el color del padre.
   Cubre AppSidebar, AppHeader, navs, dropdowns y menus. */
.app-sidebar a,
.cdc-sidebar a,
.cdc-appbar a,
.app-header a,
.sidebar-nav a,
.nav.menu a,
nav a {
    color: inherit;
}
.app-sidebar a:hover,
.cdc-sidebar a:hover,
.cdc-appbar a:hover,
.app-header a:hover,
.sidebar-nav a:hover,
.nav.menu a:hover,
nav a:hover {
    color: inherit;
}

/* ============================================================
   LAYOUT STRUCTURE
   ============================================================ */

#wrapper {
    display: flex;
    min-height: 100vh;
}

#page-wrapper {
    flex: 1;
    /* Un flex item tiene `min-width: auto`, es decir NO se encoge por debajo del
       ancho minimo de su contenido. Consecuencia: cualquier contenido ancho de una
       pagina (un listado con muchas columnas, una tabla con min-width) empujaba
       este contenedor y estiraba la pagina ENTERA, cabecera incluida, con barra de
       desplazamiento horizontal en todo el documento. Medido en /maestras/dosis:
       el grid pedia 1.560 px y #page-wrapper crecia de 1.180 a 1.618 px.
       Con min-width: 0 el contenedor se queda en su ancho y el desbordamiento lo
       resuelve quien lo produce, dentro de su propio contenedor con scroll
       (ver la utilidad .cdc-grid-scroll en editorial.css). */
    min-width: 0;
    margin-left: var(--sidebar-width-expanded);
    padding-top: var(--header-height);
    background-color: var(--tf-page-bg);
    min-height: 100vh;
    transition: margin-left var(--tf-transition-normal);
}

#page-wrapper.sidebar-collapsed {
    margin-left: var(--sidebar-width-collapsed);
}

.page-content {
    padding: 24px 28px;
}

/* ============================================================
   ANIMATED GRADIENT BACKGROUND (Login)
   ============================================================ */

@keyframes gradientShift {
    0%   { background-position: 0% 50%; }
    25%  { background-position: 50% 100%; }
    50%  { background-position: 100% 50%; }
    75%  { background-position: 50% 0%; }
    100% { background-position: 0% 50%; }
}

.login-background {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(-45deg,
        #0a5c2e,
        #0d7c3e,
        #1e2a3a,
        #2c5f3f,
        #1a3a2a,
        #0d7c3e
    );
    background-size: 400% 400%;
    animation: gradientShift 16s ease infinite;
    padding: 1rem;
    position: relative;
    overflow: hidden;
}

.login-background::before {
    content: '';
    position: absolute;
    top: -50%;
    left: -50%;
    width: 200%;
    height: 200%;
    background: radial-gradient(ellipse at 30% 50%, rgba(13, 124, 62, 0.15) 0%, transparent 50%),
                radial-gradient(ellipse at 70% 20%, rgba(212, 168, 83, 0.08) 0%, transparent 40%);
    pointer-events: none;
}

/* ============================================================
   GLASS-MORPHISM LOGIN CARD
   ============================================================ */

@keyframes cardEntrance {
    from {
        opacity: 0;
        transform: translateY(24px) scale(0.98);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

.login-card {
    background: rgba(255, 255, 255, 0.88);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2),
                0 4px 12px rgba(0, 0, 0, 0.1);
    padding: 2.5rem 2.25rem;
    width: 100%;
    max-width: 420px;
    animation: cardEntrance 0.6s ease-out;
    position: relative;
    z-index: 1;
}

.login-header {
    text-align: center;
    margin-bottom: 2rem;
}

.login-branding-icon {
    width: 56px;
    height: 56px;
    background: linear-gradient(135deg, var(--tf-sidebar-header-start), var(--tf-sidebar-header-end));
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 1rem auto;
    font-size: 1.5rem;
    color: #fff;
    box-shadow: 0 4px 12px rgba(13, 124, 62, 0.3);
}

.login-logo {
    font-family: var(--tf-font-display);
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--tf-text-primary);
    margin: 0 0 0.25rem 0;
    letter-spacing: -0.5px;
}

.login-subtitle {
    font-family: var(--tf-font-body);
    font-size: 0.85rem;
    color: var(--tf-text-muted);
    margin: 0;
    font-weight: 400;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

/* Login form */
.login-form {
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
}

.form-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.form-field-label {
    font-family: var(--tf-font-display);
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--tf-text-secondary);
    letter-spacing: 0.02em;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Login form inputs */
.login-input {
    width: 100%;
    padding: 0.7rem 0.9rem;
    border-radius: 8px;
    border: 1.5px solid var(--tf-border-color);
    font-size: 0.95rem;
    font-family: var(--tf-font-body);
    background: rgba(255, 255, 255, 0.7);
    color: var(--tf-text-primary);
    transition: border-color var(--tf-transition-fast), box-shadow var(--tf-transition-fast), background var(--tf-transition-fast);
    outline: none;
}

.login-input::placeholder {
    color: var(--tf-text-muted);
}

.login-input:focus {
    border-color: var(--tf-primary);
    box-shadow: 0 0 0 3px rgba(var(--tf-primary-rgb), 0.12);
    background: #fff;
}

/* Radzen input overrides for login */
.form-field ::deep .rz-textbox,
.form-field ::deep input[type="password"],
.form-field ::deep input[type="text"] {
    padding: 0.7rem 0.9rem;
    border-radius: 8px;
    border: 1.5px solid var(--tf-border-color);
    font-size: 0.95rem;
    font-family: var(--tf-font-body);
    background: rgba(255, 255, 255, 0.7);
    color: var(--tf-text-primary);
    transition: border-color var(--tf-transition-fast), box-shadow var(--tf-transition-fast);
    outline: none;
}

.form-field ::deep .rz-textbox:focus,
.form-field ::deep input[type="password"]:focus,
.form-field ::deep input[type="text"]:focus {
    border-color: var(--tf-primary);
    box-shadow: 0 0 0 3px rgba(var(--tf-primary-rgb), 0.12);
    background: #fff;
}

/* Login button */
.btn-login {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.75rem 1.5rem;
    border: none;
    border-radius: 8px;
    font-size: 0.95rem;
    font-family: var(--tf-font-display);
    font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, var(--tf-sidebar-header-start), var(--tf-sidebar-header-end));
    cursor: pointer;
    transition: transform var(--tf-transition-fast), box-shadow var(--tf-transition-fast), opacity var(--tf-transition-fast);
    box-shadow: 0 2px 8px rgba(13, 124, 62, 0.25);
    letter-spacing: 0.02em;
}

.btn-login:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 4px 16px rgba(13, 124, 62, 0.35);
}

.btn-login:active:not(:disabled) {
    transform: translateY(0);
}

.btn-login:disabled {
    opacity: 0.65;
    cursor: not-allowed;
    transform: none;
}

/* Login error */
.login-error {
    background: var(--tf-danger-light);
    border: 1px solid rgba(220, 53, 69, 0.2);
    border-radius: 8px;
    padding: 0.65rem 0.85rem;
    color: var(--tf-danger);
    font-size: 0.85rem;
    font-family: var(--tf-font-body);
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Login spinner */
.login-spinner {
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* Login separator */
.login-separator {
    border: none;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    margin: 0.25rem 0;
}

/* ============================================================
   SIDEBAR
   ============================================================ */

.app-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--sidebar-width-expanded);
    background-color: var(--tf-sidebar-bg);
    color: var(--tf-menu-text);
    z-index: 1000;
    overflow-x: hidden;
    overflow-y: auto;
    transition: width var(--tf-transition-normal);
    display: flex;
    flex-direction: column;
}

.app-sidebar.collapsed {
    width: var(--sidebar-width-collapsed);
}

/* Sidebar header / logo area · transparent · hereda del slate-950 del wrapper.
   El monograma SI lleva gradient forest, pero el HEADER wrapper no debe
   pintarse de verde (rompe la coherencia con el resto del sidebar). */
.sidebar-header {
    background: transparent;
    padding: 18px 16px;
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 60px;
    flex-shrink: 0;
}

.sidebar-logo-monogram {
    width: 38px;
    height: 38px;
    min-width: 38px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--tf-font-display);
    font-size: 1rem;
    font-weight: 700;
    color: #fff;
    letter-spacing: -0.5px;
}

.sidebar-logo-text {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.sidebar-logo-text .logo-title {
    color: #fff;
    font-family: var(--tf-font-display);
    font-size: 0.95rem;
    font-weight: 600;
    white-space: nowrap;
    line-height: 1.2;
}

.sidebar-logo-text .logo-subtitle {
    color: rgba(255, 255, 255, 0.65);
    font-family: var(--tf-font-body);
    font-size: 0.7rem;
    white-space: nowrap;
    line-height: 1.3;
}

.app-sidebar.collapsed .sidebar-logo-text {
    display: none;
}

.app-sidebar.collapsed .sidebar-header {
    justify-content: center;
    padding: 18px 8px;
}

/* Sidebar navigation */
.sidebar-nav {
    list-style: none;
    margin: 0;
    padding: 8px 0;
    flex: 1;
    overflow-y: auto;
}

.sidebar-nav li {
    position: relative;
}

/* Section headers */
.sidebar-section-header {
    font-family: var(--tf-font-display);
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tf-menu-section-text);
    padding: 16px 20px 6px 20px;
    white-space: nowrap;
    overflow: hidden;
}

.app-sidebar.collapsed .sidebar-section-header {
    text-align: center;
    padding: 12px 4px 4px;
    font-size: 0;
}

.app-sidebar.collapsed .sidebar-section-header::after {
    content: '';
    display: block;
    width: 20px;
    height: 1px;
    background: rgba(255, 255, 255, 0.12);
    margin: 0 auto;
}

/* Sidebar separator */
.sidebar-separator {
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    margin: 8px 16px;
}

/* Menu items */
.sidebar-nav > li > a,
.sidebar-nav > li > .nav-link-toggle {
    display: flex;
    align-items: center;
    padding: 10px 20px;
    color: var(--tf-menu-text);
    text-decoration: none;
    font-family: var(--tf-font-nav);
    font-size: 0.87rem;
    font-weight: 400;
    cursor: pointer;
    transition: background-color var(--tf-transition-fast), color var(--tf-transition-fast);
    border: none;
    background: none;
    width: 100%;
    text-align: left;
    gap: 12px;
    border-left: 3px solid transparent;
}

.sidebar-nav > li > a:hover,
.sidebar-nav > li > .nav-link-toggle:hover {
    background-color: var(--tf-sidebar-hover);
    color: var(--tf-menu-text-hover);
}

.sidebar-nav > li.active > a,
.sidebar-nav > li.active > .nav-link-toggle {
    background-color: var(--tf-sidebar-active-bg);
    color: var(--tf-menu-text-active);
    border-left-color: var(--tf-sidebar-active-border);
}

/* Menu icons */
.sidebar-nav .nav-icon {
    width: 22px;
    text-align: center;
    font-size: 15px;
    flex-shrink: 0;
    opacity: 0.85;
}

.sidebar-nav > li.active .nav-icon {
    opacity: 1;
    color: var(--tf-primary);
}

/* Menu label */
.sidebar-nav .nav-label {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Arrow indicator for submenus */
.sidebar-nav .nav-arrow {
    font-size: 10px;
    transition: transform var(--tf-transition-fast);
    margin-left: auto;
    opacity: 0.5;
}

.sidebar-nav > li.open > .nav-link-toggle .nav-arrow {
    transform: rotate(90deg);
}

/* Sub-menu */
.sidebar-nav .sub-menu {
    list-style: none;
    margin: 0;
    padding: 0;
    background-color: rgba(0, 0, 0, 0.12);
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--tf-transition-normal);
}

.sidebar-nav > li.open > .sub-menu {
    max-height: 1200px;
}

.sidebar-nav .sub-menu li a,
.sidebar-nav .sub-menu li > .nav-link-toggle {
    display: flex;
    align-items: center;
    padding: 8px 12px 8px 55px;
    color: var(--tf-menu-text);
    text-decoration: none;
    font-family: var(--tf-font-nav);
    font-size: 0.83rem;
    transition: background-color var(--tf-transition-fast), color var(--tf-transition-fast);
    cursor: pointer;
    border: none;
    background: none;
    width: 100%;
    text-align: left;
}

.sidebar-nav .sub-menu li a:hover,
.sidebar-nav .sub-menu li > .nav-link-toggle:hover {
    background-color: var(--tf-sidebar-hover);
    color: var(--tf-menu-text-hover);
}

.sidebar-nav .sub-menu li.active > a {
    color: var(--tf-menu-text-active);
    font-weight: 500;
}

/* Third-level sub-menu */
.sidebar-nav .sub-menu .sub-menu {
    background-color: rgba(0, 0, 0, 0.08);
}

.sidebar-nav .sub-menu .sub-menu li a {
    padding-left: 70px;
    font-size: 0.8rem;
}

/* Sub-menu open state within sub-menu */
.sidebar-nav .sub-menu > li.open > .sub-menu {
    max-height: 600px;
}

/* Collapsed sidebar: hide labels */
.app-sidebar.collapsed .nav-label,
.app-sidebar.collapsed .nav-arrow {
    display: none;
}

.app-sidebar.collapsed .sidebar-nav > li > a,
.app-sidebar.collapsed .sidebar-nav > li > .nav-link-toggle {
    padding: 12px 0;
    justify-content: center;
    border-left-width: 0;
}

.app-sidebar.collapsed .sidebar-nav > li.active > a,
.app-sidebar.collapsed .sidebar-nav > li.active > .nav-link-toggle {
    border-left-width: 0;
    position: relative;
}

.app-sidebar.collapsed .sidebar-nav > li.active > a::before,
.app-sidebar.collapsed .sidebar-nav > li.active > .nav-link-toggle::before {
    content: '';
    position: absolute;
    left: 0;
    top: 25%;
    bottom: 25%;
    width: 3px;
    background: var(--tf-primary);
    border-radius: 0 2px 2px 0;
}

.app-sidebar.collapsed .sidebar-nav .sub-menu {
    display: none;
}

.app-sidebar.collapsed .sidebar-nav .nav-icon {
    font-size: 17px;
    width: auto;
}

/* Sidebar footer - role badge */
.sidebar-footer {
    padding: 0.75rem 1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    margin-top: auto;
}

.sidebar-role-badge {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.6);
}

.sidebar-role-badge i {
    font-size: 0.75rem;
    opacity: 0.7;
}

.app-sidebar.collapsed .sidebar-footer {
    padding: 0.75rem 0.5rem;
    text-align: center;
}

.app-sidebar.collapsed .sidebar-role-badge {
    justify-content: center;
}

/* ============================================================
   TOP NAVBAR
   ============================================================ */

.app-header {
    position: fixed;
    top: 0;
    left: var(--sidebar-width-expanded);
    right: 0;
    height: var(--header-height);
    background: var(--tf-white);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    display: flex;
    align-items: center;
    padding: 0 20px;
    gap: 16px;
    z-index: 1001;
    transition: left var(--tf-transition-normal);
}

.app-header.sidebar-collapsed {
    left: var(--sidebar-width-collapsed);
}

/* Hamburger button */
.btn-hamburger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: none;
    border-radius: 8px;
    background-color: transparent;
    color: var(--tf-text-secondary);
    font-size: 18px;
    cursor: pointer;
    transition: background-color var(--tf-transition-fast), color var(--tf-transition-fast);
    flex-shrink: 0;
}

.btn-hamburger:hover {
    background-color: var(--tf-primary-light);
    color: var(--tf-primary);
}

/* Header context / titular */
.header-context {
    font-family: var(--tf-font-display);
    font-size: 0.9rem;
    color: var(--tf-text-secondary);
    white-space: nowrap;
}

.header-context .context-label {
    font-weight: 500;
    color: var(--tf-text-primary);
}

.header-spacer {
    flex: 1;
}

.header-right {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Exercise selector - pill style */
.exercise-selector {
    position: relative;
}

.exercise-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    background: var(--tf-primary-light);
    color: var(--tf-primary);
    border: 1px solid rgba(var(--tf-primary-rgb), 0.2);
    border-radius: 20px;
    font-family: var(--tf-font-display);
    font-size: 0.82rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--tf-transition-fast), border-color var(--tf-transition-fast);
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: none;
}

.exercise-pill:hover {
    background: rgba(var(--tf-primary-rgb), 0.2);
    border-color: rgba(var(--tf-primary-rgb), 0.3);
}

.exercise-pill:focus {
    box-shadow: 0 0 0 3px rgba(var(--tf-primary-rgb), 0.12);
}

/* Fallback for native select in exercise-selector */
.exercise-selector select {
    display: inline-flex;
    align-items: center;
    padding: 6px 28px 6px 14px;
    background: var(--tf-primary-light);
    color: var(--tf-primary);
    border: 1px solid rgba(var(--tf-primary-rgb), 0.2);
    border-radius: 20px;
    font-family: var(--tf-font-display);
    font-size: 0.82rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--tf-transition-fast);
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%230d7c3e' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
}

.exercise-selector select:hover {
    background-color: rgba(var(--tf-primary-rgb), 0.2);
}

.exercise-selector select:focus {
    box-shadow: 0 0 0 3px rgba(var(--tf-primary-rgb), 0.12);
}

/* User menu */
.user-menu {
    position: relative;
}

.user-avatar {
    width: 34px;
    height: 34px;
    min-width: 34px;
    background: linear-gradient(135deg, var(--tf-sidebar-header-start), var(--tf-sidebar-header-end));
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--tf-font-display);
    font-size: 0.78rem;
    font-weight: 600;
    color: #fff;
    letter-spacing: 0.02em;
}

.user-menu-trigger {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    padding: 6px 10px;
    border-radius: 8px;
    transition: background-color var(--tf-transition-fast);
    color: var(--tf-text-secondary);
    font-family: var(--tf-font-display);
    font-size: 0.85rem;
    font-weight: 500;
    border: none;
    background: none;
}

.user-menu-trigger:hover {
    background-color: var(--tf-page-bg);
}

.user-menu-trigger .user-name {
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.role-badge {
    font-size: 11px;
    background: #2E7D32;
    color: white;
    border-radius: 12px;
    padding: 2px 8px;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
}

.user-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    background: #fff;
    border: 1px solid var(--tf-border-color);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    min-width: 200px;
    z-index: 1100;
    padding: 6px;
    animation: dropdownFade 0.15s ease-out;
}

@keyframes dropdownFade {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}

.user-dropdown a,
.user-dropdown button {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    color: var(--tf-text-secondary);
    text-decoration: none;
    font-family: var(--tf-font-body);
    font-size: 0.85rem;
    border: none;
    background: none;
    width: 100%;
    text-align: left;
    cursor: pointer;
    border-radius: 6px;
    transition: background-color var(--tf-transition-fast), color var(--tf-transition-fast);
}

.user-dropdown a:hover,
.user-dropdown button:hover {
    background-color: var(--tf-page-bg);
    color: var(--tf-primary);
}

.user-dropdown button.logout-btn:hover {
    background-color: var(--tf-danger-light);
    color: var(--tf-danger);
}

/* ============================================================
   PAGE HEADING
   ============================================================ */

.page-heading {
    padding: 24px 28px;
    background: #fff;
    margin: -24px -28px 24px -28px;
    border-bottom: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.page-heading h2 {
    font-family: var(--tf-font-display);
    font-size: 1.5rem;
    font-weight: 600;
    margin: 0;
    color: var(--tf-text-primary);
}

.page-heading .page-subtitle {
    font-family: var(--tf-font-body);
    font-size: 0.9rem;
    color: var(--tf-text-muted);
    margin: 4px 0 0;
}

/* ============================================================
   CARDS (Modern shadow-based, no borders)
   ============================================================ */

.tf-card {
    background: #fff;
    border-radius: var(--tf-card-radius);
    box-shadow: var(--tf-card-shadow);
    padding: 24px;
    transition: box-shadow var(--tf-transition-fast), transform var(--tf-transition-fast);
    border: none;
}

.tf-card:hover {
    box-shadow: var(--tf-card-shadow-hover);
}

.tf-card-clickable:hover {
    transform: translateY(-2px);
    cursor: pointer;
}

/* Stat card */
.stat-card {
    background: #fff;
    border-radius: var(--tf-card-radius);
    box-shadow: var(--tf-card-shadow);
    padding: 20px 24px;
    display: flex;
    align-items: center;
    gap: 16px;
    transition: box-shadow var(--tf-transition-fast);
}

.stat-card:hover {
    box-shadow: var(--tf-card-shadow-hover);
}

.stat-card-icon {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
    flex-shrink: 0;
}

.stat-card-icon.green {
    background: var(--tf-primary-light);
    color: var(--tf-primary);
}

.stat-card-icon.blue {
    background: var(--tf-info-light);
    color: var(--tf-info);
}

.stat-card-icon.gold {
    background: var(--tf-accent-warm-light);
    color: var(--tf-accent-warm);
}

.stat-card-icon.red {
    background: var(--tf-danger-light);
    color: var(--tf-danger);
}

.stat-card-content {
    flex: 1;
    min-width: 0;
}

.stat-card-value {
    font-family: var(--tf-font-display);
    font-size: 1.65rem;
    font-weight: 700;
    color: var(--tf-text-primary);
    line-height: 1;
    margin-bottom: 4px;
}

.stat-card-label {
    font-family: var(--tf-font-body);
    font-size: 0.82rem;
    color: var(--tf-text-muted);
    font-weight: 400;
}

/* Quick access card */
.quick-card {
    background: #fff;
    border-radius: var(--tf-card-radius);
    box-shadow: var(--tf-card-shadow);
    padding: 28px 24px;
    text-align: center;
    transition: box-shadow var(--tf-transition-fast), transform var(--tf-transition-fast);
    cursor: pointer;
    text-decoration: none;
    display: block;
}

.quick-card:hover {
    box-shadow: var(--tf-card-shadow-hover);
    transform: translateY(-2px);
}

.quick-card-icon {
    width: 52px;
    height: 52px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3rem;
    margin: 0 auto 14px auto;
}

.quick-card-title {
    font-family: var(--tf-font-display);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--tf-text-primary);
    margin-bottom: 6px;
}

.quick-card-desc {
    font-family: var(--tf-font-body);
    font-size: 0.82rem;
    color: var(--tf-text-muted);
    line-height: 1.5;
    margin: 0;
}

/* Legacy ibox - updated to modern style */
.ibox {
    background: #fff;
    border-radius: var(--tf-card-radius);
    box-shadow: var(--tf-card-shadow);
    margin-bottom: 20px;
    border: none;
}

.ibox-title {
    background-color: #fff;
    border-bottom: 1px solid var(--tf-border-color);
    padding: 16px 20px;
    display: flex;
    align-items: center;
    border-radius: var(--tf-card-radius) var(--tf-card-radius) 0 0;
}

.ibox-title h5 {
    font-family: var(--tf-font-display);
    font-size: 0.95rem;
    font-weight: 600;
    margin: 0;
    color: var(--tf-text-primary);
}

.ibox-content {
    padding: 20px;
}

/* ============================================================
   BUTTONS
   ============================================================ */

.btn-sb-primary {
    background: linear-gradient(135deg, var(--tf-primary), var(--tf-primary-hover));
    border: none;
    color: #fff;
    padding: 8px 18px;
    border-radius: 8px;
    font-family: var(--tf-font-display);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: box-shadow var(--tf-transition-fast), transform var(--tf-transition-fast);
    box-shadow: 0 2px 6px rgba(var(--tf-primary-rgb), 0.2);
}

.btn-sb-primary:hover {
    box-shadow: 0 4px 12px rgba(var(--tf-primary-rgb), 0.3);
    transform: translateY(-1px);
}

/* Override Radzen primary button */
.rz-button.rz-primary,
.rz-button.rz-button-md.rz-primary {
    background: linear-gradient(135deg, var(--tf-primary), var(--tf-primary-hover)) !important;
    border: none !important;
    border-radius: 8px !important;
    font-family: var(--tf-font-display) !important;
}

.rz-button.rz-primary:hover,
.rz-button.rz-button-md.rz-primary:hover {
    box-shadow: 0 4px 12px rgba(var(--tf-primary-rgb), 0.3) !important;
}

/* ============================================================
   RADZEN LAYOUT OVERRIDES
   ============================================================ */

.rz-header {
    position: fixed;
    top: 0;
    left: var(--sidebar-width-expanded);
    right: 0;
    z-index: 1001;
    height: var(--header-height);
    background: var(--tf-white) !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    border-bottom: none;
    transition: left var(--tf-transition-normal);
}

.rz-sidebar {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    bottom: 0 !important;
    width: var(--sidebar-width-expanded) !important;
    background-color: var(--tf-sidebar-bg) !important;
    border-right: none !important;
    z-index: 1000 !important;
    transition: width var(--tf-transition-normal);
}

.rz-body {
    background-color: var(--tf-page-bg) !important;
    min-height: calc(100vh - var(--header-height));
    margin-top: var(--header-height);
}

/* Override Radzen card */
.rz-card {
    border-radius: var(--tf-card-radius);
    border: none;
    box-shadow: var(--tf-card-shadow);
    background: #fff;
    transition: box-shadow var(--tf-transition-fast);
}

.rz-card:hover {
    box-shadow: var(--tf-card-shadow-hover);
}

/* Override Radzen validation messages */
.rz-message {
    font-family: var(--tf-font-body);
    font-size: 0.8rem;
}

/* ============================================================
   FORM INPUTS (Global)
   ============================================================ */

.rz-textbox,
input[type="text"],
input[type="email"],
input[type="number"],
input[type="password"],
textarea,
select {
    font-family: var(--tf-font-body);
    border-radius: 8px;
}

/* ============================================================
   LOADING OVERLAY
   ============================================================ */

.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.15);
    z-index: 2000000;
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(4px);
}

.loading-spinner-large {
    width: 48px;
    height: 48px;
    border: 3px solid rgba(var(--tf-primary-rgb), 0.15);
    border-top-color: var(--tf-primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

/* Legacy loading squares (compatibility) */
.loading-squares {
    position: relative;
    width: 80px;
    height: 80px;
}

.loading-squares .boxy {
    width: 45%;
    height: 45%;
    opacity: 0;
    animation: loady 1s linear infinite;
    position: absolute;
    border-radius: 4px;
}

.loading-squares .boxy:nth-of-type(1) {
    top: 2.5%; left: 2.5%;
    background: rgba(13, 124, 62, 0.9);
}

.loading-squares .boxy:nth-of-type(2) {
    top: 2.5%; right: 2.5%;
    background: rgba(10, 92, 46, 0.9);
    animation-delay: -0.25s;
}

.loading-squares .boxy:nth-of-type(3) {
    bottom: 2.5%; right: 2.5%;
    background: rgba(212, 168, 83, 0.9);
    animation-delay: -0.5s;
}

.loading-squares .boxy:nth-of-type(4) {
    bottom: 2.5%; left: 2.5%;
    background: rgba(30, 42, 58, 0.9);
    animation-delay: -0.75s;
}

@keyframes loady {
    0%   { opacity: 0; }
    30%  { opacity: 0; }
    90%  { opacity: 1; }
    100% { opacity: 0; }
}

/* ============================================================
   BADGES
   ============================================================ */

.badge-year {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 12px;
    background: var(--tf-accent-warm-light);
    color: var(--tf-accent-warm);
    border: 1px solid rgba(212, 168, 83, 0.2);
    border-radius: 16px;
    font-family: var(--tf-font-display);
    font-size: 0.8rem;
    font-weight: 600;
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 768px) {
    .app-sidebar {
        transform: translateX(-100%);
        width: var(--sidebar-width-expanded) !important;
    }

    .app-sidebar.mobile-open {
        transform: translateX(0);
        box-shadow: 4px 0 20px rgba(0, 0, 0, 0.25);
        /* Por encima de la appbar (z 1001): antes el drawer quedaba DEBAJO de la
           barra y su cabecera (logo + cierre) aparecia tapada/cortada. */
        z-index: 1200;
    }

    .app-header {
        left: 0 !important;
    }

    #page-wrapper {
        margin-left: 0 !important;
    }

    .rz-body {
        margin-left: 0 !important;
    }

    .rz-header {
        left: 0 !important;
    }

    .sidebar-overlay {
        display: none;
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0, 0, 0, 0.4);
        z-index: 1190;   /* sobre la appbar, bajo el drawer */
        backdrop-filter: blur(2px);
    }

    .sidebar-overlay.active {
        display: block;
    }

    .page-content {
        padding: 16px;
    }

    .page-heading {
        padding: 16px;
        margin: -16px -16px 16px -16px;
    }

    .user-menu-trigger .user-name {
        display: none;
    }

    .header-context {
        display: none;
    }
}

@media (min-width: 769px) {
    .sidebar-overlay {
        display: none !important;
    }
}

@media (max-width: 480px) {
    .login-card {
        max-width: 100%;
        padding: 2rem 1.5rem;
        border-radius: 12px;
    }

    .login-logo {
        font-size: 1.4rem;
    }
}

/* ============================================================
   SCROLLBAR STYLING
   ============================================================ */

.app-sidebar::-webkit-scrollbar {
    width: 4px;
}

.app-sidebar::-webkit-scrollbar-track {
    background: transparent;
}

.app-sidebar::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 4px;
}

.app-sidebar::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.25);
}

.sidebar-nav::-webkit-scrollbar {
    width: 4px;
}

.sidebar-nav::-webkit-scrollbar-track {
    background: transparent;
}

.sidebar-nav::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 4px;
}

/* Firefox scrollbar */
.app-sidebar, .sidebar-nav {
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}

/* ============================================================
   UTILITY CLASSES
   ============================================================ */

/* ============================================================
   RADZEN DATAGRID OVERRIDES
   ============================================================ */

.rz-datatable {
    border-radius: var(--tf-card-radius);
    overflow: hidden;
    border: 1px solid var(--tf-border-color);
}

.rz-datatable .rz-datatable-thead > tr > th {
    font-family: var(--tf-font-display);
    font-weight: 600;
    font-size: 0.82rem;
    color: var(--tf-text-secondary);
    background: #f8f9fa;
    border-bottom: 2px solid var(--tf-border-color);
    padding: 12px 16px;
    letter-spacing: 0.01em;
    text-transform: none;
}

.rz-datatable .rz-datatable-tbody > tr > td {
    padding: 10px 16px;
    font-family: var(--tf-font-body);
    font-size: 0.87rem;
    border-bottom: 1px solid #f0f1f3;
    color: var(--tf-text-primary);
}

.rz-datatable .rz-datatable-tbody > tr:hover > td {
    background-color: rgba(var(--tf-primary-rgb), 0.04);
}

.rz-datatable .rz-datatable-tbody > tr:nth-child(even) > td {
    background-color: #fafbfc;
}

.rz-datatable .rz-datatable-tbody > tr:nth-child(even):hover > td {
    background-color: rgba(var(--tf-primary-rgb), 0.04);
}

/* Selected row */
.rz-datatable .rz-datatable-tbody > tr.rz-state-highlight > td,
.rz-datatable .rz-datatable-tbody > tr.rz-datatable-row-selected > td {
    background-color: rgba(var(--tf-primary-rgb), 0.08) !important;
    color: var(--tf-text-primary);
}

/* Pagination */
.rz-datatable .rz-paginator {
    border-top: 1px solid var(--tf-border-color);
    padding: 10px 16px;
    background: #fafbfc;
}

.rz-paginator .rz-paginator-element {
    border-radius: 6px;
    min-width: 32px;
    height: 32px;
    font-family: var(--tf-font-display);
    font-size: 0.82rem;
    transition: all var(--tf-transition-fast);
}

.rz-paginator .rz-paginator-element:hover {
    background-color: var(--tf-primary-light);
    color: var(--tf-primary);
}

.rz-paginator .rz-paginator-element.rz-state-active,
.rz-paginator .rz-state-active {
    background: var(--tf-primary) !important;
    color: #fff !important;
    border-color: var(--tf-primary) !important;
}

/* Filter inputs */
.rz-datatable .rz-cell-filter input,
.rz-datatable .rz-cell-filter .rz-textbox {
    border-radius: 6px;
    border: 1px solid var(--tf-border-color);
    font-family: var(--tf-font-body);
    font-size: 0.82rem;
    padding: 4px 8px;
}

.rz-datatable .rz-cell-filter input:focus,
.rz-datatable .rz-cell-filter .rz-textbox:focus {
    border-color: var(--tf-primary);
    box-shadow: 0 0 0 2px rgba(var(--tf-primary-rgb), 0.1);
}

/* Sort indicators */
.rz-datatable .rz-sortable-column .rz-sortable-column-icon {
    color: var(--tf-primary);
}

/* Column resize handle */
.rz-datatable .rz-column-resizer {
    border-right: 2px solid transparent;
    transition: border-color var(--tf-transition-fast);
}

.rz-datatable .rz-column-resizer:hover {
    border-right-color: var(--tf-primary);
}

/* Empty grid message */
.rz-datatable .rz-datatable-emptymessage td {
    padding: 40px 20px;
    text-align: center;
    color: var(--tf-text-muted);
    font-family: var(--tf-font-body);
    font-size: 0.9rem;
}

/* Action buttons in grid */
.rz-datatable .rz-button.rz-button-sm {
    padding: 4px 8px;
    min-width: 30px;
    height: 30px;
}

/* ============================================================
   RADZEN DIALOG OVERRIDES
   ============================================================ */

.rz-dialog {
    border-radius: 14px !important;
    overflow: hidden;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 8px 20px rgba(0, 0, 0, 0.08) !important;
    border: none !important;
}

.rz-dialog-titlebar {
    font-family: var(--tf-font-display) !important;
    font-weight: 600 !important;
    font-size: 1.05rem !important;
    padding: 18px 24px !important;
    border-bottom: 1px solid var(--tf-border-color) !important;
    border-left: 4px solid var(--tf-primary) !important;
    background: #fff !important;
}

.rz-dialog-titlebar .rz-dialog-titlebar-close {
    border-radius: 8px;
    width: 32px;
    height: 32px;
    transition: background-color var(--tf-transition-fast);
}

.rz-dialog-titlebar .rz-dialog-titlebar-close:hover {
    background-color: var(--tf-danger-light);
    color: var(--tf-danger);
}

.rz-dialog-content {
    padding: 20px 24px !important;
}

.rz-dialog-wrapper .rz-dialog-footer,
.rz-dialog .rz-dialog-footer {
    padding: 12px 24px 18px !important;
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* Dialog overlay with blur */
.rz-dialog-mask {
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    background-color: rgba(0, 0, 0, 0.3) !important;
}

/* ============================================================
   LOADING & EMPTY STATE COMPONENTS
   ============================================================ */

@keyframes tfPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.5; }
}

@keyframes tfSpin {
    to { transform: rotate(360deg); }
}

.tf-loading-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 48px 24px;
    gap: 16px;
}

.tf-loading-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid rgba(var(--tf-primary-rgb), 0.12);
    border-top-color: var(--tf-primary);
    border-radius: 50%;
    animation: tfSpin 0.8s linear infinite;
}

.tf-loading-state p {
    font-family: var(--tf-font-body);
    font-size: 0.9rem;
    color: var(--tf-text-muted);
    margin: 0;
    animation: tfPulse 2s ease-in-out infinite;
}

/* ── Vacio con salida y dato pendiente ──────────────────────────────────────
   Estaban copiadas literalmente en las CINCO pantallas de tratamientos por ambito.
   Viven aqui, al lado de .tf-empty-state, porque son la misma familia: como se
   ensena que algo falta. .tf-falta usa el color SECUNDARIO y no el de texto
   deshabilitado — con el deshabilitado daba 1,88:1 de contraste, ilegible, y esto
   no es un control apagado sino un aviso que hay que poder leer. */
.tf-vacio-guia { padding: 2rem 1.5rem; text-align: center; }
.tf-vacio-guia__icono { font-size: 2rem; color: var(--cdc-info-text); margin-bottom: 0.75rem; display: block; }
.tf-vacio-guia__titulo { margin: 0 0 0.5rem; font-size: 1.1rem; }
.tf-vacio-guia__texto { margin: 0 0 1rem; color: var(--rz-text-secondary-color); }
.tf-vacio-guia__anios { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; }
.tf-falta { color: var(--rz-text-secondary-color, #6c757d); font-style: italic; }
.crud-toolbar-hint { color: var(--rz-text-secondary-color, #6c757d); font-size: .85em; }

.tf-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 56px 24px;
    gap: 8px;
    text-align: center;
}

.tf-empty-state > i {
    font-size: 2.5rem;
    color: var(--tf-text-muted);
    opacity: 0.4;
    margin-bottom: 8px;
}

.tf-empty-state h4 {
    font-family: var(--tf-font-display);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--tf-text-primary);
    margin: 0;
}

.tf-empty-state p {
    font-family: var(--tf-font-body);
    font-size: 0.88rem;
    color: var(--tf-text-muted);
    margin: 0;
    max-width: 320px;
}

/* ============================================================
   STAGGERED ENTRANCE ANIMATIONS
   ============================================================ */

@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.animate-in {
    opacity: 0;
    transform: translateY(12px);
    animation: fadeInUp 0.4s ease-out forwards;
}

.stagger-1 { animation-delay: 0.05s; }
.stagger-2 { animation-delay: 0.10s; }
.stagger-3 { animation-delay: 0.15s; }
.stagger-4 { animation-delay: 0.20s; }
.stagger-5 { animation-delay: 0.25s; }
.stagger-6 { animation-delay: 0.30s; }

/* ============================================================
   HOME PAGE LAYOUT CLASSES
   ============================================================ */

.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 20px;
    margin-bottom: 32px;
}

.quick-access-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 20px;
}

.section-heading {
    font-family: var(--tf-font-display);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--tf-text-primary);
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.section-heading i {
    color: var(--tf-accent-warm);
}

/* Quick card icon color variants */
.quick-card-icon.icon-green {
    background: var(--tf-primary-light);
    color: var(--tf-primary);
}

.quick-card-icon.icon-blue {
    background: var(--tf-info-light);
    color: var(--tf-info);
}

.quick-card-icon.icon-gold {
    background: var(--tf-accent-warm-light);
    color: var(--tf-accent-warm);
}

.quick-card-icon.icon-red {
    background: var(--tf-danger-light);
    color: var(--tf-danger);
}

/* ============================================================
   CRUD PAGE CLASSES
   ============================================================ */

.page-icon {
    color: var(--tf-primary);
    margin-right: 8px;
}

.page-icon.danger {
    color: var(--tf-danger);
}

.page-icon.info {
    color: var(--tf-info);
}

.crud-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    column-gap: 8px;
    margin-bottom: 16px;
}

/* El «Excel» de los listados (BotonExcel) va detrás de la cuenta: su margen automático deja la cuenta y sus
   pistas a la izquierda y junta las acciones a la derecha, separadas por el column-gap de arriba (con
   space-between y sin hueco, se habrían tocado). */
.crud-toolbar > .cdc-boton-excel {
    margin-left: auto;
}

.crud-toolbar-count {
    font-family: var(--tf-font-display);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--tf-text-primary);
}

/* Mientras llega la primera página, en lugar de la cuenta (que diría «0 registro(s)»). */
.crud-toolbar-cargando {
    font-family: var(--tf-font-display);
    font-size: 0.95rem;
    color: var(--tf-text-secondary);
}

.crud-grid-wrapper {
    margin-bottom: 24px;
    /* Permitir que las DataGrids con muchas columnas (parcelas SIGPAC, etc.)
       hagan scroll horizontal en vez de romper el layout. */
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: visible;
}

/* Cuando la wrapper esta dentro de un master-detail list, la rejilla puede
   scrollear horizontalmente sin afectar al panel de detalle. */
.tf-master-detail__list .crud-grid-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Asegurar que la datagrid Radzen no rompe el grid layout */
.tf-master-detail__list .rz-data-grid {
    min-width: 0;
}

/* ============================================================
   SIDEBAR HOVER POLISH
   ============================================================ */

.sidebar-nav > li > a,
.sidebar-nav > li > .nav-link-toggle {
    transition: background-color var(--tf-transition-fast), color var(--tf-transition-fast), padding-left var(--tf-transition-fast);
}

.sidebar-nav > li > a:hover,
.sidebar-nav > li > .nav-link-toggle:hover {
    padding-left: 24px;
}

.sidebar-nav > li.active > a,
.sidebar-nav > li.active > .nav-link-toggle {
    box-shadow: inset 0 0 12px rgba(var(--tf-primary-rgb), 0.08);
}

.sidebar-nav .sub-menu li a,
.sidebar-nav .sub-menu li > .nav-link-toggle {
    transition: background-color var(--tf-transition-fast), color var(--tf-transition-fast), padding-left var(--tf-transition-fast);
}

.sidebar-nav .sub-menu li a:hover,
.sidebar-nav .sub-menu li > .nav-link-toggle:hover {
    padding-left: 59px;
}

.sidebar-section-header {
    transition: opacity var(--tf-transition-normal);
}

.app-sidebar:not(.collapsed) .sidebar-section-header {
    animation: fadeInUp 0.3s ease-out;
}

/* ============================================================
   UTILITY CLASSES
   ============================================================ */

.gray-bg { background-color: var(--tf-page-bg); }
.white-bg { background-color: var(--tf-white); }
.text-primary { color: var(--tf-primary) !important; }
.text-gold { color: var(--tf-accent-warm) !important; }
.text-muted { color: var(--tf-text-muted) !important; }
.font-bold { font-weight: 700; }
.font-display { font-family: var(--tf-font-display); }
.m-t-sm { margin-top: 10px; }
.m-t-md { margin-top: 15px; }
.m-t-lg { margin-top: 25px; }
.m-b-sm { margin-bottom: 10px; }
.m-l-md { margin-left: 15px; }
.m-r-sm { margin-right: 4px; }
.m-r-md { margin-right: 15px; }
.p-w-xl { padding: 0 40px; }

/* ============================================================
   TF* BASE COMPONENTS (v13.0 DS-03)
   Token-driven components; consume variables from :root.
   Every value below references var(--tf-*) from Plan 01.
   Whitelist exceptions:
     - #fff (pure white text on colored backgrounds)
     - #8a6d2f (warning badge text; readable warm-brown on amber bg)
   ============================================================ */

/* -- TFButton -- */
.tf-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--tf-space-2xs);
    font-family: var(--tf-font-display);
    font-weight: var(--tf-weight-semibold);
    font-size: var(--tf-font-size-body);
    line-height: var(--tf-line-tight);
    padding: var(--tf-space-xs) var(--tf-space-md);
    border-radius: var(--tf-radius-md);
    border: 1px solid transparent;
    cursor: pointer;
    transition: background var(--tf-transition-fast),
                transform var(--tf-transition-fast),
                box-shadow var(--tf-transition-fast);
}

.tf-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.tf-btn--primary {
    background: var(--tf-primary);
    color: #fff;
}

.tf-btn--primary:hover:not(:disabled) {
    background: var(--tf-primary-hover);
    box-shadow: var(--tf-shadow-sm);
}

.tf-btn--secondary {
    background: transparent;
    color: var(--tf-primary);
    border-color: var(--tf-primary);
}

.tf-btn--secondary:hover:not(:disabled) {
    background: var(--tf-primary-light);
}

.tf-btn--tertiary {
    background: transparent;
    color: var(--tf-text-primary);
}

.tf-btn--tertiary:hover:not(:disabled) {
    background: var(--tf-border-color);
}

.tf-btn--danger {
    background: var(--tf-danger);
    color: #fff;
}

.tf-btn--danger:hover:not(:disabled) {
    background: var(--tf-danger);
    filter: brightness(0.92);
}

.tf-btn--sm {
    font-size: var(--tf-font-size-sm);
    padding: var(--tf-space-2xs) var(--tf-space-sm);
}

.tf-btn--lg {
    font-size: var(--tf-font-size-lg);
    padding: var(--tf-space-sm) var(--tf-space-lg);
}

/* -- TFCard -- */
.tf-card {
    background: var(--tf-white);
    border-radius: var(--tf-radius-lg);
    border: 1px solid var(--tf-border-color);
    color: var(--tf-text-primary);
}

.tf-card--elev-sm { box-shadow: var(--tf-shadow-sm); }
.tf-card--elev-md { box-shadow: var(--tf-shadow-md); }
.tf-card--elev-lg { box-shadow: var(--tf-shadow-lg); }

.tf-card--pad-compact .tf-card__body { padding: var(--tf-space-sm); }
.tf-card--pad-normal  .tf-card__body { padding: var(--tf-space-md); }
.tf-card--pad-loose   .tf-card__body { padding: var(--tf-space-xl); }

.tf-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--tf-space-md);
    border-bottom: 1px solid var(--tf-border-color);
}

.tf-card__title {
    margin: 0;
    font-family: var(--tf-font-display);
    font-size: var(--tf-font-size-h5);
    font-weight: var(--tf-weight-semibold);
    color: var(--tf-text-primary);
}

.tf-card__actions {
    display: flex;
    gap: var(--tf-space-xs);
}

/* -- TFInput -- */
.tf-input {
    display: flex;
    flex-direction: column;
    gap: var(--tf-space-2xs);
}

.tf-input__label {
    font-family: var(--tf-font-body);
    font-size: var(--tf-font-size-sm);
    font-weight: var(--tf-weight-medium);
    color: var(--tf-text-secondary);
}

.tf-input__required {
    color: var(--tf-danger);
    margin-left: var(--tf-space-3xs);
}

.tf-input__control {
    font-family: var(--tf-font-body);
    font-size: var(--tf-font-size-body);
    padding: var(--tf-space-xs) var(--tf-space-sm);
    border: 1px solid var(--tf-border-color);
    border-radius: var(--tf-radius-md);
    background: var(--tf-white);
    color: var(--tf-text-primary);
    transition: border-color var(--tf-transition-fast),
                box-shadow var(--tf-transition-fast);
}

.tf-input__control:focus {
    outline: none;
    border-color: var(--tf-primary);
    box-shadow: 0 0 0 3px var(--tf-primary-light);
}

.tf-input--error .tf-input__control {
    border-color: var(--tf-danger);
}

.tf-input__error {
    font-size: var(--tf-font-size-sm);
    color: var(--tf-danger);
}

/* ============================================================
   TFDialog · Premium Star modal (v2026-04 redesign)
   Backdrop blur · ring shadow multi-layer · hairline highlight
   Entry scale(0.96) + opacity Emil · transform-origin: center
   ============================================================ */

.tf-dialog__overlay {
    position: fixed;
    inset: 0;
    /* Scrim slate-900 40% + backdrop blur premium tipo iOS/Vercel */
    background: rgba(15, 23, 42, 0.40);
    backdrop-filter: saturate(150%) blur(8px);
    -webkit-backdrop-filter: saturate(150%) blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: clamp(12px, 3vw, 32px);
    /* Fade-in del scrim · más rápido que el panel (180ms vs 280ms) */
    animation: tfDialogScrimIn 180ms ease both;
}
@keyframes tfDialogScrimIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.tf-dialog__panel {
    background: var(--tf-white);
    border: 1px solid rgba(15, 23, 42, 0.06);
    border-radius: 16px;
    /* Ring shadow multi-layer Vercel Geist + drop XL */
    box-shadow:
        0 0 0 1px rgba(15, 23, 42, 0.04),
        0 1px 2px rgba(15, 23, 42, 0.06),
        0 12px 32px -8px rgba(15, 23, 42, 0.18),
        0 32px 64px -16px rgba(15, 23, 42, 0.24);
    width: 100%;
    display: flex;
    flex-direction: column;
    max-height: 90vh;
    overflow: hidden;
    position: relative;
    isolation: isolate;
    /* Entry premium · scale(0.96) + opacity (never scale(0)) Emil rule */
    transform-origin: center;
    animation: tfDialogIn 280ms cubic-bezier(0.23, 1, 0.32, 1) both;
}

/* Hairline highlight superior · efecto "lifted" Vercel */
.tf-dialog__panel::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    border-radius: 16px 16px 0 0;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(15, 23, 42, 0.08) 20%,
        rgba(15, 23, 42, 0.08) 80%,
        transparent 100%);
    pointer-events: none;
    z-index: 1;
}

@keyframes tfDialogIn {
    from { opacity: 0; transform: scale(0.96) translateY(8px); }
    to   { opacity: 1; transform: scale(1)    translateY(0); }
}

.tf-dialog__panel--sm { max-width: 420px; }
.tf-dialog__panel--md { max-width: 600px; }
.tf-dialog__panel--lg { max-width: 900px; }
.tf-dialog__panel--xl { max-width: 1200px; }

/* Header premium · flex con close button alineado a la derecha */
.tf-dialog__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    border-bottom: 1px solid rgba(15, 23, 42, 0.08);
    flex-shrink: 0;
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.6) 0%,
        transparent 100%);
}

.tf-dialog__title {
    font-family: var(--tf-font-display);
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--tf-text-primary);
    letter-spacing: -0.02em;
    margin: 0;
    line-height: 1.3;
    flex: 1;
    min-width: 0;
}

/* Close button premium · scale(0.92) on active + ring focus */
.tf-dialog__close {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    color: #64748B;
    cursor: pointer;
    transition:
        background 150ms cubic-bezier(0.23, 1, 0.32, 1),
        color 150ms cubic-bezier(0.23, 1, 0.32, 1),
        border-color 150ms cubic-bezier(0.23, 1, 0.32, 1),
        transform 100ms cubic-bezier(0.23, 1, 0.32, 1),
        box-shadow 150ms cubic-bezier(0.23, 1, 0.32, 1);
    touch-action: manipulation;
    -webkit-appearance: none;
}
.tf-dialog__close:hover {
    background: #F1F5F9;
    color: #0F172A;
    border-color: #E2E8F0;
}
.tf-dialog__close:active { transform: scale(0.92); }
.tf-dialog__close:focus-visible {
    outline: none;
    box-shadow:
        0 0 0 2px var(--tf-white),
        0 0 0 4px rgba(37, 99, 235, 0.45);
}

.tf-dialog__body {
    padding: 20px;
    overflow: auto;
    color: var(--tf-text-primary);
    flex: 1;
    min-height: 0;
    /* Scrollbar premium overlay-style */
    scrollbar-width: thin;
    scrollbar-color: rgba(15, 23, 42, 0.20) transparent;
}
.tf-dialog__body::-webkit-scrollbar { width: 10px; }
.tf-dialog__body::-webkit-scrollbar-track { background: transparent; }
.tf-dialog__body::-webkit-scrollbar-thumb {
    background: rgba(15, 23, 42, 0.18);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
}
.tf-dialog__body::-webkit-scrollbar-thumb:hover {
    background: rgba(15, 23, 42, 0.32);
    background-clip: padding-box;
}

.tf-dialog__footer {
    padding: 14px 20px;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    align-items: center;
    flex-shrink: 0;
    background: rgba(248, 250, 252, 0.6);
}

/* Dark mode */
[data-theme="dark"] .tf-dialog__overlay {
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: saturate(150%) blur(8px);
}
[data-theme="dark"] .tf-dialog__panel {
    background: #131C2E;
    border-color: rgba(255, 255, 255, 0.06);
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.04),
        0 1px 2px rgba(0, 0, 0, 0.30),
        0 12px 32px -8px rgba(0, 0, 0, 0.50),
        0 32px 64px -16px rgba(0, 0, 0, 0.60);
}
[data-theme="dark"] .tf-dialog__panel::after {
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.06) 20%,
        rgba(255, 255, 255, 0.06) 80%,
        transparent 100%);
}
[data-theme="dark"] .tf-dialog__header {
    border-bottom-color: rgba(255, 255, 255, 0.06);
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0.02) 0%,
        transparent 100%);
}
[data-theme="dark"] .tf-dialog__close { color: #94A3B8; }
[data-theme="dark"] .tf-dialog__close:hover {
    background: rgba(255, 255, 255, 0.06);
    color: #F1F5F9;
    border-color: rgba(255, 255, 255, 0.08);
}
[data-theme="dark"] .tf-dialog__footer {
    border-top-color: rgba(255, 255, 255, 0.06);
    background: rgba(0, 0, 0, 0.20);
}

/* Reduced motion · keep opacity, kill movement */
@media (prefers-reduced-motion: reduce) {
    .tf-dialog__overlay,
    .tf-dialog__panel {
        animation-duration: 100ms !important;
        animation-timing-function: ease !important;
    }
    .tf-dialog__panel {
        transform: none !important;
    }
}

/* -- TFBadge -- */
.tf-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--tf-space-3xs);
    font-family: var(--tf-font-body);
    font-weight: var(--tf-weight-medium);
    padding: var(--tf-space-3xs) var(--tf-space-xs);
    border-radius: var(--tf-radius-pill);
    font-size: var(--tf-font-size-sm);
    line-height: var(--tf-line-tight);
}

.tf-badge--sm {
    font-size: var(--tf-font-size-xs);
    padding: var(--tf-space-3xs) var(--tf-space-2xs);
}

.tf-badge--success {
    background: rgba(13, 124, 62, 0.15);
    color: var(--tf-success);
}

.tf-badge--warning {
    background: var(--tf-accent-warm-light);
    color: #8a6d2f;
}

.tf-badge--danger {
    background: var(--tf-danger-light);
    color: var(--tf-danger);
}

.tf-badge--info {
    background: var(--tf-info-light);
    color: var(--tf-info);
}

.tf-badge--neutral {
    background: var(--tf-border-color);
    color: var(--tf-text-secondary);
}

/* ============================================================
   MOBILE FIRST FOUNDATION (v13.0 MOB-01 / MOB-02 / MOB-04)
   Touch targets, safe areas, hit-slop, grid-as-cards.
   Additive only - desktop rendering unchanged.
   ============================================================ */

:root {
    /* Touch target minimum - Apple HIG / Material Design baseline */
    --tf-touch-target-min: 44px;

    /* Safe-area tokens - resolve to env() on iOS, 0 elsewhere */
    --tf-safe-top: env(safe-area-inset-top, 0px);
    --tf-safe-right: env(safe-area-inset-right, 0px);
    --tf-safe-bottom: env(safe-area-inset-bottom, 0px);
    --tf-safe-left: env(safe-area-inset-left, 0px);
}

/* -- Kill the 300 ms tap delay and disable double-tap zoom on
      interactive elements. Applied globally because it is safe
      on desktop (no-op when no touch). -- */
button,
a,
[role="button"],
input[type="checkbox"],
input[type="radio"],
input[type="submit"],
input[type="button"],
.rz-button,
.nav-link-toggle,
.tf-btn {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* -- Hit-slop utility - extends tap area 12 px in every direction
      without changing the visual size of the icon. Wrapper must be
      position: relative (the utility sets it) and should contain
      only the icon. -- */
.tf-hit-slop {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.tf-hit-slop::before {
    content: "";
    position: absolute;
    inset: -12px;
    /* Transparent but clickable; no visual change. */
}

/* ============================================================
   MOBILE VIEWPORT (< 768 px)
   ============================================================ */

@media (max-width: 767px) {
    /* -- 44 pt minimum on every interactive element -- */
    button,
    a,
    [role="button"],
    input[type="checkbox"],
    input[type="radio"],
    input[type="submit"],
    input[type="button"],
    select,
    .rz-button,
    .rz-checkbox,
    .rz-radiobutton,
    .rz-dropdown,
    .tf-btn,
    .nav-link-toggle,
    .sidebar-nav > li > a,
    .sidebar-nav .sub-menu li > a {
        min-height: var(--tf-touch-target-min);
        min-width: var(--tf-touch-target-min);
    }

    /* Links inside flowing text must NOT grow to 44 px - they
       would break paragraph layout. Restrict expansion to
       interactive contexts. */
    p a, li a:not(.sidebar-nav a), .rz-card a {
        min-height: auto;
        min-width: auto;
    }

    /* -- Safe-area padding for chrome elements -- */
    .app-header {
        padding-top: calc(var(--tf-safe-top) + var(--tf-space-2xs));
        padding-left: calc(var(--tf-safe-left) + var(--tf-space-md));
        padding-right: calc(var(--tf-safe-right) + var(--tf-space-md));
    }

    .app-sidebar {
        padding-top: var(--tf-safe-top);
        padding-bottom: var(--tf-safe-bottom);
        padding-left: var(--tf-safe-left);
    }

    /* Page content: avoid bottom gesture bar / home indicator */
    #page-wrapper,
    .page-content {
        padding-bottom: calc(var(--tf-safe-bottom) + var(--tf-space-md));
    }

    /* Fixed CTAs or bottom bars (e.g. add/save buttons docked at
       the bottom) must clear the home indicator. Any element with
       the .tf-fixed-bottom utility class receives the inset. */
    .tf-fixed-bottom {
        padding-bottom: calc(var(--tf-safe-bottom) + var(--tf-space-sm));
        left: var(--tf-safe-left);
        right: var(--tf-safe-right);
    }

    /* ============================================================
       GRID AS CARD-LIST (MOB-04)
       Radzen DataGrid collapses to a stacked card list. Each row
       becomes a rounded card. Each td becomes a label/value row
       where the label comes from the td[data-title] attribute
       (Radzen emits data-title on every body cell).
       ============================================================ */
    .rz-data-grid,
    .rz-data-grid > .rz-data-grid-data,
    .rz-data-grid .rz-grid-table,
    .rz-data-grid tbody,
    .rz-data-grid tr,
    .rz-data-grid td {
        display: block;
        width: 100%;
    }

    .rz-data-grid thead {
        /* Hide the header row - each cell re-emits its label below. */
        display: none;
    }

    .rz-data-grid {
        /* Suppress horizontal scroll that the table normally forces. */
        overflow-x: visible;
    }

    .rz-data-grid tr {
        background: var(--tf-white);
        border: 1px solid var(--tf-border-color);
        border-radius: var(--tf-radius-lg);
        box-shadow: var(--tf-shadow-sm);
        margin-bottom: var(--tf-space-sm);
        padding: var(--tf-space-sm);
    }

    .rz-data-grid td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: var(--tf-space-sm);
        padding: var(--tf-space-2xs) 0;
        border: none;
        text-align: right;
        min-height: var(--tf-touch-target-min);
    }

    .rz-data-grid td::before {
        content: attr(data-title);
        font-weight: var(--tf-weight-semibold);
        color: var(--tf-text-secondary);
        font-size: var(--tf-font-size-sm);
        text-align: left;
        flex: 0 0 auto;
        margin-right: var(--tf-space-sm);
    }

    /* Action cells (edit/delete buttons) should stack vertically
       with the label above to keep the 44 pt button area intact. */
    .rz-data-grid td:has(> .rz-button),
    .rz-data-grid td:has(> button) {
        flex-direction: column;
        align-items: flex-start;
        text-align: left;
    }

    /* Hide the Radzen empty-row filler if present. */
    .rz-data-grid tr:empty,
    .rz-data-grid td:empty:not([data-title]) {
        display: none;
    }

    /* Pager stays horizontal but compact. */
    .rz-data-grid .rz-pager {
        display: flex;
        flex-wrap: wrap;
        gap: var(--tf-space-2xs);
        padding: var(--tf-space-sm);
    }
}

/* ============================================================
   PRINT / REDUCED MOTION - honor user preferences.
   Touch targets don't matter on print; reduced motion users get
   no extra animation from this foundation.
   ============================================================ */
@media print {
    .rz-data-grid,
    .rz-data-grid tr,
    .rz-data-grid td {
        /* Restore table layout for print so rows stay grouped. */
        display: revert;
    }
    .rz-data-grid thead { display: table-header-group; }
}

/* ============================================================
   BOTTOM SHEET + PULL TO REFRESH (v13.0 MOB-03)
   Patrones mobile-nativos: bottom sheet con drag-to-dismiss,
   pull-to-refresh con indicador circular. Slide-up en mobile,
   modal centrado en tablet/desktop.
   ============================================================ */

/* ============================================================
   BottomSheet · Premium Star (v2026-04 redesign)
   iOS drawer curve cubic-bezier(0.32, 0.72, 0, 1) Ionic
   Backdrop blur · ring shadow · grabber refinado
   ============================================================ */

.tf-bottom-sheet {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: flex-end;
    justify-content: center;
}
.tf-bottom-sheet__backdrop {
    position: absolute;
    inset: 0;
    /* Scrim slate-900 + backdrop blur premium */
    background: rgba(15, 23, 42, 0.40);
    backdrop-filter: saturate(150%) blur(8px);
    -webkit-backdrop-filter: saturate(150%) blur(8px);
    animation: tfBottomSheetFadeIn 180ms ease both;
}
.tf-bottom-sheet__panel {
    position: relative;
    width: 100%;
    max-width: 720px;
    max-height: 90vh;
    background: var(--tf-white);
    border-top-left-radius: 20px;
    border-top-right-radius: 20px;
    /* Ring shadow Vercel + drop XL */
    box-shadow:
        0 0 0 1px rgba(15, 23, 42, 0.04),
        0 -1px 0 rgba(15, 23, 42, 0.06),
        0 -12px 32px -8px rgba(15, 23, 42, 0.18),
        0 -32px 64px -16px rgba(15, 23, 42, 0.20);
    display: flex;
    flex-direction: column;
    padding-bottom: calc(var(--tf-safe-bottom) + var(--tf-space-sm));
    /* iOS drawer curve · 320ms enter (deeper movement = más tiempo) */
    animation: tfBottomSheetIn 320ms cubic-bezier(0.32, 0.72, 0, 1) both;
    will-change: transform;
    overflow: hidden;
    isolation: isolate;
}

/* Hairline highlight superior · efecto glass top edge */
.tf-bottom-sheet__panel::after {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    border-radius: 20px 20px 0 0;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(15, 23, 42, 0.08) 20%,
        rgba(15, 23, 42, 0.08) 80%,
        transparent 100%);
    pointer-events: none;
    z-index: 1;
}

@keyframes tfBottomSheetFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes tfBottomSheetIn {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}

/* Grabber refinado · 36x4 con color premium */
.tf-bottom-sheet__handle {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px 0 6px;
    cursor: grab;
    min-height: 28px;
    touch-action: none;
    user-select: none;
}
.tf-bottom-sheet__handle:active { cursor: grabbing; }
.tf-bottom-sheet__grabber {
    width: 36px;
    height: 4px;
    border-radius: 999px;
    background: rgba(15, 23, 42, 0.18);
    transition: background 150ms cubic-bezier(0.23, 1, 0.32, 1);
}
.tf-bottom-sheet__handle:hover .tf-bottom-sheet__grabber {
    background: rgba(15, 23, 42, 0.32);
}

.tf-bottom-sheet__title {
    padding: 4px 20px 12px;
    font-family: var(--tf-font-display);
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--tf-text-primary);
    letter-spacing: -0.02em;
    line-height: 1.3;
    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
}
.tf-bottom-sheet__body {
    padding: 16px 20px;
    overflow-y: auto;
    flex: 1;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: rgba(15, 23, 42, 0.20) transparent;
}
.tf-bottom-sheet__body::-webkit-scrollbar { width: 10px; }
.tf-bottom-sheet__body::-webkit-scrollbar-track { background: transparent; }
.tf-bottom-sheet__body::-webkit-scrollbar-thumb {
    background: rgba(15, 23, 42, 0.18);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: padding-box;
}
.tf-bottom-sheet__footer {
    padding: 12px 20px;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    background: rgba(248, 250, 252, 0.6);
}

/* Tablet/desktop · sheet → modal centrado con ring premium */
@media (min-width: 768px) {
    .tf-bottom-sheet {
        align-items: center;
        padding: clamp(12px, 3vw, 32px);
    }
    .tf-bottom-sheet__panel {
        max-width: 600px;
        max-height: 80vh;
        border-radius: 16px;
        padding-bottom: 0;
        box-shadow:
            0 0 0 1px rgba(15, 23, 42, 0.04),
            0 1px 2px rgba(15, 23, 42, 0.06),
            0 12px 32px -8px rgba(15, 23, 42, 0.18),
            0 32px 64px -16px rgba(15, 23, 42, 0.24);
        animation: tfBottomSheetCenterIn 280ms cubic-bezier(0.23, 1, 0.32, 1) both;
    }
    .tf-bottom-sheet__panel::after {
        border-radius: 16px 16px 0 0;
    }
    .tf-bottom-sheet__handle { display: none; }
    .tf-bottom-sheet__title { padding-top: 16px; }
}
@keyframes tfBottomSheetCenterIn {
    from { opacity: 0; transform: scale(0.96) translateY(8px); }
    to   { opacity: 1; transform: scale(1)    translateY(0); }
}

/* Dark mode */
[data-theme="dark"] .tf-bottom-sheet__backdrop {
    background: rgba(0, 0, 0, 0.55);
}
[data-theme="dark"] .tf-bottom-sheet__panel {
    background: #131C2E;
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.04),
        0 -1px 0 rgba(255, 255, 255, 0.04),
        0 -12px 32px -8px rgba(0, 0, 0, 0.50),
        0 -32px 64px -16px rgba(0, 0, 0, 0.60);
}
[data-theme="dark"] .tf-bottom-sheet__panel::after {
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.06) 20%,
        rgba(255, 255, 255, 0.06) 80%,
        transparent 100%);
}
[data-theme="dark"] .tf-bottom-sheet__title {
    border-bottom-color: rgba(255, 255, 255, 0.06);
}
[data-theme="dark"] .tf-bottom-sheet__grabber {
    background: rgba(255, 255, 255, 0.20);
}
[data-theme="dark"] .tf-bottom-sheet__handle:hover .tf-bottom-sheet__grabber {
    background: rgba(255, 255, 255, 0.32);
}
[data-theme="dark"] .tf-bottom-sheet__footer {
    border-top-color: rgba(255, 255, 255, 0.06);
    background: rgba(0, 0, 0, 0.20);
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    .tf-bottom-sheet__backdrop,
    .tf-bottom-sheet__panel {
        animation-duration: 100ms !important;
    }
    .tf-bottom-sheet__panel {
        transform: none !important;
    }
}

/* ---- PullToRefresh ---- */
.tf-ptr {
    position: relative;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.tf-ptr__indicator {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -100%);
    width: var(--tf-touch-target-min);
    height: var(--tf-touch-target-min);
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--tf-radius-pill);
    background: var(--tf-white);
    box-shadow: var(--tf-shadow-sm);
    color: var(--tf-primary);
    pointer-events: none;
    z-index: 10;
    will-change: transform;
}
.tf-ptr__content {
    min-height: 100%;
}

/* Pull-to-refresh es una affordance mobile - ocultar el indicador en desktop. */
@media (min-width: 768px) {
    .tf-ptr__indicator { display: none; }
}

/* ============================================================
   TABLET ADAPTIVE LAYOUTS (v13.0 TAB-02, TAB-03)
   ============================================================
   Foundation layer for Phase 77 tablet-adaptive UX.
   Three viewport behaviours driven purely by media queries:
     - < 768px (mobile)          -> sidebar drawer (existing 76-01, untouched)
     - 768-1023px (tablet port.) -> sidebar rail icon-only, always visible
     - >= 1024px (landscape/desk)-> sidebar full 260px with labels + submenus
   Plus:
     - Tablet landscape modal-as-sheet (right-side 60vw panel)
     - .tf-grid-responsive utility (1/2/3 auto-fit columns)
   0 Razor/C# changes -- pure CSS.
   ============================================================ */

/* BLOCK A -- Tablet portrait rail (768px <= viewport < 1024px) */
@media (min-width: 768px) and (max-width: 1023px) {
    /* Sidebar always visible, forced to rail icon-only regardless of .collapsed class.
       Uses same visual rules as .app-sidebar.collapsed but activated purely by viewport. */
    .app-sidebar {
        transform: translateX(0) !important;           /* override mobile drawer translateX(-100%) */
    }
    .app-sidebar:not(.mobile-open) {
        width: var(--sidebar-width-collapsed) !important;  /* 72px rail en reposo */
    }
    /* Con la hamburguesa, el rail se expande como drawer superpuesto (igual que
       en movil): antes el boton no tenia NINGUN efecto visible en tablet. */
    .app-sidebar.mobile-open {
        width: var(--sidebar-width-expanded) !important;
        z-index: 1200;
        box-shadow: 4px 0 20px rgba(0, 0, 0, 0.25);
    }

    /* IMPORTANTE: esta lista tiene que cubrir lo mismo que oculta la clase
       `.collapsed` en AppSidebar.razor.css (seccion 13 · ESTADO COLAPSADO).
       Si se añade ahi un elemento que sobra en el rail, hay que añadirlo aqui
       tambien: este bloque estrecha el sidebar a 72 px por viewport, pero NO
       pone la clase `.collapsed`, asi que las reglas de aquella no se aplican.
       Faltaban --hud, --stamp-meta, --role-label, --role-name y .nav-kbd, y al
       seguir renderizando dentro de un rail de 71 px de contenido el
       `overflow: hidden` del sidebar los cortaba a media palabra: medido a 900 px
       el sidebar pedia 201 px de ancho y el chip "Ejercicio 2026 · Verano" se
       salia 110 px, con "SESION" quedando en "ESION" y "v.1.0.0" en "v.1". */
    .app-sidebar:not(.mobile-open) .sidebar-logo-text,
    .app-sidebar:not(.mobile-open) .nav-label,
    .app-sidebar:not(.mobile-open) .nav-arrow,
    .app-sidebar:not(.mobile-open) .sub-menu,
    .app-sidebar:not(.mobile-open) .cdc-sidebar__hud,
    .app-sidebar:not(.mobile-open) .nav-kbd,
    .app-sidebar:not(.mobile-open) .cdc-sidebar__role-label,
    .app-sidebar:not(.mobile-open) .cdc-sidebar__role-name,
    .app-sidebar:not(.mobile-open) .cdc-sidebar__stamp-meta {
        display: none !important;
    }

    .app-sidebar:not(.mobile-open) .sidebar-header {
        justify-content: center;
        padding: 18px 8px;
    }

    /* Sidebar nav items center their icon in the rail. */
    .app-sidebar:not(.mobile-open) .sidebar-nav > li > a,
    .app-sidebar:not(.mobile-open) .sidebar-nav > li > .nav-link-toggle {
        justify-content: center;
        padding: 12px 0;
    }

    /* Section headers become a thin divider line -- label hidden, tiny visual separator. */
    .app-sidebar:not(.mobile-open) .sidebar-section-header {
        font-size: 0 !important;
        padding: 4px 12px;
        border-top: 1px solid rgba(255, 255, 255, 0.08);
        margin: 8px 0;
        height: 1px;
    }

    /* El overlay SI hace falta cuando el rail se expande como drawer. */
    .sidebar-overlay:not(.active) {
        display: none !important;
    }
    .sidebar-overlay.active {
        display: block;
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0, 0, 0, 0.4);
        z-index: 1190;
        backdrop-filter: blur(2px);
    }

    /* Page wrapper sits beside the 72px rail. */
    #page-wrapper {
        margin-left: var(--sidebar-width-collapsed) !important;
    }

    .app-header {
        left: var(--sidebar-width-collapsed) !important;
    }

    .rz-body { margin-left: var(--sidebar-width-collapsed) !important; }
    .rz-header { left: var(--sidebar-width-collapsed) !important; }
}

/* BLOCK B -- Tablet landscape + desktop full sidebar (>= 1024px) */
@media (min-width: 1024px) {
    /* Sidebar always visible, full width 260px with labels + sub-menus. */
    .app-sidebar {
        transform: translateX(0) !important;
    }

    /* Respect the .collapsed toggle on desktop -- user can still manually collapse.
       But default state (no .collapsed class) shows full sidebar. */
    .app-sidebar:not(.collapsed) {
        width: var(--sidebar-width-expanded);
    }

    .app-sidebar:not(.collapsed) .sidebar-logo-text,
    .app-sidebar:not(.collapsed) .nav-label,
    .app-sidebar:not(.collapsed) .nav-arrow {
        display: inline-block;
    }

    .app-sidebar:not(.collapsed) .sub-menu {
        /* Revert to the existing sub-menu behaviour (controlled by .open class). */
        display: block;
    }
}

/* BLOCK C -- Tablet landscape modal-as-sheet (>= 768px AND orientation: landscape, < 1200px) */
@media (min-width: 768px) and (max-width: 1199px) and (orientation: landscape) {
    /* Radzen dialogs become a right-side lateral sheet occupying ~60% of the viewport.
       This only applies on tablet landscape -- portrait keeps centered dialogs,
       desktop (>= 1200px) keeps centered dialogs for mouse-first UX. */
    .rz-dialog-wrapper {
        position: fixed !important;
        top: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        left: auto !important;
        transform: none !important;
        width: 60vw !important;
        max-width: 720px;
        max-height: 100vh !important;
        height: 100vh !important;
        border-radius: 0 !important;
        animation: tf-dialog-slide-in-right 220ms ease-out;
        box-shadow: var(--tf-shadow-xl);
    }

    .rz-dialog-wrapper > .rz-dialog-content {
        max-height: calc(100vh - 120px);  /* leave room for header + footer */
        overflow-y: auto;
    }
}

@keyframes tf-dialog-slide-in-right {
    from { transform: translateX(100%); }
    to   { transform: translateX(0); }
}

/* BLOCK D -- Responsive grid utility (.tf-grid-responsive) */
/* Utility class: children laid out in 1/2/3 columns automatically via auto-fit.
   Used by 77-02 MasterDetailLayout and can be reused by any grid of cards. */
.tf-grid-responsive {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--tf-space-md);
}

/* Narrower min-col variant for compact card grids (e.g. KPI tiles). */
.tf-grid-responsive--compact {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--tf-space-sm);
}

/* Wider variant for content-heavy cards (e.g. document previews). */
.tf-grid-responsive--wide {
    grid-template-columns: repeat(auto-fit, minmax(480px, 1fr));
    gap: var(--tf-space-lg);
}

/* ============================================================
   MASTER-DETAIL LAYOUT (v13.0 TAB-01)
   Stacking responsive split view. Mobile stacks to one pane at
   a time; tablet+ shows 40/60 grid side-by-side.
   ============================================================ */

.tf-master-detail {
    display: block;
    width: 100%;
    min-height: 60vh;
}

/* Mobile (< 768px): stack. Show List XOR Detail driven by .has-selection flag. */
.tf-master-detail__list,
.tf-master-detail__detail {
    width: 100%;
}

.tf-master-detail .tf-master-detail__detail {
    display: none;
}

.tf-master-detail.has-selection .tf-master-detail__list {
    display: none;
}

.tf-master-detail.has-selection .tf-master-detail__detail {
    display: block;
}

/* Back button in mobile detail pane */
.tf-master-detail__back {
    display: inline-flex;
    align-items: center;
    gap: var(--tf-space-xs);
    margin-bottom: var(--tf-space-md);
    min-height: var(--tf-touch-target-min);
    padding: 0 var(--tf-space-md);
}

/* Empty state when no item selected on tablet+ */
.tf-master-detail__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: var(--tf-space-3xl) var(--tf-space-lg);
    text-align: center;
    color: var(--tf-text-muted);
    min-height: 50vh;
}

.tf-master-detail__empty-icon {
    font-size: 3rem;
    color: var(--tf-text-muted);
    margin-bottom: var(--tf-space-md);
    opacity: 0.5;
}

.tf-master-detail__empty-text {
    font-size: var(--tf-font-size-body);
    color: var(--tf-text-secondary);
    margin: 0;
}

/* Tablet+ (>= 768px): side-by-side, list flex / detail fixed.
   Cuando NO hay seleccion: lista 100%, panel oculto.
   Cuando SI hay seleccion: lista flex (min-width:0 -> scrollable), panel fijo 360-440px. */
@media (min-width: 768px) {
    .tf-master-detail {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        gap: var(--tf-space-md);
        align-items: start;
    }

    .tf-master-detail.has-selection {
        grid-template-columns: minmax(0, 1fr) clamp(340px, 28%, 440px);
    }

    /* List visible siempre. Min-width:0 permite que el grid interno haga scroll horizontal */
    .tf-master-detail .tf-master-detail__list,
    .tf-master-detail.has-selection .tf-master-detail__list {
        display: block;
        min-width: 0;
        overflow: hidden;
    }

    /* Detail solo si hay seleccion */
    .tf-master-detail .tf-master-detail__detail {
        display: none;
    }
    .tf-master-detail.has-selection .tf-master-detail__detail {
        display: block;
        min-width: 0;
    }

    /* Back button is mobile-only -- hide on tablet+ where both panes are visible. */
    .tf-master-detail__back {
        display: none;
    }

    .tf-master-detail__detail {
        background: var(--tf-white);
        border-radius: var(--tf-card-radius);
        box-shadow: var(--tf-card-shadow);
        padding: var(--tf-space-lg);
        position: sticky;
        top: calc(var(--header-height) + var(--tf-space-md));
        max-height: calc(100vh - var(--header-height) - var(--tf-space-2xl));
        overflow-y: auto;
    }
}

/* Desktop (>= 1024px): slightly looser gap for readability. */
@media (min-width: 1024px) {
    .tf-master-detail {
        gap: var(--tf-space-lg);
    }
}

/* Detail preview styling (consumed by the 5 wired pages) */
.tf-detail-preview {
    display: flex;
    flex-direction: column;
    gap: var(--tf-space-md);
}

.tf-detail-preview h3 {
    margin: 0 0 var(--tf-space-xs) 0;
    font-family: var(--tf-font-display);
    font-size: var(--tf-font-size-h4);
    font-weight: var(--tf-weight-semibold);
    color: var(--tf-text-primary);
    display: flex;
    align-items: center;
    gap: var(--tf-space-xs);
}

.tf-detail-preview h3 i {
    color: var(--tf-primary);
    font-size: 1.25rem;
}

.tf-detail-list {
    display: flex;
    flex-direction: column;
    gap: var(--tf-space-xs);
    margin: 0;
    padding: var(--tf-space-sm) 0;
    border-top: 1px solid var(--tf-border-color);
    border-bottom: 1px solid var(--tf-border-color);
}

.tf-detail-list > div {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--tf-space-sm);
    padding: var(--tf-space-2xs) 0;
}

.tf-detail-list dt {
    font-weight: var(--tf-weight-semibold);
    color: var(--tf-text-secondary);
    font-size: var(--tf-font-size-sm);
    margin: 0;
}

.tf-detail-list dd {
    margin: 0;
    color: var(--tf-text-primary);
    text-align: right;
}

.tf-detail-actions {
    display: flex;
    gap: var(--tf-space-xs);
    justify-content: flex-end;
    flex-wrap: wrap;
}

/* ============================================================
   COMMAND PALETTE + KEYBOARD SHORTCUTS HELP (Phase 78-01 DSK-01/02)
   ============================================================ */

.tf-cmdp-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding-top: 10vh;
    z-index: 10000;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.tf-cmdp-overlay.open {
    display: flex;
}

.tf-command-palette {
    background: var(--tf-white);
    border-radius: var(--tf-card-radius);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
    width: min(640px, 92vw);
    max-height: 70vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--tf-border-color);
    font-family: var(--tf-font-body);
}

.tf-cmdp-input {
    border: none;
    border-bottom: 1px solid var(--tf-border-color);
    padding: 18px 20px;
    font-size: 16px;
    font-family: inherit;
    width: 100%;
    outline: none;
    background: transparent;
    color: var(--tf-text-primary);
}

.tf-cmdp-input::placeholder {
    color: var(--tf-text-muted);
}

.tf-cmdp-list {
    overflow-y: auto;
    padding: 6px;
    flex: 1 1 auto;
}

.tf-cmdp-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-radius: 8px;
    cursor: pointer;
    color: var(--tf-text-primary);
    user-select: none;
}

.tf-cmdp-item.selected {
    background: var(--tf-primary-light);
}

.tf-cmdp-item .tf-cmdp-icon {
    width: 20px;
    text-align: center;
    color: var(--tf-primary);
    font-size: 0.95rem;
}

.tf-cmdp-item .tf-cmdp-label {
    flex: 1;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tf-cmdp-item .tf-cmdp-cat {
    font-size: 11px;
    color: var(--tf-text-muted);
    background: var(--tf-page-bg);
    padding: 2px 8px;
    border-radius: 4px;
    white-space: nowrap;
}

.tf-cmdp-empty {
    padding: 32px;
    text-align: center;
    color: var(--tf-text-muted);
    font-style: italic;
}

.tf-cmdp-footer {
    padding: 10px 16px;
    border-top: 1px solid var(--tf-border-color);
    font-size: 12px;
    color: var(--tf-text-muted);
    display: flex;
    gap: 16px;
    background: var(--tf-page-bg);
    flex-wrap: wrap;
}

.tf-cmdp-footer kbd,
.tf-shortcuts-table kbd {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11px;
    background: var(--tf-white);
    border: 1px solid var(--tf-border-color);
    border-radius: 4px;
    padding: 1px 5px;
    box-shadow: 0 1px 0 var(--tf-border-color);
    color: var(--tf-text-primary);
    display: inline-block;
    line-height: 1.4;
}

.tf-shortcuts-help {
    background: var(--tf-white);
    border-radius: var(--tf-card-radius);
    padding: 24px 28px;
    width: min(640px, 92vw);
    max-height: 80vh;
    overflow-y: auto;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
    border: 1px solid var(--tf-border-color);
    font-family: var(--tf-font-body);
}

.tf-shortcuts-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.tf-shortcuts-header h3 {
    margin: 0;
    font-size: 1.15rem;
    color: var(--tf-text-primary);
    display: flex;
    align-items: center;
    gap: 8px;
}

.tf-shortcuts-header h3 i {
    color: var(--tf-primary);
}

.tf-shortcuts-close {
    background: transparent;
    border: none;
    color: var(--tf-text-muted);
    cursor: pointer;
    font-size: 1.1rem;
    padding: 6px 10px;
    border-radius: 6px;
}

.tf-shortcuts-close:hover {
    background: var(--tf-page-bg);
    color: var(--tf-text-primary);
}

.tf-shortcuts-category {
    margin: 16px 0 6px 0;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--tf-primary);
    font-weight: 600;
}

.tf-shortcuts-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 8px;
}

.tf-shortcuts-table td {
    padding: 8px 4px;
    border-bottom: 1px solid var(--tf-border-color);
    vertical-align: middle;
}

.tf-shortcuts-table .tf-shortcuts-combo {
    width: 180px;
    white-space: nowrap;
}

.tf-shortcuts-table .tf-shortcuts-desc {
    color: var(--tf-text-secondary);
    font-size: 0.92rem;
}

.tf-shortcuts-then {
    font-size: 11px;
    color: var(--tf-text-muted);
    font-style: italic;
}

/* Mobile: palette fills most of viewport */
@media (max-width: 767px) {
    .tf-cmdp-overlay {
        padding-top: 4vh;
    }

    .tf-command-palette,
    .tf-shortcuts-help {
        width: 96vw;
        max-height: 90vh;
    }

    .tf-shortcuts-table .tf-shortcuts-combo {
        width: 120px;
    }
}

/* ============================================================
   DENSITY (phase 78-02 DSK-03)
   Variables de densidad globales aplicadas via data-density
   en el elemento <html>. Comfortable es el default.
   ============================================================ */

:root {
    --tf-grid-row-height: 44px;
    --tf-grid-cell-padding: 10px 12px;
    --tf-grid-font-size: 0.9rem;
    --tf-density-spacing: 1rem;
}

html[data-density="compact"] {
    --tf-grid-row-height: 32px;
    --tf-grid-cell-padding: 4px 8px;
    --tf-grid-font-size: 0.82rem;
    --tf-density-spacing: 0.6rem;
}

html[data-density="comfortable"] {
    --tf-grid-row-height: 44px;
    --tf-grid-cell-padding: 10px 12px;
    --tf-grid-font-size: 0.9rem;
    --tf-density-spacing: 1rem;
}

html[data-density="spacious"] {
    --tf-grid-row-height: 56px;
    --tf-grid-cell-padding: 16px 14px;
    --tf-grid-font-size: 0.95rem;
    --tf-density-spacing: 1.4rem;
}

/* Aplicar a RadzenDataGrid globalmente */
.rz-data-grid .rz-data-row {
    height: var(--tf-grid-row-height);
}

/* El .rz-column-title solo en la cabecera: con Responsive="true" tambien
   existe dentro de las celdas del cuerpo (etiqueta de las fichas moviles) y
   ahi el padding de densidad no pinta nada. */
.rz-data-grid .rz-cell-data,
.rz-data-grid thead .rz-column-title {
    padding: var(--tf-grid-cell-padding) !important;
    font-size: var(--tf-grid-font-size);
}

.rz-data-grid .rz-grid-table {
    font-size: var(--tf-grid-font-size);
}

/* Density selector button + menu (header) */
.tf-density-selector {
    position: relative;
    display: inline-block;
}

.tf-density-btn {
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    padding: 6px 10px;
    cursor: pointer;
    color: var(--tf-text-secondary);
    font-size: 1rem;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
}

.tf-density-btn:hover,
.tf-density-btn.open {
    background: var(--tf-page-bg);
    color: var(--tf-primary);
    border-color: var(--tf-border-color);
}

.tf-density-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    background: var(--tf-white);
    border: 1px solid var(--tf-border-color);
    border-radius: 8px;
    min-width: 200px;
    z-index: 1100;
    box-shadow: var(--tf-card-shadow-hover);
    overflow: hidden;
    padding: 4px;
}

.tf-density-menu-header {
    padding: 8px 12px 4px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tf-text-muted);
}

.tf-density-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--tf-text-primary);
    text-align: left;
    font-size: 0.9rem;
    border-radius: 6px;
    transition: background 0.15s;
}

.tf-density-item:hover {
    background: var(--tf-page-bg);
}

.tf-density-item.active {
    background: var(--tf-primary-light);
    color: var(--tf-primary);
    font-weight: 600;
}

.tf-density-item .fa-check {
    margin-left: auto;
    color: var(--tf-primary);
}

.tf-density-item i:first-child {
    width: 16px;
    text-align: center;
}

.tf-density-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1099;
}

/* ============================================================
   PHASE 79 — MOTION & MICRO-INTERACTIONS (MOT-01, MOT-03)
   ============================================================
   Motion foundation: standardized duration + easing tokens,
   global prefers-reduced-motion override (WCAG 2.1 SC 2.3.3),
   stagger utility, and shared keyframes for Skeleton +
   SuccessCheckmark components.

   Emil Kowalski motion philosophy applied:
     - Exit durations are 65% of enter (snappier dismissals)
     - Spring easing for playful state changes
     - Ease-out quart for natural deceleration
     - NO linear timing (sole documented exception: shimmer)

   These tokens are ADDITIVE — legacy --tf-transition-fast/normal/slow
   tokens remain untouched for backwards compatibility (170+ pages).
   ============================================================ */

:root {
    /* Enter durations */
    --tf-duration-micro: 150ms;       /* hover, focus, tap, button press */
    --tf-duration-state: 250ms;       /* dialog open/close, expand/collapse, modal fade */
    --tf-duration-page: 400ms;        /* page transitions, navigations */

    /* Exit durations (65% of enter — Emil Kowalski snappier-exit principle) */
    --tf-duration-exit-micro: 97ms;   /* 65% of 150ms */
    --tf-duration-exit-state: 162ms;  /* 65% of 250ms */
    --tf-duration-exit-page: 260ms;   /* 65% of 400ms */

    /* Easings */
    --tf-easing-spring: cubic-bezier(0.34, 1.56, 0.64, 1);  /* bouncy overshoot */
    --tf-easing-out: cubic-bezier(0.16, 1, 0.3, 1);         /* ease-out quart (natural deceleration) */
    --tf-easing-in: cubic-bezier(0.7, 0, 0.84, 0);          /* ease-in quart (natural acceleration) */
    --tf-easing-inout: cubic-bezier(0.87, 0, 0.13, 1);      /* symmetric */
}

/* -----------------------------------------------------------
   Accessibility: respect OS-level prefers-reduced-motion.
   Collapses all transitions/animations to 0.01ms globally.
   WCAG 2.1 SC 2.3.3 compliance.
   ----------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* -----------------------------------------------------------
   Stagger list utility.
   Apply `.tf-stagger-list` to a parent, set inline `style="--i:N"`
   on each child (0-based index) for a sequential fade-in cascade.
   ----------------------------------------------------------- */
.tf-stagger-list > * {
    animation: tf-stagger-in var(--tf-duration-state) var(--tf-easing-out) both;
    animation-delay: calc(var(--i, 0) * 40ms);
}

@keyframes tf-stagger-in {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* -----------------------------------------------------------
   Skeleton loading placeholder (MOT-03).
   NOTE: Shimmer intentionally uses `linear` timing — this is the
   ONE documented exception to MOT-01's "no linear" rule because
   the gradient sweep must be perceptually constant-speed.
   ----------------------------------------------------------- */
.tf-skeleton {
    display: inline-block;
    background: linear-gradient(90deg, #e5e7eb 0%, #f3f4f6 50%, #e5e7eb 100%);
    background-size: 200% 100%;
    animation: tf-shimmer 1200ms linear infinite;
    border-radius: var(--tf-radius-sm, 6px);
}

.tf-skeleton--text {
    height: 1em;
    border-radius: 4px;
}

.tf-skeleton--circle {
    border-radius: 50%;
}

.tf-skeleton--rect {
    border-radius: var(--tf-radius-md, 8px);
}

@keyframes tf-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* -----------------------------------------------------------
   SuccessCheckmark animation (MOT-03).
   Parent container pops in with spring easing; the inner SVG
   circle + check path draw sequentially via stroke-dasharray.
   ----------------------------------------------------------- */
.tf-success-checkmark {
    display: inline-flex;
    animation: tf-success-pop var(--tf-duration-state) var(--tf-easing-spring) both;
}

.tf-success-checkmark circle {
    stroke-dasharray: 166;
    stroke-dashoffset: 166;
    animation: tf-draw-circle 300ms var(--tf-easing-out) forwards;
}

.tf-success-checkmark path {
    stroke-dasharray: 48;
    stroke-dashoffset: 48;
    animation: tf-draw-check 200ms var(--tf-easing-out) 150ms forwards;
}

@keyframes tf-success-pop {
    0%   { transform: scale(0.6); opacity: 0; }
    60%  { transform: scale(1.1); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

@keyframes tf-draw-circle {
    to { stroke-dashoffset: 0; }
}

@keyframes tf-draw-check {
    to { stroke-dashoffset: 0; }
}

/* ============================================================
   PHASE 79-02 — VIEW TRANSITIONS (MOT-02)
   ============================================================
   Progressive enhancement: only active on browsers that support
   View Transitions API (Chrome 111+, Edge 111+). Safari/Firefox
   gracefully no-op until they ship support.

   PageTransition.razor subscribes to NavigationManager.LocationChanged
   and invokes document.startViewTransition() via motion-interop.js.
   When supported, the browser snapshots the old DOM, lets Blazor
   render the new one, and runs FLIP-style morphs automatically
   for any elements that share a view-transition-name across routes.
   ============================================================ */

@supports (view-transition-name: none) {

    /* Root cross-fade for the whole page during navigation */
    ::view-transition-old(root) {
        animation: tf-fade-out var(--tf-duration-exit-state) var(--tf-easing-in) both;
    }
    ::view-transition-new(root) {
        animation: tf-fade-in var(--tf-duration-state) var(--tf-easing-out) both;
    }

    /* Shared elements tagged via .tf-vt-* classes get FLIP automatically.
       Consumers set `--tf-vt-id` inline per element so each card/row gets
       a unique name across the list->detail navigation. */
    .tf-vt-card {
        view-transition-name: var(--tf-vt-id);
        contain: layout;
    }
    .tf-vt-header {
        view-transition-name: tf-vt-header;
    }
    .tf-vt-title {
        view-transition-name: tf-vt-title;
    }

    /* Card->detail morph uses spring easing + page duration */
    ::view-transition-group(*) {
        animation-duration: var(--tf-duration-page);
        animation-timing-function: var(--tf-easing-spring);
    }
}

@keyframes tf-fade-out {
    from { opacity: 1; }
    to   { opacity: 0; }
}
@keyframes tf-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ============================================================
   PHASE 80-01 — A11Y + DARK MODE (v13.0 A11Y-01 / A11Y-02)
   ============================================================
   Global dark-mode palette applied via [data-theme="dark"] on <html>.
   The attribute is set pre-boot by theme-interop.js (anti-FOUC) and
   toggled at runtime via ThemeService / ThemeToggle component.

   DESIGN NOTES:
   - Tonal palette (Linear / Notion style), NOT color inversion. Surfaces
     were chosen manually so navbar/card/page have graduated contrast.
   - Only the --tf-* CSS custom properties are redefined here. The 170+
     existing pages consume var(--tf-*) and adapt transparently without
     any Razor/CSS edits.
   - --tf-primary is LIGHTER in dark mode (#4caf50 vs production #0d7c3e)
     because the dark green would fail AA on dark surfaces (~2.8:1). The
     lighter green reaches ~5.3:1 contrast on #0f1419, safely above AA.
   - Radzen semantic tokens (--rz-*) inherit automatically because the
     existing CSS maps them to var(--tf-*).
   - .ds-dark (DesignSystem showcase scope, phase 75-02) is preserved
     intentionally as a parallel mechanism. data-theme covers the whole
     app, .ds-dark previews tokens inside the showcase page.
   ============================================================ */

[data-theme="dark"] {
    /* --- Surfaces (tonal gradient, not inverted) --- */
    --tf-page-bg: #0f1419;        /* base background */
    --tf-navbar-bg: #1a1f2b;      /* elevated over page */
    --tf-card-bg: #1e2432;        /* elevated over navbar */
    --tf-white: #1e2432;          /* token aliased to card surface for components that consume it */
    --tf-border-color: #2d3442;   /* low-contrast divider in dark */

    /* --- Text --- */
    --tf-text-primary: #e6e9ec;
    --tf-text-secondary: #a0a8b4;
    --tf-text-muted: #6c7582;

    /* --- Primary brand (AA-safe on dark surfaces ~5.3:1) --- */
    --tf-primary: #4caf50;
    --tf-primary-hover: #66bb6a;
    --tf-primary-rgb: 76, 175, 80;
    --tf-primary-light: rgba(76, 175, 80, 0.18);

    /* --- Shadows softened (dark surfaces need less depth) --- */
    --tf-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --tf-shadow-md: 0 4px 8px rgba(0, 0, 0, 0.45);
    --tf-shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.5);
}

/* -----------------------------------------------------------
   Global :focus-visible (WCAG 2.4.7 Focus Visible).
   Keyboard users get a 2px primary outline with 2px offset on
   every interactive element, regardless of component library.
   Mouse users get nothing (matches OS platform conventions).
   ----------------------------------------------------------- */
:focus-visible {
    outline: 2px solid var(--tf-primary);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Primary-background buttons need a contrasted ring:
   use a white inner stroke + primary halo so the focus is
   visible on top of the primary fill itself. */
.rz-button-primary:focus-visible,
.tf-btn--primary:focus-visible,
.btn-cmd-palette:focus-visible {
    outline: 3px solid #ffffff;
    outline-offset: 3px;
    box-shadow: 0 0 0 5px var(--tf-primary);
}

/* Avoid double outlines when a component already paints
   its own box-shadow on focus (Radzen dropdowns, etc). */
:focus:not(:focus-visible) {
    outline: none;
}

/* -----------------------------------------------------------
   prefers-contrast: more
   Users who request higher contrast at the OS level get pure
   black/white text and borders plus wider focus rings.
   ----------------------------------------------------------- */
@media (prefers-contrast: more) {
    :root {
        --tf-text-primary: #000000;
        --tf-text-secondary: #222222;
        --tf-border-color: #000000;
    }
    [data-theme="dark"] {
        --tf-text-primary: #ffffff;
        --tf-text-secondary: #e0e0e0;
        --tf-border-color: #ffffff;
    }
    :focus-visible {
        outline-width: 3px;
    }
}

/* -----------------------------------------------------------
   Reinforce prefers-reduced-motion for phase 79-02 View Transitions.
   The generic rule at line ~3390 collapses all animations and
   transitions. Here we additionally neutralize the View Transitions
   pseudo-elements (::view-transition-group / -old / -new) so the
   FLIP morphs don't linger, plus forbid smooth-scroll.
   ----------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto !important;
    }
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation-duration: 1ms !important;
    }
}

/* ===========================================================
   SKIP LINK + SR-ONLY + UNDO TOAST (v13.0 phase 80-02 A11Y)
   -----------------------------------------------------------
   - .sr-only: utility WCAG 4.1.2 para texto solo-lector
   - .skip-link: WCAG 2.4.1 (Bypass Blocks) -- primera parada de Tab
   - .tf-undo-toast: toast deshacer con aria-live (acciones destructivas)
   =========================================================== */

/* Screen reader only utility -- NO usar display:none (lectores lo saltan) */
.sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* Skip to main content link -- offscreen hasta recibir :focus */
.skip-link {
    position: absolute;
    top: -100px;
    left: 0;
    z-index: 10000;
    padding: 12px 20px;
    background: var(--tf-primary);
    color: #ffffff;
    font-weight: 600;
    text-decoration: none;
    border-radius: 0 0 6px 0;
    transition: top 0.15s ease;
}

.skip-link:focus {
    top: 0;
    outline: 3px solid #ffffff;
    outline-offset: -1px;
}

/* El texto del skip-link se mantiene blanco en cualquier estado.
   Sin esto, `a:hover { color: var(--tf-primary) }` (especificidad 0,1,1) gana a
   `.skip-link { color: #ffffff }` (0,1,0) y el enlace queda verde sobre verde,
   es decir invisible justo cuando el usuario acaba de tabular hasta el. */
.skip-link,
.skip-link:hover,
.skip-link:focus,
.skip-link:focus-visible,
.skip-link:active {
    color: #ffffff;
}

/* En tema oscuro --tf-primary pasa a #4caf50, y blanco sobre ese verde solo da
   2.78:1 -- por debajo del 4.5:1 de AA. Se fija el verde oscuro del tema claro,
   que con texto blanco da 5.02:1. Solo afecta a este enlace de salto. */
[data-theme="dark"] .skip-link {
    background: #15803D;
}

/* Undo toast host -- fila stacking abajo-izquierda */
.tf-undo-toast-host {
    position: fixed;
    bottom: 20px;
    left: 20px;
    display: flex;
    flex-direction: column-reverse;
    gap: 8px;
    z-index: 9999;
    pointer-events: none;
}

.tf-undo-toast {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 280px;
    max-width: 420px;
    padding: 12px 16px;
    background: var(--tf-card-bg, #ffffff);
    color: var(--tf-text-primary);
    border: 1px solid var(--tf-border-color);
    border-radius: 8px;
    box-shadow: var(--tf-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.15));
    position: relative;
    overflow: hidden;
    animation: tf-undo-enter 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes tf-undo-enter {
    from { transform: translateY(20px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

.tf-undo-toast__message {
    flex: 1;
    font-size: 0.9rem;
    line-height: 1.35;
}

.tf-undo-toast__action {
    background: transparent;
    border: 1px solid var(--tf-primary);
    color: var(--tf-primary);
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.85rem;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background 120ms ease, color 120ms ease;
}

.tf-undo-toast__action:hover {
    background: var(--tf-primary-light, var(--tf-primary));
    color: #ffffff;
}

.tf-undo-toast__close {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--tf-text-secondary);
    font-size: 1rem;
    padding: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    transition: color 120ms ease;
}

.tf-undo-toast__close:hover {
    color: var(--tf-text-primary);
}

.tf-undo-toast__progress {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 100%;
    background: var(--tf-primary);
    transform-origin: left;
    animation: tf-undo-progress linear forwards;
}

@keyframes tf-undo-progress {
    from { width: 100%; }
    to { width: 0%; }
}

/* Respeto prefers-reduced-motion: sin animaciones del toast */
@media (prefers-reduced-motion: reduce) {
    .tf-undo-toast {
        animation: none;
    }
    .tf-undo-toast__progress {
        animation: none;
        opacity: 0;
    }
}
