                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

                                                                                                                                                                                                                                                                                                                                                                                                  

.vod-card,
.channel-item,
.cat-item,
.dash-tile,
.hcard-media,
.hcard-ch,
.sett-cat-item,
.search-key,
.sd-similar-card,
.vrow-card,
.dash-fav-ch,
.dash-action-btn {
  -webkit-transition: none !important;
  transition:         none !important;
}

/* ── 2. Cartes Films / Series : anneau net, AUCUN agrandissement ───────────── */

.vod-card:focus,
.vod-card.focused,
.vod-card.active-focus {
  -webkit-transform: none !important;
  transform:         none !important;
  outline: none !important;
  border-color: var(--rsk-accent) !important;
  z-index: auto !important;
  /* flou 0 : le compositeur dessine ces trois anneaux sans filtre. Mesure a
     0,1 ms — soit le bruit de mesure. */
  -webkit-box-shadow: var(--rsk-focus-ring) !important;
  box-shadow:         var(--rsk-focus-ring) !important;
}

/* L'affiche ne bouge plus non plus : la rescaler forcait une seconde
   rasterisation de l'image a chaque deplacement. */
.vod-card:focus        .vod-card-img,
.vod-card.focused      .vod-card-img,
.vod-card.active-focus .vod-card-img,
.vrow-card:focus       .vrow-img,
.vrow-card.is-focused  .vrow-img {
  -webkit-transform: none !important;
  transform:         none !important;
  -webkit-transition: none !important;
  transition:         none !important;
}

/* Le titre passe en blanc : changement de couleur sur un petit texte, le seul
   repaint qu'on s'autorise ici. C'est ce qui remplace l'effet de zoom. */
.vod-card:focus        .vod-card-title,
.vod-card.focused      .vod-card-title,
.vod-card.active-focus .vod-card-title {
  color: #FFFFFF !important;
  font-weight: 700 !important;
  text-shadow: none !important;
}

/* ── 3. Colonne des categories : fond plein, jamais de halo ────────────────── */

.cat-item:focus,
.cat-item.focused,
.cat-item.active-focus {
  -webkit-transform: none !important;
  transform:         none !important;
  -webkit-box-shadow: inset 5px 0 0 rgba(0,0,0,0.22) !important;
  box-shadow:         inset 5px 0 0 rgba(0,0,0,0.22) !important;
  outline: none !important;
}

/* ── 4. Liste des chaines : ombre INSET seulement ──────────────────────────────
   Liste dense : une ombre exterieure floue repeindrait les lignes voisines a
   chaque cran. */

.channel-item:focus,
.channel-item.focused,
.channel-item.ch-cursor {
  -webkit-transform: none !important;
  transform:         none !important;
  -webkit-box-shadow: var(--rsk-focus-bar) !important;
  box-shadow:         var(--rsk-focus-bar) !important;
  outline: none !important;
}

/* ── 5. Tuiles de l'accueil ────────────────────────────────────────────────── */

.dash-tile:focus,
.dash-tile.focused,
.dash-tile.active-focus {
  -webkit-transform: none !important;
  transform:         none !important;
  outline: none !important;
  z-index: auto !important;
  -webkit-box-shadow: var(--rsk-focus-ring) !important;
  box-shadow:         var(--rsk-focus-ring) !important;
}

/* ── 6. Rangees Films/Series (module vodrows) ──────────────────────────────── */

.vrow-card.is-focused,
.vrow-card:focus {
  -webkit-transform: none !important;
  transform:         none !important;
  z-index: auto !important;
  -webkit-box-shadow: var(--rsk-focus-ring) !important;
  box-shadow:         var(--rsk-focus-ring) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   0. JETONS DE FOCUS — une seule source de verite                    (v502)
   --------------------------------------------------------------------
   Regle Samsung 4.4 : « The focus pattern or image should be similar or
   consistent within the same application. Avoid using various focus
   patterns. »   (developer.samsung.com/smarttv/design/ux-checklist.html)

   AUDIT DU 23/08 : les valeurs de l'anneau etaient recopiees a la main dans
   SIX blocs, et deux d'entre eux (tuiles du hub, tuiles d'accueil) avaient
   perdu le halo en route. Meme motif, deux rendus selon l'ecran.

   LE SYSTEME, en trois motifs pour trois NATURES de surface — ce que font
   aussi Netflix et Apple, et ce que la regle 4.4 autorise :

     CARTE SUR ILLUSTRATION -> anneau + halo   (affiches, tuiles, jaquettes)
         le halo detache la carte d'une affiche chargee
     CONTROLE SUR FOND PLAT -> anneau seul     (touches du clavier, reglages)
         a 76 px avec 14 px de gouttiere, un halo de 8 px mordrait la touche
         voisine : le halo n'apporte rien et nuit
     LISTE DENSE            -> barre + teinte  (liste des chaines)
     MENU                   -> fond clair      (panneaux langue et pistes)

   Changer la couleur d'accent du produit = changer --rsk-focus ci-dessous.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  --rsk-focus:            var(--rsk-accent);
  --rsk-focus-ring:       0 0 0 4px var(--rsk-accent), 0 0 0 8px rgba(var(--rsk-accent-rgb), 0.25);
  /* ⚠️ v502b — ces deux jetons DOIVENT porter des valeurs litterales.
     Ma passe de remplacement global avait reecrit chaque valeur par son propre
     jeton, y compris DANS sa definition : `--rsk-focus-bar: var(--rsk-focus-bar)`
     est circulaire, donc vide, et la barre de la liste Direct avait disparu.
     Mesure sur TV : boxShadow = "none". Ne jamais laisser une substitution
     automatique toucher le bloc :root. */
  --rsk-focus-ring-plain: 0 0 0 4px var(--rsk-accent);
  --rsk-focus-bar:        inset 4px 0 0 var(--rsk-accent);
  --rsk-focus-tint:       rgba(var(--rsk-accent-rgb), 0.15);
  --rsk-focus-wash:       rgba(255,255,255,0.14);
}

