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

button,
a {
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}

/* Thème adaptatif : valeurs "light" par défaut dans :root, override
   automatique via @media (prefers-color-scheme: dark), et override manuel
   explicite (persisté en localStorage, voir theme.js) via l'attribut
   data-theme sur <html> — qui gagne dans les deux sens grâce à sa
   spécificité plus élevée que :root seul, qu'il soit dans la media query
   ou non. Les blocs light/dark sont donc dupliqués une fois chacun : c'est
   le prix du pattern en CSS pur, sans préprocesseur. */
:root {
    /* Light (par défaut / fallback) */
    --bg: #F2F0EB;
    --surface: rgba(255, 255, 255, 0.7);
    --surface-strong: rgba(255, 255, 255, 0.85);
    --chrome-bg: rgba(242, 240, 235, 0.85);
    --border: rgba(0, 0, 0, 0.08);
    --border-strong: rgba(0, 0, 0, 0.16);
    --blur: 20px;
    --accent: #B8924A;
    --accent-dim: rgba(184, 146, 74, 0.14);
    --accent-glass: rgba(184, 146, 74, 0.12);
    --accent-border: rgba(184, 146, 74, 0.4);
    --text: #1A1A1A;
    --muted: #6B6760;
    --muted-faint: rgba(26, 26, 26, 0.35);
    --error: #D6453F;
    --error-bg: rgba(214, 69, 63, 0.08);
    --error-border: rgba(214, 69, 63, 0.35);
    --success: #2E9B5C;
    --success-border: rgba(46, 155, 92, 0.35);
    --warning: #A6701A;
    --warning-border: rgba(166, 112, 26, 0.35);
    --toast-bg: rgba(255, 255, 255, 0.85);
    --skeleton-base: rgba(0, 0, 0, 0.05);
    --skeleton-shine: rgba(0, 0, 0, 0.1);

    /* Spring = personnalité (boutons, pill, sheet) ; smooth = le standard
       Material/Apple pour tout le reste (fades, couleurs, layout). */
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
    --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0A0A0B;
        --surface: rgba(255, 255, 255, 0.06);
        --surface-strong: rgba(255, 255, 255, 0.1);
        --chrome-bg: rgba(10, 10, 11, 0.85);
        --border: rgba(255, 255, 255, 0.08);
        --border-strong: rgba(255, 255, 255, 0.14);
        --accent: #C8A96E;
        --accent-dim: rgba(200, 169, 110, 0.14);
        --accent-glass: rgba(200, 169, 110, 0.12);
        --accent-border: rgba(200, 169, 110, 0.4);
        --text: #F0EDE8;
        --muted: #6B6760;
        --muted-faint: rgba(240, 237, 232, 0.35);
        --error: #FF6B6B;
        --error-bg: rgba(255, 107, 107, 0.1);
        --error-border: rgba(255, 107, 107, 0.35);
        --success: #63D48A;
        --success-border: rgba(99, 212, 138, 0.45);
        --warning: #E8B04B;
        --warning-border: rgba(232, 176, 75, 0.35);
        --toast-bg: rgba(20, 19, 21, 0.85);
        --skeleton-base: rgba(255, 255, 255, 0.04);
        --skeleton-shine: rgba(255, 255, 255, 0.1);
    }
}

:root[data-theme="light"] {
    --bg: #F2F0EB;
    --surface: rgba(255, 255, 255, 0.7);
    --surface-strong: rgba(255, 255, 255, 0.85);
    --chrome-bg: rgba(242, 240, 235, 0.85);
    --border: rgba(0, 0, 0, 0.08);
    --border-strong: rgba(0, 0, 0, 0.16);
    --accent: #B8924A;
    --accent-dim: rgba(184, 146, 74, 0.14);
    --accent-glass: rgba(184, 146, 74, 0.12);
    --accent-border: rgba(184, 146, 74, 0.4);
    --text: #1A1A1A;
    --muted: #6B6760;
    --muted-faint: rgba(26, 26, 26, 0.35);
    --error: #D6453F;
    --error-bg: rgba(214, 69, 63, 0.08);
    --error-border: rgba(214, 69, 63, 0.35);
    --success: #2E9B5C;
    --success-border: rgba(46, 155, 92, 0.35);
    --warning: #A6701A;
    --warning-border: rgba(166, 112, 26, 0.35);
    --toast-bg: rgba(255, 255, 255, 0.85);
    --skeleton-base: rgba(0, 0, 0, 0.05);
    --skeleton-shine: rgba(0, 0, 0, 0.1);
}

