/* =============================================================================
   GLASS-THEME.CSS — Glassmorphism component styles

   Este archivo SOLO añade estilos visuales glass que los tokens no pueden
   expresar (backdrop-filter, body bg, gradients). Los TOKENS están en
   variables.css (single source of truth).

   Sin !important salvo donde compita con !important pre-existente
   en archivos legacy (documentado in-line cuando aplique).

   Carga al final en index.html para ganar empates de especificidad por cascade.

   PRINCIPIOS GLASSMORPHISM:
   1. Frosted: backdrop-filter blur + tint translúcido
   2. Multi-capa: blobs vivid de fondo + glass surfaces sobre ellos
   3. Vivid background: contraste fuerte detrás del glass
   4. Sombras profundas: doble layer drop shadow
   5. Border highlight: borde sutil + inset highlight superior

   ESTRUCTURA:
   1. Foundation universal (body, scrollbar, selección, app/main transparent)
   2. Surfaces — backdrop-filter en componentes que ya consumen tokens glass
   3. Componentes específicos (modal-backdrop, button variants, sidebar, fab)
   4. Bottom nav + FAB (mobile)
   5. Login (mobile)
   6. Utilidades (.glass-surface, .glass-surface-strong)
   7. Reduced motion
   ============================================================================= */


/* =====================================================
   0. iOS AUTO-ZOOM PREVENTION
   Safari iOS zoom-in al focus inputs con font-size < 16px.
   Fuerza 16px en touch devices para todos los inputs.
   ===================================================== */
@media (pointer: coarse) {
    /* Inputs generales: 16px previene auto-zoom iOS sin user-scalable=no.
       Con user-scalable=no en meta viewport el zoom está bloqueado de todos
       modos. Mantenemos 16px solo para inputs grandes (forms editor, login). */
    input,
    select,
    textarea,
    .form-input,
    .form-select,
    [contenteditable="true"] {
        font-size: var(--text-base); /* 16px */
    }
    /* Filtros: tamaño consistente compacto para match estandar UI */
    .calendar-filters .search-input-compact input,
    .calendar-filters .filter-select-compact,
    .songs-filters .search-input-compact input,
    .songs-filters .filter-select-compact,
    .calendar-filters .filter-tab,
    .songs-filters .filter-tab,
    .calendar-filter-tabs .filter-tab,
    .stats-tabs .stats-tab {
        font-size: var(--text-xs); /* 13px */
    }
}


/* =====================================================
   0.5 — NO-SELECT en menús y botones flotantes
   Long-press iOS/Android dispara selección/callout/magnifier.
   Bloquea selección de texto + callout en elementos interactivos.
   ===================================================== */
.mobile-nav,
.mobile-nav-item,
.mobile-nav-items,
.sidebar,
.sidebar-nav-item,
.sidebar-nav-label,
.sidebar-header,
.sidebar-footer,
.header,
.app-header,
.header-actions,
.user-menu,
.user-menu-trigger,
.notifications-btn,
.btn,
.btn-primary,
.btn-secondary,
.btn-outline,
.btn-ghost,
.btn-danger,
.btn-success,
.btn-icon,
.fab-new-btn,
.filter-tab,
.calendar-filter-tabs,
.stats-tabs,
.dropdown-trigger,
.dropdown-menu,
.dropdown-item,
.dropdown-portal,
.modal-close,
.toast-close,
.tag-removable {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}


/* =====================================================
   1. FOUNDATION UNIVERSAL
   bg gradient + blobs en <html> (fixed attachment llena viewport).
   body transparente para no tapar el bg del html. .app y wrappers
   también transparent garantiza que los blobs sean visibles a través
   de toda la jerarquía de containers. */
html {
    background-color: var(--glass-body-color);
    min-height: 100vh;
    min-height: 100dvh;
    color: var(--text-primary);
    overscroll-behavior-y: contain;
}

/* Layer de blobs: fixed al viewport, debajo de todo. Animado con drift sutil
   y desplazado por parallax via --bg-y (set por JS en App.setupParallax). */
body::before {
    content: '';
    position: fixed;
    inset: -10%;
    z-index: -1;
    pointer-events: none;
    background-image: var(--glass-body-bg);
    background-repeat: no-repeat;
    background-size: 130% 130%;
    transform: translate3d(0, var(--bg-y, 0px), 0);
    animation: blobDrift 14s ease-in-out infinite alternate;
    will-change: transform, background-position;
}

@keyframes blobDrift {
    0%   { background-position: 0% 0%; }
    20%  { background-position: -12% 8%; }
    40%  { background-position: 10% -10%; }
    60%  { background-position: -8% -14%; }
    80%  { background-position: 14% 6%; }
    100% { background-position: -6% 12%; }
}

/* === PARTÍCULAS DE FONDO ===
   Container fixed sobre el viewport (debajo del contenido). Partículas
   inyectadas por App.setupBgParticles() con posiciones+timings random. */
.bg-particles {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: -1;
    overflow: hidden;
}
.bg-particle {
    position: absolute;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--particle-color, rgba(124, 77, 255, 0.35));
    box-shadow: 0 0 8px var(--particle-color, rgba(124, 77, 255, 0.35));
    opacity: 0;
    will-change: transform, opacity;
    animation: particleFloat var(--p-duration, 18s) ease-in-out infinite;
    animation-delay: var(--p-delay, 0s);
}

/* Light theme: partículas purple intenso para contraste sobre fondo claro */
:root:not([data-theme="dark"]) .bg-particle,
[data-theme="light"] .bg-particle {
    --particle-color: rgba(76, 42, 133, 0.78);
}

/* Dark theme: partículas blanco/lavanda translúcido */
[data-theme="dark"] .bg-particle {
    --particle-color: rgba(196, 181, 253, 0.45);
}