/* ══════════════════════════════════════════════════════════════════════════
   GRIDNAV — grille Films/Series sans focus natif (js/ui/gridnav.js)
   Mesure : 18,8 ms / 53 fps contre 59,5 ms / 17 fps avec le focus natif.
   Le plancher physique de la TV est a 16,8 ms.

   IMPORTANT : seuls .gn-track et .gn-cursor portent will-change. Les cartes
   restent dans le flux normal. Promouvoir 60 cartes de 240x394 en couches GPU
   ferait ~22 Mo de textures — la configuration mesuree a 18,8 ms ne promeut
   que la piste et le curseur.
   ══════════════════════════════════════════════════════════════════════════ */

.gn-host {
  position: relative !important;
  display:  block    !important;
  overflow: hidden   !important;   /* le defilement passe par transform */
}

.gn-track {
  position: absolute;
  left: 0; top: 0; right: 0;
  display: -webkit-flex; display: flex;
  -webkit-flex-wrap: wrap; flex-wrap: wrap;
  -webkit-align-content: flex-start; align-content: flex-start;
  padding: 0 44px;                 /* padding-top pose par le JS */
  -webkit-transform: translate3d(0,0,0);
  transform:         translate3d(0,0,0);
  will-change: transform;
}

/* Les gouttieres sont EN DUR ici : le JS calcule les positions a partir de
   _cardW + 40 et _cardH + 36. Si tu changes ces deux marges, change aussi
   _cw et _ch dans gridnav.js, sinon le curseur se decale des cartes. */
.gn-card {
  margin: 0 40px 36px 0 !important;
  -webkit-flex: 0 0 auto; flex: 0 0 auto;
  -webkit-transform: none !important;
  transform:         none !important;
  -webkit-transition: none !important;
  transition:         none !important;
  -webkit-box-shadow: none !important;
  box-shadow:         none !important;
  z-index: auto !important;
}

/* Le curseur : un seul element, deplace uniquement en transform.
   Anneaux a flou 0 — mesures a 0,1 ms, soit le bruit de mesure. */
.gn-cursor {
  position: absolute;
  left: 0; top: 0;
  pointer-events: none;
  border-radius: 12px;
  -webkit-box-shadow: var(--rsk-focus-ring);
  box-shadow:         var(--rsk-focus-ring);
  -webkit-transform: translate3d(0,0,0);
  transform:         translate3d(0,0,0);
  will-change: transform;
  z-index: 50;
}

/* ══════════════════════════════════════════════════════════════════════════
   HUB D'ACCUEIL (dash-v2) — meme maladie que la grille, meme remede.

   Mesure TV du 21/08/2026, RETOUR depuis une section vers l'accueil :
     resetScreensaverTimer() ......   0,4 ms
     showSection('dashboard') .....   2,4 ms
     DashV2.focus() ............... 110,2 ms   <-- 80 % du retour
                                    136,8 ms

   Pourquoi 110 ms : DashV2.focus() pose la classe .dv-focused, PUIS appelle
   hub.focus() sur le conteneur. Le style est « sale » depuis le changement de
   classe, donc ce focus() force un recalcul de style et un layout SYNCHRONES de
   tout le hub. Et .dv-focused portait `transform: scale()` — la propriete qui
   sort l'element du flux et oblige a tout recalculer.
   (Mesure de controle : hub.focus() sur un style deja propre coute 0,3 ms.)

   Comme pour les cartes Films, on garde l'anneau net et on retire
   l'agrandissement. Gain attendu sur le RETOUR : ~137 ms -> ~30 ms.
   Bonus : la navigation DANS le hub devient elle aussi instantanee.
   ══════════════════════════════════════════════════════════════════════════ */

html.ui-v2 #dash-v2 .dv-tile.dv-focused,
html.ui-v2 #dash-v2 .dv-tile.is-focused,
html.ui-v2 #dash-v2 .dv-card.dv-focused,
html.ui-v2 #dash-v2 .dv-card.is-focused,
html.ui-v2 #dash-v2 .dv-poster.dv-focused,
html.ui-v2 #dash-v2 .dv-poster.is-focused,
html.ui-v2 #dash-v2 .dv-hero-x.dv-focused,
html.ui-v2 #dash-v2 .dv-hero-x.is-focused {
  -webkit-transform: none !important;
  transform:         none !important;
  z-index: auto !important;
  -webkit-box-shadow: var(--rsk-focus-ring) !important;
  box-shadow:         var(--rsk-focus-ring) !important;
  outline: none !important;
}

