/* =====================================================================
   FAVORITES-PAGE.CSS — Additions spécifiques à favorites.html.
   Le shell du player + grille d'albums réutilise accueil.css / album.css.
   Cette feuille couvre les éléments PROPRES à cette page ET garantit
   que le thème choisi (Dark / Light / Ambient) propage correctement
   à toute la page.
   ===================================================================== */

/* === Fond du body — corrige le gradient par défaut =================
   accueil.css + album.css définissent body → linear-gradient entre
   --bg-color-2 et --main-color (l'accent). En mode Ambient c'est
   joli (dégradé de couleurs chanson). En Dark/Light, ça tinte
   la page avec l'accent dans un coin (blanc cassé en Dark, vert
   foncé en Light). On FORCE un fond solide en non-ambient. */
html.theme-dark body,
html.theme-light body {
    background-image: linear-gradient(
        135deg,
        var(--bg-color-2) 0%,
        var(--bg-color-2) 100%
    );
}
/* En Ambient on garde le gradient original (sera animé dynamiquement
   par player.js selon la chanson en cours). */

/* === .playlist-sidebar — désactive la transparence héritée d'album.css
   album.css force `.playlist-sidebar { background: transparent; }`
   après accueil.css. C'est invisible sur les pages album-grid parce
   que les `.album-card` remplissent densément le conteneur (chacun a
   son propre bg rgba 18,18,18). Mais sur favorites.html (mode=list),
   les <li> sont CLARSEMÉS ~50px de haut avec gaps → le body-gradient
   passe à travers, donnant un rendu "à trous" très différent de la
   page album, et ce dans TOUS les thèmes (incluant Ambient qui est le
   défaut car aucune préférence utilisateur stockée).
   On FORCE un fond solide sur les 3 thèmes pour matcher le rendu album.
   Le gradient ambient reste visible sur le body (autour du panneau),
   ce qui préserve la signature visuelle du mode — c'est juste le
   contenu playlist qui stoppe la transparence. */
html.theme-dark .playlist-sidebar,
html.theme-ambient .playlist-sidebar {
    background: rgba(0, 0, 0, 0.78);
    border: 1px solid rgba(255, 255, 255, 0.10);
}
/* Theme-light : theme.js pose déjà `html.theme-light .playlist-sidebar
   { background: rgba(255,255,255,0.95); color:#1a1a1a; ... }`. On
   ajoute juste la bordure cohérente avec les autres cartes light. */
html.theme-light .playlist-sidebar {
    border: 1px solid rgba(0, 0, 0, 0.10);
}

/* === .middle-column override — neutralise le overflow:hidden ===
   album.css (chargé AVANT favorites-page.css dans le <head> de
   favorites.html et playlist.html) pose
       .middle-column { overflow: hidden; }
   pour contenir la grille d'albums sur les pages par catégorie.
   Sur favorites + playlist, pas de grille — seulement un toolbar
   + une sidebar → cet overflow:hidden est INUTILE et CLIPPE la
   box-shadow du .fav-toolbar / .pl-toolbar sur les côtés
   (le rendu "coupé aux extrémités gauche/droite" vient de là, pas
   du blur ou de la composition de la shadow).
   On neutralise via cette feuille, qui charge en dernier donc
   gagne la cascade à spécificité égale (0,0,1,0 vs 0,0,1,0).
   Le scroll de la playlist reste géré par .playlist-sidebar
   lui-même (overflow-y: auto), donc on ne perd rien fonctionnellement
   (pas de scroll parasite sur la colonne, pas de dépassement de
   hauteur, etc.). */
.middle-column {
    overflow: visible;
}

/* === Toolbar compacté (search + view-toggle dans la même pill) =====
   Conteneur horizontal unique façon "search bar de l'accueil" :
   fond sombre + bordure accent + ombre interne. Le bouton
   .view-toggle-btn reste à GAUCHE (chip dans la pill) et la
   search bar occupe le reste à droite — volontaire (cf. demande
   utilisateur "switch de mode ... suivi de la barre de recherche").
   .view-toggle-btn garde ses styles définis plus bas (background,
   border, etc.) : on n'override ici que ce qui concerne le layout
   dans la pill et la transparence de l'input pour qu'il se fonde
   visuellement dans le containeur. */