@keyframes particleFloat {
    0%   { transform: translate3d(0, 0, 0); opacity: 0; }
    15%  { opacity: var(--p-opacity, 0.7); }
    50%  { transform: translate3d(var(--p-tx, 30px), var(--p-ty, -50px), 0); opacity: var(--p-opacity, 0.7); }
    85%  { opacity: var(--p-opacity, 0.7); }
    100% { transform: translate3d(calc(var(--p-tx, 30px) * -0.6), calc(var(--p-ty, -50px) * 1.4), 0); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    body::before { animation: none; }
    .bg-particle { animation: none; opacity: 0; }
}

/* Bloquear scroll del body cuando sidebar está abierto (mobile).
   Sidebar tiene su propio overflow-y interno; permitir touch dentro. */
html.sidebar-open,
body.sidebar-open {
    overflow: hidden;
}
body.sidebar-open .sidebar.open,
body.sidebar-open .sidebar.open .sidebar-nav {
    touch-action: pan-y;
    overscroll-behavior: contain;
}

/* Blur progresivo aplicado via JS (App.animateSidebarBlur). CSS transition
   en filter no interpolaba consistente en todos browsers. */

/* Garantizar que .desktop-only en filtros NO se muestre en mobile.
   Specificity (0,2,0) supera reglas .btn / .desktop-only base (0,1,0). */
@media (max-width: 820px) {
    .calendar-filters .desktop-only,
    .songs-filters .desktop-only,
    .setlists-filters .desktop-only,
    .calendar-controls .desktop-only {
        display: none;
    }
}

/* === MOBILE LAYOUT FIX (≤820px) ===
   Problema previo: .app (flex column) + .app-content (overflow:hidden) +
   .main (overflow:hidden) clipaban el contenido y body no scrolleaba.
   Mobile-nav fixed se anclaba al viewport correctamente, pero como nada
   scrolleaba realmente la nav parecía estática.
   Fix: en mobile romper el flex+overflow:hidden para que body sea scroll
   container natural. Topbar sticky + mobile-nav fixed funcionan al viewport. */
@media (max-width: 820px) {
    .app {
        display: block;
        min-height: 100vh;
        min-height: 100dvh;
    }
    .app-content {
        display: block;
        overflow: visible;
        margin-left: 0;
        min-width: 0;
    }
    .main {
        overflow: visible;
        flex: none;
    }
}
body {
    background: transparent;
    color: var(--text-primary);
    overscroll-behavior-y: contain;
}
.app, .app-content, .main, main {
    background: transparent;
    overscroll-behavior-y: contain;
}

/* Theme dark/auto: bg-color viene del token --glass-body-color
   actualizado en variables.css al theme correspondiente. */

.app, .app-content, .main, main {
    background: transparent;
}

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb {
    background: var(--surface-4);
    border-radius: var(--glass-radius-pill);
}
::-webkit-scrollbar-thumb:hover { background: var(--surface-5); }
::-webkit-scrollbar-track { background: transparent; }

::selection { background: rgba(167, 139, 250, 0.35); color: #fff; }


/* =====================================================
   2. SURFACES — backdrop-filter en componentes
   Selector compuesto cubre todo surface visible que use tokens glass.
   ===================================================== */
.card, .panel, .stat-card, .stat-card-compact, .stats-panel,
.song-card, .song-card-modern,
.setlist-card, .setlist-card-past, .setlist-card-today, .setlist-card-upcoming,
.minister-card,
.more-section, .more-grid-item,
.calendar-card, .event-card,
.dashboard-card, .dashboard-stat-card, .dashboard-section,
.song-list-item, .song-row, .setlist-row, .minister-row,
.list-item, .row-card, .empty-state,
.popover, .alert,
.modal,
.dropdown-menu, .dropdown-portal,
.toast,
.filter-tab, .calendar-filter-tabs, .stats-tabs,
.search-input-compact, .filter-select-compact,
.header, .app-header,
.sidebar,
:where(input, select, textarea) {
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
}

/* Input dentro de wrapper no necesita su propio backdrop (wrapper ya lo aplica).
   Evita doble layer de blur que oscurece. */
.search-input-compact input {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

/* Filtros: cada control es pill glass independiente.
   Selectores con .calendar-filters / .songs-filters prefijos igualan
   especificidad (0,2,0) de components.css y ganan por cascade order. */
/* === Filter row containers — layout uniforme entre páginas ===
   Todas las filas de filtros (Songs, Setlists, Calendar) usan el mismo
   layout: flex row con wrap, mismo gap, misma margin. Garantiza que
   se vean idénticas. */
.calendar-filters,
.songs-filters,
.calendar-controls {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-5) 0;
    padding: 0;
}

/* Altura uniforme 36px para TODOS los wrappers de filtros (children directos). */
.calendar-filters > *,
.songs-filters > *,
.calendar-controls > * {
    height: 36px;
    min-height: 36px;
    max-height: 36px;
    box-sizing: border-box;
    flex-shrink: 0;
}

.search-input-compact,
.filter-select-compact,
.calendar-filters .search-input-compact,
.calendar-filters .filter-select-compact,
.songs-filters .search-input-compact,
.songs-filters .filter-select-compact {
    background-color: var(--surface-3);
    border: none;
    border-radius: var(--glass-radius-pill);
    color: var(--text-primary);
    box-shadow: var(--glass-edge-ring), var(--glass-highlight);
    padding: 0 var(--space-4);
    backdrop-filter: blur(var(--glass-blur)) saturate(120%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(120%);
    transition: background-color var(--transition-base),
                box-shadow var(--transition-base);
}

/* Date filter wrappers + calendar nav compact: forma pill consistente */
.calendar-date-filter,
.setlists-date-filter,
.songs-date-filter,
.calendar-nav-compact {
    background: var(--surface-3);
    border: none;
    border-radius: var(--glass-radius-pill);
    padding: 0 var(--space-3);
    color: var(--text-primary);
    box-shadow: var(--glass-edge-ring), var(--glass-highlight);
    backdrop-filter: blur(var(--glass-blur)) saturate(120%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(120%);
    height: 36px;
    align-items: center;
    display: inline-flex;
    gap: var(--space-2);
}

/* Input dentro del wrapper: transparente, sin radius propio,
   deja que el wrapper sea el visual pill */
.calendar-date-filter input[type="date"],
.setlists-date-filter input[type="date"],
.songs-date-filter input[type="date"] {
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    height: auto;
    color: var(--text-primary);
}
.calendar-date-filter input[type="date"]:focus,
.setlists-date-filter input[type="date"]:focus,
.songs-date-filter input[type="date"]:focus {
    background: transparent;
    box-shadow: none;
}

/* Date inputs sueltos en filtros */
.calendar-filters input[type="date"],
.songs-filters input[type="date"],
.filter-date,
input[type="date"].filter-input {
    background-color: var(--surface-3);
    border: none;
    border-radius: var(--glass-radius-pill);
    padding: 0 var(--space-4);
    color: var(--text-primary);
    box-shadow: var(--glass-edge-ring), var(--glass-highlight);
    backdrop-filter: blur(var(--glass-blur)) saturate(120%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(120%);
}

/* Selects necesitan padding-right extra por el chevron */
.filter-select-compact,
.calendar-filters .filter-select-compact,
.songs-filters .filter-select-compact {
    padding-right: var(--space-8);
}

/* Filter-tab pills inside .calendar-filter-tabs container — height controlado
   por regla unificada más abajo (.calendar-filter-tabs .filter-tab → 32px). */
.calendar-filter-tabs .filter-tab {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
}
.search-input-compact:hover,
.filter-select-compact:hover,
.calendar-filters .search-input-compact:hover,
.calendar-filters .filter-select-compact:hover,
.songs-filters .search-input-compact:hover,
.songs-filters .filter-select-compact:hover {
    background-color: var(--surface-4);
}
.search-input-compact:focus-within,
.calendar-filters .search-input-compact:focus-within,
.songs-filters .search-input-compact:focus-within {
    background-color: var(--surface-4);
    box-shadow: var(--glass-highlight), 0 0 0 3px rgba(167, 139, 250, 0.18);
}
.search-input-compact i { color: var(--text-muted); }

/* Input interno: reset total. Solo aporta texto + cursor.
   Toda decoración (bg, borde, sombra, radius) la maneja el wrapper.
   `appearance: none` evita que browser dibuje su control nativo. */
.search-input-compact input {
    all: unset;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 0;
    margin: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    outline: none;
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--font-size-sm);
    line-height: 1;
}
.search-input-compact input::placeholder { color: var(--text-muted); }
.search-input-compact input:focus,
.search-input-compact input:hover,
.search-input-compact input:active {
    background: none;
    border: 0;
    box-shadow: none;
    outline: none;
}
/* Override autofill removido a pedido del usuario.
   Browser nativo dibuja autofill bg propio. */

/* Select chevron y option: legible sobre glass.
   Native <option> no se puede estilizar bien — el browser usa colores OS. */
.filter-select-compact option,
.calendar-filters .filter-select-compact option,
.songs-filters .filter-select-compact option {
    background-color: #1d0f3d;
    color: var(--text-primary);
}

/* Cards principales: SIN border crisp. Definición visual via:
   - shadow exterior (depth)
   - glass-edge-ring (outline luminoso ultra-sutil 0.5px)
   - glass-highlight (top reflection muy suave) */
.card, .panel, .stat-card, .stat-card-compact, .stats-panel,
.song-card, .song-card-modern,
.setlist-card, .minister-card,
.more-section, .more-grid-item,
.calendar-card, .event-card,
.dashboard-card, .dashboard-stat-card, .dashboard-section,
.song-list-item, .setlist-row,
.list-item, .row-card,
.popover, .alert, .empty-state {
    border: none;
    border-radius: var(--glass-radius-md);
    box-shadow: var(--glass-shadow-md), var(--glass-edge-ring), var(--glass-highlight);
    transition: background-color var(--transition-slow),
                box-shadow var(--transition-slow),
                transform var(--transition-base);
}

.card:hover,
.minister-card:hover, .more-grid-item:hover,
.dashboard-card:hover,
.list-item:hover, .row-card:hover {
    background-color: var(--bg-card-hover);
    box-shadow: var(--glass-shadow-lg), var(--glass-edge-ring-strong), var(--glass-highlight);
    transform: translateY(-2px);
}

/* Overlays flotantes: blur fuerte y radius mayor, edge ring sutil */
.modal,
.dropdown-menu, .dropdown-portal,
.toast {
    backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    box-shadow: var(--glass-shadow-lg), var(--glass-edge-ring-strong), var(--glass-highlight);
    border: none;
}
.modal { border-radius: var(--glass-radius-lg); }

/* Modal light theme: bg sólido para legibilidad. Los tokens glass son
   muy translúcidos sobre bg claro y matan contraste. */
[data-theme="light"] .modal,
:root:not([data-theme="dark"]) .modal,
[data-theme="light"] .modal-backdrop > *,
:root:not([data-theme="dark"]) .modal-backdrop > * {
    background-color: rgba(255, 255, 255, 0.97) !important;
    color: var(--glass-text-on-light, #1a0a3a);
}
[data-theme="light"] .modal *:not(.btn):not(.btn-primary):not(.btn-secondary):not(.btn-danger):not(.btn-success):not(input):not(select):not(textarea),
:root:not([data-theme="dark"]) .modal *:not(.btn):not(.btn-primary):not(.btn-secondary):not(.btn-danger):not(.btn-success):not(input):not(select):not(textarea) {
    color: inherit;
}
[data-theme="light"] .modal-header,
:root:not([data-theme="dark"]) .modal-header {
    border-bottom-color: rgba(76, 42, 133, 0.10);
}
[data-theme="light"] .modal-footer,
:root:not([data-theme="dark"]) .modal-footer {
    border-top-color: rgba(76, 42, 133, 0.10);
}
[data-theme="light"] .modal-title,
:root:not([data-theme="dark"]) .modal-title {
    color: #1a0a3a;
}

/* Modal posición — desktop centrado. Mobile maneja modal.js inline. */
.modal-backdrop {
    padding: var(--space-4);
}

/* Dropdown menu light theme — bg sólido */
[data-theme="light"] .dropdown-menu,
:root:not([data-theme="dark"]) .dropdown-menu,
[data-theme="light"] .dropdown-portal,
:root:not([data-theme="dark"]) .dropdown-portal {
    background-color: rgba(255, 255, 255, 0.97) !important;
    color: #1a0a3a;
}
[data-theme="light"] .dropdown-item,
:root:not([data-theme="dark"]) .dropdown-item {
    color: #1a0a3a;
}
[data-theme="light"] .dropdown-item:hover,
:root:not([data-theme="dark"]) .dropdown-item:hover {
    background: rgba(124, 77, 255, 0.10);
}
.dropdown-menu, .dropdown-portal, .toast { border-radius: var(--glass-radius-md); }

.header, .app-header, .sidebar {
    backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    color: var(--text-primary);
}

/* =====================================================
   PAGE TOPBAR — reemplazo del header tradicional
   - Dashboard: avatar (con dropdown user-menu) + saludo + nombre
   - Otras páginas: título de la página
   - Right: refresh + notifications (juntos)
   ===================================================== */
.page-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: calc(var(--safe-area-top) + var(--space-3)) var(--space-6) var(--space-3) var(--space-6);
    background: transparent;
    color: inherit;
}

.page-topbar-left {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    min-width: 0;
    flex: 1 1 auto;
}

.page-topbar-right {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-shrink: 0;
}

.page-topbar-action {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    transition: color var(--transition-base), background var(--transition-base);
}
.page-topbar-action:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}

/* Dashboard avatar trigger */
.page-topbar-user { position: relative; }
.page-topbar-avatar {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}
.page-topbar-avatar {
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.page-topbar-avatar .avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--grad-primary);
    color: #fff;
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-xs); /* 11px */
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: none;
    border: none;
}

/* Saludo + nombre */
.page-topbar-greeting {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
    min-width: 0;
}
.page-topbar-greeting-text {
    font-size: var(--text-xs);
    line-height: var(--text-xs--line-height);
    font-weight: var(--font-weight-medium);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.page-topbar-greeting-name {
    font-size: var(--text-xl);
    line-height: var(--text-xl--line-height);
    font-weight: var(--font-weight-normal);
    color: var(--text-primary);
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* === Tipografía: tokens definidos en variables.css ===
   --font-title (Audiowide), --font-heading (Poppins), --font-body (Nunito) */

/* Display only: topbar título + greeting name = Audiowide.
   El resto (cards/sections/headings) usa Poppins via base.css h1-h4. */
.page-topbar-title,
.page-topbar-greeting-name {
    font-family: var(--font-title);
    font-weight: var(--font-weight-normal);
    letter-spacing: -0.01em;
}

/* Section/card titles que NO son <h1>-<h4> nativos: forzar Poppins. */
.dashboard-card-title,
.setlist-builder-title span,
.song-picker-header span,
.setlist-editor-header-left h1,
.calendar-list-month,
.dashboard-hero-title,
.page-header h1,
.page-header h2,
h1.page-title {
    font-family: var(--font-heading);
    font-weight: var(--font-weight-semibold);
    letter-spacing: -0.01em;
}

/* Caption / micro: Poppins en badges, labels, meta text */
.badge,
.tag,
.song-tag-mini,
.minister-pill,
.page-topbar-greeting-text,
.dashboard-card-link,
.dashboard-hero-label,
.dashboard-hero-date,
.setlist-card-meta,
.setlist-builder-hint,
label {
    font-family: var(--font-heading);
}

/* Botón back en topbar (sub-views modales como Nuevo Setlist) */
.page-topbar-back {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0;
    transition: background var(--transition-base), color var(--transition-base);
    flex-shrink: 0;
}
.page-topbar-back:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}
.page-topbar-back i {
    font-size: var(--text-sm); /* 14px */
}

/* Título de página (rutas no-dashboard) — text-3xl UPPERCASE */
.page-topbar-title {
    font-size: var(--text-3xl);
    line-height: var(--text-3xl--line-height);
    font-weight: var(--font-weight-normal);
    text-transform: uppercase;
    color: var(--text-primary);
    margin: 0;
    padding-left: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 480px) {
    .page-topbar { padding-left: var(--space-6); padding-right: var(--space-6); }
    .page-topbar-greeting-name { font-size: var(--text-xl); line-height: var(--text-xl--line-height); }
    .page-topbar-title { font-size: var(--text-3xl); line-height: var(--text-3xl--line-height); }
    /* Títulos largos truncan en mobile — reducir font solo en rutas de edición/nuevo
       evento. Aplica solo a estas rutas, no afecta resto del app. */
    body.route-eventos-new .page-topbar-title,
    body[class*="route-eventos-"][class*="-edit"] .page-topbar-title {
        font-size: var(--text-xl);
        line-height: var(--text-xl--line-height);
    }
}

/* === Desktop ≥821px: alinear avatar topbar con margen del contenido ===
   Pages con max-width 1200 + margin auto + padding var(--space-4).
   Main padding lateral var(--space-5).
   Topbar padding lateral debe igualar: main_pad + max(0, (app_content_w - main_pad*2 - 1200) / 2) + page_pad. */
@media (min-width: 821px) {
    .dashboard-page,
    .songs-page,
    .setlists-page,
    .calendar-page,
    .ministers-page,
    .stats-page,
    .settings-page,
    .logs-page,
    .yt-audio-page,
    .stem-page,
    .more-page,
    .pitch-page,
    .voice-stack-page,
    .piano-page,
    .tools-page,
    .song-editor-page {
        max-width: 1400px;
        margin: 0 auto;
        padding: var(--space-4);
    }
    /* Topbar es hijo de .app-content (sibling de .main). 100% del topbar =
       app-content width = main_outer. main_inner = main_outer - 2*space-5
       (.main padding). .page abajo: max-width 1400 + margin auto + padding
       space-4. Edge content .page desde app-content left =
       space-5 (main pad) + (main_inner - 1400)/2 + space-4 (page pad). */
    .page-topbar {
        padding-left: calc(var(--space-5) + max(0px, (100% - var(--space-5) * 2 - 1400px) / 2) + var(--space-4));
        padding-right: calc(var(--space-5) + max(0px, (100% - var(--space-5) * 2 - 1400px) / 2) + var(--space-4));
    }

    /* Editor de canción página extendida (max-width 100%, sin centering).
       Topbar alinea con edge de .song-editor-page (space-5 main + space-4 pad). */
    body.editor-mode .page-topbar {
        padding-left: calc(var(--space-5) + var(--space-4));
        padding-right: calc(var(--space-5) + var(--space-4));
    }

    /* Voice Stack V2: full-width page sin max-width centering.
       Topbar alinea con edge del .vs2-page (main padding only). */
    body.vs2-mode .page-topbar {
        padding-left: var(--space-5);
        padding-right: var(--space-5);
    }

    /* Songs page: grid 2 cols 2 rows. Filtros span full width, debajo
       table (col 1) y pending panel (col 2) alineados al mismo top. */
    .songs-layout-container {
        display: grid;
        grid-template-columns: 1fr 320px;
        grid-template-rows: auto 1fr;
        gap: var(--space-4) var(--space-5);
        align-items: start;
    }
    .songs-layout-container > .songs-filters-row {
        grid-column: 1 / -1;
        grid-row: 1;
        justify-content: space-between;
        gap: var(--space-3);
    }
    .songs-layout-container > .songs-main-column {
        grid-column: 1;
        grid-row: 2;
    }
    .songs-layout-container > .songs-pending-panel {
        grid-column: 2;
        grid-row: 2;
    }
    .songs-add-btn-end {
        margin-left: auto;
    }
}

/* Iconos heredan text color del contenedor (themed) */
.header svg, .app-header svg, .sidebar svg,
.mobile-nav svg, .mobile-nav-items svg {
    color: inherit;
    fill: currentColor;
    stroke: currentColor;
}

/* SVG con stroke="currentColor" deben mantener fill: none */
.header svg[stroke], .app-header svg[stroke], .sidebar svg[stroke],
.mobile-nav svg[stroke] {
    fill: none;
}


/* =====================================================
   3. COMPONENTES ESPECÍFICOS
   ===================================================== */

/* Modal backdrop con blur dark */
.modal-backdrop {
    background: var(--bg-overlay);
    backdrop-filter: blur(10px) saturate(140%);
    -webkit-backdrop-filter: blur(10px) saturate(140%);
}

/* Botones primary: gradient purple */
.btn-primary {
    background: var(--grad-primary);
    border: none;
    box-shadow: var(--grad-primary-shadow);
    color: #fff;
    transition: transform var(--transition-base),
                box-shadow var(--transition-slow),
                background var(--transition-slow);
}
.btn-primary:hover {
    box-shadow: var(--grad-primary-shadow-hover);
    transform: translateY(-1px);
}
.btn-primary:active { transform: translateY(0); }

/* Botones secondary: glass tint, sin border */
.btn-secondary {
    background: var(--surface-3);
    border: none;
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
    color: var(--text-primary);
    box-shadow: var(--glass-highlight);
}
.btn-secondary:hover {
    background: var(--surface-4);
}

/* Botones outline → glass tint sutil (sin border) */
.btn-outline {
    background: var(--surface-1);
    border: none;
    color: var(--text-primary);
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
}
.btn-outline:hover {
    background: var(--surface-3);
}

/* Botones ghost: hover-only */
.btn-ghost {
    background: transparent;
    border: none;
    color: var(--text-secondary);
}
.btn-ghost:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}

/* Status buttons */
.btn-danger {
    background: linear-gradient(135deg, var(--red-500) 0%, var(--red-600) 100%);
    border: none;
    color: #fff;
    box-shadow: 0 8px 24px rgba(239, 68, 68, 0.4);
}
.btn-success {
    background: linear-gradient(135deg, var(--green-500) 0%, var(--green-600) 100%);
    border: none;
    color: #fff;
    box-shadow: 0 8px 24px rgba(16, 185, 129, 0.4);
}

/* Mobile (≤820): labels SIEMPRE visibles, sin gate .sidebar.open.
   ANTES gated → margin/padding: revert dropeaba padding natural; al cerrar
   (.open removed) padding/margin de .sidebar-nav-label volvía → contenido
   shift DOWN durante close. Fix: aplicar siempre en mobile. */
@media (max-width: 820px) {
    .sidebar .sidebar-title,
    .sidebar .sidebar-nav-item span,
    .sidebar .sidebar-nav-label {
        opacity: 1;
        width: auto;
        height: auto;
    }
    .sidebar {
        width: 280px;
    }
    .sidebar .sidebar-nav-item {
        width: auto;
        justify-content: flex-start;
        padding: var(--space-3);
    }
}

/* Sidebar nav items — sin highlight al drag, solo en .active route */
.sidebar-nav-item {
    color: var(--text-secondary);
    border-radius: var(--glass-radius-sm);
    margin: 2px 8px;
    transition: background var(--transition-base),
                color var(--transition-base);
    -webkit-tap-highlight-color: transparent;
}

/* Hover solo en dispositivos con mouse (no sticky en touch) */
@media (hover: hover) {
    .sidebar-nav-item:hover {
        background: var(--surface-2);
        color: var(--text-primary);
    }
}

/* :active (touch) sin bg highlight — evita que arrastrar sobre items los marque */
.sidebar-nav-item:active {
    background: transparent;
}

.sidebar-nav-item.active {
    background: var(--grad-primary);
    color: #fff;
    box-shadow: 0 6px 20px rgba(124, 77, 255, 0.45);
}
.sidebar-nav-label { color: var(--text-muted); }
/* Overlay backdrop-filter ahora se anima en layout.css (0px → 8px via .active).
   Constante 8px pisaba transición. */

/* Filter tabs glass pill */
.filter-tab {
    background: transparent;
    border: none;
    color: var(--text-secondary);
    border-radius: var(--glass-radius-pill);
    padding: 6px 14px;
    transition: background var(--transition-base),
                color var(--transition-base);
}
.filter-tab:hover {
    background: var(--surface-2);
    color: var(--text-primary);
}
.filter-tab.active {
    background: var(--grad-primary);
    color: #fff;
    box-shadow: 0 4px 14px rgba(124, 77, 255, 0.4);
}

.calendar-filter-tabs,
.stats-tabs {
    background: var(--surface-1);
    border: none;
    border-radius: var(--glass-radius-pill);
    padding: 4px;
}

/* Filter tabs uniformes en TODAS las páginas (setlists, calendar, songs).
   Override de setlists.css y components.css que tenían sizes distintos. */
.calendar-filters .filter-tab,
.songs-filters .filter-tab,
.setlists-filter-tabs .filter-tab,
.calendar-filter-tabs .filter-tab {
    padding: 6px 14px;
    border-radius: var(--glass-radius-pill);
    font-size: var(--text-xs); /* 13px */
    height: 32px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    flex-shrink: 0;
}
.calendar-filters .filter-tab i,
.songs-filters .filter-tab i,
.setlists-filter-tabs .filter-tab i,
.calendar-filter-tabs .filter-tab i {
    font-size: var(--text-xs); /* 11px */
}

/* Inputs / forms — flat, sin border. Surface tinted + focus ring sutil. */
:where(input, select, textarea) {
    background-color: var(--bg-input);
    border: none;
    color: var(--text-primary);
    border-radius: var(--glass-radius-sm);
    transition: background-color var(--transition-base),
                box-shadow var(--transition-base);
}
:where(input, select, textarea):focus {
    background-color: var(--surface-2);
    box-shadow: 0 0 0 2px rgba(167, 139, 250, 0.35);
    outline: none;
}
:where(input, textarea)::placeholder {
    color: var(--text-muted);
}

/* Chevron del select: cambiar stroke gris (#64748b) por color glass-friendly */
select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a78bfa' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
}