/* Aucune transition sur le chemin de deplacement du hub. */
html.ui-v2 #dash-v2 .dv-tile,
html.ui-v2 #dash-v2 .dv-card,
html.ui-v2 #dash-v2 .dv-poster,
html.ui-v2 #dash-v2 .dv-hero-x {
  -webkit-transition: none !important;
  transition:         none !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   SIDEBAR DU HUB — deployer/replier ne doit RIEN relayouter

   Symptome : sur l'accueil, appuyer sur GAUCHE pour ouvrir la sidebar met du
   temps a repondre.

   Cause : ui-v2.css declare le decalage du contenu en `transform` — et son
   commentaire dit bien « le decalage se fait en TRANSFORM (GPU, zero reflow) ».
   Mais la regle du mode rail ajoute EN PLUS :

       html.ui-v2.v2-hub.sb-hidden .home-main { width: calc(100% - rail); }

   `width` est une propriete de LAYOUT. La basculer fait recalculer la mise en
   page de TOUT le hub — chaque etagere, chaque affiche, chaque tuile — a chaque
   ouverture ou fermeture de la sidebar. Le reflow qu'on croyait avoir supprime
   revenait par cette ligne.

   Remede : `.home-main` ne bouge plus DU TOUT. Elle garde en permanence la
   largeur et le decalage du rail. Quand la sidebar se deploie, elle passe
   simplement PAR-DESSUS les 200 premiers pixels du contenu — c'est le motif
   habituel des interfaces TV, et l'utilisateur regarde la sidebar a ce
   moment-la, pas le contenu qu'elle recouvre.

   Resultat : ouvrir la sidebar ne touche plus que son propre sous-arbre
   (une colonne et huit entrees) au lieu de la page entiere.
   ══════════════════════════════════════════════════════════════════════════ */

/* ⚠️ CORRECTIF v501 — ma propre regression de v488, mesuree le 23/08.
   v488 posait `left:0; right:0` (donc largeur 1920) PUIS
   `transform: translateX(100px)` : le contenu allait de x=100 a x=2020, soit
   100 px hors dalle a droite. Toutes les etagures du hub etaient rognees.
   ui-v2.css:165 avait `width: calc(100% - rail)` precisement pour ca — son
   commentaire le dit : « bord droit a l'ecran, hero droit non rogne ». Je
   l'avais neutralise parce que basculer `width` provoquait un reflow complet
   a chaque ouverture de sidebar. L'erreur etait de le retirer dans les DEUX
   etats au lieu de le FIGER.
   Ici : position posee une seule fois, jamais rebasculee -> aucun reflow a
   l'interaction, et le bord droit tombe juste. */
html.ui-v2.v2-hub .home-main,
html.ui-v2.v2-hub.sb-hidden .home-main {
  left:  var(--sb-rail) !important;       /* decalage FIGE, plus de transform */
  right: 0 !important;
  width: auto !important;                 /* -> 1920 - rail, bord droit a l'ecran */
  -webkit-transform: none !important;
  transform:         none !important;
  -webkit-transition: none !important;
  transition:         none !important;
}

/* La sidebar deployee passe au-dessus du contenu. Elle a deja un fond opaque
   (degrade) dans ui-v2.css — on retire la transition qui retarderait l'affichage.

   ⚠️ MAIS z-index:60 NE SUFFISAIT PAS. `#dv-weather-sec` porte AUSSI z-index:60,
   et `.home-main` (z-index:auto) ne cree pas de contexte d'empilement : les deux
   elements se disputent donc le MEME contexte, a egalite. A z-index egal, c'est
   l'ordre du DOM qui tranche — et `#screen-home` vient apres `#sidebar-v2` dans
   index.html. La barre meteo (132 px de haut, x=100 a 1920) recouvrait donc le
   HAUT de la sidebar deployee, c'est-a-dire exactement le bloc de marque.

   Mesure au banc le 20/09/2026, sidebar ouverte par la touche GAUCHE :
       elementFromPoint(131, 82) -> #dv-weather-sec, et non le logo.

   Compter les z-index ne suffit pas : il faut savoir QUEL contexte
   d'empilement les arbitre. */
html.ui-v2.v2-hub #sidebar-v2 {
  -webkit-transition: none !important;
  transition:         none !important;
  z-index: 70 !important;
}

/* ── Bloc de marque de la sidebar : le motif « manchette » d'Android ────────
   Le verrou complet dit deja « RSKTV PLAYER PRO TV ». Le repeter a cote en
   toutes lettres ne tenait pas : mesure au banc, « LECTEUR MULTIMEDIA » demande
   ~250 px et il en restait 134 — le texte etait coupe net au bord de la barre.

   Android resout le meme probleme dans RstvBrand.kt (`RstvBrandMasthead`) :
   verrou cale a gauche, contraint en hauteur, et sous lui un court filet
   d'accent qui s'estompe — le procede des manchettes de presse. Pas de texte
   redondant. On le reprend tel quel.

   L'element .sb-brand-sub est CONSERVE dans le DOM : i18n.js le traduit
   (liste de selecteurs, ligne ~676) et un `display:none` est sans effet sur
   lui, alors qu'une suppression rendrait cette entree muette sans qu'on le
   voie. */