.fav-toolbar,
.pl-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    /* 20px (au lieu de 14) pour laisser la box-shadow (4px offset + 15px
       blur = ~19px de portée verticale totale) s'étendre entièrement
       DANS la marge avant que le sibling .playlist-sidebar ne la
       recouvre avec son propre fond. Évite l'effet "ombre tronquée"
       sur la face inférieure du pill. */
    margin-bottom: 20px;
    background: rgba(18, 18, 18, 0.9);
    border: 2px solid var(--main-color);
    border-radius: 14px;
    /* Shadow clean drop — maintenant que .middle-column a
       overflow:visible (cf. règle en haut de la feuille), la
       shadow peut s'étendre naturellement au-delà des bords
       arrondis 14px du pill sans être clippée. On retire le
       compound ring (qui visait à "fermer" les côtés à l'époque
       où ils étaient tronqués par overflow:hidden) et on garde
       une seule drop propre, plus lisible et plus en accord
       avec la drop-shadow du .opening juste en-dessous
       (accueil.css .opening { box-shadow: 0 10px 30px ... }). */
    box-shadow: 0 4px 12px rgba(0,0,0,0.45);
    padding: 5px 6px;
    min-height: 48px;
    position: relative;
}
.fav-toolbar .search-box,
.pl-toolbar .search-box {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    margin: 0;
}
.fav-toolbar .search-box input,
.pl-toolbar .search-box input {
    flex: 1 1 auto;
    width: 100%;
    box-sizing: border-box;
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 9px 14px;
    margin: 0;
    color: white;
    font-size: 1rem;
    outline: none;
}
.fav-toolbar .search-box input::placeholder,
.pl-toolbar .search-box input::placeholder {
    color: rgba(255,255,255,0.55);
    opacity: 1;
}
/* Layout du bouton à l'intérieur du pill : chip compact sur la
   gauche, sans marge externe (le containeur gère déjà l'espacement). */
.fav-toolbar .view-toggle-btn,
.pl-toolbar .view-toggle-btn {
    flex: 0 0 auto;
    margin: 0;
    border-radius: 9px;
    padding: 8px 14px;
    font-size: 0.85rem;
}

/* === Bouton List / Covers — partagé favorites + playlist =============
   Thème-aware via fallbacks et color-mix(). S'adapte aux 3 thèmes
   sans dépendre d'une spécificité fragile de theme.js. */
.view-toggle-btn {
    flex: 0 0 auto;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.20);
    color: rgba(255, 255, 255, 0.92);
    border-radius: 10px;
    padding: 9px 14px;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.3px;
    cursor: pointer;
    transition: background 0.22s ease, border-color 0.22s ease,
                color 0.22s ease, transform 0.15s ease;
    user-select: none;
}
.view-toggle-btn:hover {
    background: var(--main-color);
    border-color: var(--main-color);
    color: #ffffff;
    transform: translateY(-1px);
}
.view-toggle-btn:active {
    transform: translateY(0);
}
.view-toggle-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--main-color) 35%, transparent);
}
.view-toggle-btn[aria-pressed="true"] {
    background: color-mix(in srgb, var(--main-color) 22%, transparent);
    border-color: var(--main-color);
    color: var(--main-color);
}
/* Hover sur bouton déjà actif : DOIT primer sur l'aria-pressed (même
   spécificité, déclarée après pour gagner en cascade). */
.view-toggle-btn[aria-pressed="true"]:hover {
    background: color-mix(in srgb, var(--main-color) 88%, white);
    border-color: var(--main-color);
    color: #ffffff;
}

/* === Empty state — dark/ambient defaults ===========================
   Sélecteur partagé pour les deux empty-states (favorites + playlist)
   — évite la duplication ligne-à-ligne et garantit qu'on ne diverge pas
   par mégarde entre les deux pages. */