/* Badges — sin border */
.badge {
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
    border: none;
    border-radius: var(--glass-radius-pill);
}

/* Badge primary en dark: --color-primary-light (rgba 0.18) queda muy
   debil + --color-primary (purple-300) sobre fondo oscuro tampoco contrasta.
   Subir saturacion del bg y aclarar texto a purple-100. */
[data-theme="dark"] .badge-primary {
    background: color-mix(in srgb, var(--purple-300) 30%, transparent);
    color: var(--purple-100);
}
[data-theme="dark"] .badge-secondary {
    background: color-mix(in srgb, var(--purple-200) 22%, transparent);
    color: var(--purple-100);
}
[data-theme="dark"] .badge-outline {
    background: transparent;
    color: var(--purple-100);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--purple-300) 50%, transparent);
}

/* Tags — sin border */
.tag {
    background: var(--surface-2);
    border: none;
    color: var(--text-primary);
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
    border-radius: var(--glass-radius-pill);
}

/* Alerts glass — sin border */
.alert {
    border-radius: var(--glass-radius-md);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    border: none;
}
.alert-success { background: var(--color-success-light); }
.alert-warning { background: var(--color-warning-light); }
.alert-error,
.alert-danger  { background: var(--color-error-light); }
.alert-info    { background: var(--color-info-light); }

/* === SONG CARDS — comprimidas verticalmente, sombra suave ===
   Padding vertical reducido para que altura de cada song sea más compacta.
   Sin !important — specificity + cascade order suficientes. */
.song-card,
.song-card-modern {
    padding: 8px var(--space-4);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12), var(--glass-edge-ring), var(--glass-highlight);
    gap: var(--space-3);
    min-height: 0;
}
.song-card-modern .song-card-action,
.song-card-modern .song-play-btn,
.song-card-modern .song-card-action button {
    width: 36px;
    height: 36px;
}
.song-card-modern .song-card-title {
    font-size: var(--text-sm); /* 14px */
    line-height: 1.25;
    margin: 0;
}
.song-card-modern .song-card-author {
    font-size: var(--text-xs); /* 12px */
    line-height: 1.2;
    margin: 0;
}
[data-theme="dark"] .song-card,
[data-theme="dark"] .song-card-modern {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28), var(--glass-edge-ring), var(--glass-highlight);
}


/* === NIVEL 1 — Dashboard hero glass brillante con highlight ===
   Sombra doble layer (depth) pero moderada — mantiene efecto glassy. */
.dashboard-hero {
    background: linear-gradient(135deg,
        rgba(124, 77, 255, 0.55) 0%,
        rgba(167, 139, 250, 0.40) 100%);
    backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    border: none;
    border-radius: var(--glass-radius-lg);
    box-shadow:
        0 10px 28px rgba(76, 42, 133, 0.22),
        0 3px 8px rgba(76, 42, 133, 0.12),
        var(--glass-highlight);
    color: #fff;
}

/* Light theme: colores vibrantes purple, sombra moderada con tinte */
[data-theme="light"] .dashboard-hero,
:root:not([data-theme="dark"]) .dashboard-hero {
    background: linear-gradient(135deg,
        rgba(124, 77, 255, 0.85) 0%,
        rgba(167, 139, 250, 0.70) 50%,
        rgba(94, 53, 216, 0.80) 100%);
    box-shadow:
        0 10px 28px rgba(124, 77, 255, 0.25),
        0 3px 8px rgba(76, 42, 133, 0.14),
        var(--glass-highlight);
}

/* Dark theme: sombra más oscura para depth en fondo oscuro */
[data-theme="dark"] .dashboard-hero {
    box-shadow:
        0 10px 28px rgba(0, 0, 0, 0.40),
        0 3px 8px rgba(0, 0, 0, 0.20),
        var(--glass-highlight);
}

/* === NIVEL 2 — Surfaces planas (sin sombra, sin highlight, sin selectores).
   Saturate 100% (sin amplificar colores) para que el bg sea uniforme
   independiente del tamaño del elemento o blob de fondo detrás.
   isolation: isolate normaliza stacking context. */
