/* ===== RETOUCHES GRAPHIQUES =====
 *
 * Inspiration : tropistream.fr. Trois idees reprises, pas la maquette.
 *
 * Fichier separe et charge EN DERNIER plutot que des retouches dans
 * style.css (275 Ko) : on voit d'un coup tout ce qui a ete change, et on
 * revient en arriere en retirant une seule ligne de index.php.
 */

/* --------------------------------------------------------------------------
 * 1. CALMER LE FOND
 *
 * Le body portait une grille rouge (rgba(255,35,55,.13) tous les 46 px, dans
 * les deux sens), un halo rouge, et DEUX animations infinies : redGridMove sur
 * le body, redGlowSweep sur body::before. Resultat : un quadrillage rouge qui
 * bouge en permanence derriere les affiches, et deux animations qui tournent
 * tant que l'onglet est ouvert — sur mobile c'est de la batterie pour rien.
 *
 * Les affiches sont le contenu ; le fond doit les porter, pas leur disputer
 * l'attention. On garde la grille — elle fait partie de l'identite — mais
 * divisee par ~4, et on arrete les animations de fond.
 * ------------------------------------------------------------------------ */
body {
    background:
        linear-gradient(rgba(255, 35, 55, 0.035) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 35, 55, 0.035) 1px, transparent 1px),
        radial-gradient(circle at 50% 0%, rgba(255, 35, 55, 0.05), transparent 55%),
        #0a0a0f !important;
    background-size: 46px 46px, 46px 46px, 100% 900px, auto !important;
    background-position: 0 0, 0 0, center top, center !important;
    background-attachment: fixed !important;
    /* La grille ne defile plus : elle etait le seul mouvement permanent de la
       page, et il n'apportait rien. */
    animation: none !important;
}

/* Le balayage rouge animé par-dessus tout le site : retire. */
body::before { display: none !important; }

/* --------------------------------------------------------------------------
 * 2. TITRES DE SECTION
 *
 * Repris de TropiStream : une barre d'accent verticale devant le titre. Les
 * sections s'enchainaient sans rien pour marquer leur debut, et l'oeil ne
 * savait pas ou commencait une rangee. Un filet de 4 px suffit — c'est moins
 * lourd qu'un trait de separation sur toute la largeur.
 * ------------------------------------------------------------------------ */
.section-title h2 {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 1.32rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: #f4f7fa;
}
.section-title h2::before {
    content: '';
    flex: 0 0 auto;
    width: 4px;
    height: 1.05em;
    border-radius: 3px;
    /* currentColor serait blanc : on veut l'accent du theme, pour que la barre
       devienne orange a Halloween et verte a Noel sans regle en plus. */
    background: var(--theme-accent, #ff3b4e);
}

/* Le lien « Voir tout » : discret au repos, net au survol. */
.section-title a {
    color: #8e97a3;
    font-size: 0.84rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    transition: color 0.18s ease;
}
.section-title a:hover { color: var(--theme-accent, #ff3b4e); }

/* --------------------------------------------------------------------------
 * 3. BANDEAU DISCORD
 *
 * Repris de TropiStream, qui ouvre sur « Rejoins le Discord ». Il n'est servi
 * (voir index.php) qu'aux visiteurs qui n'ont PAS encore l'acces lecture :
 * inutile de demander a un membre de rejoindre ce qu'il a deja rejoint.
 * ------------------------------------------------------------------------ */
.bandeau-discord {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px 14px;
    padding: 9px 46px 9px 16px;
    position: relative;
    background: linear-gradient(90deg, #4752c4, #5865F2);
    color: #fff;
    font-size: 0.88rem;
    font-weight: 600;
    text-align: center;
    line-height: 1.35;
}
.bandeau-discord a {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 13px;
    border-radius: 7px;
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
    font-weight: 800;
    font-size: 0.82rem;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.18s ease;
}
.bandeau-discord a:hover { background: rgba(255, 255, 255, 0.3); }
.bandeau-discord-fermer {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: #fff;
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.75;
}
.bandeau-discord-fermer:hover { opacity: 1; background: rgba(255, 255, 255, 0.16); }

@media (max-width: 768px) {
    .bandeau-discord {
        font-size: 0.8rem;
        padding: 9px 42px 9px 12px;
    }
    /* Sur un ecran etroit la phrase complete pousse le bouton hors de vue ;
       l'essentiel est l'action, pas l'argumentaire. */
    .bandeau-discord-detail { display: none; }
}

/* Quelqu'un qui a demande moins d'animations ne doit pas en recevoir une de
   plus : la transition des liens est deja courte, mais la regle vaut pour tout
   ce que ce fichier ajoute. */
@media (prefers-reduced-motion: reduce) {
    .section-title a,
    .bandeau-discord a,
    .bandeau-discord-fermer { transition: none !important; }
}

/* --------------------------------------------------------------------------
 * 4. APPARITION AU DEFILEMENT
 *
 * Voir js/apparition-scroll.js. Le masquage ne vise QUE `.app-masque`, classe
 * posee par le JS et retiree a l'entree dans l'ecran : sans JS, rien n'est
 * cache. Un effet decoratif ne doit jamais pouvoir rendre le catalogue
 * invisible — c'est la seule regle non negociable de ce bloc.
 *
 * translateY court (14 px) et opacite : un deplacement plus ample attire
 * l'oeil sur le mouvement au lieu du contenu, et donne le mal de mer sur une
 * page qui enchaine les rangees.
 * ------------------------------------------------------------------------ */
.app-masque {
    opacity: 0 !important;
    transform: translateY(14px) !important;
}

[data-motion="on"] .section-title,
[data-motion="on"] .grid > *,
[data-motion="on"] .episodes-recents > * {
    transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

/* La demande systeme prime sur tout : le JS s'abstient deja, mais si une
   classe restait posee (bascule du reglage en cours de visite), le contenu
   doit redevenir visible immediatement plutot que de rester masque. */
@media (prefers-reduced-motion: reduce) {
    .app-masque {
        opacity: 1 !important;
        transform: none !important;
    }
    [data-motion="on"] .section-title,
    [data-motion="on"] .grid > *,
    [data-motion="on"] .episodes-recents > * {
        transition: none !important;
    }
}

/* --------------------------------------------------------------------------
 * 5. TOP 10 NUMEROTE
 *
 * Repris de TropiStream. Le « Top 10 » de Kinoo etait une rangee de cartes
 * identiques a toutes les autres : rien ne disait que c'etait un classement,
 * et l'ordre — la seule information de la section — passait inapercu.
 *
 * Compteur CSS plutot que des numeros ecrits dans le HTML : la numerotation
 * suit l'ordre reel des cartes, meme quand le JS les remplace apres l'appel a
 * l'API, sans une ligne de script en plus.
 * ------------------------------------------------------------------------ */
#popularGrid {
    counter-reset: kinoo-top;
}
#popularGrid > * {
    counter-increment: kinoo-top;
    position: relative;
}

/* La numerotation d origine du site (grand chiffre pose derriere l affiche)
   reste masquee : deux series de chiffres sur une meme carte, c est une de
   trop. */
#popularGrid .rang-chiffre {
    display: none !important;
}

/* Badge de rang.
 *
 * Une pastille en haut a gauche plutot qu un grand chiffre : taille fixe quel
 * que soit le nombre de chiffres, et l affiche reste lisible. Le fond sombre
 * translucide tient sur une affiche claire comme sombre, ce qu un chiffre
 * blanc seul ne fait pas.
 */
#popularGrid > * > .card-media {
    position: relative;
    overflow: visible;
}
#popularGrid > * > .card-media::after {
    content: counter(kinoo-top);
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 3;
    pointer-events: none;
    /* min-width + padding : « 1 » reste carre, « 10 » s allonge en pilule sans
       deborder ni decaler ses voisines. */
    min-width: 26px;
    height: 26px;
    padding: 0 7px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: rgba(8, 8, 12, 0.72);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 0.82rem;
    font-weight: 800;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
    /* On annule explicitement l habillage de la version precedente : sans ca,
       une regle restee en cache redonnerait un chiffre creux. */
    text-shadow: none;
    -webkit-text-stroke: 0;
}

/* Au-dela de 10 le classement n en est plus un : la section s appelle Top 10. */
#popularGrid > *:nth-child(n + 11) > .card-media::after {
    content: none;
}

/* Le panneau de survol recouvre l affiche : le badge n a plus rien a signaler
   et gene la lecture. */
#popularGrid > *:hover > .card-media::after {
    opacity: 0;
    transition: opacity 0.16s ease;
}

@media (max-width: 768px) {
    #popularGrid > * > .card-media::after {
        min-width: 22px;
        height: 22px;
        font-size: 0.72rem;
        top: 6px;
        left: 6px;
        border-radius: 7px;
    }
}

/* --------------------------------------------------------------------------
 * 6. PAGE DE CONNEXION
 *
 * Avant : un titre en haut a gauche, deux boites alignees dans beaucoup de
 * vide, et aucune trace de Discord — alors que c'est devenu la seule voie qui
 * ouvre la lecture. La page disait « remplis un formulaire » quand la reponse
 * utile tenait en un bouton.
 *
 * Apres : une colonne centree, les deux formulaires en cartes lisibles, et le
 * bouton Discord en bas, detache par un separateur.
 * ------------------------------------------------------------------------ */