html.ui-v2.v2-hub .sb-brand {
  -webkit-box-orient: vertical; -webkit-flex-direction: column; flex-direction: column;
  -webkit-box-align: start; -webkit-align-items: flex-start; align-items: flex-start;
}
html.ui-v2.v2-hub .sb-brand-text { display: none !important; }
html.ui-v2.v2-hub .sb-brand:after {
  content: ''; display: block; width: 36px; height: 2px; margin-top: 14px;
  border-radius: 1px;
  background: -webkit-linear-gradient(left, var(--rsk-accent), rgba(var(--rsk-accent-rgb), 0));
  background:         linear-gradient(90deg, var(--rsk-accent), rgba(var(--rsk-accent-rgb), 0));
}
/* En rail, le filet serait un trait perdu sous une icone : on le retire. */
html.ui-v2.v2-hub.sb-hidden .sb-brand:after { display: none; }
html.ui-v2.v2-hub.sb-hidden .sb-brand {
  -webkit-box-align: center; -webkit-align-items: center; align-items: center; }

/* ══════════════════════════════════════════════════════════════════════════
   PANNEAU PISTES AUDIO / SOUS-TITRES (v490)
   La piste active porte une coche. Sans reperage visuel, l'utilisateur ne sait
   pas ce qu'il ecoute ni ce qu'il lit — c'est la premiere chose que fait
   Netflix. La gouttiere est reservee sur TOUTES les lignes pour que le texte
   reste aligne quand la selection change.
   ══════════════════════════════════════════════════════════════════════════ */

.pl-track-item {
  position: relative;
  padding-left: 46px !important;
}
.pl-track-item::before {
  content: '';
  position: absolute;
  left: 16px; top: 50%;
  margin-top: -11px;
  width: 22px; height: 22px;
  font-size: 22px; line-height: 22px;
  color: var(--rsk-accent);
}
.pl-track-item.active::before { content: '\2713'; }   /* ✓ */

/* ── 7. Vignettes de l'accueil (etagere) ───────────────────────────────────── */

/* Cartes posees sur une illustration -> anneau AVEC halo (il detache
   l'element d'une affiche chargee). */
.hcard-media:focus,
.hcard-ch:focus,
.sd-similar-card:focus,
.dash-fav-ch:focus {
  -webkit-transform: none !important;
  transform:         none !important;
  outline: none !important;
  -webkit-box-shadow: var(--rsk-focus-ring) !important;
  box-shadow:         var(--rsk-focus-ring) !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   PANNEAU PISTES — mention « langues non fournies » (v493)
   Affichee uniquement quand AUCUNE piste n'a de langue connue. Sans elle, le
   client attribue a l'application une information que son fournisseur ne
   livre pas.
   ══════════════════════════════════════════════════════════════════════════ */
.pl-track-hint {
  margin: 14px 16px 4px;
  padding: 10px 14px;
  font-size: 20px;
  line-height: 1.35;
  color: rgba(255,255,255,0.62);
  border-left: 3px solid rgba(var(--rsk-accent-rgb), 0.55);
  max-width: 560px;
}


/* ══════════════════════════════════════════════════════════════════════════
   9. PANNEAU DES PISTES — deux colonnes, hauteur bornee            (v495)
   --------------------------------------------------------------------
   MESURE sur la TV, film a 20 pistes de sous-titres :
     ecran 1920x1080 · panneau haut de 1765 px · bord superieur a y = -885
     ligne de 71 px · ni max-height ni overflow declares
   => HUIT pistes hors de l'ecran, impossibles a atteindre.

   Le panneau etait ancre `bottom: 200px` et grandissait vers le HAUT :
   plus il y a de pistes, plus il sort par en haut. On borne donc la
   hauteur (top + bottom) et chaque colonne defile pour son compte.

   Contraintes Tizen 4 (Chromium M56) respectees : pas de `gap`, pas de
   `calc()`, pas de `filter`, prefixes -webkit- sur les boites flexibles.
   ══════════════════════════════════════════════════════════════════════════ */

.pl-track-panel {
  top: 90px !important;
  bottom: 90px !important;
  right: 90px !important;
  left: auto !important;
  width: 940px !important;
  min-width: 0 !important;
  max-width: none !important;
  padding: 30px 34px !important;
  background: rgba(8, 8, 20, 0.97) !important;
  border: 1px solid rgba(255, 255, 255, 0.10) !important;
  border-radius: 14px !important;
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-flex-direction: column;
  flex-direction: column;
}

.pl-tp-cols {
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  -webkit-box-flex: 1;
  -webkit-flex: 1 1 auto;
  flex: 1 1 auto;
  min-height: 0;          /* sans ca, un enfant flexible refuse de retrecir */
}

.pl-tp-col {
  -webkit-flex: 1 1 50%;
  flex: 1 1 50%;
  min-width: 0;
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-flex-direction: column;
  flex-direction: column;
}

.pl-tp-col + .pl-tp-col {
  margin-left: 30px;
  padding-left: 30px;
  border-left: 1px solid rgba(255, 255, 255, 0.08);
}

.pl-tp-head {
  font-size: 23px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, 0.52);
  margin: 0 0 16px 46px;
}

/* La zone qui defile. Une seule par colonne : le curseur reste dedans. */
.pl-tp-scroll {
  -webkit-box-flex: 1;
  -webkit-flex: 1 1 auto;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}
.pl-tp-scroll::-webkit-scrollbar { width: 4px; }
.pl-tp-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); border-radius: 2px; }
.pl-tp-scroll::-webkit-scrollbar-track { background: transparent; }