.dashboard-card,
.songs-compact-view .song-list,
.setlist-card,
.calendar-card,
.setlist-builder-panel,
.song-picker-panel {
    background: var(--surface-2);
    backdrop-filter: blur(var(--glass-blur)) saturate(100%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(100%);
    border: 1px solid var(--edge-soft);
    border-radius: var(--glass-radius-md);
    box-shadow: none;
    isolation: isolate;
    -webkit-tap-highlight-color: transparent;
}

/* Sub-secciones del builder/picker (no panels propios) — transparentes,
   integradas al panel padre. Separación visual via border-top sutil. */
.setlist-quick-info,
.setlist-notes-section {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: none;
    box-shadow: none;
    border-radius: 0;
}
.setlist-notes-section {
    border-top: 1px solid var(--edge-soft);
    padding: var(--space-3) var(--space-4);
    margin-top: var(--space-2);
}

/* Sin cambio de bg en hover/active — color dinámico solo del fondo.
   Specificity (0,1,1) > section 4 hover (0,1,1) por cascade order. */
.dashboard-card:hover,
.dashboard-card:active,
.dashboard-card:focus,
.dashboard-card:focus-within,
.songs-compact-view .song-list:hover,
.songs-compact-view .song-list:active,
.songs-compact-view .song-list:focus,
.songs-compact-view .song-list:focus-within,
.setlist-card:hover,
.setlist-card:active,
.setlist-card:focus,
.setlist-card:focus-within,
.calendar-card:hover,
.calendar-card:active,
.calendar-card:focus,
.calendar-card:focus-within,
.setlist-builder-panel:hover,
.song-picker-panel:hover {
    background: var(--surface-2);
    box-shadow: none;
    transform: none;
    border-color: var(--edge-soft);
}

/* Setlist cards — kill bordes-left de status y backgrounds extra del diseño
   antiguo. Status visual lo damos solo con accent en fecha/badge si aplica. */
.setlist-card,
.setlist-card-past,
.setlist-card-today,
.setlist-card-upcoming,
.setlist-card-nodate,
.calendar-card,
.calendar-card-past,
.calendar-card-today {
    border-left: none;
}
/* Past = fantasma: muy desaturado y desvanecido */
.setlist-card-past,
.calendar-card-past {
    background: var(--surface-2);
    opacity: 0.45;
    filter: saturate(0.4);
}
.setlist-card-past:hover,
.calendar-card-past:hover {
    opacity: 0.7;
    filter: saturate(0.7);
}
/* Today = pulse verde — borde grosor + halo pulsan juntos. */
@keyframes todayPulseGreen {
    0%, 100% {
        box-shadow:
            inset 0 0 0 1px var(--color-success),
            0 0 0 0 rgba(16, 185, 129, 0);
    }
    50% {
        box-shadow:
            inset 0 0 0 3px var(--color-success),
            0 0 0 5px rgba(16, 185, 129, 0.30);
    }
}
.setlist-card-today,
.calendar-card-today {
    background: var(--surface-2);
    animation: todayPulseGreen 1.4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.setlist-card-today:hover,
.calendar-card-today:hover {
    box-shadow: none;
}

/* Closest upcoming = pulse purple — borde + halo notorios + rápidos. */
@keyframes closestPulse {
    0%, 100% {
        box-shadow:
            inset 0 0 0 1px var(--color-primary),
            0 0 0 0 rgba(124, 77, 255, 0);
    }
    50% {
        box-shadow:
            inset 0 0 0 3px var(--color-primary),
            0 0 0 6px rgba(124, 77, 255, 0.30);
    }
}
.setlist-card-closest {
    background: var(--surface-2);
    animation: closestPulse 1.4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
/* Si el setlist más cercano ES hoy, gana pulse verde (specificity 0,2,0). */
.setlist-card-today.setlist-card-closest {
    animation: todayPulseGreen 1.4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.setlist-card-closest .setlist-card-title {
    font-weight: var(--font-weight-semibold);
}

/* Setlist view header: forzar fila única en todas las viewports */
.setlist-view-header {
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: nowrap;
}
.setlist-view-actions {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
/* Mobile/touch: feedback :active visible al pulsar (scale + opacidad).
   :focus removed + :hover NO aplica (gate via @media hover:hover) para
   evitar que el botón quede marcado morado tras tap (iOS no quita auto). */
@media (hover: none) {
    .setlist-view-actions .btn:active,
    .setlist-view-actions .fab-new-btn:active,
    .setlist-view-actions .fab-secondary-btn:active {
        transform: scale(0.93);
        opacity: 0.85;
    }
    .setlist-view-actions .btn:focus,
    .setlist-view-actions .btn:focus-visible,
    .setlist-view-actions .fab-new-btn:focus,
    .setlist-view-actions .fab-secondary-btn:focus {
        outline: none;
        box-shadow: none;
    }
    /* Anular :hover en touch: surface-4 sobre bg purple = parece marcado. */
    .setlist-view-actions .btn-secondary:hover {
        background: var(--surface-3);
    }
    .setlist-view-actions .btn-icon:hover {
        background: var(--surface-3);
        color: var(--text-primary);
    }
}

/* Confirmación grande centro de pantalla al copiar setlist. Garantiza
   feedback visible en mobile aunque Toast quede tapado por overlays. */
.setlist-copy-confirm {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.9);
    background: var(--color-success);
    color: #fff;
    padding: 18px 28px;
    border-radius: 14px;
    font-size: var(--text-lg); /* 17px */
    font-weight: 600;
    z-index: 99999;
    box-shadow: 0 12px 40px rgba(16, 185, 129, 0.45), 0 4px 12px rgba(0, 0, 0, 0.2);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
}
.setlist-copy-confirm.show {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

/* Toast container — en mobile, posicionar bajo el topbar y centrado
   horizontalmente para que el user lo vea siempre. z-index máximo. */
@media (max-width: 820px) {
    .toast-container {
        top: calc(var(--safe-area-top, 0px) + 76px);
        left: var(--space-3);
        right: var(--space-3);
        max-width: none;
        z-index: 9999;
    }
    .toast {
        transform: translateY(-120%);
    }
    .toast.toast-enter {
        transform: translateY(0);
    }
    .toast.toast-exit {
        transform: translateY(-120%);
    }
}
@media (max-width: 820px) {
    .setlist-view-header {
        flex-direction: row;
        align-items: center;
    }
    .setlist-view-actions {
        width: auto;
    }
}

/* === Setlist detail edit + play === */
.setlist-fab-play.fab-new-btn,
.setlist-fab-edit.fab-secondary-btn {
    display: inline-flex;
}
.setlist-fab-play.fab-new-btn {
    background: var(--color-success);
    color: #fff;
    box-shadow: 0 8px 24px rgba(16, 185, 129, 0.45);
}
.setlist-fab-play.fab-new-btn:hover {
    background: var(--color-success-dark);
    box-shadow: 0 10px 28px rgba(16, 185, 129, 0.55);
}
.setlist-fab-edit {
    width: 44px;
    height: 44px;
    font-size: var(--text-base); /* 16px */
    color: var(--text-primary);
}

/* Desktop ≥821: edit + play inline en .setlist-view-actions, no flotantes.
   Pill con icono + label, colores del tema (Play=success, Editar=primary).
   Copy queda btn-icon ghost. */
@media (min-width: 821px) {
    .setlist-view-actions .setlist-fab-edit,
    .setlist-view-actions .setlist-fab-play {
        position: static;
        bottom: auto;
        right: auto;
        z-index: auto;
        width: auto;
        height: 40px;
        border-radius: var(--border-radius-md);
        padding: 0 var(--space-3);
        gap: var(--space-2);
        font-size: var(--font-size-sm);
        font-weight: var(--font-weight-semibold);
    }
    .setlist-view-actions .setlist-fab-play {
        background: var(--color-success);
        color: #fff;
        box-shadow: none;
    }
    .setlist-view-actions .setlist-fab-play:hover {
        background: var(--color-success-dark);
        box-shadow: none;
    }
    .setlist-view-actions .setlist-fab-edit {
        background: var(--color-primary);
        color: #fff;
    }
    .setlist-view-actions .setlist-fab-edit:hover {
        background: var(--color-primary-dark, color-mix(in srgb, var(--color-primary) 85%, #000));
    }
    .setlist-view-actions .setlist-action-label {
        display: inline;
    }
}
/* Mobile: ocultar labels, FABs vuelven a circular */
@media (max-width: 820px) {
    .setlist-action-label {
        display: none;
    }
}

/* === Setlist song card detail view: una sola fila ===
   Cols: número | info(título+autor) | ministro | tono+bpm (stack) | (flecha).
   Override de setlists.css que en max-width:768px usaba flex-wrap y order. */
.setlist-view .setlist-songs-list .setlist-song-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    grid-template-rows: auto;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    flex-wrap: nowrap;
}
.setlist-view .setlist-songs-list .setlist-song-card > * {
    grid-row: 1;
    order: 0;
}
.setlist-view .setlist-song-card .song-number { grid-column: 1; }
.setlist-view .setlist-song-card .song-left {
    grid-column: 2;
    min-width: 0;
}
/* Desktop ≥769: separar el chip ministro del título para que respire al
   centro. Padding lateral en el chip (no expande la columna tono/bpm). */
@media (min-width: 769px) {
    .setlist-view .setlist-song-card .song-right {
        margin-left: var(--space-12);
        margin-right: var(--space-12);
    }
}
.setlist-view .setlist-song-card .song-left .song-title {
    margin: 0;
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.setlist-view .setlist-song-card .song-left .song-author {
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}
.setlist-view .setlist-song-card .song-right {
    grid-column: 3;
    flex-shrink: 0;
}
/* song-center: stack tono arriba bpm abajo, ambos mismo ancho/alto. */
.setlist-view .setlist-song-card .song-center {
    grid-column: 4;
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: stretch;
}
/* === Ripple verde de entrada al modo zen === */
.play-zen-ripple {
    position: fixed;
    top: var(--ripple-y, 50%);
    left: var(--ripple-x, 50%);
    width: var(--ripple-size, 200vmax);
    height: var(--ripple-size, 200vmax);
    margin-top: calc(var(--ripple-size, 200vmax) / -2);
    margin-left: calc(var(--ripple-size, 200vmax) / -2);
    border-radius: 50%;
    background: var(--color-success);
    box-shadow: 0 0 80px 20px rgba(16, 185, 129, 0.5);
    transform: scale(0);
    transform-origin: center center;
    z-index: 9999;
    pointer-events: none;
    transition: transform 0.7s cubic-bezier(0.65, 0, 0.35, 1);
}
.play-zen-ripple.expanding {
    transform: scale(1);
}

/* Shrinker de salida: fixed inset:0, bg verde uniforme, clip-path que
   contrae el círculo desde 150% (cobertura total) hasta 0% en top-left.
   Mismo cubic-bezier que la entrada — efecto inverso anclado en (0,0). */
.play-zen-shrinker {
    position: fixed;
    inset: 0;
    background: var(--color-success);
    z-index: 9999;
    pointer-events: none;
    clip-path: circle(150% at 0% 0%);
    -webkit-clip-path: circle(150% at 0% 0%);
    transition: clip-path 0.75s cubic-bezier(0.65, 0, 0.35, 1),
                -webkit-clip-path 0.75s cubic-bezier(0.65, 0, 0.35, 1);
}
.play-zen-shrinker.shrinking {
    clip-path: circle(0% at 0% 0%);
    -webkit-clip-path: circle(0% at 0% 0%);
}

/* === ZEN MODE — entrada animada profesional + sin chrome ===
   Sidebar sale por la izq, topbar arriba, mobile-nav abajo, partículas fade.
   Contenido entra fade+scale. Duración 750ms cubic-bezier suave. */
.sidebar,
.mobile-nav,
.page-topbar,
.bg-particles {
    transition: opacity 0.75s cubic-bezier(0.65, 0, 0.35, 1),
                transform 0.75s cubic-bezier(0.65, 0, 0.35, 1);
}
/* will-change solo activo en zen-mode (evita romper backdrop-filter children) */
body.zen-mode .sidebar,
body.zen-mode .mobile-nav,
body.zen-mode .page-topbar,
body.zen-mode .bg-particles {
    will-change: opacity, transform;
}
.app-content,
.main {
    transition: margin 0.75s cubic-bezier(0.65, 0, 0.35, 1),
                padding 0.75s cubic-bezier(0.65, 0, 0.35, 1);
    overflow: visible;
}

body.zen-mode .sidebar {
    opacity: 0;
    transform: translateX(-100%);
    pointer-events: none;
}
body.zen-mode .mobile-nav {
    opacity: 0;
    transform: translateY(100%);
    pointer-events: none;
}
body.zen-mode .page-topbar {
    opacity: 0;
    transform: translateY(-100%);
    pointer-events: none;
    /* display: none ahorra el espacio del topbar; nav-bar de play-mode
       queda pegado al top sin gap. */
    display: none;
}
body.zen-mode .sidebar-overlay {
    display: none;
}
/* Zen mode: cero distracciones — particles y blobs ocultos. */
body.zen-mode .bg-particles {
    display: none;
}
/* Setlist editor: drag-reorder mobile — bloquear selección texto / callout
   long-press; mejora la captura del item por el handle. */
.editable-song-item,
.editable-song-item * {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}
/* Inputs/selects dentro del item siguen seleccionables */
.editable-song-item input,
.editable-song-item textarea,
.editable-song-item select {
    -webkit-user-select: auto;
    user-select: auto;
}

/* Vista canción: ocultar botón Volver inline — la flecha back vive en el
   page-topbar arriba (BACK_ROUTES incluye /songs/). */
.song-view-modern:not(.play-mode-active) .controls-left {
    display: none;
}

/* Dashboard pills/badges en dark — contraste mejorado.
   Antes: bg color-primary-light + color color-primary = purple-on-purple
   sobre el blob del fondo. */
[data-theme="dark"] .dashboard-list-badge {
    background: color-mix(in srgb, var(--color-primary) 25%, var(--bg-card));
    color: color-mix(in srgb, var(--color-primary) 30%, #ffffff);
    border: 1px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
}
[data-theme="dark"] .dashboard-card-link {
    color: color-mix(in srgb, var(--color-primary) 30%, #ffffff);
}

/* Songs page: disclaimer de swipe a la derecha → añadir a setlist. */
.songs-swipe-hint {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    margin-bottom: var(--space-3);
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-primary) 25%, transparent);
    border-radius: var(--border-radius-md);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
}
.songs-swipe-hint i {
    color: var(--color-primary);
    font-size: var(--text-sm); /* 14px */
    flex-shrink: 0;
}
body.zen-mode .app-content {
    margin-left: 0;
    padding: 0;
}
body.zen-mode .main {
    padding: 0;
}
body.zen-mode .app {
    min-height: 100vh;
    min-height: 100dvh;
}
/* Zen mode: blobs ocultos completamente para no distraer. */
body.zen-mode::before {
    animation: none;
    opacity: 0;
    transition: opacity 0.6s ease;
}

/* zenContentEnter eliminado — la animación de entrada (0.85s) chocaba con
   la primera transición song-slide cuando user clickeaba siguiente antes
   de que terminara, dando efecto 'doble'. Sin entry animation, transición
   entre canciones es siempre limpia. */

/* Zen mode: nav-bar de canciones FIXED arriba (suple a la topbar). Estilo
   glass para combinar con el tema (translucent, sin bordes duros).
   Contenido limitado a max-width centrada para que los botones queden
   alineados con el card de la canción (no pegados a las esquinas viewport). */
body.zen-mode .play-mode-nav-bar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    margin: 0;
    z-index: var(--z-sticky, 100);
    /* Aligns con .song-view-modern (max-width 1200px + padding space-4 lateral).
       padding lateral = (100vw - 1200px)/2 + space-4 → bordes nav-bar coinciden
       con bordes del card de la canción. Min space-4 en mobile. */
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
    padding-left: calc(max(0px, (100vw - 1200px) / 2) + var(--space-4));
    padding-right: calc(max(0px, (100vw - 1200px) / 2) + var(--space-4));
    background: color-mix(in srgb, var(--bg-body) 60%, transparent);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border-bottom: 1px solid color-mix(in srgb, var(--border-color) 50%, transparent);
}
/* @media mobile movido AL FINAL después de las reglas universales para que
   no las sobrescriban. */

/* Botones de nav prev/next: pill glass, sin borde duro, contenido centrado. */
body.zen-mode .play-mode-nav-bar .play-nav-btn {
    background: var(--surface-2);
    border: none;
    border-radius: var(--border-radius-full);
    color: var(--text-primary);
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
    transition: background var(--transition-base);
    justify-content: center;
}
@media (hover: hover) {
    body.zen-mode .play-mode-nav-bar .play-nav-btn:hover:not(:disabled) {
        background: var(--surface-3);
    }
}
body.zen-mode .play-mode-nav-bar .play-nav-btn:disabled {
    opacity: 0.35;
}

/* Botón Salir: rojo translúcido, mismo radius pill. */
body.zen-mode .play-mode-nav-bar .btn-exit-play {
    background: color-mix(in srgb, var(--color-danger) 75%, transparent);
    border-radius: var(--border-radius-full);
    padding: var(--space-2) var(--space-4);
}
@media (hover: hover) {
    body.zen-mode .play-mode-nav-bar .btn-exit-play:hover {
        background: var(--color-danger) !important;
    }
}

/* Mobile ≤820: borde inferior fuera + altura uniforme 36px en los 3 botones.
   DEBE ir después de las reglas universales arriba (misma specificity 0,3,0
   → la posterior gana). btn-exit-play tiene clases .btn .btn-sm; en touch
   coarse devices, .btn-sm setea min-height:44px (touch-target-min) → mi
   height:36px se ignora. Por eso reseteo min-height aquí. */
@media (max-width: 820px) {
    body.zen-mode .play-mode-nav-bar {
        border-bottom: none;
    }
    body.zen-mode .play-mode-nav-bar .btn-exit-play,
    body.zen-mode .play-mode-nav-bar .play-nav-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        height: 36px;
        min-height: 0;
        padding: 0 var(--space-3);
        font-size: var(--font-size-sm);
        line-height: 1;
        box-sizing: border-box;
    }
}

/* Song list overview: card glass redondeada, ítem activo con tinte primary.
   Posición static dentro de song-view-modern → fluye con scroll. */
body.zen-mode .play-mode-song-list {
    background: var(--surface-2);
    border: 1px solid color-mix(in srgb, var(--border-color) 40%, transparent);
    border-radius: var(--border-radius-lg);
    backdrop-filter: blur(var(--glass-blur-soft));
    -webkit-backdrop-filter: blur(var(--glass-blur-soft));
    padding: var(--space-2);
    margin-bottom: var(--space-4);
}
body.zen-mode .play-mode-song-list .play-list-item {
    border-radius: var(--border-radius-md);
    transition: background var(--transition-fast);
}
body.zen-mode .play-mode-song-list .play-list-item.active {
    background: color-mix(in srgb, var(--color-primary) 65%, transparent);
}
@media (hover: hover) {
    body.zen-mode .play-mode-song-list .play-list-item:hover:not(.active) {
        background: var(--surface-3);
    }
}
body.zen-mode .song-view-modern.play-mode-active {
    padding-top: 56px; /* compensa nav-bar fixed */
}

/* En vista canción y zen mode, atenúa partículas y blobs para que no
   distraigan al leer letras+acordes. */
body:has(.song-view-modern) .bg-particles {
    opacity: 0.35;
}
body:has(.song-view-modern)::before {
    opacity: 0.5;
}

/* Editor de canción: sin partículas + blobs congelados (reducir distracción) */
body.editor-mode .bg-particles {
    display: none;
}
body.editor-mode::before {
    animation: none;
}
body.editor-mode .bg-particle {
    animation: none;
}

/* Editor mobile: ocultar bottom-nav + botones flotantes circulares en
   esquina inferior derecha — Guardar grande (primary), Cancelar más chico
   arriba, mismo color (purple primary). */
@media (max-width: 820px) {
    body.editor-mode .mobile-nav,
    body:has(.setlist-editor-bottom-actions) .mobile-nav {
        display: none;
    }

    /* Reset reglas universales que dan estilo pill rectangular.
       Shape común — color por botón abajo. Aplica a song-editor (gated por
       body.editor-mode) y a setlist-editor (clases setlist-editor-*). */
    body.editor-mode .btn.song-editor-bottom-cancel,
    body.editor-mode .btn.song-editor-bottom-save,
    .btn.setlist-editor-bottom-cancel,
    .btn.setlist-editor-bottom-save {
        position: fixed;
        z-index: calc(var(--z-fixed, 300) + 1);
        right: var(--space-5);
        left: auto;
        transform: none;
        padding: 0;
        min-width: 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        color: #fff;
        border: none;
        border-radius: 50%;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        line-height: 1;
        font-weight: var(--font-weight-semibold);
    }

    /* Save = primary purple */
    body.editor-mode .btn.song-editor-bottom-save,
    .btn.setlist-editor-bottom-save {
        background: var(--color-primary);
        box-shadow: 0 6px 20px rgba(124, 77, 255, 0.45),
                    0 2px 6px rgba(0, 0, 0, 0.25);
    }
    body.editor-mode .btn.song-editor-bottom-save:hover,
    body.editor-mode .btn.song-editor-bottom-save:active,
    .btn.setlist-editor-bottom-save:hover,
    .btn.setlist-editor-bottom-save:active {
        background: color-mix(in srgb, var(--color-primary) 88%, #000);
    }

    /* Cancel = danger red */
    body.editor-mode .btn.song-editor-bottom-cancel,
    .btn.setlist-editor-bottom-cancel {
        background: var(--color-danger);
        box-shadow: 0 4px 14px color-mix(in srgb, var(--color-danger) 50%, transparent),
                    0 2px 6px rgba(0, 0, 0, 0.25);
    }
    body.editor-mode .btn.song-editor-bottom-cancel:hover,
    body.editor-mode .btn.song-editor-bottom-cancel:active,
    .btn.setlist-editor-bottom-cancel:hover,
    .btn.setlist-editor-bottom-cancel:active {
        background: color-mix(in srgb, var(--color-danger) 88%, #000);
    }

    /* Save grande, esquina inferior derecha */
    body.editor-mode .btn.song-editor-bottom-save,
    .btn.setlist-editor-bottom-save {
        bottom: calc(var(--safe-area-bottom, 0px) + var(--space-5));
        width: 60px;
        height: 60px;
    }

    /* Cancel más chico, arriba del save */
    body.editor-mode .btn.song-editor-bottom-cancel,
    .btn.setlist-editor-bottom-cancel {
        bottom: calc(var(--safe-area-bottom, 0px) + var(--space-5) + 60px + var(--space-3));
        width: 44px;
        height: 44px;
        right: calc(var(--space-5) + 8px);
    }

    /* Ocultar texto — solo iconos */
    body.editor-mode .btn.song-editor-bottom-cancel .btn-label,
    body.editor-mode .btn.song-editor-bottom-save .btn-label,
    .btn.setlist-editor-bottom-cancel .btn-label,
    .btn.setlist-editor-bottom-save .btn-label {
        display: none;
    }

    /* Padding-bottom reducido — ya no hace falta espacio para el nav oculto */
    body.editor-mode .song-editor-body,
    body.editor-mode .song-editor-info-grid {
        padding-bottom: calc(var(--space-12) + var(--space-8));
    }
}

/* Modal de sección/acorde: bg sólido + blur backdrop, contraste light + dark */
.ce-chord-modal {
    background: color-mix(in srgb, #000 55%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.ce-chord-modal-content {
    background: var(--glass-body-color);
    border: 1px solid var(--border-color);
    box-shadow: var(--glass-shadow-lg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}

/* Chord selector popup: bg sólido tematizado (light/dark). Original usaba
   --bg-primary que no existe → fallback #fff blanco eterno en dark. */
.ce-chord-selector,
.ce-section-selector {
    background: var(--glass-body-color);
    border: 1px solid var(--border-color);
    color: var(--text-primary);
    box-shadow: var(--glass-shadow-lg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}
.ce-chord-selector-search input,
.ce-section-selector-search input {
    background: var(--bg-input, var(--bg-card));
    color: var(--text-primary);
    border-color: var(--border-color);
}
.ce-chord-selector-btn,
.ce-section-selector-btn {
    background: var(--bg-input, var(--bg-card));
    color: var(--text-primary);
    border: 1px solid var(--border-color);
}
.ce-chord-selector-btn:hover,
.ce-chord-selector-btn:focus,
.ce-section-selector-btn:hover,
.ce-section-selector-btn:focus {
    background: color-mix(in srgb, var(--color-primary) 15%, var(--bg-card));
    color: var(--color-primary);
    border-color: var(--color-primary);
}
.ce-section-selector-header {
    color: var(--text-secondary);
    border-bottom-color: var(--border-color);
}
/* Popup chord/section: bg sólido en ambos temas. Iconos heredan text-primary. */
.ce-chord-popup,
.ce-section-popup {
    background: var(--glass-body-color);
    border: 1px solid var(--border-color);
    box-shadow: var(--glass-shadow-lg);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
}
.ce-chord-popup-btn {
    color: var(--text-primary);
}
.ce-chord-popup-btn:hover {
    background: color-mix(in srgb, var(--color-primary) 12%, transparent);
    color: var(--color-primary);
}
.ce-chord-popup-delete:hover,
.ce-section-popup-delete:hover {
    background: color-mix(in srgb, var(--color-danger) 14%, transparent);
    color: var(--color-danger);
}

/* === Swipe transition entre canciones del play mode === */
/* New view entra desde la derecha (next) o izquierda (prev) deslizándose
   completamente. Sin opacity — la página entra ya sólida desde el lado. */
@keyframes songSlideInLeft {
    from { transform: translateX(100%); }
    to   { transform: translateX(0); }
}
@keyframes songSlideInRight {
    from { transform: translateX(-100%); }
    to   { transform: translateX(0); }
}
/* Specificity (0,3,0) supera la regla zenContentEnter (0,3,1 con body.zen-mode)
   con !important alternativa? Usamos selector específico body.zen-mode + 3 clases. */
body.zen-mode .song-view-modern.play-mode-active.song-enter-next,
.song-view-modern.play-mode-active.song-enter-next {
    animation: songSlideInLeft 0.35s cubic-bezier(0.32, 0.72, 0, 1) both;
}
body.zen-mode .song-view-modern.play-mode-active.song-enter-prev,
.song-view-modern.play-mode-active.song-enter-prev {
    animation: songSlideInRight 0.35s cubic-bezier(0.32, 0.72, 0, 1) both;
}


/* Clone overlay: snapshot estático de la canción actual durante el swipe.
   Se posiciona absoluto sobre la página y se desliza hacia el lado opuesto
   al de la nueva canción, mientras esta entra desde el lado correspondiente. */
.song-clone-overlay {
    position: absolute;
    z-index: 9000;
    pointer-events: none;
    margin: 0;
    transition: transform 0.35s cubic-bezier(0.32, 0.72, 0, 1),
                opacity 0.35s cubic-bezier(0.32, 0.72, 0, 1);
}
.song-clone-overlay.song-clone-out-next {
    transform: translateX(-100%);
    opacity: 0;
}
.song-clone-overlay.song-clone-out-prev {
    transform: translateX(100%);
    opacity: 0;
}

/* Hover sobre cards: cero cambio. user-select: none + transition: none.
   IMPORTANTE: NO override del bg en children — eso cambiaría .song-key etc. */
.setlist-view .setlist-songs-list .setlist-song-card,
.song-card-modern {
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    transition: none;
}
.setlist-view .setlist-songs-list .setlist-song-card *,
.song-card-modern * {
    user-select: none;
    -webkit-user-select: none;
    transition: none;
}
.setlist-view .setlist-songs-list .setlist-song-card:hover,
.song-card-modern:hover {
    background: var(--bg-card);
    background-color: var(--bg-card);
    box-shadow: none;
    transform: none;
    border-color: var(--border-color);
    filter: none;
}

/* Tono y BPM: bg translúcido. Color blanco en dark, purple en light. */
.setlist-view .setlist-song-card .song-center .song-key,
.setlist-view .setlist-song-card .song-center .song-bpm {
    background: rgba(99, 102, 241, 0.1);
    color: #fff;
    min-width: 56px;
    height: 24px;
    padding: 0 var(--space-2);
    box-sizing: border-box;
    justify-content: center;
    font-size: var(--font-size-xs);
}
.setlist-view .setlist-song-card .song-center .song-key i,
.setlist-view .setlist-song-card .song-center .song-bpm i {
    color: #fff;
}
/* Light mode: texto e iconos en purple (mejor contraste sobre bg claro). */
:root:not([data-theme="dark"]) .setlist-view .setlist-song-card .song-center .song-key,
:root:not([data-theme="dark"]) .setlist-view .setlist-song-card .song-center .song-bpm,
[data-theme="light"] .setlist-view .setlist-song-card .song-center .song-key,
[data-theme="light"] .setlist-view .setlist-song-card .song-center .song-bpm {
    color: var(--color-primary);
}
:root:not([data-theme="dark"]) .setlist-view .setlist-song-card .song-center .song-key i,
:root:not([data-theme="dark"]) .setlist-view .setlist-song-card .song-center .song-bpm i,
[data-theme="light"] .setlist-view .setlist-song-card .song-center .song-key i,
[data-theme="light"] .setlist-view .setlist-song-card .song-center .song-bpm i {
    color: var(--color-primary);
}
.setlist-view .setlist-song-card .song-action {
    grid-column: 5;
    color: var(--text-muted);
    flex-shrink: 0;
}
@media (max-width: 820px) {
    .setlist-view .setlist-song-card {
        gap: var(--space-1);
        padding: var(--space-2) var(--space-3);
    }
    .setlist-view .setlist-song-card .song-action {
        display: none;
    }
    .setlist-view .setlist-song-card .song-center .song-key,
    .setlist-view .setlist-song-card .song-center .song-bpm {
        min-width: 48px;
    }
}

/* Editor: paneles internos planos. Header sin border separador. */
.setlist-builder-header,
.song-picker-header {
    border-bottom: none;
    background: transparent;
}

/* Quick info inline DENTRO del builder panel — fila slim arriba */
.setlist-quick-info-inline {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4) var(--space-2);
    margin: 0;
    background: transparent;
    border: none;
}
.setlist-quick-info-inline .setlist-info-name {
    flex: 1 1 auto;
    min-width: 0;
}
.setlist-quick-info-inline .setlist-info-date {
    flex: 0 0 auto;
}
.setlist-quick-info-inline .setlist-info-field {
    margin: 0;
    padding: 0;
    background: transparent;
    border: none;
}
.setlist-quick-info-inline .setlist-info-field input {
    height: 36px;
    padding: 0 var(--space-3);
    font-size: var(--font-size-sm);
    background: transparent;
    border: 1px solid var(--edge-soft);
    border-radius: var(--glass-radius-pill);
    box-shadow: none;
    color: var(--text-primary);
    width: 100%;
    box-sizing: border-box;
}
.setlist-quick-info-inline .setlist-info-name input {
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-medium);
}
.setlist-quick-info-inline .setlist-info-date input {
    width: 150px;
}
.setlist-quick-info-inline .setlist-info-field input:focus {
    outline: none;
    background: transparent;
    border-color: var(--color-primary);
    box-shadow: none;
}

/* Picker panel: misma altura que builder (grid stretch). Scroll interno en lista. */
@media (min-width: 1025px) {
    .setlist-editor-layout {
        align-items: stretch;
    }
    .song-picker-panel,
    .setlist-builder-panel {
        align-self: stretch;
        display: flex;
        flex-direction: column;
        min-height: 0;
        overflow: hidden;
    }
    .song-picker-list {
        flex: 0 0 auto;
        overflow: hidden;
        min-height: 0;
    }
    .setlist-songs-container {
        flex: 1 1 auto;
        overflow-y: auto;
        min-height: 0;
    }
}

/* === Section header unificado para los 3 paneles === */
.setlist-section-header,
.setlist-builder-header,
.song-picker-header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    font-weight: var(--font-weight-semibold);
    color: var(--text-primary);
    font-family: var(--font-heading);
    background: transparent;
    border-bottom: none;
}

/* Título canción + botón editar sutil al lado, manteniendo title centrado */
.song-title-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}
/* Wrapper mobile-only — botones edit/pdf entre author y meta-row. */
.song-title-actions-mobile {
    display: none;
}
@media (max-width: 820px) {
    .song-title-action-desktop {
        display: none !important;
    }
    /* Author en mobile sin margin-bottom — los botones de abajo deciden
       cuánta separación va. */
    .song-header-section .song-author-subtle {
        margin-bottom: 0;
    }
    .song-title-actions-mobile {
        display: flex;
        justify-content: center;
        gap: var(--space-2);
        margin: var(--space-3) 0;
    }
}
.song-title-edit-btn {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: transparent;
    border: 1px solid var(--edge-soft);
    color: var(--text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background var(--transition-base), color var(--transition-base), border-color var(--transition-base);
    font-size: var(--text-xs); /* 12px */
    padding: 0;
}
.song-title-edit-btn:hover {
    background: var(--surface-3);
    color: var(--color-primary);
    border-color: var(--color-primary);
}

/* === Swipe-right "A setlist" en song cards ===
   Wrap toma identidad visual del card. Card interior sin chrome propio.
   Reveal usa width animable nativamente (sin custom properties). */
.song-card-swipe-wrap {
    position: relative;
    overflow: hidden;
    border-radius: var(--border-radius-lg);
    border: 1px solid var(--border-color);
    background-color: var(--bg-card);
}
.song-card-swipe-wrap .song-card-modern {
    position: relative;
    z-index: 1;
    border: none;
    border-radius: 0;
    box-shadow: none;
    touch-action: pan-y;
    will-change: transform;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}
.song-card-swipe-wrap .song-card-modern:hover {
    transform: none;
    box-shadow: none;
}
.songs-compact-view .song-card-swipe-wrap {
    border-radius: var(--glass-radius-md);
    border: none;
    background: transparent;
}
.song-card-swipe-reveal {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    background: var(--color-primary);
    color: #fff;
    font-family: var(--font-heading);
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-sm);
    pointer-events: none;
    z-index: 0;
    transition: width 0.25s cubic-bezier(0.32, 0.72, 0, 1),
                background var(--transition-base);
    white-space: nowrap;
}
.song-card-swipe-reveal-content {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding-left: var(--space-5);
}
.song-card-swipe-reveal i {
    font-size: var(--text-base); /* 16px */
}
.song-card-swipe-wrap.swipe-trigger-ready .song-card-swipe-reveal {
    background: var(--color-success);
}
/* Triggered close: fade-out instant del contenido para evitar overlap con
   la card mientras vuelve. El bg verde sigue animando width suavemente. */
.song-card-swipe-wrap.swipe-closing .song-card-swipe-reveal-content {
    opacity: 0;
    transition: opacity 0.08s ease-out;
}


/* === Botones de acción de modales: cancelar (rojo) + confirmar (verde) ===
   Reutilizables. Misma paleta que swipe ready (success) y cancelar editor. */
.btn.btn-cancel-action {
    background: color-mix(in srgb, var(--color-danger) 92%, transparent);
    color: #fff;
    border: 1px solid color-mix(in srgb, var(--color-danger) 92%, transparent);
    padding: var(--space-2) var(--space-5);
    font-weight: var(--font-weight-semibold);
}
.btn.btn-cancel-action:hover,
.btn.btn-cancel-action:active {
    background: var(--color-danger);
    border-color: var(--color-danger);
    color: #fff;
}
.btn.btn-confirm-action {
    background: color-mix(in srgb, var(--color-success) 92%, transparent);
    color: #fff;
    border: 1px solid color-mix(in srgb, var(--color-success) 92%, transparent);
    padding: var(--space-2) var(--space-5);
    font-weight: var(--font-weight-semibold);
}
.btn.btn-confirm-action:hover,
.btn.btn-confirm-action:active {
    background: var(--color-success-dark);
    border-color: var(--color-success-dark);
    color: #fff;
}

/* Form "Añadir a setlist" modal */
.add-to-setlist-form .form-group {
    margin-bottom: var(--space-3);
}
.add-to-setlist-form label {
    display: block;
    font-size: var(--font-size-sm);
    color: var(--text-secondary);
    margin-bottom: var(--space-1);
    font-family: var(--font-heading);
    font-weight: var(--font-weight-medium);
}
.add-to-setlist-form .form-control {
    width: 100%;
    height: 40px;
    padding: 0 var(--space-3);
    background: var(--surface-3);
    border: 1px solid var(--edge-soft);
    border-radius: var(--glass-radius-md);
    color: var(--text-primary);
    font-size: var(--font-size-base);
    font-family: var(--font-body);
    box-sizing: border-box;
}
.add-to-setlist-form .form-control:focus {
    outline: none;
    border-color: var(--color-primary);
}
.add-to-setlist-song {
    padding: var(--space-3);
    background: var(--surface-2);
    border-radius: var(--glass-radius-md);
    margin-bottom: var(--space-4);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.add-to-setlist-song-info {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
    flex: 1;
}
.add-to-setlist-song-info strong {
    font-size: var(--font-size-base);
    color: var(--text-primary);
}
.add-to-setlist-song-info span {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}
.add-to-setlist-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    flex-shrink: 0;
}
.ats-meta-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px 10px;
    background: var(--surface-3);
    border: 1px solid var(--edge-soft);
    border-radius: var(--glass-radius-pill);
    font-size: var(--font-size-xs);
    color: var(--text-secondary);
    font-family: var(--font-heading);
    font-weight: var(--font-weight-medium);
}
.ats-meta-pill i {
    font-size: var(--text-xs); /* 10px */
    color: var(--color-primary);
}

/* Botón Mixear — más bajo + más contraste */
.btn.btn-mix-songs {
    margin-left: auto;
    padding: var(--space-1) var(--space-3);
    height: auto;
    min-height: 0;
    font-size: var(--font-size-sm);
    background: color-mix(in srgb, var(--color-primary) 92%, transparent);
    color: #fff;
    border: 1px solid color-mix(in srgb, var(--color-primary) 92%, transparent);
    line-height: 1.2;
}
.btn.btn-mix-songs:hover,
.btn.btn-mix-songs:active {
    background: var(--color-primary-dark);
    border-color: var(--color-primary-dark);
    color: #fff;
}

/* Número de sección — badge circular purple */
.section-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--color-primary);
    color: #fff;
    font-size: var(--text-xs); /* 12px */
    font-weight: var(--font-weight-bold);
    font-family: var(--font-heading);
    flex-shrink: 0;
    line-height: 1;
}

/* === LAYOUT 3 SECCIONES === */
/* Config panel (Sección 1) */
.setlist-config-panel {
    background: var(--surface-2);
    backdrop-filter: blur(var(--glass-blur)) saturate(100%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(100%);
    border: none;
    border-radius: var(--glass-radius-md);
    isolation: isolate;
    display: flex;
    flex-direction: column;
}
.setlist-config-fields {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
}
.setlist-config-fields .setlist-info-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.setlist-config-fields .setlist-info-field label {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
    font-family: var(--font-heading);
    font-weight: var(--font-weight-medium);
}
/* Inputs de form editor — estilo unificado para Configuración + Picker.
   surface-3 visible + border edge-soft + border-radius md. */
.setlist-config-fields input[type="text"],
.setlist-config-fields input[type="date"],
.song-picker-search,
.tag-filter-select {
    height: 40px;
    padding: 0 var(--space-3);
    background: var(--surface-3);
    border: 1px solid var(--edge-soft);
    border-radius: var(--glass-radius-md);
    color: var(--text-primary);
    font-size: var(--font-size-base);
    font-family: var(--font-body);
    box-sizing: border-box;
    box-shadow: none;
    width: 100%;
}
.setlist-config-fields input:focus,
.song-picker-search:focus-within,
.tag-filter-select:focus {
    outline: none;
    border-color: var(--color-primary);
    background: var(--surface-3);
    box-shadow: none;
}
.song-picker-search {
    display: flex;
    align-items: center;
    padding: 0;
}
.song-picker-search input {
    width: 100%;
    height: 100%;
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 0 var(--space-3);
    font-size: var(--font-size-base);
    color: var(--text-primary);
    box-sizing: border-box;
}
.song-picker-search input:focus {
    outline: none;
    background: transparent;
    box-shadow: none;
}

/* Mobile: 3 secciones apiladas vertical. Specificity (0,2,0) supera
   regla base .setlist-editor-layout (0,1,0) de setlists.css. */
.setlist-editor-layout.setlist-editor-layout-3sec {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    min-height: 0;
}
/* Override de setlists.css que forzaba .song-picker-panel { order: -1 }
   en mobile, lo cual ponía el picker primero en lugar de DOM order. */
.setlist-editor-layout.setlist-editor-layout-3sec .setlist-config-panel,
.setlist-editor-layout.setlist-editor-layout-3sec .song-picker-panel,
.setlist-editor-layout.setlist-editor-layout-3sec .setlist-builder-panel {
    order: 0;
}

/* Desktop ≥1025: 2 columnas. Izq (col 1) = Config + Songs Selected.
   Der (col 2) = Picker, alto completo abarcando ambas filas. */
@media (min-width: 1025px) {
    .setlist-editor-layout.setlist-editor-layout-3sec {
        display: grid;
        grid-template-columns: 1fr 380px;
        grid-template-rows: auto 1fr;
        gap: var(--space-5);
        align-items: stretch;
    }
    .setlist-editor-layout.setlist-editor-layout-3sec .setlist-config-panel {
        grid-column: 1;
        grid-row: 1;
    }
    .setlist-editor-layout.setlist-editor-layout-3sec .setlist-builder-panel {
        grid-column: 1;
        grid-row: 2;
        min-height: 400px;
    }
    .setlist-editor-layout.setlist-editor-layout-3sec .song-picker-panel {
        grid-column: 2;
        grid-row: 1 / span 2;
        align-self: stretch;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }
}

/* === Editor mobile: ocultar header inline (back+title+buttons),
   topbar global ya muestra back + title. Buttons van en fixed bottom. === */
@media (max-width: 820px) {
    .setlist-editor-header {
        display: none;
    }
}

/* Acciones flotantes mobile: cancelar centrada entre Inicio↔Canciones (~20% X),
   guardar centrada entre Calendario↔Más (~80% X). Por encima del bottom-nav. */
.setlist-editor-bottom-actions,
.song-editor-bottom-actions {
    display: contents;
}
.setlist-editor-bottom-cancel,
.setlist-editor-bottom-save,
.song-editor-bottom-cancel,
.song-editor-bottom-save {
    display: none;
}
.btn.song-editor-bottom-cancel,
.btn.song-editor-bottom-save {
    position: fixed;
    bottom: calc(var(--space-6) + var(--safe-area-bottom, 0px));
    z-index: calc(var(--z-fixed, 300) + 1);
    padding: var(--space-2) var(--space-5);
    min-height: 0;
    height: auto;
    min-width: 110px;
    justify-content: center;
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    line-height: 1.2;
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    box-shadow: var(--glass-shadow-md), var(--glass-edge-ring);
    color: #fff;
}
.btn.song-editor-bottom-cancel {
    left: var(--space-5);
    background: color-mix(in srgb, var(--color-danger) 92%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-danger) 92%, transparent);
}
.btn.song-editor-bottom-cancel:hover,
.btn.song-editor-bottom-cancel:active {
    background: var(--color-danger);
    border-color: var(--color-danger);
}
.btn.song-editor-bottom-save {
    right: var(--space-5);
    background: color-mix(in srgb, var(--color-primary) 92%, transparent);
    border: 1px solid color-mix(in srgb, var(--color-primary) 92%, transparent);
}
.btn.song-editor-bottom-save:hover,
.btn.song-editor-bottom-save:active {
    background: var(--color-primary);
    border-color: var(--color-primary);
}
@media (max-width: 820px) {
    /* Bloque legacy — solo padding-bottom extra al builder. Estilos de los
       botones se manejan arriba (regla scoped body.editor-mode + setlist-editor-*). */
    .setlist-songs-container,
    .song-picker-list,
    .song-editor-body,
    .song-editor-info-grid {
        padding-bottom: calc(var(--space-12, 56px) + var(--mobile-nav-height, 78px));
    }
}

/* Header picker — texto legible (override color: white de setlists.css 1110) */
.song-picker-header {
    background: transparent;
    color: var(--text-primary);
}
.song-picker-header > span:not(.section-number):not(.badge),
.song-picker-header > .setlist-builder-title,
.song-picker-header > .setlist-builder-title > span:not(.section-number):not(.badge) {
    color: var(--text-primary);
}
/* Iconos del header (excepto los del botón Mixear) en purple */
.song-picker-header > i,
.setlist-builder-header > i {
    color: var(--color-primary);
}
/* section-number siempre blanco sobre bg purple */
.section-number {
    color: #fff;
}
/* Icono dentro del botón Mixear: blanco */
.btn.btn-mix-songs,
.btn.btn-mix-songs i {
    color: #fff;
}

/* Label arriba del buscador: icono lupa + "Buscar canciones" */
.song-picker-search-label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4) 0 var(--space-4);
    color: var(--text-secondary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    font-family: var(--font-heading);
}
.song-picker-search-label i {
    color: var(--color-primary);
    font-size: var(--text-sm); /* 14px */
}

/* Fila de filtros: 70/30 search/tag */
.song-picker-filter-row {
    display: grid;
    grid-template-columns: 7fr 3fr;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
}

/* Lista y tag wrapper transparentes (estilos visuales de search/select
   ya unificados arriba con .setlist-config-fields input).
   Lista del picker: SIN scroll, max 3 resultados estáticos. */
.song-picker-list,
.song-picker-tags {
    background: transparent;
    border: none;
    box-shadow: none;
}
.song-picker-list {
    overflow: hidden;
    max-height: none;
}
.song-picker-filter-row .song-picker-tags {
    padding: 0;
}
.tag-filter-dropdown {
    width: 100%;
}

/* Inputs del quick-info y notas — transparentes con border sutil. Look limpio. */
.setlist-info-field input,
.setlist-info-field select,
.setlist-notes-section textarea {
    background: transparent;
    border: 1px solid var(--edge-soft);
    box-shadow: none;
    border-radius: var(--glass-radius-md);
}
.setlist-info-field input:focus,
.setlist-info-field select:focus,
.setlist-notes-section textarea:focus {
    background: transparent;
    border-color: var(--color-primary);
    box-shadow: none;
    outline: none;
}

/* Sin línea separadora entre header y body — look más limpio */
.dashboard-card .dashboard-card-header {
    border-bottom: none;
    padding: var(--space-3) var(--space-4) var(--space-2);
}

/* Sin separadores entre items de lista, sin highlight al tap */
.dashboard-card .dashboard-list-item {
    border-bottom: none;
    -webkit-tap-highlight-color: transparent;
}
.dashboard-card .dashboard-list-item:hover,
.dashboard-card .dashboard-list-item:active {
    background: transparent;
}
.dashboard-card,
.dashboard-card * {
    -webkit-tap-highlight-color: transparent;
}

/* Empty state plano — sin bg, sin blur, sin padding extra que forme bloque.
   Se integra al fondo del card como texto puro. */
.dashboard-card .dashboard-card-body {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 0 var(--space-4) var(--space-4);
}
.dashboard-card .dashboard-card-empty {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    border: none;
    padding: var(--space-3) 0;
}
.dashboard-card .dashboard-card-empty i {
    font-size: var(--text-base); /* 16px */
    opacity: 0.25;
    margin-bottom: var(--space-1);
}
.dashboard-card .dashboard-card-empty p {
    font-size: var(--font-size-xs);
    color: var(--text-muted);
    opacity: 0.6;
    margin: 0;
}
.dashboard-hero-label,
.dashboard-hero-date,
.dashboard-hero .text-muted {
    color: rgba(255, 255, 255, 0.85);
}

/* FAB universal (.fab-new-btn) — glass purple. Override de components.css
   bottom porque mi pill nav es 78px (no 60px del var legacy). */
.fab-new-btn {
    background: var(--grad-primary);
    border: none;
    box-shadow: var(--grad-primary-shadow);
    color: #fff;
    bottom: calc(78px + max(var(--safe-area-bottom), 4px) + 22px);
}
.fab-new-btn:hover {
    box-shadow: var(--grad-primary-shadow-hover);
}

/* FAB secundario (toggle vista u otras acciones) — apilado encima del + FAB */
.fab-secondary-btn {
    position: fixed;
    bottom: calc(78px + max(var(--safe-area-bottom), 4px) + 22px + 64px);
    right: 16px;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--surface-3);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    border: none;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: var(--glass-shadow-md), var(--glass-edge-ring), var(--glass-highlight);
    z-index: var(--z-fixed, 300);
    font-size: var(--text-base); /* 16px */
    transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), background 0.2s;
}
.fab-secondary-btn:hover { background: var(--surface-4); }
.fab-secondary-btn:active { transform: scale(0.92); }
@media (min-width: 821px) {
    .fab-secondary-btn.mobile-only { display: none; }
}

