  * { box-sizing: border-box; }
  html, body { margin: 0; height: 100%; font-family: 'DM Sans', system-ui, sans-serif; background: var(--page-bg); color: var(--paper); overflow: hidden; }

  .viewer { position: relative; width: 100%; height: 100vh; display: flex; align-items: center; justify-content: center; padding-right: 56px; }
  .viewer:fullscreen { background: var(--page-bg); }

  .brand-logo {
    position: absolute; top: 20px; left: 24px; z-index: 20;
    font-family: 'Playfair Display', serif; font-weight: 700; font-size: 17px; color: var(--accent);
    max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    transform-origin: top left; transition: transform 0.35s ease;  /* réduction animée en double-page */
  }
  .brand-logo img { display: block; max-height: 36px; max-width: 220px; width: auto; height: auto; }

  .denkimedia-badge {
    display: flex; align-items: center; gap: 8px; text-decoration: none; color: var(--muted);
    font-size: 11px; white-space: nowrap;
  }
  /* max-height: none pour battre le .brand-logo img { max-height: 36px } (prévu pour les
     logos clients) qui, sinon, bride ce badge à une taille bien plus petite que sa hauteur. */
  .denkimedia-badge img { display: block; height: 60px; max-height: none; width: auto; max-width: 320px; }
  .denkimedia-badge:hover { color: var(--paper); }

  .page-stage { position: relative; flex: 1 1 auto; width: 100%; min-width: 0; height: calc(100vh - 64px); display: flex; align-items: center; justify-content: center; gap: clamp(6px, 1.6vw, 20px); overflow: auto; user-select: none; -webkit-user-select: none; }
  .pages-container { height: 100%; display: flex; align-items: center; justify-content: center; gap: 0; transform-origin: top left; transition: transform 0.15s ease; flex-shrink: 0; }
  /* La page épouse la taille réelle de son image, bornée par la hauteur ET la largeur
     disponibles. Une page haute (A4 portrait) remplit la hauteur ; une page large
     (double-page) remplit la largeur - jamais de bande blanche par letterboxing. */
  .page { display: none; position: relative; max-height: 100%; background: white; box-shadow: 0 0 24px var(--shadow-color); flex-shrink: 0; }
  .page.active { display: block; }
  /* Effets de transition de page (réglés par publication). Rejoués à chaque changement. */
  @keyframes pgFade { from { opacity: 0; } to { opacity: 1; } }
  @keyframes pgSlideNext { from { opacity: .35; transform: translateX(8%); } to { opacity: 1; transform: none; } }
  @keyframes pgSlidePrev { from { opacity: .35; transform: translateX(-8%); } to { opacity: 1; transform: none; } }
  .page.anim-fade { animation: pgFade 0.34s ease both; }
  .page.anim-slide-next { animation: pgSlideNext 0.32s cubic-bezier(.22,.61,.36,1) both; }
  .page.anim-slide-prev { animation: pgSlidePrev 0.32s cubic-bezier(.22,.61,.36,1) both; }

  /* Animations d'ENTRÉE par page (animations.json, réglées dans l'éditeur). La classe
     entrance-* est posée sur la <section.page> le temps de l'effet ; on anime le média interne
     (img OU svg.page-vector inliné), pas la page elle-même, pour ne pas entrer en conflit avec
     la transition globale au tourne-page. On clippe la page PENDANT l'effet (translate/scale
     débordent la boîte) ; la classe est retirée en fin d'anim → overflow rétabli, zones jamais
     rognées en lecture. Le sélecteur enfant capte aussi le svg inliné qui arrive un peu après. */
  @keyframes entFade { from { opacity: 0; } to { opacity: 1; } }
  @keyframes entRise { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
  @keyframes entZoom { from { opacity: 0; transform: scale(1.06); } to { opacity: 1; transform: none; } }
  @keyframes entKenburns { from { transform: scale(1.08); } to { transform: none; } }
  .page[class*="entrance-"] { overflow: hidden; }
  /* Animations par élément : page masquée le temps que son SVG soit inliné et que les
     éléments soient placés dans leur état de départ (voir applyElementAnimations). */
  .page.el-pending > img, .page.el-pending > svg.page-vector { visibility: hidden; }
  /* Avant l'arrivée des réglages (animations.json), la page affichée est masquée : sinon un
     élément animé s'affiche d'abord, puis disparaît pour entrer. Levé dès que les réglages
     sont là, et de toute façon au bout d'un court délai (voir startAnimWarmup). */
  .pages-container.anim-warmup .page.active > img,
  .pages-container.anim-warmup .page.active > svg.page-vector { visibility: hidden; }
  .page.entrance-fade > img, .page.entrance-fade > svg.page-vector { animation: entFade 0.6s ease both; }
  .page.entrance-rise > img, .page.entrance-rise > svg.page-vector { animation: entRise 0.6s cubic-bezier(.22,.61,.36,1) both; }
  .page.entrance-zoom > img, .page.entrance-zoom > svg.page-vector { animation: entZoom 0.7s cubic-bezier(.22,.61,.36,1) both; transform-origin: center; }
  .page.entrance-kenburns > img, .page.entrance-kenburns > svg.page-vector { animation: entKenburns 5s ease-out both; transform-origin: center; }
  @media (prefers-reduced-motion: reduce) {
    .page[class*="entrance-"] { overflow: visible; }
    .page[class*="entrance-"] > img, .page[class*="entrance-"] > svg.page-vector { animation: none !important; }
  }
  /* Tourne-page 3D façon livre : la double-page est coupée à la reliure (centre). En avançant, la
     MOITIÉ DROITE pivote sur la reliure (bord gauche de la feuille) de 0 à -180° et vient se
     rabattre par-dessus la moitié gauche ; son dos porte la moitié gauche de la nouvelle
     double-page. En reculant, la MOITIÉ GAUCHE pivote sur le bord droit de 0 à +180°. La feuille
     est superposée en position fixe ; la nouvelle double-page est déjà affichée dessous. */
  /* z-index 15 : AU-DESSUS des pages (z auto) mais SOUS l'habillage (logo, barre d'outils, flèches,
     pagination = z 20) pour que le tourne-page ne recouvre jamais le logo ni les commandes. */
  .flip-wrap { position: fixed; z-index: 15; pointer-events: none; perspective: 2200px; }
  /* Fond papier SOUS l'image : les pages SVG (pdftocairo) ont un fond TRANSPARENT — sans ce
     fond, la page sortante peinte sur la feuille laissait voir la nouvelle page au travers
     (textes superposés pendant le tourne-page). */
  .flip-wrap .flip-static { position: absolute; top: 0; height: 100%; background-repeat: no-repeat; background-color: #fff; }
  .flip-leaf { position: absolute; top: 0; height: 100%; transform-style: preserve-3d; }
  .flip-leaf .fl-face { position: absolute; inset: 0; width: 100%; height: 100%; backface-visibility: hidden; background-repeat: no-repeat; background-color: #fff; box-shadow: 0 10px 30px rgba(0,0,0,0.28); }
  .flip-leaf .fl-back { transform: rotateY(180deg); }
  .flip-leaf-next { animation: flipLeafNext 0.62s cubic-bezier(.4,0,.3,1) both; }
  .flip-leaf-prev { animation: flipLeafPrev 0.62s cubic-bezier(.4,0,.3,1) both; }
  @keyframes flipLeafNext { from { transform: rotateY(0deg); } to { transform: rotateY(-180deg); } }
  @keyframes flipLeafPrev { from { transform: rotateY(0deg); } to { transform: rotateY(180deg); } }
  .flip-leaf .fl-shade { position: absolute; inset: 0; opacity: 0; background: linear-gradient(to left, rgba(0,0,0,0.4), rgba(0,0,0,0) 62%); }
  .flip-leaf-prev .fl-shade { background: linear-gradient(to right, rgba(0,0,0,0.4), rgba(0,0,0,0) 62%); }
  .flip-leaf-next .fl-shade { animation: flShade 0.62s ease-in-out both; }
  .flip-leaf-prev .fl-shade { animation: flShade 0.62s ease-in-out both; }
  @keyframes flShade { 0% { opacity: 0; } 50% { opacity: .55; } 100% { opacity: 0; } }
  /* Ouverture / fermeture façon livre (« book-shift ») : le livre garde une largeur de DEUX pages et
     se DÉCALE (translateX) pour centrer la couverture, pendant que celle-ci se rabat sur la reliure.
     La double-page se dévoile sans aperçu prématuré. */
  .flip-cover-book { animation: coverBookShift 0.62s cubic-bezier(.4,0,.3,1) both; }
  @keyframes coverBookShift { from { transform: translateX(var(--shift-from,0)); } to { transform: translateX(var(--shift-to,0)); } }
  .flip-cover-book .cb-slot { position: absolute; top: 0; height: 100%; background-repeat: no-repeat; background-color: #fff; }
  .flip-cover-book .cb-empty { background: var(--page-bg); }  /* intérieur de couverture (vierge) */
  /* Pendant l'ouverture/fermeture du livre, on masque les vraies pages (le wrap coulissant, plus
     étroit que la double-page, laisserait sinon dépasser un bord). Rétabli en fin d'animation. */
  .page-stage.cb-hide-pages .page.active { visibility: hidden; }
  .flip-leaf.flip-cover-page { animation: flipCoverPage 0.62s cubic-bezier(.4,0,.3,1) both; }
  @keyframes flipCoverPage { from { transform: rotateY(var(--fl-from,0deg)); } to { transform: rotateY(var(--fl-to,-180deg)); } }
  .flip-cover-page .fl-back { background-color: #f2efe8; background-size: 100% 100%; background-repeat: no-repeat; }
  .flip-cover-page .fl-shade { animation: flShade 0.62s ease-in-out both; }
  /* On réserve ~190px de large (deux flèches + espaces + sidebar) pour que les flèches,
     placées de part et d'autre de la page, tiennent toujours sans déborder ni recouvrir. */
  .page img { display: block; max-height: calc(100vh - 64px); max-width: calc(100vw - 190px); width: auto; height: auto; }
  .page-stage.two-up .page img { max-width: calc((100vw - 190px) / 2); }
  /* Calque de texte NON sélectionnable : il est invisible (color:transparent) et sert
     uniquement à la recherche/au SEO (texte présent dans le DOM). Le laisser sélectionnable
     faisait qu'un double-clic (geste de zoom) sélectionnait ce texte, et la sélection
     s'étendait à toutes les pages et aux flèches. */
  .text-layer { position: absolute; inset: 0; color: transparent; user-select: none; -webkit-user-select: none; }
  .text-layer .w { position: absolute; white-space: nowrap; font-size: 10px; line-height: 1; color: transparent; }
  /* Résultat de recherche : effet surligneur, sans jamais afficher le texte invisible du calque
     (police générique : il se superposait, décalé, au vrai mot de la page). */
  .text-layer .w.hit { background: rgba(var(--accent-rgb, 90,154,160),0.38); color: transparent !important; mix-blend-mode: multiply;
    outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 2px; }

  .hotspot-layer { position: absolute; inset: 0; }
  .hotspot { position: absolute; cursor: pointer; }
  .hotspot:hover { background: rgba(var(--hotspot-rgb),0.12); outline: 2px solid rgba(var(--hotspot-rgb),0.5); }
  /* Zone image intégrée : l'image occupe la zone, pas de surbrillance ni de curseur cliquable. */
  .hotspot.hotspot-embed { cursor: default; }
  .hotspot.hotspot-embed:hover { background: none; outline: none; }
  .hotspot-embed-img { width: 100%; height: 100%; display: block; object-fit: contain; }
  /* Cadre affiché en permanence (option « Toujours visible »). */
  .hotspot.show-box { outline: 2px solid rgba(var(--hotspot-rgb),0.55); background: rgba(var(--hotspot-rgb),0.08); }
  /* Cadre « à l'arrivée puis au survol » (défaut) : clignotement doux à l'arrivée sur la page
     (classe .intro posée par la liseuse), puis visible au survol, au focus clavier, ou 2 s après
     un toucher sur la page (.reveal, écrans tactiles et mouvements réduits). */
  .hotspot.box-intro { transition: outline-color .3s ease, background-color .3s ease; outline: 2px solid transparent; }
  .hotspot.box-intro:hover, .hotspot.box-intro:focus-visible,
  .hotspot-layer.reveal .hotspot.box-intro { outline-color: rgba(var(--hotspot-rgb),0.55); background: rgba(var(--hotspot-rgb),0.08); }
  .hotspot-layer.intro .hotspot.box-intro { animation: dnk-box-intro 1.6s ease-in-out 1; }
  @keyframes dnk-box-intro {
    0%, 100% { outline-color: rgba(var(--hotspot-rgb),0); background-color: rgba(var(--hotspot-rgb),0); }
    25%, 75% { outline-color: rgba(var(--hotspot-rgb),0.6); background-color: rgba(var(--hotspot-rgb),0.1); }
    50% { outline-color: rgba(var(--hotspot-rgb),0.2); background-color: rgba(var(--hotspot-rgb),0.03); }
  }
  @media (prefers-reduced-motion: reduce) { .hotspot-layer.intro .hotspot.box-intro { animation: none; } }
  /* Point : cible tactile d'au moins 34 px même si la zone est petite. On agrandit la seule
     surface CLIQUABLE, invisible et centrée sur la zone : le cadre affiché garde exactement la
     taille posée dans l'éditeur. (Avant : min-width / min-height étiraient le cadre vers le bas
     et la droite, et un point agrandi en bandeau débordait sur la zone suivante.) */
  .hotspot.hotspot-point::before { content: ''; position: absolute; left: 50%; top: 50%;
    width: max(100%, 34px); height: max(100%, 34px); transform: translate(-50%, -50%); }
  .hotspot .badge {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: 28px; height: 28px; border-radius: 50%; background: var(--badge-bg);
    display: flex; align-items: center; justify-content: center; color: var(--hotspot-color);
    pointer-events: none; box-shadow: 0 2px 8px var(--shadow-color);
  }
  .hotspot .badge svg { width: 15px; height: 15px; }
  /* Étiquette de prix d'une fiche produit reliée au catalogue (réglage à activer). */
  .hotspot .hotspot-price { position: absolute; left: 50%; bottom: -4px; transform: translate(-50%, 100%);
    background: var(--badge-bg); color: var(--paper); font-size: 12px; font-weight: 700; line-height: 1;
    padding: 4px 7px; border-radius: 6px; white-space: nowrap; pointer-events: none;
    box-shadow: 0 2px 8px var(--shadow-color); }
  .hotspot .badge.pulse { animation: hotspot-pulse 1.4s ease-out 2; }
  @keyframes hotspot-pulse {
    0% { box-shadow: 0 0 0 0 rgba(var(--hotspot-rgb),0.65), 0 2px 8px var(--shadow-color); }
    100% { box-shadow: 0 0 0 18px rgba(var(--hotspot-rgb),0), 0 2px 8px var(--shadow-color); }
  }

  .lightbox {
    position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.85);
    display: none; align-items: center; justify-content: center; padding: 40px;
  }
  .lightbox.open { display: flex; }
  .lightbox-content { max-width: 90vw; max-height: 85vh; }
  .lightbox-content img { max-width: 90vw; max-height: 85vh; display: block; border-radius: 6px; }
  .lightbox-content video, .lightbox-content iframe { width: 80vw; max-width: 900px; height: 50vw; max-height: 500px; border: none; border-radius: 6px; }
  .carousel { position: relative; display: flex; align-items: center; justify-content: center; }
  /* Flèches du carrousel : même habillage que les flèches de navigation de la publication
     (couleur de flèche configurable, fond panneau, bord) et posées PRÈS DES BORDS de l'image. */
  .carousel-arrow {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
    width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
    background: var(--panel-bg); color: var(--arrow-color, var(--paper));
    border: 1px solid var(--border-color); box-shadow: 0 2px 10px var(--shadow-color);
    display: flex; align-items: center; justify-content: center; font-size: 18px; line-height: 1;
  }
  .carousel-arrow:hover { background: var(--arrow-color, var(--accent)); color: var(--ink); }
  .carousel-prev { left: 10px; }
  .carousel-next { right: 10px; }
  .carousel-dots { position: absolute; bottom: -26px; left: 50%; transform: translateX(-50%); display: flex; gap: 6px; }
  .carousel-dots .dot { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,0.35); }
  .carousel-dots .dot.active { background: var(--accent); }
  .lightbox-close {
    position: absolute; top: 20px; right: 24px; width: 40px; height: 40px; border-radius: 50%;
    background: rgba(255,255,255,0.1); border: none; color: white; font-size: 20px; cursor: pointer;
  }
  .lightbox-close:hover { background: var(--accent); color: var(--on-accent, var(--ink)); }

  /* Fiche produit (zone 'produit') : carte claire posée sur l'overlay sombre. */
  .product-card {
    background: #fff; color: #12211c; border-radius: 12px; overflow: hidden;
    width: min(92vw, 420px); max-height: 85vh; overflow-y: auto;
    box-shadow: 0 12px 40px rgba(0,0,0,0.4);
  }
  .pc-media { background: #f2f0ea; }
  .pc-media img { width: 100%; max-width: 100%; max-height: 300px; object-fit: contain; display: block; border-radius: 0; }
  .pc-body { padding: 20px 22px 22px; }
  .pc-name { font-family: 'Playfair Display', serif; font-size: 22px; line-height: 1.2; margin: 0 0 4px; color: #12211c; }
  .pc-ref { font-size: 12px; color: rgba(13,31,26,0.55); text-transform: uppercase; letter-spacing: .04em; }
  .pc-availability { font-size: 13px; color: var(--muted); margin-top: 4px; }
  .pc-unavailable { font-size: 13px; font-weight: 700; margin-top: 6px; }
  .pc-price { font-size: 20px; font-weight: 700; margin-top: 8px; color: #12211c; }
  .pc-desc { font-size: 14px; line-height: 1.5; color: rgba(13,31,26,0.8); margin: 12px 0 0; white-space: pre-line; }
  .pc-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
  .pc-btn {
    flex: 1 1 auto; text-align: center; padding: 12px 16px; border-radius: 9px; cursor: pointer;
    font-size: 14px; font-weight: 600; text-decoration: none; border: 1px solid var(--panel-accent, var(--accent));
    background: transparent; color: #12211c;
  }
  .pc-btn-primary { background: var(--panel-accent, var(--accent)); color: var(--on-panel-accent, #12211c); border-color: var(--panel-accent, var(--accent)); }
  .pc-btn:hover { filter: brightness(0.96); }
  .pc-btn:disabled { opacity: .7; cursor: default; }

  /* « Ma sélection » : bouton flottant + panneau (dans la lightbox). */
  .selection-fab {
    position: fixed; right: 20px; bottom: 20px; z-index: 90;
    display: inline-flex; align-items: center; gap: 8px; cursor: pointer; border: none;
    background: var(--panel-accent, var(--accent)); color: var(--on-panel-accent, #12211c); border-radius: 999px;
    padding: 12px 20px; font-size: 14px; font-weight: 700; box-shadow: 0 6px 20px rgba(0,0,0,0.25);
  }
  /* Repli pour les publications générées AVANT le bouton panier de la barre latérale : le
     bouton flottant n'apparaît alors qu'une fois le panier non vide. [hidden] doit l'emporter
     sur le display:inline-flex ci-dessus (sinon pastille vide toujours visible). */
  .selection-fab[hidden] { display: none !important; }
  .selection-fab .sel-count { background: rgba(13,31,26,0.85); color: #fff; border-radius: 999px; padding: 1px 8px; font-size: 12px; }
  .selection-panel {
    background: #fff; color: #12211c; border-radius: 12px; width: min(92vw, 460px);
    max-height: 85vh; overflow-y: auto; padding: 22px; box-shadow: 0 12px 40px rgba(0,0,0,0.4);
  }
  /* Panier dans la barre d'outils : pastille de comptage sur l'icône. */
  .tool-btn.cart-btn { position: relative; }
  .tool-btn.cart-btn.has-items { color: var(--bar-accent, var(--accent)); }
  .cart-count {
    position: absolute; top: 2px; right: 2px; min-width: 17px; height: 17px; padding: 0 4px;
    border-radius: 999px; background: var(--bar-accent, var(--accent)); color: var(--on-bar-accent, #12211c);
    font-size: 10px; font-weight: 700; line-height: 17px; text-align: center;
  }
  .cart-count[hidden] { display: none; }

  /* Quantité choisie sur la fiche produit, avant l'ajout au panier. */
  .pc-qty { display: inline-flex; align-items: center; gap: 6px; margin-right: 10px; }
  .pc-qty-btn { width: 34px; height: 40px; border-radius: 9px; border: 1px solid rgba(13,31,26,0.2);
    background: #fff; color: #12211c; font-size: 17px; cursor: pointer; }
  .pc-qty input { width: 54px; height: 40px; text-align: center; border-radius: 9px;
    border: 1px solid rgba(13,31,26,0.2); background: #fff; color: #12211c; font: inherit; font-size: 15px; }
  .pc-incart { margin: 10px 0 0; font-size: 13px; color: rgba(13,31,26,0.65); }
  .sel-qty-input { width: 48px; height: 26px; text-align: center; border-radius: 6px;
    border: 1px solid rgba(13,31,26,0.2); background: #fff; color: #12211c; font: inherit; font-size: 13px; }
  .sel-total { margin: 14px 0 0; font-size: 13px; color: rgba(13,31,26,0.6); }

  .selection-panel .sel-title { font-family: 'Playfair Display', serif; font-size: 22px; margin: 0 0 14px; }
  .sel-empty { color: rgba(13,31,26,0.6); }
  .sel-row { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid rgba(13,31,26,0.1); }
  .sel-info { flex: 1; min-width: 0; }
  .sel-name { font-weight: 600; }
  .sel-ref { font-size: 12px; color: rgba(13,31,26,0.55); }
  .sel-price { font-size: 13px; color: rgba(13,31,26,0.8); }
  .sel-qty { display: inline-flex; align-items: center; gap: 8px; }
  .sel-qty button { width: 26px; height: 26px; border-radius: 6px; border: 1px solid rgba(13,31,26,0.2); background: #fff; cursor: pointer; font-size: 15px; line-height: 1; }
  .sel-remove { background: none; border: none; color: rgba(13,31,26,0.5); font-size: 20px; cursor: pointer; line-height: 1; padding: 0 2px; }
  .sel-remove:hover { color: #c0392b; }
  .sel-actions { display: flex; gap: 10px; margin-top: 18px; }

  /* Flèches ancrées aux BORDS du cadre (position absolue), centrées verticalement.
     Auparavant elles étaient en flux, collées de part et d'autre du bloc de pages : leur
     position horizontale suivait donc la largeur de la page et « sautait » d'une page à
     l'autre (page portrait étroite -> flèches au milieu de l'écran ; double-page large ->
     flèches aux bords), et sur une page à fond perdu elles finissaient sur le contenu.
     En absolu, leur position est CONSTANTE quelle que soit la page. Elles restent dans la
     marge que .page img réserve déjà (calc(100vw - 190px), soit ~95px de chaque côté), donc
     elles ne recouvrent jamais le contenu. Ancrage relatif à .page-stage (position:relative). */
  /* z-index 20 : au-dessus de la feuille du tourne-page (z 15, ajoutée en fin de <body>) — à
     égalité, elle passait devant et les flèches semblaient disparaître pendant l'effet. */
  .nav-arrow-group {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 20;
    display: flex; flex-direction: column; align-items: center; gap: 10px;
  }
  .nav-arrow-group-left { left: 24px; }
  .nav-arrow-group-right { right: 24px; }
  /* En zoom, la page agrandie déborde par-dessus les flèches -> on les masque (on
     navigue au scroll/doigt ; dézoomer pour changer de page). */
  .page-stage.zoomed .nav-arrow-group { display: none; }
  .nav-arrow {
    position: relative; margin: 0;
    width: 44px; height: 44px; border-radius: 50%; cursor: pointer;
    /* Pastille opaque + ombre : lisible sur n'importe quel fond de page (blanc, photo,
       letterbox), contrairement à l'ancien fond translucide invisible en thème clair. */
    background: var(--panel-bg); color: var(--arrow-color, var(--paper));
    border: 1px solid var(--border-color); box-shadow: 0 2px 10px var(--shadow-color);
    font-size: 20px; display: flex; align-items: center; justify-content: center;
  }
  .nav-arrow:hover { background: var(--arrow-color, var(--accent)); color: var(--ink); }
  .nav-arrow:disabled { opacity: 0.35; cursor: default; }
  .nav-arrow-edge { width: 32px; height: 32px; font-size: 14px; opacity: 0.7; }
  .nav-arrow-edge:hover { opacity: 1; }
  .nav-arrow-edge.hidden { visibility: hidden; pointer-events: none; }
  /* Sur petit écran : flèches plus compactes et réserve réduite, pour laisser
     un maximum de place à la page. */
  @media (max-width: 560px) {
    .page img { max-width: calc(100vw - 96px); }
    .page-stage.two-up .page img { max-width: calc((100vw - 96px) / 2); }
    .nav-arrow { width: 34px; height: 34px; font-size: 16px; }
    .nav-arrow-edge { width: 26px; height: 26px; font-size: 12px; }
    /* Marge réservée plus étroite (48px) -> flèches collées au bord pour ne pas mordre la page. */
    .nav-arrow-group-left { left: 7px; }
    .nav-arrow-group-right { right: 7px; }
  }

  /* Bandeau de consentement (affiché UNIQUEMENT si l'éditeur a configuré un tracker tiers).
     Discret, en bas à gauche, jamais par-dessus les commandes de lecture. */
  .consent-bar {
    position: fixed; left: 16px; bottom: 16px; z-index: 95; max-width: 380px;
    background: var(--panel-bg-strong, var(--panel-bg)); color: var(--paper);
    border: 1px solid var(--border-color); border-radius: 12px; padding: 14px 16px;
    box-shadow: 0 8px 30px var(--shadow-color); font-size: 13px; line-height: 1.5;
  }
  .consent-bar p { margin: 0 0 10px; }
  .consent-bar .consent-actions { display: flex; gap: 8px; justify-content: flex-end; }
  .consent-bar button {
    padding: 7px 14px; border-radius: 7px; font-size: 13px; font-weight: 600; cursor: pointer;
    border: 1px solid var(--border-color); background: transparent; color: inherit;
  }
  .consent-bar .consent-yes { background: var(--accent); border-color: var(--accent); color: var(--on-accent, var(--ink)); }
  @media (max-width: 560px) { .consent-bar { left: 8px; right: 8px; bottom: 8px; max-width: none; } }

  .fullscreen-btn {
    position: absolute; bottom: 20px; left: 24px; z-index: 20;
    width: 38px; height: 38px; border-radius: 8px; border: none; cursor: pointer;
    background: var(--overlay-2); color: var(--muted); display: flex; align-items: center; justify-content: center;
  }
  .fullscreen-btn:hover { background: var(--overlay-3); color: var(--paper); }
  .fullscreen-btn svg { width: 18px; height: 18px; }

  .theme-toggle-btn {
    position: absolute; bottom: 20px; left: 70px; z-index: 20;
    width: 38px; height: 38px; border-radius: 8px; border: none; cursor: pointer;
    background: var(--overlay-2); color: var(--muted); display: flex; align-items: center; justify-content: center;
  }
  .theme-toggle-btn:hover { background: var(--overlay-3); color: var(--paper); }
  .theme-toggle-btn svg { width: 18px; height: 18px; }
  .theme-toggle-btn .icon-moon { display: none; }
  [data-theme="dark"] .theme-toggle-btn .icon-sun { display: none; }
  [data-theme="dark"] .theme-toggle-btn .icon-moon { display: block; }

  .page-counter {
    position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 20;
    font-size: 12px; color: #ffffff; background: rgba(20,24,28,0.75);
    padding: 4px 14px; border-radius: 12px; white-space: nowrap;
    align-items: center; justify-content: center; cursor: pointer;
  }
  .page-counter:hover { background: rgba(20,24,28,0.9); }
  .page-counter #pageCounterInput {
    width: 40px; background: transparent; border: none; border-bottom: 1px solid #ffffff;
    color: #ffffff; font-size: 12px; text-align: center; padding: 0; outline: none;
  }
  .page-counter #pageCounterInput::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

  .sidebar-tools {
    position: absolute; top: 0; right: 0; height: 100vh; width: 56px; z-index: 20;
    background: var(--sidebar-bg); border-left: 1px solid var(--border-color);
    display: flex; flex-direction: column; align-items: center; padding-top: 20px; gap: 8px;
  }
  .tool-btn {
    width: 40px; height: 40px; border-radius: 8px; border: none; cursor: pointer;
    background: transparent; color: var(--muted); display: flex; align-items: center; justify-content: center;
  }
  /* [hidden] doit l'emporter sur le display:flex ci-dessus, sinon un outil « masqué » reste
     visible (cas du panier, affiché alors sans être activé). */
  .tool-btn[hidden] { display: none !important; }
  .tool-btn:hover { background: var(--overlay-2); color: var(--paper); }
  .tool-btn.active { background: rgba(var(--bar-accent-rgb, 90,154,160),0.15); color: var(--bar-accent, var(--accent)); }
  .tool-btn:disabled { opacity: 0.3; cursor: default; }
  .tool-btn:disabled:hover { background: transparent; color: var(--muted); }
  .tool-btn svg { width: 19px; height: 19px; }

  .search-panel {
    position: absolute; top: 16px; right: 68px; z-index: 25; width: 320px;
    background: var(--panel-bg); border: 1px solid var(--border-color); border-radius: 10px;
    padding: 12px; box-shadow: 0 12px 30px var(--shadow-color); display: none;
  }
  .search-panel.open { display: block; }
  .search-panel input {
    width: 100%; padding: 9px 12px; border-radius: 7px; border: 1px solid var(--border-color);
    background: var(--overlay-2); color: var(--paper); font-size: 14px; margin-bottom: 8px;
  }
  .search-panel input:focus { border-color: var(--accent); }
  .search-results { max-height: 280px; overflow-y: auto; }
  .search-results .result { padding: 9px 10px; cursor: pointer; border-radius: 6px; font-size: 13px; }
  .search-results .result:hover { background: rgba(var(--accent-rgb, 90,154,160),0.08); }
  .search-results .result b { color: var(--accent); }
  .search-results .page-tag { color: var(--muted); font-size: 11px; display: block; margin-bottom: 2px; }
  .search-results .none { padding: 10px; color: var(--muted); font-size: 13px; }
  .search-results .result.active { background: rgba(var(--accent-rgb, 90,154,160),0.16); outline: 1px solid var(--accent); }
  /* Navigation entre résultats (préc / X-N / suiv). */
  .search-nav { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
  .search-nav-btn {
    width: 32px; height: 28px; border-radius: 6px; border: 1px solid var(--border-color);
    background: var(--overlay-2); color: var(--paper); cursor: pointer; font-size: 16px; line-height: 1;
  }
  .search-nav-btn:hover { border-color: var(--accent); color: var(--accent); }
  .search-count { font-size: 12px; color: var(--muted); }
  /* Sur petit écran, le panneau (320px + 68px de marge) déborderait : on l'étire bord à bord. */
  @media (max-width: 560px) {
    .search-panel { top: 8px; right: 8px; left: 8px; width: auto; }
  }
  .toc-viewer-title { font-weight: 700; font-size: 14px; margin-bottom: 8px; color: var(--paper); }
  #tocViewerList .toc-viewer-entry {
    display: flex; justify-content: space-between; align-items: center; padding: 9px 10px;
    cursor: pointer; border-radius: 6px; font-size: 13px;
  }
  #tocViewerList .toc-viewer-entry:hover { background: rgba(var(--hotspot-rgb),0.08); }
  #tocViewerList .toc-viewer-page { color: var(--muted); font-size: 12px; flex-shrink: 0; margin-left: 10px; }

  .thumbs-panel {
    position: absolute; inset: 0 56px 0 0; z-index: 40; background: var(--panel-bg-strong);
    display: none; overflow-y: auto; padding: 70px 40px;
  }
  .thumbs-panel.open { display: block; }
  .thumbs-close {
    position: absolute; top: 20px; right: 24px; z-index: 41;
    width: 36px; height: 36px; border-radius: 8px; border: none; cursor: pointer;
    background: var(--overlay-2); color: var(--paper); font-size: 15px;
  }
  .thumbs-close:hover { background: var(--overlay-4); }
  .thumbs-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 18px; max-width: 1100px; margin: 0 auto;
  }
  .thumb-item { cursor: pointer; text-align: center; }
  .thumb-item img {
    width: 100%; border-radius: 4px; box-shadow: 0 6px 16px var(--shadow-color);
    border: 2px solid transparent; display: block;
    background: #fff;   /* miniature d'une page SVG (sans fond) : feuille blanche, comme la page */
  }
  .thumb-item:hover img { border-color: var(--accent); }
  .thumb-item .thumb-label { font-size: 11px; color: var(--muted); margin-top: 6px; }

  .toast {
    position: absolute; bottom: 70px; left: 50%; transform: translateX(-50%); z-index: 30;
    background: var(--accent); color: var(--on-accent, var(--ink)); font-size: 13px; font-weight: 600;
    padding: 8px 16px; border-radius: 20px; opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
  }
  .toast.show { opacity: 1; }

  /* ── Téléphone (≤ 560 px) : lecture en plein écran ─────────────────────────────────────────
     Avant : barre d'outils verticale de 56 px à droite, flèches posées sur les bords de la page
     et page réduite à ~280 px de large. Désormais : outils dans une barre en bas de l'écran
     (comme une appli), page quasi pleine largeur, flèches sous la page, et on tourne les pages
     d'un balayage du doigt (voir viewer.js). `100dvh` : la barre reste visible au-dessus de la
     barre d'adresse du navigateur mobile. */
  @media (max-width: 560px) {
    html, body { height: 100%; height: 100dvh; }
    .viewer { height: 100vh; height: 100dvh; padding: 56px 0 56px; }
    .page-stage { height: calc(100vh - 112px); height: calc(100dvh - 112px); gap: 0; }
    .page img { max-width: calc(100vw - 16px); max-height: calc(100vh - 176px); max-height: calc(100dvh - 176px); }
    .page-stage.two-up .page img { max-width: calc((100vw - 16px) / 2); }

    .sidebar-tools {
      top: auto; bottom: 0; left: 0; right: 0; width: 100%; height: 56px;
      padding: 0 4px env(safe-area-inset-bottom); flex-direction: row; justify-content: space-around;
      align-items: center; gap: 0; border-left: none; border-top: 1px solid var(--border-color);
    }
    .tool-btn { width: 44px; height: 44px; }
    #printBtn { display: none; }                          /* imprimer depuis un téléphone : rare */

    /* Flèches : sous la page, jamais par-dessus le contenu ; « première / dernière » masquées. */
    .nav-arrow-group { top: auto; bottom: 8px; transform: none; flex-direction: row; }
    .nav-arrow-group-left { left: 12px; }
    .nav-arrow-group-right { right: 12px; }
    .nav-arrow-edge { display: none; }
    .nav-arrow { width: 44px; height: 44px; font-size: 20px; opacity: 0.92; }

    .brand-logo { top: 12px; left: 14px; }
    .brand-logo img { max-height: 30px; max-width: 180px; }
    .brand-logo .denkimedia-badge img { height: 42px; max-height: 42px; max-width: 220px; }
    .fullscreen-btn { display: none; }                    /* plein écran d'élément non pris en charge sur iPhone */
    .theme-toggle-btn { top: 9px; bottom: auto; left: auto; right: 12px; width: 44px; height: 44px; }
    /* Compteur de pages : entre les deux flèches, au-dessus de la barre d'outils du bas (placé à
       18 px du bas, il passait sous la barre). 56 px de barre + 8 px de marge des flèches + la
       moitié de leur hauteur (44 px) moins la moitié du compteur (~22 px). */
    .page-counter { bottom: calc(75px + env(safe-area-inset-bottom)); }

    .thumbs-panel { inset: 0 0 56px 0; padding: 60px 14px 20px; }
    .thumbs-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
    .consent-bar { bottom: 64px; }
    .selection-fab { bottom: 70px; right: 12px; }
    .lightbox { padding: 12px; }
  }


/* ── Accessibilité ───────────────────────────────────────────── */
.a11y-sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
/* Repère de focus visible au clavier sur tout ce qui est interactif (jamais masqué). */
.viewer button:focus-visible, .viewer a:focus-visible, .viewer input:focus-visible,
.viewer [role="button"]:focus-visible, .viewer [role="link"]:focus-visible,
.lightbox button:focus-visible, .lightbox a:focus-visible, .lightbox input:focus-visible,
.hotspot:focus-visible, .thumb-item:focus-visible, .toc-viewer-entry:focus-visible, .page-counter [role="button"]:focus-visible {
  outline: 3px solid #1a73e8 !important; outline-offset: 2px; box-shadow: 0 0 0 5px #ffffff; }
.hotspot:focus-visible { background: rgba(26,115,232,0.14); }
@media (prefers-reduced-motion: reduce) {
  .badge.pulse, .hotspot .badge { animation: none !important; }
  .page, .page img { transition: none !important; animation: none !important; }
}
.a11y-skip { position: fixed; left: 12px; top: -80px; z-index: 10000; padding: 10px 14px; border-radius: 8px;
  background: #0d1f1a; color: #ffffff; font: 600 14px/1.2 system-ui, sans-serif; text-decoration: none; }
.a11y-skip:focus { top: 12px; outline: 3px solid #1a73e8; outline-offset: 2px; }
a.tool-btn { text-decoration: none; }

/* ── Bouton FR | EN (langue de l'interface, ajouté par viewer.js) ───────────── */
.tool-btn.lang-btn { font: 700 12px/1 system-ui, -apple-system, "Segoe UI", sans-serif; letter-spacing: 0.04em; }
/* Téléphone : barre du bas pleine ; les outils rétrécissent au besoin plutôt que de déborder. */
@media (max-width: 560px) {
  .sidebar-tools .tool-btn { flex: 0 1 44px; min-width: 32px; }
}