/* ── Lignes : texte simple. Un seul signal a la fois. ───────────────────── */
.pl-track-panel .pl-track-item {
  padding: 11px 12px 11px 46px !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 8px !important;
  font-size: 25px !important;
  font-weight: 400 !important;
  color: rgba(255, 255, 255, 0.60) !important;
  white-space: nowrap;
  overflow: hidden;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
}

/* Piste ACTIVE : la coche suffit, plus de pave rouge. */
.pl-track-panel .pl-track-item.active {
  background: transparent !important;
  border: 0 !important;
  color: #fff !important;
}

/* CURSEUR : un fond clair, rien d'autre. Pas de bordure qui change en meme
   temps, pas d'agrandissement (cause racine mesuree le 21/08 sur la grille). */
.pl-track-panel .pl-track-item.is-focused,
.pl-track-panel .pl-track-item:focus {
  background: rgba(255, 255, 255, 0.14) !important;
  border: 0 !important;
  color: #fff !important;
  outline: none !important;
  -webkit-transform: none !important;
  transform: none !important;
  -webkit-box-shadow: none !important;
  box-shadow: none !important;
}

.pl-track-panel .pl-track-item::before {
  left: 14px;
  color: #fff;
}

/* Colonne SANS le curseur : reculee, jamais eteinte. */
.pl-tp-col.pl-tp-idle .pl-tp-head            { color: rgba(255, 255, 255, 0.30); }
.pl-tp-col.pl-tp-idle .pl-track-item         { color: rgba(255, 255, 255, 0.34) !important; }
.pl-tp-col.pl-tp-idle .pl-track-item.active  { color: rgba(255, 255, 255, 0.78) !important; }
.pl-tp-col.pl-tp-idle .pl-track-item::before { color: rgba(255, 255, 255, 0.78); }

.pl-track-empty {
  color: rgba(255, 255, 255, 0.32) !important;
  padding-left: 46px !important;
}

.pl-track-panel .pl-track-hint {
  -webkit-flex: 0 0 auto;
  flex: 0 0 auto;
  margin: 20px 0 0 46px !important;
  max-width: none !important;
  font-size: 19px;
}

/* Le titre d'origine n'existe plus dans la structure ; on neutralise au cas
   ou une ancienne feuille le ferait reapparaitre. */
.pl-track-panel-title { display: none !important; }


/* ══════════════════════════════════════════════════════════════════════════
   10. BOUTON LANGUE — grille unique, puis audio ou sous-titres      (v496)
   --------------------------------------------------------------------
   v495 affichait deux colonnes ou les memes noms de langue revenaient des
   deux cotes. Une seule grille suffit : chaque langue y figure une fois,
   avec ce qui existe reellement pour elle dans le fichier.
   Pas de `gap` ni de `calc()` : Tizen 4 / Chromium M56.
   ══════════════════════════════════════════════════════════════════════════ */

.pl-lang-grid { font-size: 0; }        /* absorbe les blancs entre inline-block */