.favs-empty-state,
.pl-empty-state {
    text-align: center;
    padding: 50px 28px 38px;
    background: rgba(255, 255, 255, 0.045);
    border: 2px dashed rgba(255, 255, 255, 0.22);
    border-radius: 16px;
    margin-top: 18px;
    color: rgba(255, 255, 255, 0.92);
    animation: favs-empty-in 0.4s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.favs-empty-state p,
.pl-empty-state p {
    margin: 0 auto;
    max-width: 480px;
    font-size: 1.02rem;
    line-height: 1.5;
    opacity: 0.92;
}
.favs-empty-state .favs-empty-hint,
.pl-empty-state .favs-empty-hint {
    margin-top: 8px;
    opacity: 0.7;
    font-size: 0.92rem;
}
.fav-inline-heart {
    display: inline-block;
    color: var(--main-color);
    font-size: 1.15em;
    line-height: 1;
    transform: translateY(1px);
    transition: transform 0.25s ease;
}
.favs-empty-state:hover .fav-inline-heart {
    transform: translateY(1px) scale(1.15);
}
.favs-empty-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    margin-top: 22px;
}
.favs-empty-btn {
    display: inline-block;
    padding: 10px 18px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.07);
    color: rgba(255, 255, 255, 0.92);
    font-size: 0.88rem;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease,
                color 0.2s ease, transform 0.15s ease;
}
.favs-empty-btn:hover {
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.32);
    transform: translateY(-1px);
}
.favs-empty-btn.primary {
    background: var(--main-color);
    border-color: var(--main-color);
    color: #ffffff;
}
.favs-empty-btn.primary:hover {
    background: color-mix(in srgb, var(--main-color) 88%, white);
    border-color: color-mix(in srgb, var(--main-color) 88%, white);
}
.favs-empty-tag {
    display: inline-block;
    margin-top: 22px;
    padding: 4px 12px;
    border: 1px solid rgba(255, 255, 255, 0.20);
    border-radius: 999px;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: rgba(255, 255, 255, 0.85);
    opacity: 0.7;
}
@keyframes favs-empty-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0);   }
}

/* === Player atténué quand empty ===================================== */
.opening.is-empty,
.volume-container.is-empty {
    opacity: 0.42;
    pointer-events: none;
    filter: saturate(0.4);
    transition: opacity 0.3s ease, filter 0.3s ease;
}

/* === Theme-Light overrides ========================================== */
html.theme-light .fav-toolbar,
html.theme-light .pl-toolbar {
    background: rgba(255, 255, 255, 0.95);
    border-color: rgba(0, 0, 0, 0.18);
    /* Drop shadow light rail — pâle pour rester subtil sur fond clair,
       mais cohérent avec le dark (12px de blur). */
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
}
html.theme-light .fav-toolbar .search-box input,
html.theme-light .pl-toolbar .search-box input {
    color: #1a1a1a;
}
html.theme-light .fav-toolbar .search-box input::placeholder,
html.theme-light .pl-toolbar .search-box input::placeholder {
    color: rgba(0, 0, 0, 0.45);
}
html.theme-light .view-toggle-btn {
    background: rgba(0, 0, 0, 0.05);
    border-color: rgba(0, 0, 0, 0.20);
    color: #1a1a1a;
}
html.theme-light .view-toggle-btn:hover {
    background: var(--main-color);
    border-color: var(--main-color);
    color: #ffffff;
}
html.theme-light .view-toggle-btn[aria-pressed="true"] {
    background: color-mix(in srgb, var(--main-color) 28%, transparent);
    border-color: var(--main-color);
    color: #1a1a1a;
}
html.theme-light .view-toggle-btn[aria-pressed="true"]:hover {
    background: color-mix(in srgb, var(--main-color) 92%, white);
    border-color: var(--main-color);
    color: #ffffff;
}
html.theme-light .favs-empty-state,
html.theme-light .pl-empty-state {
    background: rgba(0, 0, 0, 0.04);
    border-color: rgba(0, 0, 0, 0.22);
    color: #1a1a1a;
}
html.theme-light .favs-empty-btn {
    color: #1a1a1a;
    background: rgba(0, 0, 0, 0.05);
    border-color: rgba(0, 0, 0, 0.22);
}
html.theme-light .favs-empty-btn:hover {
    background: rgba(0, 0, 0, 0.10);
}
html.theme-light .favs-empty-btn.primary {
    color: #ffffff;
}
html.theme-light .favs-empty-tag {
    color: #1a1a1a;
    border-color: rgba(0, 0, 0, 0.22);
}

/* === Mode no-animations ============================================ */
html.no-animations .favs-empty-state,
html.no-animations .pl-empty-state,
html.no-animations .view-toggle-btn,
html.no-animations .fav-inline-heart,
html.no-animations .opening.is-empty {
    animation: none !important;
    transition: none !important;
}

/* === Mobile — toolbar garde une seule ligne, plus compact ========== */
@media (max-width: 600px) {
    .fav-toolbar,
    .pl-toolbar {
        /* On reste sur une seule ligne pour ne pas briser l'effet "pill
           tout-en-un" — paddings et font réduits pour respirer sur
           petits écrans. */
        min-height: auto;
        padding: 4px;
        gap: 4px;
    }
    .fav-toolbar .search-box input,
    .pl-toolbar .search-box input {
        padding: 7px 10px;
        font-size: 0.95rem;
    }
    .view-toggle-btn {
        padding: 7px 10px;
        font-size: 0.78rem;
    }
    .favs-empty-state,
    .pl-empty-state {
        padding: 36px 18px 28px;
    }
    .favs-empty-actions {
        flex-direction: column;
        align-items: stretch;
    }
    .favs-empty-btn {
        text-align: center;
    }
}