#page-login > h2 {
    text-align: center;
    margin: 6px 0 4px;
    font-size: 1.9rem !important;
    font-weight: 800 !important;
    letter-spacing: -0.02em !important;
    text-transform: none !important;
    color: #f4f7fa !important;
}

/* Accroche sous le titre, ajoutee en CSS : elle n'apporte aucune information
   nouvelle au lecteur d'ecran (le contexte est deja donne par le titre et les
   champs), donc pas de raison de l'ecrire dans le HTML. */
#page-login > h2::after {
    content: 'Retrouve ta liste, ton historique et ta progression.';
    display: block;
    margin-top: 9px;
    font-size: 0.88rem;
    font-weight: 500;
    letter-spacing: 0;
    color: #8e97a3;
}

#page-login .login-container {
    max-width: 920px;
    margin-left: auto;
    margin-right: auto;
}

#page-login .login-box {
    background: rgba(255, 255, 255, 0.032);
    border: 1px solid rgba(255, 255, 255, 0.075);
    border-radius: 18px;
    padding: 26px 24px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
}

#page-login .login-box h3 {
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: #9aa4b2;
    margin-bottom: 16px;
}

#page-login .login-box input {
    border-radius: 11px;
    padding: 13px 15px;
    background: rgba(255, 255, 255, 0.045);
    border: 1px solid rgba(255, 255, 255, 0.09);
    color: #eef3f8;
    transition: border-color 0.18s ease, background 0.18s ease;
}
#page-login .login-box input:focus {
    border-color: var(--theme-accent, #ff3b4e);
    background: rgba(255, 255, 255, 0.07);
    outline: none;
}
#page-login .login-box input::placeholder { color: #727c88; }

#page-login .btn-login,
#page-login .btn-register {
    border-radius: 11px;
    padding: 13px 16px;
    font-weight: 800;
    letter-spacing: 0.02em;
}

/* --- Bloc Discord --- */
.login-discord {
    max-width: 440px;
    margin: 26px auto 10px;
    text-align: center;
}

/* Separateur « ou » : deux filets et le mot au milieu. Il marque que ce qui
   suit est une alternative aux formulaires, pas une etape de plus. */
.login-separateur {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
    color: #6f7885;
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 1.4px;
    text-transform: uppercase;
}
.login-separateur::before,
.login-separateur::after {
    content: '';
    flex: 1;
    height: 1px;
    background: rgba(255, 255, 255, 0.1);
}

.login-discord-bouton {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 11px;
    width: 100%;
    /* 52 px : une cible confortable au doigt, et le poids visuel que merite
       l'action principale de la page. */
    min-height: 52px;
    padding: 14px 20px;
    border-radius: 13px;
    background: #5865F2;
    color: #fff;
    font-size: 0.98rem;
    font-weight: 800;
    text-decoration: none;
    box-shadow: 0 10px 28px rgba(88, 101, 242, 0.3);
    transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.login-discord-bouton:hover {
    background: #4752c4;
    transform: translateY(-2px);
    box-shadow: 0 14px 34px rgba(88, 101, 242, 0.42);
}
.login-discord-bouton:active { transform: translateY(0); }
.login-discord-bouton:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 3px;
}
.login-discord-bouton svg { flex: 0 0 auto; }

.login-discord-note {
    margin-top: 11px;
    color: #7c8692;
    font-size: 0.79rem;
    line-height: 1.5;
}

@media (max-width: 768px) {
    #page-login > h2 { font-size: 1.55rem !important; }
    #page-login > h2::after { font-size: 0.82rem; }
    .login-discord { margin-top: 20px; }
}

@media (prefers-reduced-motion: reduce) {
    .login-discord-bouton,
    #page-login .login-box input { transition: none !important; }
    .login-discord-bouton:hover { transform: none !important; }
}

/* --------------------------------------------------------------------------
 * 7. BARRE DE NAVIGATION
 *
 * Repris de TropiStream : des liens en pastilles, une pastille pleine sur la
 * page courante, et un bouton de compte qui ressemble a un bouton.
 *
 * Avant : des liens serres a 10 px d'ecart, sans zone cliquable au-dela du
 * texte, et la page courante signalee par la seule couleur orange. Pour
 * quelqu'un qui distingue mal le rouge et le vert — la forme de daltonisme la
 * plus repandue — rien ne disait ou l'on se trouvait. La pastille ajoute une
 * forme a la couleur, et agrandit la cible au passage.
 * ------------------------------------------------------------------------ */

/* `html[data-theme]` en prefixe : sans lui, themes.css et halloween-theme.css
   l'emportent et le padding retombe a 0 des qu'un theme saisonnier est actif —
   c'est-a-dire la plupart du temps. */
html[data-theme] header > nav > a,
html[data-theme] header > nav > .nav-explorer > a,
html[data-theme] header > nav > .nav-explorer > button {
    padding: 9px 14px !important;
    border-radius: 10px !important;
    font-weight: 600;
    line-height: 1;
    transition: background 0.16s ease, color 0.16s ease;
}

/* La pastille de la page courante, rendue a tous les themes. Les feuilles
   saisonnieres la remettaient a transparent ; on la repose en se servant de
   l'accent du theme, donc elle reste orange a Halloween et verte a Noel. */
html[data-theme] header > nav > a.active-link {
    background: rgba(255, 255, 255, 0.09) !important;
}
html[data-theme] header > nav > a.active-link:hover {
    background: rgba(255, 255, 255, 0.14) !important;
}

html[data-theme] header > nav > a:hover,
html[data-theme] header > nav > .nav-explorer:hover > a,
html[data-theme] header > nav > .nav-explorer:hover > button {
    background: rgba(255, 255, 255, 0.07) !important;
    color: #f1f5f9 !important;
}

/* Page courante : le fond est DEJA pose par style.css
   (`nav a.active-link { background: rgba(255,59,78,.12) }`) et il convient.
   On ne le redefinit pas ici : une premiere version le remplacait par un
   color-mix() qui calculait transparent, donc supprimait une pastille qui
   fonctionnait. On se contente d'appuyer la graisse.

   Le theme Halloween remet ce fond a transparent de son cote : c'est son
   parti pris, pas un defaut. */
header > nav > a.active-link {
    font-weight: 800;
}

/* --- Recherche --- */
header .search-header input {
    border-radius: 11px !important;
    padding: 10px 14px 10px 38px !important;
    background: rgba(255, 255, 255, 0.05) !important;
    border: 1px solid rgba(255, 255, 255, 0.09) !important;
    color: #eef3f8 !important;
    transition: border-color 0.16s ease, background 0.16s ease;
}
header .search-header input:focus {
    border-color: var(--theme-accent, #ff3b4e) !important;
    background: rgba(255, 255, 255, 0.08) !important;
    outline: none !important;
}

/* --- Bouton de compte ---
   TropiStream en fait un vrai bouton plein ; ici c'etait un texte avec un
   rond. Une bordure et un fond suffisent a le faire lire comme une action. */
header .compte-btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 7px 13px 7px 8px;
    border-radius: 11px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.05);
    font-weight: 700;
    /* 40 px : la cible reste confortable sans grossir la barre. */
    min-height: 40px;
    transition: background 0.16s ease, border-color 0.16s ease;
}
header .compte-btn:hover {
    background: rgba(255, 255, 255, 0.09);
    border-color: rgba(255, 255, 255, 0.18);
}

header .search-toggle-btn {
    border-radius: 10px;
    transition: background 0.16s ease;
}
header .search-toggle-btn:hover { background: rgba(255, 255, 255, 0.08); }

/* Le focus clavier doit rester visible partout dans la barre : c'est le seul
   reperage de quelqu'un qui navigue sans souris. */
header > nav > a:focus-visible,
header .compte-btn:focus-visible,
header .search-toggle-btn:focus-visible {
    outline: 2px solid var(--theme-accent, #ff3b4e);
    outline-offset: 2px;
}

@media (max-width: 768px) {
    /* La barre mobile a sa propre mise en page (menu burger) : on n'y touche
       pas, sinon les pastilles poussent le logo hors de l'ecran. */
    header > nav > a,
    header > nav > .nav-explorer > a,
    header > nav > .nav-explorer > button {
        padding: 8px 11px !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    header > nav > a,
    header .compte-btn,
    header .search-toggle-btn,
    header .search-header input { transition: none !important; }
}

/* Specificite par l'ID du nav. Les variantes sans ID etaient bien chargees et
   matchaient l'element, mais quelque chose dans la cascade des feuilles de
   theme continuait de l'emporter ; plutot que de poursuivre a l'aveugle, on
   monte d'un cran avec #mainNav, qui tranche sans ambiguite. */
html[data-theme] header > nav#mainNav > a,
html[data-theme] header > nav#mainNav > .nav-explorer > a,
html[data-theme] header > nav#mainNav > .nav-explorer > button {
    padding: 9px 14px !important;
    border-radius: 10px !important;
}
html[data-theme] header > nav#mainNav > a.active-link {
    background: rgba(255, 255, 255, 0.1) !important;
}
html[data-theme] header > nav#mainNav > a:hover {
    background: rgba(255, 255, 255, 0.07) !important;
}