.pl-lang-cell {
  display: -webkit-inline-box;
  display: inline-block;
  vertical-align: top;
  width: 274px;
  margin: 0 12px 12px 0;
  padding: 12px 16px;
  border-radius: 8px;
  background: transparent;
  overflow: hidden;
}
.pl-lang-cell.is-focused {
  background: rgba(255, 255, 255, 0.14);
  -webkit-transform: none;
  transform: none;
}
.pl-lang-name {
  display: block;
  font-size: 25px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.62);
  white-space: nowrap;
  overflow: hidden;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis;
}
.pl-lang-cell.is-focused .pl-lang-name,
.pl-lang-cell.has-on .pl-lang-name { color: #fff; }

.pl-lang-tags {
  display: block;
  margin-top: 4px;
  font-size: var(--rsk-fs-xs);
  color: rgba(255, 255, 255, 0.34);
  white-space: nowrap;
}
.pl-lang-tag.on { color: #fff; }

/* Choix audio / sous-titres — deuxieme temps */
.pl-lang-choice {
  -webkit-flex: 0 0 auto;
  flex: 0 0 auto;
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}
.pl-lang-choice.hidden { display: none; }
.pl-lang-choice-title {
  font-size: 21px;
  color: rgba(255, 255, 255, 0.52);
  margin-bottom: 12px;
}
.pl-lang-choice-row { font-size: 0; }
.pl-lang-opt {
  display: inline-block;
  min-width: 220px;
  margin-right: 14px;
  padding: 12px 20px;
  border-radius: 8px;
  font-size: 25px;
  color: rgba(255, 255, 255, 0.62);
  background: transparent;
}
.pl-lang-opt.is-focused { background: rgba(255, 255, 255, 0.14); color: #fff; }
.pl-lang-opt.hidden     { display: none; }


/* ══════════════════════════════════════════════════════════════════════════
   11. GRILLE DE LANGUES — sections Audio / Sous-titres            (v497)
   --------------------------------------------------------------------
   v496 fusionnait les deux types en une seule liste. Reproduit hors TV sur
   le film reel de l'utilisateur : 1 piste audio anonyme + 12 sous-titres,
   l'unique choix audio se retrouvait en DERNIERE position au milieu des
   sous-titres. La fusion n'a de sens que si les deux cotes partagent des
   langues — ce qui n'est pas le cas ici.
   ══════════════════════════════════════════════════════════════════════════ */

.pl-lang-sec {
  display: block;
  font-size: 20px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, 0.42);
  margin: 0 0 10px 4px;
}
.pl-lang-sec + .pl-lang-sec,
.pl-lang-cell + .pl-lang-sec { margin-top: 22px; }

/* La ligne de tags de v496 n'a plus lieu d'etre : la section porte le type. */
.pl-lang-tags { display: none !important; }

.pl-lang-cell { padding: 10px 16px; }
.pl-lang-name { font-size: 24px; }

.pl-lang-check {
  display: inline-block;
  width: 26px;
  color: #fff;
}


/* ══════════════════════════════════════════════════════════════════════════
   12. BARRE METEO — elle debordait sur TOUTES les sections          (v498)
   --------------------------------------------------------------------
   Signale le 22/08 : la meteo s'affichait par-dessus le mini-lecteur du
   Direct, identique quelle que soit la chaine.

   CHAINE DES CAUSES, verifiee dans le code :
    1. `dashboard.js:583` DEPLACE #dv-weather-sec hors de #section-dashboard
       pour en faire le premier enfant de .home-main. C'etait volontaire :
       .home-main ne defile pas, donc la barre y devient vraiment fixe.
       Effet de bord : elle devient soeur de TOUTES les sections.
    2. `renderWeather` la rend visible (sec.style.display = '').
    3. `app.js:345` retire la classe v2-hub des qu'on quitte le hub. La regle
       qui la positionnait en absolu cesse alors de s'appliquer, et la barre
       redevient un bloc normal en haut de .home-main — donc au-dessus de la
       section active, Direct compris.
    4. RIEN ne la masquait jamais.

   ⚠️ Le piege de diagnostic : le Direct N'EST PAS un `.screen` separe. Toutes
   les sections vivent dans #screen-home (index.html 510 -> 1657). Raisonner
   « l'ecran est en display:none » est donc FAUX ici.

   Le `padding-top: var(--wx-h)` qui reserve sa place est limite a
   `#section-dashboard.active` (ui-v2.css:183) : la masquer ailleurs ne laisse
   aucun espace vide.
   ══════════════════════════════════════════════════════════════════════════ */

html:not(.v2-hub) .home-main > #dv-weather-sec { display: none !important; }


/* Controles a fond plat : anneau SEUL (voir jetons, bloc 0). */
.sett-cat-item:focus,
.search-key:focus {
  -webkit-transform: none !important;
  transform:         none !important;
  outline: none !important;
  -webkit-box-shadow: var(--rsk-focus-ring-plain) !important;
  box-shadow:         var(--rsk-focus-ring-plain) !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   13. ZAPPEUR — les lignes se chevauchaient                          (v504)
   --------------------------------------------------------------------
   Mesure sur TV, panneau de zapping ouvert :
       .zap-item .............. hauteur FIXE 76 px, overflow hidden
       .zap-item-info ......... contenu 125 px
       lignes : 34 (nom) + 22 (prog) + 3 (barre) + 56 (suivant) = 115 px
   `.zap-item-next` etait en `white-space: normal` et `overflow: visible` :
   il passait sur DEUX lignes et debordait de la ligne, produisant les textes
   empiles a moitie coupes.

   Deux corrections : chaque ligne tient sur UNE ligne avec ellipse, et la
   hauteur de rangee passe a 96 px pour loger les quatre elements sans
   rognage. Interlignes explicites : `normal` varie selon la fonte chargee,
   donc la hauteur n'etait pas deterministe.
   ══════════════════════════════════════════════════════════════════════════ */

.zap-item {
  height: 96px !important;
  overflow: hidden;
}
.zap-item-name,
.zap-item-prog,
.zap-item-next {
  white-space: nowrap !important;
  overflow: hidden !important;
  -o-text-overflow: ellipsis;
  text-overflow: ellipsis !important;
  display: block;
}
.zap-item-name { font-size: 28px !important; line-height: 34px !important; }
.zap-item-prog { font-size: var(--rsk-fs-xs) !important; line-height: 22px !important; }
.zap-item-next { font-size: var(--rsk-fs-xs) !important; line-height: 22px !important; }
.zap-item-prog-bar { height: 3px !important; }


/* ══════════════════════════════════════════════════════════════════════════
   14. RECHERCHE — etiquette de perimetre                             (v506)
   Une recherche restreinte SANS le dire serait pire que pas de restriction :
   l'utilisateur croirait le catalogue vide. Le perimetre est donc affiche.
   ══════════════════════════════════════════════════════════════════════════ */
.search-scope {
  margin-left: 18px;
  padding: 6px 16px;
  border-radius: 999px;
  font-size: var(--rsk-fs-xs);
  font-weight: 500;
  color: #fff;
  background: var(--rsk-focus-tint);
  border: 1px solid var(--rsk-accent);
  white-space: nowrap;
}
.search-scope:empty { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   BLOC 13 — LISTE DIRECT FENETREE (v513)
   ---------------------------------------------------------------------------
   Le <ul> n'est plus le conteneur qui defile : il devient la PISTE, deplacee
   en translate3d par _liveWinPaint(). Le clipping passe au viewport parent.

   Pourquoi : `scrollTop` coute une image entiere (mesure : 13,4 ms par
   deplacement a 60 items, 47,5 ms a 600) parce que le conteneur n'est pas
   composite. Un transform est pris en charge par le compositeur.

   ⚠️ `contain: strict` doit etre neutralise sur la piste : il impose un
   confinement de TAILLE, donc la piste serait ramenee a la hauteur du
   viewport et les lignes au-dela seraient coupees. Le confinement utile
   (layout + style) est porte par le viewport.
   ═══════════════════════════════════════════════════════════════════════════ */
.live-ch-viewport {
  -webkit-flex: 1; flex: 1;
  position: relative;
  overflow: hidden;
  -webkit-contain: layout style;
  contain: layout style;
}
.live-ch-viewport > #live-channel-list.live-tv-ch-list {
  height: auto;
  max-height: none;
  overflow: visible;
  contain: none;
  padding-top: 0;          /* la marge haute est pilotee par la fenetre */
  -webkit-transform: translate3d(0, 0, 0);
  transform:         translate3d(0, 0, 0);
  will-change: transform;
}


/* ══════════════════════════════════════════════════════════════════════════
   SURFACES THEMATIQUES (D2 — 20/09/2026)

   Ces fonds etaient ecrits en dur, donc identiques dans les sept themes. Le
   defaut ne se voyait pas sur les six themes sombres — il fallait le theme
   CLAIR pour le reveler : des ilots sombres au milieu d'une interface claire,
   dont le texte restait pourtant parfaitement lisible (blanc sur noir). Un
   controle de contraste seul ne les signale donc PAS.

   Liste etablie par mesure sur les 14 ecrans et sections
   (scratchpad/balayage_clair.js) : 43 ilots distincts.

   Le bloc est ici, et pas dans les six feuilles d'origine, parce que
   perf-nav.css est charge en dernier et fait autorite : une seule adresse a
   lire, un seul bloc a supprimer pour revenir en arriere.

   ⚠️ RESTENT SOMBRES, VOLONTAIREMENT :
     - #player-epg-panel / #player-ch-selector : poses SUR LA VIDEO. Un panneau
       clair par-dessus un film serait illisible, et eblouissant dans le noir.
     - .act-poster.c1..c7 : mosaique d'affiches factices, decoration figurative.
     - .act-key-box : carte d'accent, elle suit deja la couleur de marque.
   ══════════════════════════════════════════════════════════════════════════ */

/* ecran de chargement */
#spl-loading {
  background: var(--rsk-bg) !important;
}

/* fond de l'ecran d'activation */
#screen-activation .act-bg {
  background: var(--rsk-bg) !important;
}

/* les 7 sections du hub portaient toutes #0C0C18 en dur */
#section-live, #section-vod, #section-series, #section-radio,
#section-catchup, #section-search, #section-favoris {
  background: var(--rsk-bg) !important;
}