/* === pl-name-banner — heading H2 du playlist view (SPA) ============
   2026-08-09 : 신설. Mise en avant du nom du playlist au-dessus du
   toolbar, façon "page de garde". Sur playlist.html standalone, cet
   élément n'existait pas — le titre était dans le h1 du .custom-header
   (« Playlist: <name> »). Sur la SPA, le h1 du header global doit
   rester générique (par défaut « Norex Music» sur les routes SPA), donc
   le nom du playlist vit dans son propre H2 local au pl-view-root.
   Style : chip OPAQUE sombre avec accent vert/cyan du thème, aligné
   à gauche pour matcher la toolbar en-dessous.
   NB : la classe `.pl-view-root` est volontairement ABSENTE de cette
   feuille. Si on l'ajoutait avec `display: block`, elle écraserait
   le `display: none` posé par l'attribut HTML `hidden` du conteneur
   #playlist-view-root quand on n'est PAS sur la route playlist
   (= bug : la barre de titre + search playlist apparaissent sur
   l'accueil / library / favoris / catégories). Cf. plus bas la
   règle `#playlist-view-root[hidden]` qui force le display:none. */
.pl-name-banner {
    margin: 0 0 14px;
    padding: 10px 16px;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: rgba(255, 255, 255, 0.95);
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid color-mix(in srgb, var(--main-color) 45%, transparent);
    border-radius: 12px;
    /* Tronque proprement les noms >50 chars pour ne pas casser le layout
       sur mobile ou sidebar étroite. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Animation fade-in coupée en no-animations (cf. règle globale). */
    animation: pl-name-banner-in 0.32s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes pl-name-banner-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0);   }
}

/* === #playlist-view-root[hidden] — force display:none ==============
   BUG FIX 2026-08-09 : le markup initial de #playlist-view-root dans
   accueil.html porte l'attribut `hidden`. Le browser applique la règle
   UA `[hidden] { display: none }` (spécificité 0,1,0). Si on définit
   `.pl-view-root { display: block }` dans cette feuille, CE rule a
   priorité (specificity 0,1,0 également, mais déclarée après → cascade)
   → le conteneur devient visible PARTOUT, et l'user voit le
   "Playlist:" banner + toolbar toggle + search input collés sur
   l'accueil / library / favorites / catégories. FIX : on n'écrit
   pas de `.pl-view-root { display: ... }` général, et on pose
   explicitement `[hidden] { display: none !important }` pour gagner
   contre toute spécificité par défaut que d'autres règles pourraient
   atteindre. NB : on n'a PAS le même problème avec
   #favs-view-root et #library-hub-root — ils n'ont pas de rule
   `display: …` qui les force visible, donc leur `[hidden]` marche
   en cascade normale.
   Pourquoi aussi sur #favs-view-root : un futur regression où
   quelqu'un pose `display: flex` sur .favs-view-root provoquerait
   le même bug. On blinde les DEUX conteneurs. */
#playlist-view-root[hidden] { display: none !important; }
#favs-view-root[hidden]     { display: none !important; }

/* === #pl-search-input — placeholder dédié au playlist ==============
   En SPA accueil.html, la .search-box globale (accueil home) cohabite
   avec celle du #playlist-view-root. On distingue par id pour ne pas
   déclencher le searchInput handler home quand l'user tape dans le
   search playlist. Le state playlist est tenu par l'id `pl-search-input`.
   Styles hérités de .pl-toolbar .search-box input (cf. règle plus haut
   dans cette feuille). On n'override QUE la sémantique d'aria-label + le
   placeholder sémantique déjà dans l'attribut HTML. */
#pl-search-input {
    /* Reprise du sentir visuel identique à la search-box accueil : */
    cursor: text;
}

/* === Theme-light overrides pour .pl-name-banner ==================== */
html.theme-light .pl-name-banner {
    background: rgba(255, 255, 255, 0.92);
    color: #1a1a1a;
    border-color: color-mix(in srgb, var(--main-color) 55%, rgba(0,0,0,0.18));
}

/* === Mode no-animations ============================================ */
html.no-animations .pl-name-banner {
    animation: none !important;
}