/* --------------------------------------------------------------------------
 * 8. RAPPEL « LISTE LOCALE »
 *
 * Ma liste fonctionne sans compte, par identifiant d'appareil. C'est voulu,
 * mais rien ne disait que la liste ne suit pas la personne d'un appareil a
 * l'autre — on le decouvrait en la retrouvant vide ailleurs. Affiche seulement
 * aux visiteurs sans session (condition en PHP dans index.php).
 * ------------------------------------------------------------------------ */
.rappel-liste {
    margin: -4px 0 18px;
    padding: 11px 15px;
    border-radius: 11px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.035);
    color: #98a2ae;
    font-size: 0.85rem;
    line-height: 1.5;
}
.rappel-liste a {
    color: #5865F2;
    font-weight: 700;
    text-decoration: none;
}
.rappel-liste a:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
 * 9. BARRE DE NAVIGATION TRANSLUCIDE
 *
 * Mesure faite sur tropistream.fr pour comparer, plutot que de deviner :
 *
 *                  Kinoo avant          TropiStream
 *   fond           rgb(12,9,18) opaque  rgba(8,8,9,.82)
 *   flou           aucun                blur(18px) saturate(1.6)
 *   bordure        1px violette         0.8px blanc a 6 %
 *   graisse liens  600                  800
 *
 * Le flou est l'ecart qui compte : sur un fond opaque la barre est un bandeau
 * pose sur la page, le contenu disparait dessous d'un coup. Avec le flou il
 * continue d'exister derriere, et la barre parait posee SUR la page au lieu
 * de la couper. C'est tout l'effet « premium », et ca tient en deux lignes.
 *
 * La barre reste en position sticky (elle l etait deja) et non fixed comme
 * fixed l'otant du flux, il faudrait compenser par un padding en tete de
 * chaque page — pour le meme rendu visuel.
 * ------------------------------------------------------------------------ */
html[data-theme] header {
    background: rgba(10, 9, 14, 0.82) !important;
    -webkit-backdrop-filter: blur(18px) saturate(1.6);
    backdrop-filter: blur(18px) saturate(1.6);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important;
}

/* Repli pour les navigateurs sans backdrop-filter (Firefox ancien) : sans lui
   la barre serait simplement transparente et le texte illisible des qu'une
   affiche passe dessous. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    html[data-theme] header { background: rgba(10, 9, 14, 0.97) !important; }
}

/* Liens plus affirmes : 600 se lisait comme du texte courant a 11 px. */
html[data-theme] header > nav#mainNav > a,
html[data-theme] header > nav#mainNav > .nav-explorer > a,
html[data-theme] header > nav#mainNav > .nav-explorer > button {
    font-weight: 800 !important;
    letter-spacing: 0.015em !important;
}

/* La bordure resistait : une feuille de theme la repose avec une specificite
   superieure. Meme remede que pour les liens de nav — on passe par le
   conteneur de page, qui tranche. */
html[data-theme] body header,
html[data-theme] #site-content > header {
    border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important;
    border-top: 0 !important;
    border-left: 0 !important;
    border-right: 0 !important;
}

/* --------------------------------------------------------------------------
 * 10. VIGNETTES DU HERO
 *
 * Navigation du carrousel par les affiches plutot que par cinq points
 * identiques : on voit ce qu'on va ouvrir.
 *
 * Premiere version refaite : le conteneur gardait la bordure et le rayon de
 * 30 px des anciens points, ce qui dessinait une boite autour des vignettes, et
 * un transform le centrait au milieu de la banniere. Les numeros sur chaque
 * affiche n'apprenaient rien que la position ne disait deja.
 * ------------------------------------------------------------------------ */

html[data-theme] #page-home .hero-banner-dots,
html[data-theme] .hero-banner-dots {
    display: flex !important;
    align-items: flex-end !important;
    gap: 10px !important;
    /* Ancre en bas a droite, et on neutralise le centrage des anciens points :
       left + transform les placaient au milieu. */
    left: auto !important;
    right: 28px !important;
    bottom: 26px !important;
    transform: none !important;
    /* La boite : bordure, fond et rayon venaient du style des points. */
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    padding: 0 !important;
    width: auto !important;
}

html[data-theme] #page-home .hero-dot-vignette,
html[data-theme] .hero-dot-vignette {
    position: relative !important;
    /* Proportion d'affiche 2:3. */
    width: 58px !important;
    height: 87px !important;
    flex: 0 0 auto !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: 7px !important;
    background: rgba(255, 255, 255, 0.05) !important;
    overflow: hidden !important;
    cursor: pointer;
    opacity: 0.45;
    /* L'ombre detache les vignettes de l'image de fond, souvent claire. */
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
    transition: opacity 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

html[data-theme] #page-home .hero-dot-vignette img,
html[data-theme] .hero-dot-vignette img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    display: block !important;
}

html[data-theme] .hero-dot-vignette:hover { opacity: 0.8; }

/* La vignette courante : pleine opacite, legerement plus grande, et un contour
   dans l'accent du theme. Un contour plutot qu'une bordure : il se pose
   par-dessus l'image sans en rogner un pixel. */
html[data-theme] #page-home .hero-dot-vignette.active,
html[data-theme] .hero-dot-vignette.active {
    opacity: 1 !important;
    transform: translateY(-5px) scale(1.06);
    outline: 2px solid var(--theme-accent, #ff3b4e);
    outline-offset: -2px;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.65);
}

html[data-theme] .hero-dot-vignette:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
    opacity: 1;
}

/* Slide sans affiche : le point simple d'origine. */
html[data-theme] #page-home .hero-dot-vide,
html[data-theme] .hero-dot-vide {
    width: 9px !important;
    height: 9px !important;
    border-radius: 50% !important;
    align-self: center;
}