/* reglages */
#section-settings, .sett-layout, #sett-right {
  background: var(--rsk-bg) !important;
}

/* recherche */
.search-layout {
  background: var(--rsk-bg) !important;
}

/* bandeau d'accueil */
#home-ticker {
  background: var(--rsk-bg) !important;
}

#live-actbar {
  background: var(--rsk-bg-2) !important;
}

#cu-topbar, #cu-infobar {
  background: var(--rsk-bg-2) !important;
}

/* colonnes du Direct */
#live-ch-col, #live-cat-col {
  background: var(--rsk-surface) !important;
}

.live-tv-epg {
  background: var(--rsk-surface) !important;
}

/* colonne des categories */
#sett-left {
  background: var(--rsk-surface) !important;
}

/* panneaux du Catch-up */
#cu-panel-chans, #cu-panel-cats {
  background: var(--rsk-surface) !important;
}

/* en-tetes de colonne */
#cu-chans-hdr, #cu-cats-hdr {
  background: var(--rsk-surface-2) !important;
}

.live-info-bar {
  background: var(--rsk-surface-2) !important;
}

/* carte de l'adresse MAC */
#screen-activation .act-mac-box {
  background: var(--rsk-surface-2) !important;
}


/* Surfaces d'ACCENT : elles suivent la couleur de marque. */

/* categorie active des Favoris (etait un rouge sombre litteral) */
#fav-cat-list .cat-item.active {
  background: var(--rsk-accent-deep) !important;
}


/* ══════════════════════════════════════════════════════════════════════════
   TEXTES THEMATIQUES (D2 — 20/09/2026)

   Ces couleurs de texte etaient ecrites en dur, en blanc ou en gris clair.
   Elles ne se voyaient pas tant que les fonds etaient sombres — ce sont les
   surfaces devenues thematiques (bloc precedent) qui les ont REVELEES : du
   blanc sur du blanc.

   C'est la mecanique attendue d'une tokenisation : chaque fond eclairci fait
   apparaitre les textes qui comptaient sur lui. La liste vient du balayage,
   pas d'une relecture (scratchpad/balayage_clair.js, contraste < 3,0).

   Les valeurs a transparence (rgba(255,255,255,0.38)...) perdent leur alpha :
   `--rsk-text-mute` porte deja ce role, et il est lisible sur les sept fonds.
   ══════════════════════════════════════════════════════════════════════════ */

#splash-msg { color: var(--rsk-text-mute) !important; }
#search-input-display { color: var(--rsk-text) !important; }
#sett-left .sett-cat-label { color: var(--rsk-text-dim) !important; }
#live-prev-name { color: var(--rsk-text) !important; }
#live-prev-now-title { color: var(--rsk-text-dim) !important; }
#live-actbar .lab-txt { color: var(--rsk-text-dim) !important; }
#screen-activation .act-steps li { color: var(--rsk-text-dim) !important; }
#screen-activation .act-steps li strong { color: var(--rsk-text) !important; }