/* === Compact view canciones: container ya estilizado en bloque Nivel 2 arriba.
   Aquí solo agregamos propiedades exclusivas del compact list (gap, overflow). */
.songs-compact-view .song-list {
    gap: 0;
    overflow: hidden;
    border: 1px solid var(--edge-soft);
}
/* Filas dentro del compact list — sin bg propio ni backdrop-filter,
   comparten el bg + blur del container Nivel 2. */
.songs-compact-view .song-card-modern {
    grid-template-columns: 1fr auto;
    padding: 6px var(--space-3);
    gap: var(--space-2);
    background: transparent;
    border-radius: 0;
    box-shadow: none;
    border-bottom: 1px solid var(--edge-soft);
    transform: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
/* PC compact: layout row con main (título+autor) | center (key+bpm) | tags | edit
   Tags col 2fr (la más generosa) para que las chips entren sin cortarse. */
@media (min-width: 821px) {
    .songs-compact-view .song-card-modern {
        grid-template-columns: minmax(200px, 1.4fr) auto minmax(220px, 2fr) auto;
        align-items: center;
    }
    .songs-compact-view .song-card-modern .song-card-action {
        display: flex;
    }
}
.songs-compact-view .song-card-modern:last-child {
    border-bottom: none;
}
.songs-compact-view .song-card-modern:hover,
.songs-compact-view .song-card-modern:active,
.songs-compact-view .song-card-modern:focus {
    background: transparent;
    transform: none;
    box-shadow: none;
}
.songs-compact-view .song-card-modern .song-card-play-btn {
    width: 24px;
    height: 24px;
    min-width: 24px;
    flex-shrink: 0;
    padding: 0;
    border-radius: 50%;
}
.songs-compact-view .song-card-modern .song-card-play-btn svg {
    width: 10px;
    height: 10px;
}
.songs-compact-view .song-card-modern .song-card-main {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-3);
    min-width: 0;
    overflow: hidden;
}
.songs-compact-view .song-card-modern .song-card-info {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-2);
    min-width: 0;
    overflow: hidden;
    flex: 1;
}
.songs-compact-view .song-card-modern .song-card-title {
    font-size: var(--text-xs); /* 12px */
    font-weight: var(--font-weight-medium);
    margin: 0;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 1;
}
.songs-compact-view .song-card-modern .song-card-author {
    font-size: var(--text-xs); /* 10px */
    margin: 0;
    line-height: 1.25;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 2;
}
.songs-compact-view .song-card-modern .song-card-center {
    display: flex;
    align-items: center;
    justify-content: flex-end;
}
/* Compact view: ocultar action (botones edit/delete via grid) y ministers
   (keys preferidas por minister) — solo se muestra el tono original.
   .song-card-action se re-habilita más abajo en PC media query. */