:root[data-theme="dark"] {
    --bg: #0A0A0B;
    --surface: rgba(255, 255, 255, 0.06);
    --surface-strong: rgba(255, 255, 255, 0.1);
    --chrome-bg: rgba(10, 10, 11, 0.85);
    --border: rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.14);
    --accent: #C8A96E;
    --accent-dim: rgba(200, 169, 110, 0.14);
    --accent-glass: rgba(200, 169, 110, 0.12);
    --accent-border: rgba(200, 169, 110, 0.4);
    --text: #F0EDE8;
    --muted: #6B6760;
    --muted-faint: rgba(240, 237, 232, 0.35);
    --error: #FF6B6B;
    --error-bg: rgba(255, 107, 107, 0.1);
    --error-border: rgba(255, 107, 107, 0.35);
    --success: #63D48A;
    --success-border: rgba(99, 212, 138, 0.45);
    --warning: #E8B04B;
    --warning-border: rgba(232, 176, 75, 0.35);
    --toast-bg: rgba(20, 19, 21, 0.85);
    --skeleton-base: rgba(255, 255, 255, 0.04);
    --skeleton-shine: rgba(255, 255, 255, 0.1);
}

html,
body {
    transition: background-color 0.3s ease, color 0.3s ease;
}

html,
body {
    background: var(--bg);
    color: var(--text);
    font-family: 'Inter', sans-serif;
    font-size: 15px;
    /* Empêche le rebond élastique / pull-to-refresh natif iOS & Android : un
       seul conteneur scrollable (#view-container / #auth-screen) gère le scroll. */
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: 100vw;
    overflow: hidden;
    overscroll-behavior: none;
}

/* Auth */
#auth-screen {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    padding: calc(32px + env(safe-area-inset-top)) calc(24px + env(safe-area-inset-right)) calc(32px + env(safe-area-inset-bottom)) calc(24px + env(safe-area-inset-left));
    gap: 32px;
}

.logo {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}

.vinyl {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: conic-gradient(#141416 0deg, #1e1e21 10deg, #141416 20deg, #1e1e21 30deg,
            #141416 40deg, #1e1e21 50deg, #141416 60deg, #1e1e21 70deg,
            #141416 80deg, #1e1e21 90deg, #141416 100deg, #1e1e21 110deg,
            #141416 120deg, #1e1e21 130deg, #141416 140deg, #1e1e21 150deg,
            #141416 160deg, #1e1e21 170deg, #141416 180deg, #1e1e21 190deg,
            #141416 200deg, #1e1e21 210deg, #141416 220deg, #1e1e21 230deg,
            #141416 240deg, #1e1e21 250deg, #141416 260deg, #1e1e21 270deg,
            #141416 280deg, #1e1e21 290deg, #141416 300deg, #1e1e21 310deg,
            #141416 320deg, #1e1e21 330deg, #141416 340deg, #1e1e21 350deg, #141416 360deg);
    box-shadow: 0 0 0 3px var(--accent), 0 8px 28px rgba(200, 169, 110, 0.25);
    position: relative;
}

.vinyl::after {
    content: '';
    position: absolute;
    inset: 50%;
    transform: translate(-50%, -50%);
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--accent);
}

.logo h1 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.6px;
}

.logo p {
    color: var(--muted);
    font-size: 13px;
}