/* ── Deuxieme passe (le filtre de l'audit etait casse au premier tour) ──────
   Mon premier balayage annoncait « 0 texte illisible ». C'etait faux : le
   filtre cense ecarter les pictogrammes utilisait
   /[ἀ0-ᾯF]/ — hors mode `u`, ce n'est PAS un point de code mais
   `ἀ` suivi de la plage `0-ᾯ`, qui couvre tout le latin, les
   chiffres et les accents. Il avalait donc la quasi-totalite des defauts.
   Filtre remplace par son contraire (« aucune lettre ni chiffre = pictogramme »),
   qui ne peut pas deraper. Nouveau relevé : 18 textes illisibles, ci-dessous. */

/* Ecran de chargement */
.spl-disclaimer-fr { color: var(--rsk-text-dim) !important; }
.spl-disclaimer-en { color: var(--rsk-text-mute) !important; }

/* Accueil */
#home-ticker .home-disclaimer { color: var(--rsk-text-mute) !important; }

/* Activation */
#screen-activation .act-title { color: var(--rsk-text) !important; }
#screen-activation #act-mac-display { color: var(--rsk-text) !important; }
#screen-activation .act-mac-label { color: var(--rsk-text-dim) !important; }
#screen-activation .act-disclaimer { color: var(--rsk-text-mute) !important; }
#screen-activation .act-topbar-label { color: var(--rsk-text-dim) !important; }

/* Direct */
#live-cat-col .live-col-hdr,
#live-ch-col #live-cat-name { color: var(--rsk-text-dim) !important; }
.live-tv-epg .lprev-guide-title { color: var(--rsk-text) !important; }

/* Films / Series */
#vod-cat-name, #series-cat-name { color: var(--rsk-text-dim) !important; }
.vod-cats-col .col-header { color: var(--rsk-text-dim) !important; }

/* Reglages */
#sett-left .sett-left-title { color: var(--rsk-text-dim) !important; }

/* Radio, Catch-up, Favoris */
.radio-now-info .radio-now-label { color: var(--rsk-text-dim) !important; }
#cu-infobar #cu-ib-title { color: var(--rsk-text) !important; }
#fav-cat-list .cat-item { color: var(--rsk-text-dim) !important; }
/* ⚠️ Texte POSE SUR l'accent : ce n'est pas une couleur de theme, c'est une
   couleur « sur accent ». `--rsk-text` y etait une erreur — en theme Clair il
   vaut #111 et tombait a 2,1 de contraste sur l'accent sombre. Le blanc
   convient aux SEPT accents (mesure : 4,3 a 8,0), il est donc correct sans
   etre thematique. Aucun jeton « on-accent » n'existe, ni ici ni sur Android. */
#fav-cat-list .cat-item.active { color: #fff !important; }

/* ═══ Lot 1 — accueil composé (mesuré sur TV le 04/10/2026) ═══════════════════
   Le défilement de #section-dashboard n'est pas composité sur ces TV : chaque
   déplacement du focus faisait REPEINDRE tout l'écran (1820x1080, calque
   relevé par LayerTree.layerPainted), avec ses dégradés, ombres et textes.
   Médiane 432 ms par appui, pics de 3 s. En plaçant le contenu sur ses propres
   calques, le défilement ne fait plus que les déplacer : 49 ms, pic 0,67 s.
   Ne pas retirer sans remesurer sur TV (le banc PC ne montre pas ce coût). */
#section-dashboard > * { will-change: transform; }

/* ═══ Lot 1 — dessin allégé du hub (mesuré sur TV le 04/10/2026) ═══════════════
   Descendre d'une rangée fait apparaître des zones neuves à dessiner. Avec une
   ombre floue (28-40 px) sous CHAQUE affiche et un texte ombré sur chaque titre,
   ce dessin coûtait 0,6 à 1,1 s par appui sur cette TV. Sans eux : 0,09 s
   médiane, 0,15 s au pire (séries alternées, même point de départ).
   L'élément SÉLECTIONNÉ garde son anneau net (--rsk-focus-ring) : le relief ne
   coûte rien tant qu'il n'y a pas de flou. Le dégradé sous le titre suffit à
   sa lisibilité. */
#dash-v2 .dv-poster:not(.dv-focused),
#dash-v2 .dv-hero-x:not(.dv-focused),
#dash-v2 .dv-tile:not(.dv-focused) { box-shadow: none !important; }
#dash-v2 .dv-pl { text-shadow: none !important; }

/* Lot 2 — grille Films/Séries : une carte = pas un calque. Relevé sur TV : 60
   cartes en `will-change: transform, box-shadow` + animation d'entrée
   (brand-card-enter) = 1013 calques à l'entrée dans Films. Le curseur flottant
   de gridnav fait le travail ; les cartes ne bougent jamais seules. */
.vod-card.gn-card { will-change: auto !important; -webkit-animation: none !important; animation: none !important; }

/* v576 (A3) — Image sans source = icone d'image cassee du navigateur (Direct,
   grilles). Une <img> sans src (logo absent, ou retire par onerror selon la
   regle v528) ou avec src vide ne peut rien montrer d'utile : on la masque.
   visibility (et non display) : la place du logo est gardee, les noms restent
   alignes. Selecteurs d'attribut : valables sous Chromium 53/56. */
img:not([src]), img[src=""] { visibility: hidden; }