@media (max-width: 900px) {
    /* Retour aux points sur mobile. Les vignettes, meme reduites a 34 px,
       retombaient sur le bouton « Decouvrir le film » : la banniere y est trop
       courte pour loger une rangee d affiches. On masque l image et on rend au
       bouton sa forme de point — la navigation reste disponible, ce qui est
       l essentiel puisque les fleches sont deja cachees sur mobile. */
    html[data-theme] .hero-banner-dots {
        right: auto !important;
        left: 50% !important;
        transform: translateX(-50%) !important;
        bottom: 12px !important;
        gap: 6px !important;
        align-items: center !important;
    }
    html[data-theme] #page-home .hero-dot-vignette,
    html[data-theme] .hero-dot-vignette {
        width: 7px !important;
        height: 7px !important;
        border-radius: 50% !important;
        background: rgba(255, 255, 255, 0.45) !important;
        box-shadow: none !important;
        opacity: 1;
    }
    /* #page-home ici aussi : la regle qui met l'image en display:block plus
       haut porte cet ID, et l'emportait — on voyait des bouts d'affiche dans
       des points de 7 px. */
    html[data-theme] #page-home .hero-dot-vignette img,
    html[data-theme] .hero-dot-vignette img { display: none !important; }
    html[data-theme] #page-home .hero-dot-vignette.active,
    html[data-theme] .hero-dot-vignette.active {
        width: 20px !important;
        border-radius: 4px !important;
        background: var(--theme-accent, #ff3b4e) !important;
        outline: none !important;
        transform: none !important;
        box-shadow: none !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .hero-dot-vignette { transition: opacity 0.2s ease !important; }
    html[data-theme] .hero-dot-vignette.active { transform: none !important; }
}

/* --------------------------------------------------------------------------
 * 11. HERO : TROISIEME ACTION, ET SURTITRE DE SECTION
 *
 * Repris de TropiStream : un bouton secondaire « Ma liste » a cote de Lecture
 * et Plus d'infos, et un surtitre « En direct » au-dessus du classement.
 *
 * var(--theme-accent) partout plutot qu'une couleur en dur : les quatre themes
 * suivent sans une regle de plus (voir l'audit du 2026-10-08).
 * ------------------------------------------------------------------------ */

html[data-theme] .btn-hero-liste {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 11px 18px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(255, 255, 255, 0.08);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    color: #eef3f8;
    font: inherit;
    font-weight: 700;
    font-size: 0.86rem;
    cursor: pointer;
    /* 44 px : la meme cible tactile que les deux autres actions du hero. */
    min-height: 44px;
    transition: background 0.18s ease, border-color 0.18s ease;
}
html[data-theme] .btn-hero-liste:hover {
    background: rgba(255, 255, 255, 0.15);
    border-color: rgba(255, 255, 255, 0.28);
}
html[data-theme] .btn-hero-liste svg {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    transition: transform 0.18s ease;
}

/* Deja dans la liste : le bouton prend l'accent du theme, et le « + » pivote
   en « x ». La forme change en meme temps que la couleur — un changement de
   teinte seul ne se voit pas pour une personne daltonienne. */
html[data-theme] .btn-hero-liste.actif {
    background: color-mix(in srgb, var(--theme-accent, #ff3b4e) 22%, transparent);
    border-color: var(--theme-accent, #ff3b4e);
    color: #fff;
}
html[data-theme] .btn-hero-liste.actif svg { transform: rotate(45deg); }

/* Repli : color-mix est recent, et sans lui la regle entiere serait ignoree. */
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
    html[data-theme] .btn-hero-liste.actif { background: rgba(255, 255, 255, 0.22); }
}

html[data-theme] .btn-hero-liste:focus-visible {
    outline: 2px solid var(--theme-accent, #ff3b4e);
    outline-offset: 2px;
}

/* --- Surtitre de section --- */
/* Le badge vit DANS le .section-title (voir index.php) : en frere, il restait
   seul a l ecran quand le theme Halloween masquait le bloc du Top 10.
   margin-right: auto le colle au titre, sinon le space-between du conteneur
   l enverrait a l autre bout de la ligne. */
html[data-theme] .section-title .section-direct {
    margin-left: 12px;
    margin-right: auto;
}
html[data-theme] .section-direct {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 10px 4px 9px;
    border-radius: 6px;
    background: color-mix(in srgb, var(--theme-accent, #ff3b4e) 16%, transparent);
    color: var(--theme-accent, #ff3b4e);
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 1.1px;
    text-transform: uppercase;
}
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
    html[data-theme] .section-direct { background: rgba(255, 255, 255, 0.1); }
}

/* La pastille clignotante : c'est elle qui dit « en direct ». Animation
   desactivee plus bas pour qui demande moins de mouvement. */
html[data-theme] .section-direct::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    animation: kinooPulse 2s ease-in-out infinite;
}
@keyframes kinooPulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.25; }
}

html[data-theme] .section-surtitre-texte {
    color: #7c8692;
    font-size: 0.76rem;
    font-weight: 600;
}

@media (max-width: 768px) {
    html[data-theme] .btn-hero-liste {
        padding: 10px 14px;
        font-size: 0.8rem;
    }
    html[data-theme] .section-surtitre-texte { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .section-direct::before { animation: none !important; }
    html[data-theme] .btn-hero-liste,
    html[data-theme] .btn-hero-liste svg { transition: none !important; }
}

/* --------------------------------------------------------------------------
 * 12. ONGLETS DE FILTRE DE SECTION
 *
 * Repris de TropiStream : « Tous / Films / Séries » a droite du titre, dans la
 * meme ligne, plutot qu'un bloc de filtres sous la section.
 *
 * Voir js/onglets-section.js : ils ne sont poses que sur les sections qui
 * melangent reellement plusieurs types.
 * ------------------------------------------------------------------------ */

html[data-theme] .section-onglets {
    display: flex;
    align-items: center;
    gap: 4px;
    /* Pousse les onglets a droite : .section-title est un flex avec
       space-between, et le lien « Voir tout » reste apres eux. */
    margin-left: auto;
    margin-right: 14px;
    padding: 3px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.045);
    border: 1px solid rgba(255, 255, 255, 0.07);
}

html[data-theme] .section-onglet {
    padding: 6px 13px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: #8e97a3;
    font: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.16s ease, color 0.16s ease;
}

html[data-theme] .section-onglet:hover {
    color: #e8eef4;
    background: rgba(255, 255, 255, 0.06);
}

/* L'onglet courant : fond plein et texte clair. La couleur seule ne suffirait
   pas a le distinguer sans le contraste du fond. */
html[data-theme] .section-onglet.actif {
    background: var(--theme-accent, #ff3b4e);
    color: #fff;
}

html[data-theme] .section-onglet:focus-visible {
    outline: 2px solid var(--theme-accent, #ff3b4e);
    outline-offset: 2px;
}

@media (max-width: 768px) {
    html[data-theme] .section-onglets {
        margin-right: 8px;
        gap: 2px;
        padding: 2px;
    }
    html[data-theme] .section-onglet {
        padding: 6px 10px;
        font-size: 0.72rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .section-onglet { transition: none !important; }
}

/* --------------------------------------------------------------------------
 * 13. BOUTON « AU HASARD » DU PANNEAU D AJOUT
 *
 * Tire un film sur TMDB et remplit la fiche. Pose dans la barre de recherche
 * du panneau : c est la meme action — trouver un titre a ajouter — par un
 * autre chemin.
 * ------------------------------------------------------------------------ */
html[data-theme] .ajout-hasard {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    margin-left: 10px;
    padding: 8px 13px;
    border-radius: 9px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(255, 255, 255, 0.05);
    color: #c8d0d8;
    font: inherit;
    font-size: 0.76rem;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}
html[data-theme] .ajout-hasard:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--theme-accent, #ff3b4e);
    color: #f1f5f9;
}
/* Pendant le tirage : le bouton doit cesser de repondre, sinon deux clics
   rapides lancent deux appels TMDB et la fiche se remplit deux fois. */
html[data-theme] .ajout-hasard:disabled {
    opacity: 0.5;
    cursor: wait;
}
html[data-theme] .ajout-hasard.occupe svg {
    animation: kinooDeRoule 0.9s linear infinite;
}
@keyframes kinooDeRoule {
    to { transform: rotate(360deg); }
}
html[data-theme] .ajout-hasard:focus-visible {
    outline: 2px solid var(--theme-accent, #ff3b4e);
    outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
    html[data-theme] .ajout-hasard { transition: none !important; }
    html[data-theme] .ajout-hasard.occupe svg { animation: none !important; }
}

/* --------------------------------------------------------------------------
 * 14. ENCART DE DEMANDE
 *
 * Le systeme de demandes existait deja (page Demandes, vote, commande du bot)
 * mais ne se signalait que depuis le pied de page. L'encart lui donne une
 * porte d'entree depuis l'accueil.
 *
 * Teinte par var(--theme-accent) : orange a Halloween, dore a Noel, sans une
 * regle de plus.
 * ------------------------------------------------------------------------ */
html[data-theme] .encart-demande {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    margin: 40px 0 8px;
    padding: 26px 30px;
    border-radius: 18px;
    border: 1px solid rgba(255, 255, 255, 0.07);
    /* Degrade partant de l'accent : l'encart se detache du fond sans etre un
       bloc de couleur pleine, qui ecraserait les affiches au-dessus. */
    background:
        radial-gradient(120% 140% at 0% 50%,
            color-mix(in srgb, var(--theme-accent, #ff3b4e) 16%, transparent),
            transparent 62%),
        rgba(255, 255, 255, 0.025);
    overflow: hidden;
}

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
    html[data-theme] .encart-demande { background: rgba(255, 255, 255, 0.04); }
}

html[data-theme] .encart-demande-texte { max-width: 640px; }

html[data-theme] .encart-demande h2 {
    margin: 0 0 8px;
    font-size: 1.45rem;
    font-weight: 800;
    letter-spacing: -0.015em;
    color: #f4f7fa;
}

html[data-theme] .encart-demande p {
    margin: 0 0 18px;
    color: #a6b0bc;
    font-size: 0.92rem;
    line-height: 1.55;
}

html[data-theme] .encart-demande-bouton {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 12px 20px;
    border: 0;
    border-radius: 11px;
    background: var(--theme-accent, #ff3b4e);
    color: #fff;
    font: inherit;
    font-weight: 800;
    font-size: 0.9rem;
    cursor: pointer;
    /* 44 px : cible tactile confortable. */
    min-height: 44px;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}
html[data-theme] .encart-demande-bouton:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
}
html[data-theme] .encart-demande-bouton:active { transform: translateY(0); }
html[data-theme] .encart-demande-bouton:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 3px;
}
html[data-theme] .encart-demande-bouton svg { flex: 0 0 auto; }

/* L'icone decorative : grande, tres pale, elle habille la droite du bloc sans
   disputer l'attention au texte. aria-hidden dans le HTML. */
html[data-theme] .encart-demande-deco {
    flex: 0 0 auto;
    color: var(--theme-accent, #ff3b4e);
    opacity: 0.16;
}
html[data-theme] .encart-demande-deco svg {
    width: 128px;
    height: 128px;
    display: block;
}

@media (max-width: 860px) {
    /* L'icone part la premiere : c'est le seul element purement decoratif. */
    html[data-theme] .encart-demande-deco { display: none; }
}

@media (max-width: 768px) {
    html[data-theme] .encart-demande {
        padding: 20px 18px;
        margin: 28px 0 8px;
        border-radius: 14px;
    }
    html[data-theme] .encart-demande h2 { font-size: 1.18rem; }
    html[data-theme] .encart-demande p { font-size: 0.86rem; }
    html[data-theme] .encart-demande-bouton { width: 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .encart-demande-bouton { transition: none !important; }
    html[data-theme] .encart-demande-bouton:hover { transform: none !important; }
}

/* --------------------------------------------------------------------------
 * 15. PAGE « SOUTENIR KINOO »
 *
 * Trois offres cote a cote, celle du milieu mise en avant. Les contreparties
 * sont cosmetiques : la page le dit, et le style ne doit pas suggerer le
 * contraire — pas de cadenas, pas de « debloquer ».
 * ------------------------------------------------------------------------ */

html[data-theme] .boutique-entete {
    text-align: center;
    max-width: 680px;
    margin: 8px auto 34px;
}
html[data-theme] .boutique-entete h2 {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: #f4f7fa;
    margin: 0 0 12px;
}
html[data-theme] .boutique-accroche {
    color: #a6b0bc;
    font-size: 0.98rem;
    line-height: 1.6;
    margin: 0;
}
html[data-theme] .boutique-accroche strong { color: #e8eef4; }

/* auto-fit + minmax : trois colonnes au large, deux puis une en dessous, sans
   point de rupture a maintenir. */
html[data-theme] .boutique-offres {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
    max-width: 1020px;
    margin: 0 auto 44px;
}

html[data-theme] .boutique-offre {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 28px 24px 24px;
    border-radius: 18px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.028);
    transition: transform 0.18s ease, border-color 0.18s ease;
}
html[data-theme] .boutique-offre:hover {
    transform: translateY(-3px);
    border-color: rgba(255, 255, 255, 0.16);
}

/* L'offre mise en avant : bordure a l'accent du theme, pas un fond plein qui
   ecraserait les deux autres. */
html[data-theme] .boutique-offre.vedette {
    border-color: var(--theme-accent, #ff3b4e);
    background:
        radial-gradient(130% 120% at 50% 0%,
            color-mix(in srgb, var(--theme-accent, #ff3b4e) 13%, transparent),
            transparent 65%),
        rgba(255, 255, 255, 0.03);
}
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
    html[data-theme] .boutique-offre.vedette { background: rgba(255, 255, 255, 0.06); }
}

html[data-theme] .boutique-economie {
    position: absolute;
    top: -11px;
    left: 50%;
    transform: translateX(-50%);
    padding: 4px 12px;
    border-radius: 20px;
    background: var(--theme-accent, #ff3b4e);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    white-space: nowrap;
}

html[data-theme] .boutique-offre h3 {
    margin: 0 0 10px;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: #9aa4b2;
}
html[data-theme] .boutique-prix {
    margin: 0;
    font-size: 2.5rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: #f4f7fa;
    line-height: 1;
}
html[data-theme] .boutique-parmois {
    margin: 7px 0 18px;
    color: #7c8692;
    font-size: 0.8rem;
}

html[data-theme] .boutique-liste {
    list-style: none;
    margin: 0 0 22px;
    padding: 0;
    /* Pousse le bouton en bas : les cartes n'ont pas le meme nombre de lignes
       et leurs boutons doivent rester alignes. */
    flex: 1 1 auto;
}
html[data-theme] .boutique-liste li {
    position: relative;
    padding: 0 0 0 24px;
    margin-bottom: 10px;
    color: #b8c2cf;
    font-size: 0.88rem;
    line-height: 1.45;
}
html[data-theme] .boutique-liste li::before {
    content: '';
    position: absolute;
    left: 2px;
    top: 0.42em;
    width: 11px;
    height: 6px;
    border-left: 2px solid var(--theme-accent, #ff3b4e);
    border-bottom: 2px solid var(--theme-accent, #ff3b4e);
    transform: rotate(-45deg);
}

html[data-theme] .boutique-bouton {
    width: 100%;
    min-height: 46px;
    padding: 13px 18px;
    border: 0;
    border-radius: 11px;
    background: rgba(255, 255, 255, 0.09);
    color: #eef3f8;
    font: inherit;
    font-weight: 800;
    font-size: 0.92rem;
    cursor: pointer;
    transition: background 0.18s ease;
}
html[data-theme] .boutique-offre.vedette .boutique-bouton {
    background: var(--theme-accent, #ff3b4e);
    color: #fff;
}
html[data-theme] .boutique-bouton:hover { background: rgba(255, 255, 255, 0.16); }
html[data-theme] .boutique-offre.vedette .boutique-bouton:hover { filter: brightness(1.1); }
html[data-theme] .boutique-bouton:focus-visible {
    outline: 2px solid var(--theme-accent, #ff3b4e);
    outline-offset: 2px;
}

/* --- Le detail --- */
html[data-theme] .boutique-detail {
    max-width: 1020px;
    margin: 0 auto;
    padding: 26px 28px;
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.07);
    background: rgba(255, 255, 255, 0.022);
}
html[data-theme] .boutique-detail h3 {
    margin: 0 0 18px;
    font-size: 1.05rem;
    font-weight: 800;
    color: #f4f7fa;
}
html[data-theme] .boutique-detail-grille {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 18px;
}
html[data-theme] .boutique-detail-grille div {
    display: flex;
    flex-direction: column;
    gap: 5px;
}
html[data-theme] .boutique-detail-grille strong {
    color: #e8eef4;
    font-size: 0.9rem;
    font-weight: 700;
}
html[data-theme] .boutique-detail-grille span {
    color: #8e97a3;
    font-size: 0.84rem;
    line-height: 1.5;
}
html[data-theme] .boutique-mention {
    margin: 22px 0 0;
    padding-top: 18px;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    color: #7c8692;
    font-size: 0.82rem;
    line-height: 1.6;
}

@media (max-width: 768px) {
    html[data-theme] .boutique-entete h2 { font-size: 1.5rem; }
    html[data-theme] .boutique-offres { gap: 22px; margin-bottom: 32px; }
    html[data-theme] .boutique-detail { padding: 20px 18px; }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .boutique-offre,
    html[data-theme] .boutique-bouton { transition: none !important; }
    html[data-theme] .boutique-offre:hover { transform: none !important; }
}

/* --------------------------------------------------------------------------
 * 16. MARQUES DE SOUTIEN
 *
 * Contreparties annoncees par la page Soutenir : badge et pseudo colore. La
 * troisieme, la navigation sans publicite, vit dans js/publicites.js — elle
 * depend du marqueur .kinoo-soutien pose sur le body par app.js.
 *
 * Rien ici ne touche au catalogue : ce sont des decorations, conformement a ce
 * que la page promet.
 * ------------------------------------------------------------------------ */

html[data-theme] .pseudo-soutien {
    color: var(--theme-accent, #ff3b4e) !important;
}

html[data-theme] .badge-soutien {
    display: inline-flex;
    align-items: center;
    margin-left: 7px;
    padding: 2px 8px;
    border-radius: 5px;
    background: color-mix(in srgb, var(--theme-accent, #ff3b4e) 18%, transparent);
    border: 1px solid color-mix(in srgb, var(--theme-accent, #ff3b4e) 45%, transparent);
    color: var(--theme-accent, #ff3b4e);
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    line-height: 1.5;
    white-space: nowrap;
    vertical-align: middle;
}

/* color-mix est recent : sans repli, la regle entiere serait ignoree et le
   badge deviendrait un texte nu sans fond ni bordure. */
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
    html[data-theme] .badge-soutien {
        background: rgba(255, 255, 255, 0.1);
        border-color: rgba(255, 255, 255, 0.22);
    }
}

/* Les emplacements publicitaires laissent une place vide une fois masques :
   on la reprend, sinon la page garde des trous chez les soutiens. */
html[data-theme] body.kinoo-soutien [data-kinoo-ad] {
    display: none !important;
}

/* --------------------------------------------------------------------------
 * 17. MESSAGE D AIDE DU LECTEUR
 *
 * Le selecteur de source existait sans rien dire de son role. Ce message le
 * presente, et renvoie au Discord quand aucune source ne marche.
 *
 * Pose sous le selecteur, en haut du lecteur : visible au moment ou l on
 * cherche pourquoi la video ne demarre pas, et hors du chemin de l image.
 * ------------------------------------------------------------------------ */
html[data-theme] .lecteur-aide {
    position: absolute;
    top: 52px;
    left: 18px;
    z-index: 6;
    display: flex;
    align-items: center;
    gap: 9px;
    flex-wrap: wrap;
    max-width: min(560px, calc(100% - 36px));
    margin: 0;
    padding: 8px 13px;
    border-radius: 9px;
    background: rgba(8, 8, 12, 0.72);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: #b8c2cf;
    font-size: 0.78rem;
    line-height: 1.45;
    /* Le message informe, il ne doit pas intercepter un clic destine a la
       video ; seul le lien reste cliquable. */
    pointer-events: none;
}
html[data-theme] .lecteur-aide[hidden] { display: none; }

html[data-theme] .lecteur-aide a {
    pointer-events: auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 6px;
    background: #5865F2;
    color: #fff;
    font-weight: 700;
    font-size: 0.74rem;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.16s ease;
}
html[data-theme] .lecteur-aide a:hover { background: #4752c4; }
html[data-theme] .lecteur-aide a:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Discret au repos, net au survol. Premiere version : je ciblais
   .player-overlay.barres-masquees, une classe qui n existe pas — le masquage
   automatique du lecteur pose .lecteur-masque sur le lecteur natif, qui n est
   pas un ancetre de ce message. La regle ne matchait rien. */
html[data-theme] .lecteur-aide {
    opacity: 0.72;
    transition: opacity 0.2s ease;
}
html[data-theme] .lecteur-aide:hover { opacity: 1; }

@media (max-width: 768px) {
    html[data-theme] .lecteur-aide {
        top: 46px;
        left: 10px;
        right: 10px;
        max-width: none;
        font-size: 0.72rem;
        padding: 7px 10px;
    }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .lecteur-aide a { transition: none !important; }
    html[data-theme] .lecteur-aide { transition: none !important; }
}

/* --------------------------------------------------------------------------
 * 18. SELECTEUR D HEBERGEUR DU PANNEAU DE LECTEURS
 *
 * Coche d un coup tous les lecteurs d un hebergeur, et retient le choix pour
 * les recherches suivantes (voir js/scraper-ui.js).
 *
 * Aligne sur les boutons voisins : .scraper-actions est un flex, un select
 * brut y detonnerait avec son chrome natif.
 * ------------------------------------------------------------------------ */
html[data-theme] .scraper-hote {
    flex: 0 0 auto;
    min-width: 170px;
    padding: 8px 30px 8px 12px;
    border-radius: 9px;
    border: 1px solid #33333f;
    background-color: #ffffff08;
    color: #e8eef4;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    /* La fleche en SVG inline : le chrome natif du select est gris clair sur
       Chrome et casse le fond sombre du panneau. */
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239b9bad' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 9px center;
    background-size: 13px;
}
html[data-theme] .scraper-hote:hover { border-color: #4a4a5a; }
html[data-theme] .scraper-hote:focus-visible {
    outline: 2px solid #e44362;
    outline-offset: 1px;
}
/* Les options restent rendues par le systeme : on force le fond sombre, sinon
   elles sortent en blanc sur Windows. */
html[data-theme] .scraper-hote option {
    background: #1a1a22;
    color: #e8eef4;
}

/* --------------------------------------------------------------------------
 * 19. PASTILLES D HEBERGEURS, ET LISTES DEFILANTES
 *
 * Selection multiple par hebergeur, partagee par le panneau de lecteurs et
 * celui d import de saison (voir kinooPastillesHebergeurs dans app.js).
 *
 * Des pastilles a bascule plutot qu un select multiple : ce dernier oblige a
 * garder Ctrl enfonce, ce que personne ne devine, et n affiche pas l etat
 * courant d un coup d oeil.
 * ------------------------------------------------------------------------ */
html[data-theme] .hebergeurs-pastilles {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin: 12px 0;
}
html[data-theme] .hebergeurs-pastilles:empty { display: none; }

html[data-theme] .hebergeurs-titre {
    color: #8e97a3;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-right: 2px;
}

html[data-theme] .hebergeur-pastille {
    padding: 6px 11px;
    border-radius: 8px;
    border: 1px solid #33333f;
    background: #ffffff08;
    color: #c6c6d3;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}
html[data-theme] .hebergeur-pastille:hover {
    border-color: #4a4a5a;
    color: #e8eef4;
}
/* Actif : fond plein et texte clair. La couleur seule ne suffirait pas a
   distinguer une pastille active d une pastille survolee. */
html[data-theme] .hebergeur-pastille.actif {
    background: #692238;
    border-color: #e44362;
    color: #fff;
    font-weight: 700;
}
html[data-theme] .hebergeur-vider {
    margin-left: 4px;
    opacity: 0.75;
    font-style: italic;
}
html[data-theme] .hebergeur-pastille:focus-visible {
    outline: 2px solid #e44362;
    outline-offset: 1px;
}

/* Liste des episodes : 100 lecteurs sur huit episodes donnaient une page
   interminable, et le bouton d import se retrouvait a plusieurs ecrans de la
   selection. On plafonne et on fait defiler a l interieur. */
html[data-theme] .saison-liste {
    max-height: 440px;
    overflow-y: auto;
    margin: 12px 0;
    padding-right: 6px;
    border: 1px solid #2a2a35;
    border-radius: 12px;
    background: #00000026;
}
html[data-theme] .saison-liste > details {
    padding: 8px 12px;
    border-bottom: 1px solid #ffffff0d;
}
html[data-theme] .saison-liste > details:last-child { border-bottom: 0; }
html[data-theme] .saison-liste > details > summary {
    cursor: pointer;
    font-weight: 700;
    font-size: 13px;
    padding: 4px 0;
    /* position: sticky : en parcourant une longue saison, on perd sinon de vue
       l episode auquel appartiennent les lecteurs affiches. */
    position: sticky;
    top: 0;
    background: #14141b;
    z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .hebergeur-pastille { transition: none !important; }
}

/* --------------------------------------------------------------------------
 * 20. FENETRE D AJOUT — VOLET FILM
 *
 * Reorganisation : la fiche (titre, genre, annee) d abord, la lecture ensuite.
 * Le lien venait avant le titre, alors qu on verifie la fiche puis on colle le
 * lien.
 *
 * Les identifiants et les onclick sont inchanges : le JS, le scraper et le
 * tirage au hasard s y accrochent.
 * ------------------------------------------------------------------------ */

/* Deux groupes separes par un filet : on voit d un coup d oeil ou finit la
   fiche et ou commence la lecture. */
html[data-theme] .ajout-bloc {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-bottom: 14px;
    margin-bottom: 14px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
html[data-theme] .ajout-bloc:last-of-type {
    border-bottom: 0;
    padding-bottom: 0;
    margin-bottom: 10px;
}

/* L aide des formats, repliee : trois lignes affichees en permanence pour une
   regle qu on lit une fois. */
html[data-theme] .ajout-aide-repliee {
    margin: -2px 0 2px;
}
html[data-theme] .ajout-aide-repliee > summary {
    cursor: pointer;
    color: #7c8692;
    font-size: 0.74rem;
    font-weight: 600;
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 0;
}
html[data-theme] .ajout-aide-repliee > summary::-webkit-details-marker { display: none; }
html[data-theme] .ajout-aide-repliee > summary::before {
    content: '?';
    display: inline-grid;
    place-items: center;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 1px solid currentColor;
    font-size: 0.6rem;
    font-weight: 800;
}
html[data-theme] .ajout-aide-repliee > summary:hover { color: #b8c2cf; }
html[data-theme] .ajout-aide-repliee .ajout-aide-lien {
    margin: 6px 0 0;
    padding: 9px 11px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.035);
    font-size: 0.76rem;
    line-height: 1.6;
}

/* Les trois boutons de source sur une rangee : ils prenaient une ligne chacun
   avec leurs anciens libelles. */
html[data-theme] .ajout-sources-boutons {
    display: flex;
    gap: 7px;
    flex-wrap: wrap;
}
html[data-theme] .ajout-sources-boutons .ajout-fichiers-btn {
    flex: 0 1 auto;
    white-space: nowrap;
}

/* Le bouton du scraper automatique, mis en avant : c est celui qu on utilise
   le plus, et il se perdait entre deux boutons identiques. */
html[data-theme] .ajout-btn-auto {
    border-color: var(--theme-accent, #ff3b4e) !important;
    color: #fff !important;
}

@media (max-width: 768px) {
    html[data-theme] .ajout-sources-boutons .ajout-fichiers-btn {
        flex: 1 1 100%;
        white-space: normal;
    }
}

/* ==========================================================================
 * 21. FENETRE D AJOUT — REFONTE VISUELLE
 *
 * La version precedente se contentait de reordonner les champs : le changement
 * ne se voyait pas. Ici on reprend la fenetre elle-meme.
 *
 * Tout passe par le CSS, sans toucher au HTML : la refonte s applique donc aux
 * trois onglets (Film, Serie, Episode) d un coup, et elle ne peut pas casser le
 * JS, le scraper ni le tirage au hasard, qui s accrochent aux identifiants.
 * ========================================================================== */

/* ---- La boite ----
   840 px forcaient une colonne etroite ou chaque champ prenait toute la
   largeur. A 1100 px le formulaire respire et tient sur deux colonnes. */
html[data-theme] .ajout-modal-boite {
    max-width: 1100px !important;
    max-height: 90vh !important;
    border-radius: 20px !important;
    border-color: rgba(255, 255, 255, 0.12) !important;
    background: #0b0b11 !important;
    box-shadow: 0 32px 90px rgba(0, 0, 0, 0.75) !important;
}

/* ---- Tete ---- */
html[data-theme] .ajout-modal-tete {
    padding: 16px 20px !important;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.02);
}

html[data-theme] .ajout-modal-onglets {
    gap: 4px !important;
    padding: 4px !important;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.04);
}
html[data-theme] .ajout-modal-onglet {
    padding: 9px 18px !important;
    border-radius: 9px !important;
    font-size: 0.84rem !important;
    font-weight: 700 !important;
    letter-spacing: 0.01em;
}
/* L onglet courant prend l accent du theme, pas un rouge fige. */
html[data-theme] .ajout-modal-onglet.active {
    background: var(--theme-accent, #ff3b4e) !important;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}

/* ---- Barre de recherche ---- */
html[data-theme] .ajout-chercher {
    padding: 12px 16px !important;
    border-radius: 13px !important;
    background: rgba(255, 255, 255, 0.04) !important;
    border: 1px solid rgba(255, 255, 255, 0.09) !important;
}
html[data-theme] .ajout-chercher:focus-within {
    border-color: var(--theme-accent, #ff3b4e) !important;
    background: rgba(255, 255, 255, 0.06) !important;
}
html[data-theme] .ajout-chercher input { font-size: 0.95rem !important; }

/* ---- Le formulaire, en deux colonnes ----
   L affiche et les champs cote a cote, et sur le volet Film les deux groupes
   (fiche / lecture) se partagent la largeur au lieu de s empiler. */
html[data-theme] .ajout-form {
    padding: 18px 20px !important;
    gap: 22px !important;
}

/* 104 x 156 : une vignette. A 180 x 270 on voit reellement l affiche, ce qui
   est le seul moyen de reperer qu on s est trompe de film. */
html[data-theme] .ajout-affiche {
    flex: 0 0 180px !important;
    height: 270px !important;
    border-radius: 14px !important;
    border-style: solid !important;
    border-color: rgba(255, 255, 255, 0.1) !important;
    background: #07070c !important;
}
html[data-theme] .ajout-affiche img { width: 100%; height: 100%; object-fit: cover; }

html[data-theme] .ajout-form-champs { gap: 14px !important; }

/* Etiquettes plus lisibles : 0.62 rem en majuscules espacees se devinait
   plus qu il ne se lisait. */
html[data-theme] .ajout-form-champs label > span {
    font-size: 0.68rem !important;
    letter-spacing: 0.9px !important;
    color: #8e97a3 !important;
}

/* Champs de saisie : c est ce qu on regarde le plus longtemps. */
html[data-theme] .ajout-form-champs input[type="text"],
html[data-theme] .ajout-form-champs input[type="number"],
html[data-theme] .ajout-form-champs input[type="search"],
html[data-theme] .ajout-form-champs select,
html[data-theme] .ajout-form-champs textarea {
    padding: 11px 13px !important;
    border-radius: 10px !important;
    background: rgba(255, 255, 255, 0.04) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    color: #eef3f8 !important;
    font-size: 0.92rem !important;
    transition: border-color 0.16s ease, background 0.16s ease;
}
html[data-theme] .ajout-form-champs input:focus,
html[data-theme] .ajout-form-champs select:focus,
html[data-theme] .ajout-form-champs textarea:focus {
    border-color: var(--theme-accent, #ff3b4e) !important;
    background: rgba(255, 255, 255, 0.07) !important;
    outline: none !important;
}

/* Le lien de lecture est le champ decisif : on le distingue des autres. */
html[data-theme] .ajout-cle input {
    border-color: rgba(255, 255, 255, 0.16) !important;
    background: rgba(255, 255, 255, 0.055) !important;
}

html[data-theme] .ajout-trio { gap: 10px !important; }

/* ---- Pied ---- */
html[data-theme] .ajout-modal-pied {
    padding: 14px 20px !important;
    background: rgba(0, 0, 0, 0.35) !important;
    border-top-color: rgba(255, 255, 255, 0.09) !important;
}
html[data-theme] .ajout-modal-pied .ajout-btn-principal {
    padding: 11px 24px !important;
    border-radius: 10px !important;
    font-weight: 800 !important;
    font-size: 0.92rem !important;
}
html[data-theme] .ajout-modal-pied .ajout-btn-secondaire {
    padding: 11px 18px !important;
    border-radius: 10px !important;
}

/* ---- Derniers ajoutes : un aparte, pas une section ---- */
html[data-theme] .ajout-recents {
    margin: 0 20px 4px !important;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.025);
    border: 1px solid rgba(255, 255, 255, 0.06);
    max-height: 132px;
    overflow-y: auto;
}

/* ---- Deux colonnes sur grand ecran ----
   Les deux groupes du volet Film se partagent la largeur : la fiche a gauche,
   la lecture a droite. En dessous, ils restent empiles. */
@media (min-width: 1000px) {
    html[data-theme] #voletAjoutFilm .ajout-form-champs {
        display: grid !important;
        grid-template-columns: 1fr 1fr;
        align-items: start;
        gap: 14px 22px !important;
    }
    /* Le filet horizontal n a plus de sens entre deux colonnes : on le passe
       a la verticale, entre elles. */
    html[data-theme] #voletAjoutFilm .ajout-bloc {
        border-bottom: 0 !important;
        padding-bottom: 0 !important;
        margin-bottom: 0 !important;
    }
    html[data-theme] #voletAjoutFilm .ajout-bloc:nth-of-type(2) {
        border-left: 1px solid rgba(255, 255, 255, 0.07);
        padding-left: 22px;
    }
    /* Le repli « Resume et affiche » reprend toute la largeur sous les deux. */
    html[data-theme] #voletAjoutFilm .ajout-plus { grid-column: 1 / -1; }
}

@media (max-width: 760px) {
    html[data-theme] .ajout-form { flex-direction: column !important; }
    html[data-theme] .ajout-affiche {
        flex: 0 0 auto !important;
        width: 130px;
        height: 195px !important;
        align-self: center;
    }
    html[data-theme] .ajout-modal-boite { max-height: 94vh !important; }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .ajout-form-champs input,
    html[data-theme] .ajout-form-champs select,
    html[data-theme] .ajout-form-champs textarea { transition: none !important; }
}

/* ==========================================================================
 * 22. EMPLACEMENTS PUBLICITAIRES — FILET DE SECURITE
 *
 * Les listes de filtres bloquent par motif d URL : /css/publicites.css et
 * /js/publicites.js contiennent « publicite » et sont donc coupes avant meme
 * d etre lus.
 *
 * Consequence observee : sans publicites.css, .kinoo-ad-side perd son
 * position:fixed et son display:none. Les trois blocs retombent dans le flux,
 * avec bordure et label « Publicite », et poussent tout le contenu — la barre
 * de navigation se retrouvait au milieu de la page.
 *
 * Ce fichier porte un nom neutre : il passe. On y remet donc les regles dont
 * la mise en page depend, pour qu une page sans publicite reste une page
 * correcte. Il ne s agit pas de contourner le bloqueur : les emplacements
 * restent vides, ils cessent simplement de casser le reste.
 * ========================================================================== */

/* Masques par defaut. Ils ne s affichent que si publicites.js a tourne et pose
   kinoo-has-ads — donc jamais quand il est bloque. */
html[data-theme] .kinoo-ad {
    display: none;
}

html[data-theme] body.kinoo-has-ads .kinoo-ad-inline {
    display: block;
    width: 330px;
    max-width: 100%;
    margin: 0 auto 14px;
    overflow: hidden;
}

html[data-theme] body.kinoo-has-ads .kinoo-ad-native {
    display: block;
    max-width: 860px;
    margin: 14px auto;
    overflow: hidden;
}

/* Les colonnes laterales sont en position fixe : meme affichees, elles ne
   poussent rien. C est leur retour dans le flux qui cassait la page. */
@media (min-width: 1680px) {
    html[data-theme] body.kinoo-has-ads .kinoo-ad-side {
        display: block;
        position: fixed;
        top: 130px;
        width: 330px;
        z-index: 10;
    }
    html[data-theme] .kinoo-ad-left { left: 12px; }
    html[data-theme] .kinoo-ad-right { right: 12px; }
    html[data-theme] body.kinoo-has-ads .kinoo-ad-inline { display: none; }
}

/* Bloqueur detecte par publicites.js : on retire aussi par le style, au cas ou
   un emplacement serait injecte apres coup. */
html[data-theme] body.kinoo-pub-bloquee .kinoo-ad {
    display: none !important;
}

/* ==========================================================================
 * 23. PANNEAU TRAFIC — SEMAINE TYPE ET JOURNAL
 *
 * Deux blocs ajoutes a un panneau qui existait deja. Les reperes, la courbe
 * quotidienne et les listes gardent leurs styles de style.css : seules les
 * classes nouvelles sont definies ici.
 *
 * L'accent vient de var(--theme-accent) : la grille suit donc les quatre
 * themes sans une regle par theme.
 * ========================================================================== */

/* ---- Semaine type (7 jours x 24 heures) ----
   Une grille, pas des barres : l'intensite se lit d'un coup d'oeil et 168
   valeurs ne tiendraient pas en barres lisibles. */
html[data-theme] .trafic-grille {
    display: flex;
    flex-direction: column;
    gap: 3px;
    margin-top: 12px;
}

html[data-theme] .trafic-grille-ligne {
    display: grid;
    /* 34px pour le nom du jour, les 24 heures se partagent le reste. */
    grid-template-columns: 34px repeat(24, 1fr);
    gap: 3px;
    align-items: center;
}

html[data-theme] .trafic-grille-jour {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: #7b8492;
    text-transform: uppercase;
}

/* L'opacite est calculee en JS d'apres le maximum de la periode : la couleur
   est donc toujours la meme, seule l'intensite varie. Une case a zero est
   transparente et laisse voir le fond, qui tient lieu de grille vide. */
html[data-theme] .trafic-case {
    display: block;
    height: 15px;
    border-radius: 3px;
    background: var(--theme-accent, #ff3b4e);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04);
    transition: transform 0.1s ease;
}
html[data-theme] .trafic-case:hover {
    transform: scale(1.35);
    position: relative;
    z-index: 2;
}

html[data-theme] .trafic-grille-axe small {
    font-size: 0.6rem;
    color: #666f7c;
    text-align: center;
}

/* ---- Journal des dernieres visites ----
   Un tableau sans <table> : les colonnes sont fixes, et la liste defile dans
   sa propre hauteur pour ne pas pousser le reste du panneau. */
html[data-theme] .trafic-journal {
    margin-top: 12px;
    max-height: 340px;
    overflow-y: auto;
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 10px;
}

html[data-theme] .trafic-journal-ligne {
    display: grid;
    grid-template-columns: 94px 62px minmax(0, 1fr) 128px 120px;
    gap: 10px;
    align-items: center;
    padding: 8px 12px;
    font-size: 0.78rem;
    color: #c3cbd6;
    border-bottom: 1px solid rgba(255, 255, 255, 0.045);
}
html[data-theme] .trafic-journal-ligne:last-child { border-bottom: 0; }
html[data-theme] .trafic-journal-ligne:hover { background: rgba(255, 255, 255, 0.03); }

html[data-theme] .trafic-journal-heure { color: #8b95a3; font-variant-numeric: tabular-nums; }

/* Monospace : deux identifiants proches se distinguent a l'oeil. */
html[data-theme] .trafic-journal-visiteur {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.72rem;
    color: var(--theme-accent, #ff3b4e);
}

html[data-theme] .trafic-journal-chemin {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: #e6ecf3;
}

html[data-theme] .trafic-journal-appareil,
html[data-theme] .trafic-journal-source {
    font-size: 0.72rem;
    color: #7d8795;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Les robots restent dans le journal — les retirer cacherait justement ce
   qu'on veut pouvoir verifier — mais en retrait, pour ne pas les confondre
   avec du trafic humain. */
html[data-theme] .trafic-journal-ligne.est-robot { opacity: 0.45; }
html[data-theme] .trafic-journal-ligne.est-robot .trafic-journal-visiteur { color: #7d8795; }

/* ---- Bouton d'export ---- */
html[data-theme] .trafic-export {
    padding: 6px 13px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(255, 255, 255, 0.04);
    color: #d4dbe4;
    font-size: 0.74rem;
    font-weight: 700;
    cursor: pointer;
    transition: border-color 0.14s ease, background 0.14s ease;
}
html[data-theme] .trafic-export:hover {
    border-color: var(--theme-accent, #ff3b4e);
    background: rgba(255, 255, 255, 0.07);
}

/* Sur mobile le journal perd ses deux colonnes les moins utiles : l'appareil
   et la source tiendraient sur 40 px, donc illisibles. */
@media (max-width: 760px) {
    html[data-theme] .trafic-journal-ligne {
        grid-template-columns: 84px 56px minmax(0, 1fr);
    }
    html[data-theme] .trafic-journal-appareil,
    html[data-theme] .trafic-journal-source { display: none; }
    html[data-theme] .trafic-grille-ligne { grid-template-columns: 28px repeat(24, 1fr); gap: 2px; }
    html[data-theme] .trafic-case { height: 11px; }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .trafic-case,
    html[data-theme] .trafic-export { transition: none; }
    html[data-theme] .trafic-case:hover { transform: none; }
}

/* ==========================================================================
 * 24. PANNEAU TRAFIC — FLUX EN DIRECT
 *
 * Une ligne par lecture, affiche a gauche, phrase au milieu, anciennete a
 * droite. Les lectures en cours sont marquees ; les autres restent visibles
 * mais en retrait, parce qu'une liste qui se vide des qu'il n'y a personne ne
 * dit pas si le systeme fonctionne ou si le site est vide.
 * ========================================================================== */

html[data-theme] .trafic-bloc-direct {
    border-color: color-mix(in srgb, var(--theme-accent, #ff3b4e) 26%, transparent);
}

/* Le pouls ne clignote que pour dire « ces donnees sont vivantes » : il est
   decoratif, donc aria-hidden dans le HTML. */
html[data-theme] .trafic-pouls {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 7px;
    border-radius: 50%;
    background: var(--theme-accent, #ff3b4e);
    animation: trafic-pouls 2s ease-in-out infinite;
}
@keyframes trafic-pouls {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--theme-accent, #ff3b4e) 55%, transparent); }
    50%      { opacity: 0.55; box-shadow: 0 0 0 5px transparent; }
}

html[data-theme] .trafic-direct {
    margin-top: 12px;
    max-height: 380px;
    overflow-y: auto;
}

html[data-theme] .trafic-direct-ligne {
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr) auto;
    gap: 11px;
    align-items: center;
    padding: 8px 4px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.045);
}
html[data-theme] .trafic-direct-ligne:last-child { border-bottom: 0; }

/* Les lectures terminees sont attenuees : l'oeil doit tomber sur ce qui se
   passe maintenant, sans que le reste disparaisse. */
html[data-theme] .trafic-direct-ligne:not(.est-direct) { opacity: 0.66; }

html[data-theme] .trafic-direct-affiche {
    display: block;
    width: 34px;
    height: 51px;
    object-fit: cover;
    border-radius: 5px;
    background: #14141f;
}

html[data-theme] .trafic-direct-texte {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}

html[data-theme] .trafic-direct-phrase {
    font-size: 0.82rem;
    color: #9aa4b1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
html[data-theme] .trafic-direct-phrase b { color: #eef3f8; font-weight: 700; }
/* Un visiteur sans compte n'a pas de nom : le montrer en retrait evite de le
   confondre avec un membre. */
html[data-theme] .trafic-direct-phrase b.est-anonyme { color: #8d97a4; font-weight: 600; }

html[data-theme] .trafic-direct-titre { color: #e4eaf2; font-weight: 600; }
html[data-theme] .trafic-direct-titre em {
    font-style: normal;
    font-size: 0.74rem;
    color: var(--theme-accent, #ff3b4e);
    margin-left: 3px;
}

/* Barre d'avancement : absente quand la duree du titre est inconnue, plutot
   qu'une barre a zero qui laisserait croire a un abandon. */
html[data-theme] .trafic-direct-barre {
    display: block;
    height: 3px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.09);
    overflow: hidden;
}
html[data-theme] .trafic-direct-barre i {
    display: block;
    height: 100%;
    border-radius: 2px;
    background: var(--theme-accent, #ff3b4e);
}

html[data-theme] .trafic-direct-quand {
    font-size: 0.72rem;
    color: #7d8795;
    white-space: nowrap;
}

html[data-theme] .trafic-direct-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--theme-accent, #ff3b4e);
    color: #fff;
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

@media (max-width: 600px) {
    html[data-theme] .trafic-direct-ligne { grid-template-columns: 28px minmax(0, 1fr) auto; gap: 8px; }
    html[data-theme] .trafic-direct-affiche { width: 28px; height: 42px; }
    html[data-theme] .trafic-direct-phrase { white-space: normal; }
}

@media (prefers-reduced-motion: reduce) {
    html[data-theme] .trafic-pouls { animation: none; }
}

/* ==========================================================================
 * 25. PANNEAU DE L IMPORT AUTOMATIQUE
 *
 * L essentiel reutilise les classes du panneau Trafic : meme forme de page,
 * deja stylee pour les quatre themes. Seules les deux nuances propres a
 * l import sont definies ici.
 * ========================================================================== */

/* Une source ecartee reste visible — savoir laquelle a ete mise de cote est
   justement l information utile — mais en retrait, pour que l oeil tombe sur
   celles qui travaillent. */
html[data-theme] .trafic-ligne.est-ecartee {
    opacity: 0.45;
}
html[data-theme] .trafic-ligne.est-ecartee .trafic-ligne-nb {
    color: #8b95a3;
    font-style: italic;
}

/* Un ajout reussi est la seule ligne du journal qui merite d etre vue de
   loin : tout le reste est du bruit de fonctionnement. */
html[data-theme] .trafic-journal-source.est-ajout {
    color: var(--theme-accent, #ff3b4e);
    font-weight: 700;
}

/* Le journal de l import a une colonne de moins que celui du trafic (pas de
   provenance) : on redonne la place au libelle du resultat. */
html[data-theme] #importJournal .trafic-journal-ligne {
    grid-template-columns: 94px 70px minmax(0, 1fr) 96px 150px;
}

@media (max-width: 760px) {
    html[data-theme] #importJournal .trafic-journal-ligne {
        grid-template-columns: 84px minmax(0, 1fr) 120px;
    }
    html[data-theme] #importJournal .trafic-journal-visiteur,
    html[data-theme] #importJournal .trafic-journal-appareil {
        display: none;
    }
    /* Le resultat, lui, reste : c est la seule colonne qui dit ce qui s est
       passe. */
    html[data-theme] #importJournal .trafic-journal-source { display: block; }
}