.auth-form {
    width: 100%;
    max-width: 360px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

input[type="password"],
input[type="text"],
input[type="url"],
input[type="number"],
input[type="search"],
select {
    width: 100%;
    background: var(--surface);
    backdrop-filter: blur(var(--blur));
    -webkit-backdrop-filter: blur(var(--blur));
    border: 1px solid var(--border);
    border-radius: 12px;
    color: var(--text);
    font-family: 'Inter', sans-serif;
    /* iOS zoome automatiquement au focus sur tout input < 16px — jamais en dessous. */
    font-size: 16px;
    padding: 14px 16px;
    outline: none;
    transition: border-color 0.25s var(--ease-smooth), background 0.25s var(--ease-smooth);
}

input:focus,
select:focus {
    border-color: var(--accent-border);
    background: var(--surface-strong);
}

/* Placeholder forcé ("-- Choisir une playlist --") : grisé tant qu'aucun
   choix explicite n'a été fait, texte normal une fois une vraie valeur
   sélectionnée. */
select:required:invalid {
    color: var(--muted);
}

input::placeholder {
    color: var(--muted-faint);
}

.btn {
    width: 100%;
    background: var(--accent);
    border: none;
    border-radius: 12px;
    color: #0A0A0B;
    cursor: pointer;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 15px;
    font-weight: 600;
    padding: 14px;
    transition: transform 0.3s var(--ease-spring), opacity 0.2s ease;
}

.btn:active {
    transform: scale(0.94);
    opacity: 0.9;
}

.btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.btn-sm {
    width: auto;
    padding: 9px 16px;
    font-size: 13px;
    background: var(--surface-strong);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    color: var(--text);
    cursor: pointer;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    flex-shrink: 0;
    backdrop-filter: blur(var(--blur));
    -webkit-backdrop-filter: blur(var(--blur));
    transition: transform 0.3s var(--ease-spring), background 0.2s ease;
}

.btn-sm:active {
    transform: scale(0.94);
    background: var(--surface);
}

.btn-outline {
    width: auto;
    background: transparent;
    border: 1px solid var(--border-strong);
    color: var(--text);
    border-radius: 10px;
    padding: 9px 16px;
    font-size: 13px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    cursor: pointer;
    flex-shrink: 0;
    transition: transform 0.3s var(--ease-spring), border-color 0.2s ease;
}

.btn-outline:active {
    transform: scale(0.94);
    border-color: var(--accent-border);
}

.btn-danger {
    background: transparent;
    border: 1px solid var(--error);
    color: var(--error);
    border-radius: 8px;
    padding: 6px 10px;
    font-size: 12px;
    cursor: pointer;
    flex-shrink: 0;
    transition: transform 0.3s var(--ease-spring);
}

.btn-danger:active {
    transform: scale(0.9);
}

.error-msg {
    color: var(--error);
    font-size: 13px;
    text-align: center;
}

/* App shell */
#app {
    display: none;
    height: 100%;
    flex-direction: column;
}

#app.visible {
    display: flex;
}

header {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex-shrink: 0;
    padding: calc(16px + env(safe-area-inset-top)) calc(20px + env(safe-area-inset-right)) 18px calc(20px + env(safe-area-inset-left));
    background: var(--chrome-bg);
    backdrop-filter: blur(var(--blur)) saturate(1.5);
    -webkit-backdrop-filter: blur(var(--blur)) saturate(1.5);
    border-bottom: 1px solid var(--border);
}

.header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

header .vinyl-sm {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: conic-gradient(#141416 0deg, #1e1e21 15deg, #141416 30deg, #1e1e21 45deg,
            #141416 60deg, #1e1e21 75deg, #141416 90deg, #1e1e21 105deg,
            #141416 120deg, #1e1e21 135deg, #141416 150deg, #1e1e21 165deg,
            #141416 180deg, #1e1e21 195deg, #141416 210deg, #1e1e21 225deg,
            #141416 240deg, #1e1e21 255deg, #141416 270deg, #1e1e21 285deg,
            #141416 300deg, #1e1e21 315deg, #141416 330deg, #1e1e21 345deg, #141416 360deg);
    box-shadow: 0 0 0 2px var(--accent);
    position: relative;
    flex-shrink: 0;
}

header .vinyl-sm::after {
    content: '';
    position: absolute;
    inset: 50%;
    transform: translate(-50%, -50%);
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
}

.view-title {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 28px;
    font-weight: 700;
    letter-spacing: -0.6px;
    /* 0.3s pour que le changement de texte (nav.js, à 150ms) tombe
       exactement à mi-chemin du fondu, quand l'opacité est ~0. */
    transition: opacity 0.3s var(--ease-smooth);
}

.header-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

.theme-toggle {
    background: var(--surface);
    backdrop-filter: blur(var(--blur));
    -webkit-backdrop-filter: blur(var(--blur));
    border: 1px solid var(--border);
    border-radius: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    transition: transform 0.3s var(--ease-spring), background 0.25s var(--ease-smooth);
}

.theme-toggle:active {
    transform: scale(0.88) rotate(-12deg);
    background: var(--surface-strong);
}

.logout-btn {
    background: none;
    border: none;
    color: var(--muted);
    cursor: pointer;
    font-size: 13px;
    padding: 4px 8px;
    transition: opacity 0.2s ease;
}

.logout-btn:active {
    opacity: 0.5;
}

/* Vues (onglets) */
#view-container {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
}

.view {
    display: none;
    padding-bottom: 24px;
}

.view.active {
    display: block;
}

/* Transition séquentielle (pas simultanée) : la vue sortante s'estompe
   entièrement (.leaving) avant que la vue entrante ne commence son propre
   fondu (.entering) — voir nav.js switchView(). */
.view.entering {
    animation: view-in 0.3s var(--ease-smooth);
}

.view.leaving {
    animation: view-out 0.15s var(--ease-smooth) forwards;
}