.songs-compact-view .song-card-modern .song-card-action,
.songs-compact-view .song-card-modern .song-card-ministers {
    display: none;
}
/* Mobile compact: además ocultar BPM + tags para layout angosto. */
@media (max-width: 820px) {
    .songs-compact-view .song-card-modern .song-badge-bpm,
    .songs-compact-view .song-card-modern .song-card-tags-section {
        display: none;
    }
}
.songs-compact-view .song-card-modern .song-badge-key,
.songs-compact-view .song-card-modern .song-badge-bpm {
    font-size: var(--text-xs); /* 10px */
    padding: 2px 6px;
}

/* Desktop ≥821: compact view tres columnas en UNA fila —
   título | tags centrados | badges. Override de pages.css que ponía
   tags en row 2 a viewport ≤1200. */
@media (min-width: 821px) {
    .songs-compact-view .song-card-modern {
        display: grid;
        grid-template-columns: 1.6fr 1fr 1fr;
        grid-template-rows: auto;
        align-items: center;
        gap: var(--space-3);
    }
    .songs-compact-view .song-card-modern .song-card-main {
        grid-column: 1;
        grid-row: 1;
    }
    .songs-compact-view .song-card-modern .song-card-tags-section {
        display: flex;
        flex-wrap: nowrap;
        gap: var(--space-1);
        justify-content: center;
        align-items: center;
        grid-column: 2;
        grid-row: 1;
        overflow: hidden;
    }
    .songs-compact-view .song-card-modern .song-card-center {
        grid-column: 3;
        grid-row: 1;
        justify-self: end;
    }
    .songs-compact-view .song-card-modern .song-card-tags-section .song-tag {
        font-size: var(--text-xs); /* 10px */
        padding: 1px 6px;
    }
}