@keyframes view-in {
    from {
        opacity: 0;
        transform: translateY(14px) scale(0.985);
    }

    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

@keyframes view-out {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

.tab-bar {
    position: relative;
    flex-shrink: 0;
    display: flex;
    /* 49px = hauteur standard d'une tab bar iOS (HIG), la safe-area vient
       s'ajouter EN PLUS pour le home indicator — jamais de valeur fixe
       supplémentaire mélangée dedans, iOS gère déjà cet espace. */
    height: calc(49px + env(safe-area-inset-bottom));
    padding: 0 calc(10px + env(safe-area-inset-right)) env(safe-area-inset-bottom) calc(10px + env(safe-area-inset-left));
    background: var(--chrome-bg);
    backdrop-filter: blur(var(--blur)) saturate(1.6);
    -webkit-backdrop-filter: blur(var(--blur)) saturate(1.6);
    border-top: 1px solid var(--border);
    transition: transform 0.25s var(--ease-smooth), opacity 0.2s var(--ease-smooth);
}

/* Mode recherche actif (focus sur #search-input) : la tab bar s'efface
   temporairement, pattern "recherche plein écran" façon Musique/Contacts iOS. */
#app.search-focused .tab-bar {
    transform: translateY(100%);
    opacity: 0;
    pointer-events: none;
}

.tab-pill {
    position: absolute;
    top: 6px;
    bottom: calc(6px + env(safe-area-inset-bottom));
    left: 10px;
    width: 0;
    background: var(--accent-glass);
    border: 1px solid var(--accent-border);
    border-radius: 16px;
    transition: transform 0.45s var(--ease-spring), width 0.45s var(--ease-spring);
    pointer-events: none;
    z-index: 0;
}

.tab-btn {
    position: relative;
    z-index: 1;
    flex: 1;
    background: none;
    border: none;
    color: var(--muted);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    cursor: pointer;
    font-family: 'Inter', sans-serif;
    font-size: 11px;
    font-weight: 500;
    transition: color 0.25s var(--ease-smooth), transform 0.3s var(--ease-spring);
}

.tab-btn:active {
    transform: scale(0.92);
}

.tab-btn .tab-icon {
    font-size: 19px;
    line-height: 1;
}

.tab-btn.active {
    color: var(--accent);
}

section {
    padding: 0 calc(20px + env(safe-area-inset-right)) 0 calc(20px + env(safe-area-inset-left));
    margin-bottom: 32px;
}

section:first-child {
    padding-top: 20px;
}

.section-title {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 12px;
}

/* Réduit l'espace uniquement quand une description suit (sections "Ajouter") */
.section-title:has(+ .section-desc) {
    margin-bottom: 4px;
}

.section-desc {
    font-size: 13px;
    color: var(--muted);
    margin-bottom: 12px;
}

.search-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 48px 20px;
    color: var(--muted);
    text-align: center;
    font-size: 14px;
}

.search-empty-icon {
    font-size: 36px;
    opacity: 0.6;
}

.card,
.search-result,
.job-item,
.watch-item,
.playlist-card,
.stats-bar,
.upload-drop,
.skeleton-card {
    background: var(--surface);
    backdrop-filter: blur(var(--blur)) saturate(1.4);
    -webkit-backdrop-filter: blur(var(--blur)) saturate(1.4);
    border: 1px solid var(--border);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
}

.card {
    border-radius: 18px;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.url-row {
    display: flex;
    gap: 8px;
}

.url-row input {
    flex: 1;
}

.url-row .btn {
    width: auto;
    padding: 14px 18px;
    flex-shrink: 0;
    border-radius: 12px;
}

.playlist-row {
    display: flex;
    gap: 8px;
}

.playlist-row select {
    flex: 1;
}

.new-playlist-input {
    display: none;
    flex: 1;
}

/* Bandeau d'erreur (ex. Navidrome injoignable) */
.banner-error {
    display: none;
    background: var(--error-bg);
    backdrop-filter: blur(var(--blur));
    -webkit-backdrop-filter: blur(var(--blur));
    border: 1px solid var(--error-border);
    color: var(--error);
    border-radius: 14px;
    padding: 12px 14px;
    font-size: 13px;
    margin-bottom: 16px;
}

.banner-error.show {
    display: block;
}

/* Recherche YouTube */
.search-form {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
}

.search-form input {
    flex: 1;
    min-width: 0;
}

#search-input {
    transition: flex 0.2s ease;
}

#search-input:focus {
    flex: 1;
}

#search-submit-btn {
    flex-shrink: 0;
    max-width: 140px;
    overflow: hidden;
    opacity: 1;
    transition: max-width 0.25s ease, opacity 0.2s ease, padding 0.25s ease, margin 0.25s ease;
}