/* FAB con dropdown (.fab-dropdown) — wrapper fixed, menu se abre hacia arriba.
   z-index mayor que mobile-nav para no quedar tapado.
   bottom calcula para quedar bien arriba del pill (78px alto + safe-area + 22px gap). */
.fab-dropdown {
    position: fixed;
    bottom: calc(78px + max(var(--safe-area-bottom), 4px) + 22px);
    right: 16px;
    z-index: calc(var(--z-fixed, 300) + 5);
}
.fab-dropdown .fab-new-btn {
    position: static;
    display: flex;
}
.fab-dropdown .dropdown-menu {
    position: absolute;
    bottom: calc(100% + 10px);
    right: 0;
    top: auto;
    left: auto;
    min-width: 200px;
    transform-origin: bottom right;
}
@media (min-width: 821px) {
    .fab-dropdown.mobile-only { display: none; }
}

/* Loading screen glass */
.app-loading {
    background: var(--glass-body-bg);
}
.app-loading-content {
    background: var(--surface-3);
    backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    border: none;
    border-radius: var(--glass-radius-lg);
    padding: 32px 48px;
    box-shadow: var(--glass-shadow-lg), var(--glass-edge-ring), var(--glass-highlight);
}

/* Spinner */
.spinner {
    border-color: var(--surface-3);
    border-top-color: var(--purple-300);
}


/* =====================================================
   4. BOTTOM NAV + FAB CENTRO  (solo mobile ≤ 820px)
   ===================================================== */