/* Bouton "Annuler" façon Musique/Contacts iOS : caché par défaut (largeur 0,
   transition sur max-width plutôt que width:auto qui ne s'anime pas), révélé
   quand le champ de recherche est actif — remplace "Chercher" dans l'espace
   ainsi libéré par l'input qui s'étend. */
.search-cancel-btn {
    flex-shrink: 0;
    max-width: 0;
    padding: 9px 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    background: none;
    border: none;
    color: var(--accent);
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 15px;
    cursor: pointer;
    transition: max-width 0.25s ease, opacity 0.2s ease, padding 0.25s ease;
}

#app.search-focused #search-submit-btn {
    max-width: 0;
    opacity: 0;
    padding: 0;
    margin: 0;
    pointer-events: none;
}

#app.search-focused .search-cancel-btn {
    max-width: 100px;
    opacity: 1;
    padding: 9px 2px 9px 8px;
}

.search-results {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.search-result {
    border-radius: 18px;
    overflow: hidden;
    transition: transform 0.3s var(--ease-spring);
}

.search-card {
    padding: 12px;
    display: flex;
    gap: 14px;
}

.search-thumb {
    width: 108px;
    height: 108px;
    object-fit: cover;
    border-radius: 14px;
    flex-shrink: 0;
    background: var(--surface-strong);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
}

.search-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 2px 0;
}