@media (max-width: 820px) {
    /* Container fijo abajo. Padding mínimo lateral para max ancho útil.
       Bottom respeta home indicator iOS / gesture bar Android. */
    .mobile-nav {
        background: transparent;
        border-top: none;
        height: auto;
        padding: 0 8px max(var(--safe-area-bottom), 4px) 8px;
        pointer-events: none;
        /* z-fixed (300) < sidebar (400) — overlay ya no dim/blur. Mantener
           debajo del sidebar evita que el bot-nav aparezca encima durante
           la animación de cierre. */
        z-index: var(--z-fixed);
        overflow: visible;
    }

    /* Pill alto con respiración interior generosa.
       ::before crea bump curvado arriba en centro = parte del menú alrededor del FAB. */
    .mobile-nav-items {
        position: relative;
        background: rgba(255, 255, 255, 0.55);
        backdrop-filter: blur(24px) saturate(180%);
        -webkit-backdrop-filter: blur(24px) saturate(180%);
        border: none;
        border-radius: 28px;
        box-shadow:
            0 6px 20px rgba(76, 42, 133, 0.14),
            0 0 0 0.5px rgba(76, 42, 133, 0.08),
            inset 0 1px 0 rgba(255, 255, 255, 0.4);
        height: 78px;
        padding: 0 4px;
        pointer-events: auto;
        overflow: visible;
        align-items: stretch;
        display: flex;
        gap: 2px;
    }
    /* Bump del pill: círculo que extiende la pill hacia arriba, mismo bg.
       FAB se asienta sobre/dentro de este bump. */
    .mobile-nav-items::before {
        content: '';
        position: absolute;
        top: -22px;
        left: 50%;
        transform: translateX(-50%);
        width: 72px;
        height: 72px;
        border-radius: 50%;
        background: inherit;
        backdrop-filter: blur(24px) saturate(180%);
        -webkit-backdrop-filter: blur(24px) saturate(180%);
        box-shadow:
            0 -4px 12px rgba(76, 42, 133, 0.10),
            0 0 0 0.5px rgba(76, 42, 133, 0.08);
        z-index: 0;
        pointer-events: none;
    }

    [data-theme="dark"] .mobile-nav-items {
        background: rgba(75, 65, 110, 0.32);
        border: none;
        box-shadow:
            0 6px 20px rgba(0, 0, 0, 0.32),
            0 0 0 0.5px rgba(255, 255, 255, 0.10),
            inset 0 1px 0 rgba(255, 255, 255, 0.12);
    }
    [data-theme="dark"] .mobile-nav-items::before {
        background: rgba(75, 65, 110, 0.32);
        box-shadow:
            0 -4px 12px rgba(0, 0, 0, 0.25),
            0 0 0 0.5px rgba(255, 255, 255, 0.10);
    }

    /* Item: position relative para icon/label absolutos.
       Sin z-index propio para que el halo del FAB no quede clippeado.
       transform smooth para press feedback tipo botón (scale, no slide). */
    .mobile-nav-item {
        flex: 1 1 0;
        min-width: 0;
        height: 100%;
        position: relative;
        display: block;
        text-align: center;
        color: rgba(40, 40, 60, 0.55);
        font-size: var(--text-xs); /* 10px */
        font-weight: var(--font-weight-medium);
        letter-spacing: -0.01em;
        text-decoration: none;
        transition: color 0.2s ease,
                    transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
        touch-action: manipulation;
        cursor: pointer;
        white-space: nowrap;
        transform-origin: center;
    }
    .mobile-nav-item:active {
        transform: scale(0.92);
    }
    [data-theme="dark"] .mobile-nav-item { color: rgba(255, 255, 255, 0.55); }

    /* Iconos posicionados a 16px del top (mismo nivel para todos los items normales).
       Sin transform en :active del svg — el item entero hace el press scale. */
    .mobile-nav-item svg {
        position: absolute;
        top: 16px;
        left: 50%;
        transform: translateX(-50%);
        width: 22px;
        height: 22px;
    }

    /* Labels posicionados a 12px del bottom (mismo nivel para TODOS los items, incluyendo FAB) */
    .mobile-nav-item span {
        position: absolute;
        bottom: 12px;
        left: 0;
        right: 0;
        font-size: var(--text-xs); /* 10px */
        line-height: 1;
        opacity: 1;
        padding: 0 2px;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .mobile-nav-item.active span { font-weight: var(--font-weight-semibold); }

    .mobile-nav-item.active { color: var(--color-primary); }

    /* FAB centro: SVG y span se posicionan relativos a .mobile-nav-items
       (no al item) para garantizar centrado exacto en el pill. */
    .mobile-nav-item:nth-child(3) {
        flex: 0 0 auto;
        width: 68px;
        position: static;
    }
    /* FAB body — div wrapper circular con bg gradient y halo.
       SVG dentro del wrapper solo renderiza el icono, sin estilos.
       Box-shadow en div (no en svg) para que respete border-radius circular. */
    .mobile-nav-fab {
        position: absolute;
        top: -12px;
        left: 50%;
        transform: translateX(-50%);
        width: 52px;
        height: 52px;
        border-radius: 50%;
        background: var(--grad-primary);
        box-shadow:
            0 8px 22px rgba(124, 77, 255, 0.45),
            0 0 28px rgba(167, 139, 250, 0.35);
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 2;
        transition: transform 0.2s ease, box-shadow 0.25s ease;
    }
    .mobile-nav-fab svg {
        width: 24px;
        height: 24px;
    }
    [data-theme="dark"] .mobile-nav-fab {
        box-shadow:
            0 8px 22px rgba(124, 77, 255, 0.55),
            0 0 32px rgba(167, 139, 250, 0.40);
    }
    /* No transform :active aquí — el item parent ya escala (heredan descendientes) */
    .mobile-nav-item:nth-child(3).active .mobile-nav-fab {
        box-shadow:
            0 10px 26px rgba(124, 77, 255, 0.6),
            0 0 36px rgba(167, 139, 250, 0.5);
    }
    /* FAB span: hereda color del item normal (text-secondary). Active = primary. */
    .mobile-nav-item:nth-child(3) span {
        position: absolute;
        bottom: 12px;
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        color: inherit;
        font-weight: var(--font-weight-medium);
        text-align: center;
        padding: 0;
    }
    .mobile-nav-item:nth-child(3).active span {
        color: var(--color-primary);
        font-weight: var(--font-weight-semibold);
    }

    /* Padding inferior: nav 78px + safe-area + margen */
    .main,
    .app-content > .main {
        padding-bottom: calc(102px + var(--safe-area-bottom));
    }
}


/* =====================================================
   MORE PAGE — diseño limpio profesional
   Override de pages.css para look glass + ordenado
   ===================================================== */
.more-page {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
}

.more-page .more-section {
    margin: 0;
    padding: var(--space-4) var(--space-3) var(--space-3) var(--space-3);
    background: var(--surface-2);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    border: none;
    border-radius: var(--glass-radius-lg);
    box-shadow: var(--glass-shadow-sm), var(--glass-edge-ring), var(--glass-highlight);
}

.more-page .more-section-title {
    font-size: var(--text-xs); /* 11px */
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin: 0 0 var(--space-3) var(--space-2);
    padding: 0;
}

.more-page .more-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-2);
    background: transparent;
    padding: 0;
    border-radius: 0;
}

.more-page .more-grid-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-1);
    border-radius: var(--glass-radius-md);
    background: transparent;
    border: none;
    text-decoration: none;
    transition: background 0.2s ease, transform 0.15s ease;
}

.more-page .more-grid-item:hover {
    background: var(--surface-1);
}

.more-page .more-grid-item:active {
    background: var(--surface-3);
    transform: scale(0.96);
}

.more-page .more-grid-icon {
    width: 48px;
    height: 48px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-xl); /* 20px */
    flex-shrink: 0;
}

.more-page .more-grid-item span {
    font-size: var(--text-xs); /* 11px */
    font-weight: var(--font-weight-medium);
    color: var(--text-primary);
    text-align: center;
    line-height: 1.25;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 380px) {
    .more-page .more-grid { grid-template-columns: repeat(3, 1fr); }
    .more-page .more-grid-icon { width: 44px; height: 44px; font-size: var(--text-lg); /* 18px */ }
}


/* =====================================================
   5. LOGIN — dark navy minimal con blobs (mobile ≤ 820px)
   ===================================================== */
@media (max-width: 820px) {
    .login-page {
        background:
            radial-gradient(ellipse 60% 50% at 15% 15%, rgba(124, 77, 255, 0.6) 0%, transparent 55%),
            radial-gradient(ellipse 50% 45% at 85% 85%, rgba(236, 72, 153, 0.45) 0%, transparent 55%),
            radial-gradient(ellipse 45% 40% at 50% 50%, rgba(59, 130, 246, 0.4) 0%, transparent 60%),
            linear-gradient(180deg, #0a0618 0%, #14092e 50%, #1d0f3d 100%);
        min-height: 100vh;
        min-height: 100dvh;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 24px;
    }

    .login-card {
        background: var(--surface-3);
        backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
        -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
        box-shadow: var(--glass-shadow-xl), var(--glass-edge-ring-strong), var(--glass-highlight);
        border: none;
        border-radius: var(--glass-radius-lg);
        max-width: 360px;
        width: 100%;
        padding: 36px 28px;
    }

    .login-logo {
        margin-bottom: 24px;
        display: flex;
        justify-content: center;
    }
    .login-logo-icon {
        width: 64px;
        height: 64px;
        border-radius: 0;
        background: transparent;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border: none;
        box-shadow: none;
        color: var(--purple-200);
        display: flex;
        align-items: center;
        justify-content: center;
        filter: drop-shadow(0 8px 22px rgba(124, 77, 255, 0.4));
    }
    .login-logo-icon svg { width: 44px; height: 44px; }
    .login-logo-img {
        width: 100%;
        height: 100%;
        object-fit: contain;
        border-radius: 0;
        background: transparent;
        display: block;
    }

    .login-title { text-align: center; margin-bottom: 32px; }
    .login-title h1 {
        color: var(--text-primary);
        font-size: var(--text-3xl); /* 26px */
        font-weight: var(--font-weight-semibold);
        letter-spacing: var(--letter-spacing-tight);
        margin: 0 0 6px 0;
    }
    .login-title p {
        color: var(--text-secondary);
        font-size: var(--text-xs); /* 13px */
        margin: 0;
    }

    .login-form { gap: 14px; }
    .login-form .input-group { margin-bottom: 0; position: relative; }
    .login-form label {
        display: block;
        color: rgba(255, 255, 255, 0.7);
        font-size: 11px;
        font-weight: 600;
        letter-spacing: 0.5px;
        margin-bottom: 6px;
        text-transform: uppercase;
    }
    /* Inputs glass dark — matchea pages.css desktop pero compactos en mobile */
    .login-form input[type="text"],
    .login-form input[type="password"] {
        background: rgba(255, 255, 255, 0.06);
        border: 1px solid rgba(255, 255, 255, 0.14);
        border-radius: 12px;
        padding: 0 14px;
        height: 46px;
        color: #fff;
        font-size: 15px;
        font-family: inherit;
        width: 100%;
        box-sizing: border-box;
        outline: none;
        box-shadow: none;
        transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
    }
    .login-form input[type="text"]:focus,
    .login-form input[type="password"]:focus {
        border-color: rgba(167, 139, 250, 0.75);
        background: rgba(255, 255, 255, 0.09);
        box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.2);
    }
    .login-form input::placeholder { color: rgba(255, 255, 255, 0.3); }
    .login-form .btn {
        margin-top: 12px;
        height: 48px;
        background: linear-gradient(135deg, #a78bfa 0%, #7c4dff 100%);
        border: none;
        border-radius: 12px;
        color: #fff;
        font-size: 15px;
        font-weight: 600;
        letter-spacing: 0.3px;
        box-shadow:
            0 12px 26px rgba(124, 77, 255, 0.4),
            inset 0 1px 0 rgba(255, 255, 255, 0.25);
    }
}


/* =====================================================
   6. UTILIDADES GLASS REUTILIZABLES
   ===================================================== */
.glass-surface {
    background: var(--surface-2);
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
    border: none;
    border-radius: var(--glass-radius-md);
    box-shadow: var(--glass-shadow-md), var(--glass-edge-ring), var(--glass-highlight);
}

.glass-surface-strong {
    background: var(--surface-3);
    backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
    border: none;
    border-radius: var(--glass-radius-lg);
    box-shadow: var(--glass-shadow-lg), var(--glass-edge-ring-strong), var(--glass-highlight-strong);
}


/* =====================================================
   7. REDUCED MOTION
   ===================================================== */
@media (prefers-reduced-motion: reduce) {
    .card, .song-card, .setlist-card, .minister-card,
    .more-grid-item, .filter-tab, .sidebar-nav-item,
    .mobile-nav-item, .mobile-nav-item svg,
    .btn-primary, .btn-secondary, .btn-outline, .btn-ghost,
    input, select, textarea {
        transition: none;
    }
    .card:hover, .song-card:hover, .setlist-card:hover,
    .minister-card:hover, .more-grid-item:hover,
    .btn-primary:hover {
        transform: none;
    }
}

/* ============================================
   SETLIST EDITOR - DARK MODE CONTRAST FIX
   --color-primary-light (rgba 18%) + --color-primary (purple-300) =
   contraste pobre en dark. Override con primary más opaco + texto white.
   ============================================ */
[data-theme="dark"] .setlist-song-row .song-number,
[data-theme="dark"] .editable-song-item .song-number {
    background-color: color-mix(in srgb, var(--color-primary) 65%, transparent);
    color: white;
}

[data-theme="dark"] .setlist-song-row .song-key-select,
[data-theme="dark"] .editable-song-item .song-key-select {
    background: color-mix(in srgb, var(--color-primary) 65%, transparent);
    color: white;
    border-color: color-mix(in srgb, var(--color-primary) 50%, transparent);
}

[data-theme="dark"] .btn-add-verse {
    background: color-mix(in srgb, var(--purple-400) 25%, transparent);
    border-color: color-mix(in srgb, var(--purple-400) 55%, transparent);
    color: var(--purple-200);
}
[data-theme="dark"] .setlist-song-row.has-verses .btn-add-verse {
    background: var(--purple-400);
    border-color: var(--purple-400);
    color: white;
}