.search-title {
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.search-meta {
    font-size: 12px;
    color: var(--muted);
}

.search-actions {
    display: flex;
    gap: 6px;
    margin-top: auto;
    padding-top: 6px;
}

.search-preview {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    border-top: 1px solid var(--border);
}

.search-preview iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Apparition en stagger des listes — chaque item reçoit un animation-delay
   croissant (30ms) posé en inline style par le JS de rendu. */
@keyframes stagger-in {
    from {
        opacity: 0;
        transform: translateY(8px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.job-item,
.watch-item,
.playlist-card,
.search-result,
.modal-playlist-option {
    animation: stagger-in 0.35s var(--ease-smooth) backwards;
}

/* Skeleton générique pour les listes compactes (jobs/watches/playlists) —
   .skeleton-card reste dédié aux résultats de recherche (miniature + lignes). */
.skeleton-row {
    height: 60px;
    border-radius: 16px;
    border: 1px solid var(--border);
    background: linear-gradient(100deg,
            var(--skeleton-base) 30%,
            var(--skeleton-shine) 50%,
            var(--skeleton-base) 70%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.6s ease-in-out infinite;
}

/* Skeleton loaders */
.skeleton-card {
    border-radius: 18px;
    padding: 12px;
    display: flex;
    gap: 14px;
}

.skeleton-thumb {
    width: 108px;
    height: 108px;
    border-radius: 14px;
    flex-shrink: 0;
}

.skeleton-lines {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 4px 0;
}

.skeleton-block {
    border-radius: 6px;
    background: linear-gradient(100deg,
            var(--skeleton-base) 30%,
            var(--skeleton-shine) 50%,
            var(--skeleton-base) 70%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.6s ease-in-out infinite;
}

@keyframes skeleton-shimmer {
    0% {
        background-position: 200% 0;
    }

    100% {
        background-position: -200% 0;
    }
}

/* Import audio */
.upload-drop {
    min-height: 180px;
    border-radius: 20px;
    border-style: dashed;
    border-width: 2px;
    border-color: var(--border-strong);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 24px 16px;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.3s var(--ease-smooth), background 0.3s var(--ease-smooth), transform 0.3s var(--ease-spring);
}

@media (hover: hover) {
    .upload-drop:hover {
        border-color: var(--accent-border);
        background: var(--surface);
    }
}

.upload-drop-icon {
    font-size: 34px;
    margin-bottom: 6px;
    opacity: 0.85;
    transition: transform 0.3s var(--ease-spring);
}

.upload-drop-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
}

.upload-drop-subtitle {
    font-size: 13px;
    color: var(--muted);
}

/* État drag-over : bordure pleine accent, fond teinté, léger zoom —
   feedback immédiat que le drop est accepté ici. */
.upload-drop.dragover {
    border-style: solid;
    border-color: var(--accent);
    background: var(--accent-glass);
    transform: scale(1.02);
}

.upload-drop.dragover .upload-drop-icon {
    transform: translateY(-4px) scale(1.1);
}

.upload-formats {
    margin-top: 10px;
    font-size: 11px;
    color: var(--muted-faint);
    text-align: center;
    letter-spacing: 0.3px;
}

.upload-drop input[type="file"] {
    display: none;
}

/* Barre de progression d'import — remplace icône/titre/sous-titre pendant
   l'upload, la zone est désactivée pour éviter une nouvelle sélection en
   cours de traitement. */
.upload-progress {
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
}

.upload-drop.uploading {
    pointer-events: none;
    opacity: 0.7;
}

.upload-drop.uploading .upload-drop-icon,
.upload-drop.uploading .upload-drop-title,
.upload-drop.uploading .upload-drop-subtitle {
    display: none;
}

.upload-drop.uploading .upload-progress {
    display: flex;
}

.upload-progress-track {
    width: 100%;
    height: 4px;
    border-radius: 2px;
    background: var(--border);
    overflow: hidden;
}

.upload-progress-bar {
    height: 4px;
    border-radius: 2px;
    background: var(--accent);
    transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    width: 0%;
}

.upload-progress-text {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}

.upload-progress-file {
    font-size: 12px;
    color: var(--muted);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.upload-progress-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.upload-progress-errors {
    color: var(--error);
    font-weight: 600;
}

/* pointer-events:none sur .upload-drop.uploading désactiverait aussi ce
   bouton s'il n'annulait pas explicitement l'héritage ici. */
.upload-progress-cancel {
    pointer-events: auto;
    flex-shrink: 0;
    padding: 4px 12px;
    border-radius: 20px;
    border: 1px solid var(--border-strong);
    background: none;
    color: var(--muted);
    font-family: 'Inter', sans-serif;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}

@media (hover: hover) {
    .upload-progress-cancel:hover {
        border-color: var(--error-border);
        color: var(--error);
    }
}

/* Watches */
.watches-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.watch-form {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}

.watch-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.watch-row input {
    flex: 1;
}

.watch-item {
    border-radius: 16px;
    padding: 12px 14px;
    display: flex;
    align-items: center;
    gap: 12px;
}

.watch-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 6px var(--success);
    flex-shrink: 0;
    animation: pulse 2s ease-in-out infinite;
}

.watch-dot.error {
    background: var(--error);
    box-shadow: 0 0 6px var(--error);
}

.watch-info {
    flex: 1;
    min-width: 0;
}

.watch-name {
    font-size: 14px;
    font-weight: 600;
}

.watch-meta {
    font-size: 12px;
    color: var(--muted);
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.watch-status {
    font-size: 11px;
    color: var(--accent);
    margin-top: 3px;
}

.watch-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

/* Filtres de jobs */
.job-filters {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    padding-bottom: 4px;
    margin-bottom: 12px;
    scrollbar-width: none;
}

.job-filters::-webkit-scrollbar {
    display: none;
}

.job-filter-pill {
    flex-shrink: 0;
    padding: 8px 14px;
    border-radius: 999px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--muted);
    font-family: 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.2s var(--ease-smooth), border-color 0.2s var(--ease-smooth), color 0.2s var(--ease-smooth), transform 0.3s var(--ease-spring);
}

.job-filter-pill:active {
    transform: scale(0.94);
}

.job-filter-pill.active {
    background: var(--accent-glass);
    border-color: var(--accent-border);
    color: var(--accent);
}

.job-clear-btn {
    width: 100%;
    margin-top: 4px;
}

/* Jobs */
.jobs-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.job-item {
    border-radius: 16px;
    padding: 12px 14px;
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Groupe d'import (jobs partageant un batch_id) — un résumé repliable au
   lieu de N lignes individuelles, illisible au-delà de quelques fichiers. */
.job-item.job-group {
    flex-direction: column;
    align-items: stretch;
    padding: 0;
    gap: 0;
}

.job-group-summary {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    background: none;
    border: none;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
}

.job-group-chevron {
    font-size: 18px;
    color: var(--muted);
    transition: transform 0.2s var(--ease-smooth);
    flex-shrink: 0;
}

.job-group-chevron.expanded {
    transform: rotate(90deg);
}

.job-group-detail {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 8px 10px;
    border-top: 1px solid var(--border);
}

.job-group-detail .job-item {
    background: none;
    border: none;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 8px 6px;
    animation: none;
}

.job-status {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.job-status.pending {
    background: var(--muted);
}

.job-status.running {
    background: var(--accent);
    box-shadow: 0 0 6px var(--accent);
    animation: pulse 1.2s ease-in-out infinite;
}

.job-status.done {
    background: var(--success);
}

.job-status.error {
    background: var(--error);
}

.job-icon-warning {
    font-size: 15px;
    line-height: 1;
    flex-shrink: 0;
}

@keyframes pulse {

    0%,
    100% {
        opacity: 1
    }

    50% {
        opacity: 0.3
    }
}

.job-info {
    flex: 1;
    min-width: 0;
}

.job-title {
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.job-meta {
    font-size: 12px;
    color: var(--muted);
    margin-top: 2px;
}

.job-error {
    font-size: 11px;
    color: var(--error);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.job-sync-warning {
    font-size: 11px;
    color: var(--warning);
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.vinyl-spin {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: conic-gradient(#141416 0deg, #1e1e21 20deg, #141416 40deg, #1e1e21 60deg,
            #141416 80deg, #1e1e21 100deg, #141416 120deg, #1e1e21 140deg,
            #141416 160deg, #1e1e21 180deg, #141416 200deg, #1e1e21 220deg,
            #141416 240deg, #1e1e21 260deg, #141416 280deg, #1e1e21 300deg,
            #141416 320deg, #1e1e21 340deg, #141416 360deg);
    box-shadow: 0 0 0 2px var(--accent);
    position: relative;
    flex-shrink: 0;
    animation: spin 2s linear infinite;
}

.vinyl-spin::after {
    content: '';
    position: absolute;
    inset: 50%;
    transform: translate(-50%, -50%);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent);
}

@keyframes spin {
    from {
        transform: rotate(0deg)
    }

    to {
        transform: rotate(360deg)
    }
}

/* Bibliothèque */
.playlists-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.playlist-card {
    border-radius: 16px;
    padding: 14px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: transform 0.3s var(--ease-spring);
}

.playlist-card:active {
    transform: scale(0.98);
}

.playlist-name {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 15px;
    font-weight: 600;
}

.playlist-count {
    font-size: 12px;
    background: var(--accent-glass);
    color: var(--accent);
    padding: 3px 9px;
    border-radius: 20px;
    font-weight: 500;
}

.stats-bar {
    display: flex;
    gap: 18px;
    border-radius: 16px;
    padding: 16px 18px;
    overflow-x: auto;
}

.stat {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex-shrink: 0;
}

.stat-value {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 24px;
    font-weight: 700;
    color: var(--accent);
    letter-spacing: -0.5px;
}

.stat-label {
    font-size: 11px;
    color: var(--muted);
}

.empty {
    color: var(--muted);
    font-size: 13px;
    text-align: center;
    padding: 20px 0;
}

.toast {
    position: fixed;
    bottom: calc(24px + env(safe-area-inset-bottom));
    left: 50%;
    transform: translateX(-50%) translateY(80px);
    background: var(--toast-bg);
    backdrop-filter: blur(var(--blur));
    -webkit-backdrop-filter: blur(var(--blur));
    border: 1px solid var(--border-strong);
    border-radius: 12px;
    padding: 12px 20px;
    font-size: 13px;
    font-weight: 500;
    transition: transform 0.4s var(--ease-spring);
    z-index: 100;
    white-space: nowrap;
}

.toast.show {
    transform: translateX(-50%) translateY(0);
}

.toast.success {
    border-color: var(--success-border);
    color: var(--success);
}

.toast.error {
    border-color: var(--error-border);
    color: var(--error);
}

/* Modale de sélection de playlist (sheet iOS) */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: 200;
    display: none;
    align-items: flex-end;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.3s var(--ease-smooth);
}

.modal-overlay.show {
    opacity: 1;
}

.modal-sheet {
    width: 100%;
    max-width: 480px;
    /* dvh plutôt que vh : sur iOS Safari, 100vh ignore le retrait de la barre
       d'adresse et déborde sous le home indicator / l'encoche. */
    max-height: calc(90dvh - env(safe-area-inset-bottom));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
    background: var(--surface-strong);
    backdrop-filter: blur(24px) saturate(1.4);
    -webkit-backdrop-filter: blur(24px) saturate(1.4);
    border: 1px solid var(--border-strong);
    border-bottom: none;
    border-radius: 20px 20px 0 0;
    padding: 10px calc(20px + env(safe-area-inset-left)) calc(20px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-right));
    box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.3);
    transform: translateY(100%);
    opacity: 0;
    transition: transform 0.3s var(--ease-smooth), opacity 0.3s var(--ease-smooth);
}

.modal-overlay.show .modal-sheet {
    transform: translateY(0);
    opacity: 1;
    transition: transform 0.45s var(--ease-spring), opacity 0.3s var(--ease-smooth);
}

.modal-handle {
    width: 36px;
    height: 5px;
    border-radius: 3px;
    background: var(--border-strong);
    margin: 6px auto 16px;
    flex-shrink: 0;
}

.modal-title {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.4px;
    margin-bottom: 16px;
    flex-shrink: 0;
}

.modal-context {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    margin-bottom: 18px;
    flex-shrink: 0;
}

.modal-context:empty {
    display: none;
}

.modal-context-thumb {
    width: 48px;
    height: 48px;
    border-radius: 10px;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--surface-strong);
}

.modal-context-info {
    min-width: 0;
    flex: 1;
}

.modal-context-title {
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.modal-context-subtitle {
    font-size: 12px;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 2px;
}

.modal-playlist-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
    margin-bottom: 12px;
}

.modal-playlist-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    padding: 13px 16px;
    border-radius: 999px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    cursor: pointer;
    font-family: 'Inter', sans-serif;
    font-size: 14px;
    font-weight: 500;
    text-align: left;
    flex-shrink: 0;
    transition: background 0.2s var(--ease-smooth), border-color 0.2s var(--ease-smooth), transform 0.3s var(--ease-spring);
}

.modal-playlist-option:active {
    transform: scale(0.97);
}

.modal-playlist-option.selected {
    background: var(--accent-glass);
    border-color: var(--accent-border);
    color: var(--accent);
}

.modal-playlist-option-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.modal-playlist-option .radio-dot {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1.5px solid var(--border-strong);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.2s ease, background 0.2s ease;
}

.modal-playlist-option.selected .radio-dot {
    border-color: var(--accent);
    background: var(--accent);
}

.modal-playlist-option.selected .radio-dot::after {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #0A0A0B;
}

.modal-new-playlist-input {
    display: none;
    margin-bottom: 12px;
    flex-shrink: 0;
}

.modal-new-playlist-input.show {
    display: block;
}

.modal-actions {
    display: flex;
    gap: 10px;
    flex-shrink: 0;
}

.cookies-status {
    font-size: 13px;
    color: var(--muted);
}

.cookies-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
}

.btn-ghost {
    flex: 1;
    background: transparent;
    border: 1px solid var(--border-strong);
    color: var(--text);
    border-radius: 12px;
    padding: 14px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 15px;
    cursor: pointer;
    transition: transform 0.3s var(--ease-spring), background 0.2s ease;
}

.btn-ghost:active {
    transform: scale(0.96);
    background: var(--surface);
}

.modal-actions .btn {
    flex: 1.4;
}

/* ══════════════════════════════════════════════════════════════════════
   Responsive — mobile (par défaut, < 640px) / tablette (640–1023px) /
   desktop (≥ 1024px). La sidebar verticale remplace entièrement la tab
   bar basse à partir de 1024px ; en dessous, seule la largeur du contenu
   change (colonne unique centrée), la navigation reste la tab bar.
   ══════════════════════════════════════════════════════════════════════ */

.sidebar-nav {
    display: none;
}

/* ── Tablette : 640–1023px ── */
@media (min-width: 640px) and (max-width: 1023.98px) {
    #app.visible {
        max-width: 680px;
        margin: 0 auto;
    }
}

/* ── Desktop : ≥ 1024px — sidebar verticale, tab bar basse supprimée ── */
@media (min-width: 1024px) {
    .tab-bar {
        display: none;
    }

    #app.visible {
        display: grid;
        grid-template-columns: 240px 1fr;
        grid-template-rows: auto 1fr;
        max-width: none;
        margin: 0;
        height: 100%;
    }

    header {
        grid-column: 2;
        grid-row: 1;
    }

    #view-container {
        grid-column: 2;
        grid-row: 2;
    }

    .sidebar-nav {
        display: flex;
        flex-direction: column;
        gap: 4px;
        grid-column: 1;
        grid-row: 1 / -1;
        height: 100%;
        padding: 24px 16px;
        border-right: 1px solid var(--border);
        background: var(--chrome-bg);
        backdrop-filter: blur(var(--blur)) saturate(1.5);
        -webkit-backdrop-filter: blur(var(--blur)) saturate(1.5);
        overflow-y: auto;
    }

    .sidebar-brand {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 8px 12px 24px;
        font-family: 'Space Grotesk', sans-serif;
        font-weight: 600;
        font-size: 15px;
        color: var(--text);
    }

    .sidebar-link {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 12px 14px;
        border-radius: 12px;
        background: none;
        border: none;
        color: var(--muted);
        font-family: 'Inter', sans-serif;
        font-size: 14px;
        font-weight: 500;
        cursor: pointer;
        text-align: left;
        transition: background 0.2s var(--ease-smooth), color 0.2s var(--ease-smooth);
    }

    .sidebar-link .tab-icon {
        font-size: 18px;
        width: 20px;
        text-align: center;
        flex-shrink: 0;
    }

    @media (hover: hover) {
        .sidebar-link:hover {
            background: var(--surface);
        }
    }

    .sidebar-link.active {
        background: var(--accent-glass);
        color: var(--accent);
    }

    /* Le contenu des vues reste lisible sur un grand écran plutôt que de
       s'étirer sur toute la largeur disponible. */
    .view {
        max-width: 800px;
        margin: 0 auto;
    }
}
