/* © 2026 Krysh.Art — Tous droits réservés / All rights reserved.
   Contact : cshink@gmail.com */
/* ============================================================
   A/RCHIVE — immersive sci-fi photography gallery
   ============================================================ */

:root{
  --c-bg: #07060a;
  --c-gold: #8a00cb;
  --c-gold-bright: #d9a3ff;
  --c-gold-deep: #5e0089;
  --c-silver: #e6cdfa;       /* was neutral blue-white -- now light lavender, Chris 2026-07-26: "tout en mauve" */
  --c-silver-dim: #b78fd6;   /* was neutral blue-gray -- now muted purple */
  --c-glass: rgba(255,255,255,0.045);
  --c-glass-border: rgba(230,220,200,0.16);
  --c-text: #f0e6fa;         /* was near-white -- now a light violet tint */
  --c-text-dim: rgba(216,190,235,0.62); /* was neutral gray -- now dim violet */
  --c-fg-strong: #fff; /* full-contrast text/icons on glass + panels */
  --c-panel: rgba(8,7,12,0.82);        /* bars, popovers, tags */
  --c-panel-strong: rgba(10,9,14,0.92); /* modals, toast */
  --c-overlay: rgba(3,2,7,0.9);         /* lightbox / modal backdrop / grid bg */
  --c-scrim-1: rgba(5,5,10,0.35);
  --c-scrim-2: rgba(5,5,10,0.88);
  --c-vignette: rgba(0,0,0,0.85);
  --c-boot-a: #0b0b18;
  --c-boot-b: #05050a;
  --ease: cubic-bezier(.22,.9,.28,1);
  --ease-soft: cubic-bezier(.4,0,.2,1);
  --ease-float: cubic-bezier(.19,1,.22,1);
  /* Chris 2026-07-26: "le contour des cadre et pastille doit etre glowing
     grey" -- border/glow tokens for every frame + pill-shaped element
     (topbar frame, lang/my-page pills, icon buttons, chips, modal CTAs...).
     Purple stays only in fills/backgrounds; contours go grey. */
  --c-border-glow: rgba(210,215,225,0.65);
  --c-border-glow-strong: rgba(225,228,235,0.9);
  /* a crisp 1px ring + a soft halo -- pure blur alone was too faint to
     read as a "traced contour" on a near-black background, Chris 2026-07-26 */
  --glow-grey: 0 0 0 1px rgba(210,215,225,0.55), 0 0 12px rgba(210,215,225,0.4);
  --glow-grey-strong: 0 0 0 1px rgba(225,228,235,0.85), 0 0 20px rgba(220,225,235,0.6);
  /* Chris 2026-07-26: "le nouveau style de texte...doit se refleter
     partout" -- the white glow used on the active tab, reused as the
     active/hover text glow for every other icon/text control. */
  --glow-white-active: 0 0 10px rgba(255,255,255,0.75), 0 0 4px rgba(255,255,255,0.5);
  /* single-shadow variant for filter:drop-shadow() (SVG icons) -- that
     filter function only accepts one shadow, unlike text-shadow/box-shadow */
  --glow-active-drop: 0 0 5px rgba(255,255,255,0.8);
}

/* Chris 2026-08-18 : mode jour et "afficher les noms" retirés (avec le menu
   d'engrenage) -- le mode cinéma survit via son propre bouton sur la scène. */

/* Chris 2026-08-19 : accents dynamiques -- galerie ouverte, les deux couleurs
   d'accent du thème suivent la photo courante (--dyn-text/-2 posées sur body
   par updateDynamicBlockColor, script.js) ; galerie fermée, mauve d'origine. */
/* Chris 2026-09-07 : RETIRÉ -- le texte d'interface (onglets, titre de
   galerie, flèches, légende...) "respirait" en changeant de teinte à chaque
   photo, sans aucun réglage pour l'arrêter. Il reste au mauve fixe #d9a3ff
   (--c-gold-bright, choisi par Chris au sélecteur : 217,163,255). Seul le
   bloc texte avec la case "couleur dynamique" cochée suit encore la photo
   (.block-dynamic plus bas -- c'est un choix par bloc, débrayable). */
.topbar-tab, .gallery-heading, .caption-glitch, .site-footer-line,
.view-toggle, .arrow-btn, .tp-arrow, .gallery-heading-close{
  transition-property: color, text-shadow, box-shadow, opacity, filter, background;
  transition-duration: .6s;
}

*{ box-sizing: border-box; }
html,body{
  margin:0; padding:0; width:100%; height:100%;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: 'Space Grotesk', sans-serif;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
h1,h2,h3, .mono,
.caption-glitch, .grid-view-header h2{
  font-family: 'Orbitron', sans-serif;
}
::selection{ background: var(--c-silver); color:#05050a; }
button{ font-family: inherit; cursor: pointer; }
/* Chris 2026-08-19 : répulsif anti-copie -- pas de drag natif ni de
   sélection sur les images (complète le blocage du clic droit, script.js) */
img{ -webkit-user-drag:none; user-select:none; -webkit-user-select:none; }
a{ color: inherit; }

/* ---------------- scrollbar ---------------- */
::-webkit-scrollbar{ width:8px; }
::-webkit-scrollbar-track{ background: transparent; }
::-webkit-scrollbar-thumb{ background: rgba(138,0,203,0.25); border-radius:4px; }

/* ============================================================
   BOOT SCREEN
   ============================================================ */
/* Chris 2026-07-29: loading screen removed entirely (was: bar fill +
   percentage + "INITIALIZING..." text + grid, ~2.5s of choreography). The
   site now lands immediately on the empty stage. #boot-screen stays only
   as: (a) the permanent, always-visible "main page" canvas for floating
   logo/text blocks (#blocks-layer -- see below), (b) a slot for a
   load-error message if window.SiteStore.loadSiteData() actually fails. */
#boot-screen{
  position: fixed; inset:0; z-index: 2; /* same tier as the particle/bg layers -- #fx-canvas is 1, #bg-stage is 0 */
  display:flex; align-items:center; justify-content:center;
  pointer-events: none;
}
.boot-inner{ position:relative; text-align:center; z-index:2; }
/* hidden unless boot() sets an actual error message into it */
.boot-line{ font-size:.72rem; letter-spacing:.3em; color: var(--c-text-dim); margin-top: 18px; display:none; }
.boot-line.error-visible{ display:block; }

/* ============================================================
   BLOCS FLOTTANTS (logo / texte -- "page principale", voir #edit-add-panel)
   ============================================================ */
/* Calque plein écran, jamais caché, indépendant (PAS dans #boot-screen --
   voir la note dans index.html sur pourquoi z-index:2 dans #boot-screen
   laissait #stage, z-index:15, avaler tous les clics destinés aux blocs).
   z-index:16 -- juste au-dessus de #stage, toujours en dessous de #hud-top
   (50) et des modales/lightbox (80+) qui doivent rester cliquables par-dessus.
   pointer-events:none par défaut -- seuls les blocs eux-mêmes (en mode
   édition) redeviennent cliquables/déplaçables ; un visiteur ne doit jamais
   voir sa souris "accrocher" un logo. */
.blocks-layer{ position:fixed; inset:0; z-index:16; pointer-events:none; }
.block{
  position:absolute; pointer-events:none; user-select:none;
  transform-origin: top left;
  transition: opacity .6s ease; /* fondu doux quand un bloc se masque/réapparaît (case "masquer" du panneau) */
}
/* Chris 2026-08-18 : case "MASQUER QUAND UNE GALERIE EST OUVERTE" par bloc --
   posée/retirée par applyBlocksVisibility() (script.js) selon qu'une galerie
   ou le menu d'onglet est ouvert. En mode édition le bloc masqué reste
   visible à 25% (sinon impossible de le re-sélectionner pour décocher). */
/* Chris 2026-08-18 (v2) : masqué aussi en mode édition (demande explicite) --
   pour re-régler un bloc masqué, revenir à la page principale (fermer la
   galerie / le menu d'onglet), où il redevient visible et sélectionnable. */
.block.block-hidden{ opacity:0 !important; pointer-events:none !important; }
/* Chris 2026-08-18 : bloc "bouton cliquable" (linkUrl) -- cliquable et
   signalé au survol même en mode visiteur (où .block est normalement inerte). */
/* Chris 2026-08-18 : bloc texte "couleur dynamique" -- suit la couleur
   dominante de la photo affichée (--dyn-text, script.js) ; repli mauve. */
.block.block-dynamic .block-text-content{
  color: var(--dyn-text, #d9a3ff) !important;
  transition: color .6s ease;
}
.block.block-linked{ pointer-events:auto; cursor:pointer; }
.block.block-linked:hover{ filter:brightness(1.2) drop-shadow(0 0 14px rgba(138,0,203,0.45)); }
body.edit-mode .block.block-linked{ cursor:move; }
/* Chris 2026-07-29: hauteur volontairement PAS fixée en % ici -- le calque
   de blocs est plein écran (voir .blocks-layer), largeur % de la largeur ET
   hauteur % de la hauteur ne représentent PAS le même ratio réel dès que la
   fenêtre n'est pas carrée (un logo store en w%+h% indépendants se
   déformerait au redimensionnement de fenêtre). Un seul champ "w" (largeur)
   est stocké -- la hauteur suit naturellement via l'aspect ratio intrinsèque
   de l'image (height:auto), jamais de distorsion possible. */
.block-logo{ height:auto; filter: drop-shadow(0 0 22px rgba(138,0,203,0.35)); }
.block-logo img{ width:100%; height:auto; display:block; object-fit:contain; pointer-events:none; }
.block-text-content, .block-text-input{
  display:block; width:100%; height:100%; box-sizing:border-box;
  font-family:'Orbitron',sans-serif; white-space:pre-wrap; line-height:1.3; overflow:hidden;
}
/* Chris 2026-08-21 : le texte affiché ne se fait plus jamais couper par sa
   boîte (overflow visible) -- la boîte ne sert qu'au positionnement/drag.
   Le textarea d'édition garde overflow:hidden (cadre de saisie). */
.block-text-content{ pointer-events:none; overflow:visible; }
.block-text-input{
  background: rgba(10,9,14,0.55); border:1px dashed var(--c-border-glow-strong); color: inherit;
  font: inherit; resize:none; padding:2px; outline:none;
}
/* Chris 2026-07-29 (v2, retour live) : "cliquer un élément fait apparaître
   un cadre avec ses options/propriétés" -- gated sur .block-active
   (sélection persistante par clic), PAS sur :hover. :hover seul cachait le
   panneau dès que la souris quittait le bloc pour aller cliquer dedans (le
   panneau vit à droite du bloc, donc hors de sa zone de survol) -- c'était
   la vraie raison pour laquelle les contrôles semblaient inutilisables.
   Mode édition : le bloc redevient interactif (drag/resize via interact.js,
   script.js) et se signale par un contour pointillé une fois sélectionné. */
body.edit-mode .block{ pointer-events:auto; cursor:move; }
body.edit-mode .block.block-active{
  outline:1px dashed var(--c-border-glow-strong); outline-offset:4px;
}
.block-resize-handle{
  position:absolute; right:-7px; bottom:-7px; width:14px; height:14px; border-radius:50%;
  background: var(--c-panel-strong); border:1px solid var(--c-border-glow-strong);
  cursor: nwse-resize; display:none;
}
body.edit-mode .block.block-active .block-resize-handle{ display:block; }

.block-toolbar{
  position:absolute; top:-30px; right:0; display:none; gap:4px; pointer-events:auto;
}
body.edit-mode .block.block-active .block-toolbar{ display:flex; }
.block-toolbar button{
  width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  background: var(--c-panel-strong); border:1px solid var(--c-border-glow); color: var(--c-gold-bright);
  transition: box-shadow .25s;
}
.block-toolbar button:hover{ box-shadow: var(--glow-grey-strong); }
.block-toolbar svg{ width:12px; height:12px; }

/* petit panneau de réglages (police/couleur/taille/opacité) -- s'étire
   depuis le bloc. Max-width transitionné (pas le truc grid-template-rows
   du premier essai -- voir la note sur .edit-add-panel plus haut, même
   correction appliquée ici). */
.block-config{
  position:absolute; top:0; left: calc(100% + 12px); z-index:5;
  max-width:0; overflow:hidden; transition: max-width .3s var(--ease-soft);
  pointer-events:none;
}
.block-config.open{ max-width:200px; pointer-events:auto; }
.block-config-inner{
  width:200px;
  background: var(--c-panel-strong); border:1px solid var(--c-glass-border); border-radius:14px;
  backdrop-filter: blur(20px); padding: 14px 16px; box-shadow: 0 20px 50px rgba(0,0,0,0.5);
}
.block-config-row{ display:flex; flex-direction:column; gap:4px; margin-bottom:10px; }
.block-config-row:last-child{ margin-bottom:0; }
.block-config-row span{ font-size:.6rem; letter-spacing:.1em; color: var(--c-text-dim); }
.block-config-row select, .block-config-row input[type="range"]{ width:100%; }
.block-config-row input[type="color"]{ width:100%; height:26px; border:none; background:none; padding:0; }
.block-config-row textarea{
  width:100%; min-height:54px; resize:vertical; box-sizing:border-box;
  background: rgba(255,255,255,0.05); border:1px solid var(--c-glass-border); border-radius:6px;
  color:inherit; font:inherit; padding:6px;
}

/* ============================================================
   BACKGROUND LAYERS (particles + blurred photo backdrop)
   ============================================================ */
#fx-canvas{ position:fixed; inset:0; z-index:1; width:100%; height:100%; }
#bg-stage{ position:fixed; inset:0; z-index:0; overflow:hidden; }
.bg-layer{
  position:absolute; inset:-6%; background-size: cover; background-position:center;
  filter: blur(38px) saturate(1.3) brightness(.55);
  transform: scale(1.08);
  opacity:0; transition: opacity 1.1s var(--ease-soft);
  will-change: opacity, transform;
}
.bg-layer.active{ opacity: 1; }
.bg-scrim{ position:absolute; inset:0; background: radial-gradient(ellipse at 50% 35%, var(--c-scrim-1) 0%, var(--c-scrim-2) 78%); }
.bg-vignette{ position:absolute; inset:0; box-shadow: inset 0 0 220px 60px var(--c-vignette); pointer-events:none; }
.bg-scanlines{
  position:absolute; inset:0; pointer-events:none; opacity:.5;
  background: repeating-linear-gradient(0deg, rgba(255,255,255,0.025) 0px, rgba(255,255,255,0.025) 1px, transparent 2px, transparent 3px);
  mix-blend-mode: overlay;
}
.bg-noise{
  position:absolute; inset:0; pointer-events:none; opacity:.04; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIj48ZmlsdGVyIGlkPSJuIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iMC44NSIgbnVtT2N0YXZlcz0iMiIgc3RpdGNoVGlsZXM9InN0aXRjaCIvPjwvZmlsdGVyPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbHRlcj0idXJsKCNuKSIvPjwvc3ZnPg==");
}

/* ============================================================
   TOP BAR (persistent, full page width)
   ============================================================ */
.hud-top.topbar{
  position: fixed; top:0; left:0; right:0; z-index: 50;
  display:flex; flex-direction:column; align-items:stretch;
  padding: 18px clamp(16px, 3vw, 48px) 0;
  opacity:0; transform: none;
  pointer-events:none;
}
.hud-top.topbar.visible{ opacity:1; transform:none; }
.hud-top.topbar.visible > *{ pointer-events:auto; }

.topbar-row{
  /* grid, not flex+space-between: the lang button and the actions cluster
     are different widths, so space-between was centering the tabs between
     them instead of on the actual page center. 1fr/auto/1fr guarantees the
     middle column sits dead-center regardless of the side widths. */
  display:grid; grid-template-columns: 1fr auto 1fr; align-items:center; gap: clamp(10px,2vw,24px);
  width:100%;
}
.topbar-row > .topbar-left{ justify-self:start; }
.topbar-row > .topbar-actions{ justify-self:end; }
.topbar-tabs{
  display:flex; gap:4px; justify-content:center; flex-wrap:wrap;
  /* Chris 2026-07-26: "retire la bande que j'ai hachuré" -- no more solid
     filled pill behind the tabs, just the traced grey-glow outline. */
  background: transparent; border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  /* Chris 2026-07-26: no more pill/rounded ends -- match the frame it opens (14px) */
  border-radius: 14px; padding:6px; justify-self:center;
  transition: border-radius .3s var(--ease-soft), border-color .3s, box-shadow .3s;
}
/* Chris 2026-07-26: "trace le contour comme représenté" -- when a category
   is open, the tabs must read as the SAME single outlined shape as the
   frame below, not two stacked boxes with a seam. Open the bottom edge so
   it flows straight into the frame (which is flush, margin:0, right below). */
.topbar-tabs.has-active{ border-bottom:none; border-radius: 14px 14px 0 0; box-shadow:none; }
.topbar-tab{
  /* Chris 2026-07-26: the "clicked" text color applies to ALL tabs at all
     times now, not just the active one -- opacity is what distinguishes
     hover/active/dimmed states. */
  border:none; background: transparent; color: var(--c-gold-bright); opacity:.75; position:relative;
  font-family:'Orbitron',sans-serif; font-size:.64rem; letter-spacing:.16em;
  padding: 10px 16px; border-radius:999px;
  transition: color .35s var(--ease-soft), opacity .35s var(--ease-soft), text-shadow .35s var(--ease-soft);
}
.topbar-tab:hover{ opacity:1; }
.topbar-tab.active{
  /* Chris 2026-07-26: white glow replaces the underline as the selection cue */
  opacity:1; text-shadow: var(--glow-white-active);
}
.topbar-tabs.has-active .topbar-tab:not(.active){ opacity:.2; }

/* Chris 2026-07-29: X de suppression par onglet, visible dès qu'on est en
   mode édition (pas besoin de survoler -- même leçon que les blocs plus
   haut : un contrôle caché derrière :hover est facile à ne jamais trouver).
   Wrapper (span, pas un autre bouton -- un <button> ne peut pas en
   contenir un autre) qui porte le position:relative nécessaire. */
.topbar-tab-wrap{ position:relative; display:inline-block; }
.topbar-tab-delete{
  display:none; position:absolute; top:-6px; right:-6px; z-index:2;
  width:18px; height:18px; border-radius:50%; padding:0;
  background: var(--c-panel-strong); border:1px solid var(--c-border-glow-strong);
  color: var(--c-gold-bright); font-size:.75rem; line-height:1;
  align-items:center; justify-content:center;
  transition: box-shadow .2s;
}
body.edit-mode .topbar-tab-delete{ display:flex; }
/* crayon de renommage d'onglet (Chris 2026-08-21) : meme pastille que le ×,
   posee a sa gauche */
.topbar-tab-edit{
  display:none; position:absolute; top:-6px; right:16px; z-index:2;
  width:18px; height:18px; border-radius:50%; padding:0;
  background: var(--c-panel-strong); border:1px solid var(--c-border-glow-strong);
  color: var(--c-gold-bright); font-size:.6rem; line-height:1;
  align-items:center; justify-content:center;
  transition: box-shadow .2s;
}
body.edit-mode .topbar-tab-edit{ display:flex; }
.topbar-tab-edit:hover{ box-shadow: var(--glow-grey-strong); }
/* champ d'edition inline du nom d'onglet */
.tab-rename-input{
  font-family:'Orbitron',sans-serif; font-size:.66rem; letter-spacing:.12em;
  background:rgba(10,9,14,0.75); color:var(--c-gold-bright);
  border:1px dashed var(--c-border-glow-strong); border-radius:8px;
  padding:6px 8px; width:130px; text-transform:uppercase;
}
.topbar-tab-delete:hover{ box-shadow: var(--glow-grey-strong); }

.topbar-actions{ display:flex; align-items:center; gap:10px; flex-shrink:0; }

/* .lang-toggle : retiré (bouton de langue déplacé dans le footer, 2026-08-18) */

/* ---------------- inline gallery-picker frame (drawn open on tab click) ---- */
.topbar-frame{
  width:100%; max-width: 920px; margin: 0 auto; align-self:center;
  height:0; opacity:0; overflow:hidden; position:relative; border-radius:14px;
  transition: height .5s var(--ease-soft), opacity .3s ease, margin .5s var(--ease-soft);
}
/* Chris 2026-07-26: flush against the tab bar, no gap -- was margin:14px auto 0 */
/* Chris 2026-07-26: -25px top + -25px bottom = 50px shorter (was 172px) */
/* Chris 2026-07-29: 122px is now just the baseline/minimum -- syncTopbarFrameHeight()
   in script.js overrides this with an inline height matching the actual
   content (e.g. a long gallery/partner name wrapping to 3 lines), so
   nothing gets clipped by a fixed number again. */
.topbar-frame.open{ height: 122px; opacity:1; margin: 0 auto; }

/* Chris 2026-07-26: contour drawn with plain CSS bars instead of an SVG
   stroke-dashoffset trick -- the frame is ~5x wider than tall, and an SVG
   viewBox stretched that unevenly doesn't play well with
   vector-effect:non-scaling-stroke (line drew once, then vanished instead
   of staying). Plain bars + a CSS transition have no scaling math at all,
   so the "traced" end state is just the transition's normal resting value
   -- nothing relies on animation-fill-mode to persist. The parent's
   overflow:hidden + border-radius:14px clips these square-ended bars into
   the rounded corners for free.
   Chris 2026-07-28: down to 3 bars (top removed, see .tfo-bottom below) --
   the open tabs above supply that edge instead. */
.tfo{
  position:absolute; z-index:2; background: var(--c-border-glow-strong);
  box-shadow: 0 0 4px var(--c-border-glow-strong), 0 0 8px var(--c-border-glow-strong);
  transition: transform .15s var(--ease-soft); /* Chris 2026-07-29: 3x speed, was .45s */
}
/* Chris 2026-07-29: was one full-width bar growing center-outward; split into
   two halves that each start at their own outer corner and grow INWARD, so
   the traced line visibly "meets in the middle" instead of starting there. */
.tfo-bottom-left{ left:0; width:50%; height:1.5px; transform: scaleX(0); bottom:0; transform-origin: 0 100%; }
.tfo-bottom-right{ right:0; width:50%; height:1.5px; transform: scaleX(0); bottom:0; transform-origin: 100% 100%; }
/* Chris 2026-07-28: two short top stubs instead of one full-width top bar --
   left/width/right are set inline by positionTopbarTopStubs() in script.js
   (the tabs box above is intrinsically sized, so there's no fixed value to
   hardcode). They cover only the flanks the tabs box doesn't already close
   off, so the outline reads as one continuous frame with a single opening
   directly under the open tabs. */
.tfo-top-left, .tfo-top-right{ top:0; height:1.5px; transform: scaleX(0); }
/* Chris 2026-07-29: reversed -- the trace now starts at the tabs' own edge
   (where this stub meets the open tabs, i.e. "the top frame") and grows
   OUTWARD toward the frame's corner, instead of starting at the corner and
   growing in toward the tabs. */
.tfo-top-left{ left:0; transform-origin: 100% 0; }
.tfo-top-right{ right:0; transform-origin: 0 0; }
/* the shared ".topbar-frame.open .tfo{ transform: scale(1); }" rule below
   already opens these two -- scale(1) == scaleX(1) for a 1.5px-tall bar. */
.tfo-left, .tfo-right{ top:0; bottom:0; width:1.5px; transform: scaleY(0); }
.tfo-left{ left:0; transform-origin: 0 0; }
.tfo-right{ right:0; transform-origin: 100% 0; }
.topbar-frame.open .tfo{ transform: scale(1); }
/* Chris 2026-07-29: OPENING draw order, confirmed correct -- top stubs
   first (.05s), side bars (.15s), bottom halves last (.2s). Untouched. */
.topbar-frame.open .tfo-top-left, .topbar-frame.open .tfo-top-right{ transition-delay: .05s; }
.topbar-frame.open .tfo-left, .topbar-frame.open .tfo-right{ transition-delay: .15s; }
.topbar-frame.open .tfo-bottom-left, .topbar-frame.open .tfo-bottom-right{ transition-delay: .2s; }
/* Chris 2026-07-29 (correction #4): CLOSING is its own sequence, not a
   mirror of the open delays -- bottom starts retracting immediately (0s
   delay) AND takes the longest of the three (.2s duration), then the side
   bars take their turn (start once bottom's .2s is done, run for .15s),
   then the top stubs go last (start once the sides are done, run for
   .05s -- the shortest). Fully sequential, no overlap: 0-.2s bottom,
   .2-.35s sides, .35-.4s top. Scoped to :not(.open) so opening above is
   unaffected. */
.topbar-frame:not(.open) .tfo-bottom-left, .topbar-frame:not(.open) .tfo-bottom-right{
  transition-delay: 0s; transition-duration: .2s;
}
.topbar-frame:not(.open) .tfo-left, .topbar-frame:not(.open) .tfo-right{
  transition-delay: .2s; transition-duration: .15s;
}
.topbar-frame:not(.open) .tfo-top-left, .topbar-frame:not(.open) .tfo-top-right{
  transition-delay: .35s; transition-duration: .05s;
}
.topbar-panel{
  position:absolute; inset:0; border-radius:14px; overflow:hidden;
  background: var(--c-panel); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  opacity:0; transition: opacity .35s ease .3s;
  display:flex; align-items:center; gap:8px; padding: 0 10px;
}
.topbar-frame.open .topbar-panel{ opacity:1; }

/* Chris 2026-08-18 : flèches ancrées en absolu et centrées verticalement --
   en flex, la hauteur variable du cadre (syncTopbarFrameHeight) les laissait
   visuellement désalignées par rapport aux cartes. */
.tp-arrow{
  position:absolute; top:50%; transform:translateY(-50%); z-index:2;
  width:30px; height:30px; border-radius:50%;
  background: var(--c-glass); border:1px solid var(--c-border-glow); color: var(--c-gold-bright);
  box-shadow: var(--glow-grey);
  display:flex; align-items:center; justify-content:center; font-size:1.1rem; line-height:1;
  transition: text-shadow .3s, box-shadow .3s;
}
.tp-arrow-left{ left:10px; }
.tp-arrow-right{ right:10px; }
.tp-arrow svg{ width:15px; height:15px; display:block; }
.tp-arrow:hover{ text-shadow: var(--glow-white-active); box-shadow: var(--glow-grey-strong); }
.tp-row{
  flex:1; min-width:0; height:100%; display:flex; align-items:center; gap:10px;
  overflow-x:auto; scroll-behavior:smooth; padding: 10px 50px; scrollbar-width:none;
}
.tp-row::-webkit-scrollbar{ display:none; }
.tp-card-dragging{ opacity:.35; }
.tp-card{
  flex:0 0 auto; width:120px; display:flex; flex-direction:column; align-items:center; gap:6px;
  cursor:pointer; padding:8px; border-radius:10px; transition: background .25s; position:relative;
}
.tp-card:hover{ background: rgba(255,255,255,0.06); }
/* Chris 2026-07-26: the gallery-picker chip is a "pastille" too -- glowing
   grey contour, brighter on hover, same treatment as the other pastilles */
.tp-card-thumb{
  width:100%; height:78px; object-fit:cover; border-radius:8px;
  border:1px solid var(--c-border-glow); box-shadow: var(--glow-grey);
  transition: border-color .25s, box-shadow .25s;
}
.tp-card:hover .tp-card-thumb{ border-color: var(--c-border-glow-strong); box-shadow: var(--glow-grey-strong); }
/* Chris 2026-07-29: partner entries show their logo here instead of a photo
   -- contain (not cover) so the logo isn't cropped, plus a bit of padding
   and a light backing since most logos have a transparent background. */
.tp-card-thumb-partner{ object-fit:contain; background: rgba(255,255,255,0.06); padding:8px; }
.tp-card-name{ font-family:'Orbitron',sans-serif; font-size:.6rem; letter-spacing:.08em; color: var(--c-text); text-align:center; white-space:pre-line; }
/* Chris 2026-09-07 : ✎ décalé à gauche pour laisser la place au × de
   suppression (même disposition que les onglets : × à droite, ✎ à sa gauche) */
.tp-card-rename{
  display:none; position:absolute; top:4px; right:28px; width:20px; height:20px; border-radius:6px;
  background: rgba(0,0,0,0.55); border:none; color: var(--c-text-dim); font-size:.68rem;
  align-items:center; justify-content:center;
}
body.edit-mode .tp-card-rename{ display:flex; }
.tp-card-rename:hover{ color: var(--c-gold-bright); }
/* × de suppression par carte (galerie / événement / partenaire) -- même
   pastille que .topbar-tab-delete, visible dès le mode édition */
.tp-card-delete{
  display:none; position:absolute; top:4px; right:4px; z-index:2;
  width:20px; height:20px; border-radius:50%; padding:0;
  background: var(--c-panel-strong); border:1px solid var(--c-border-glow-strong);
  color: var(--c-gold-bright); font-size:.8rem; line-height:1;
  align-items:center; justify-content:center;
  transition: box-shadow .2s;
}
body.edit-mode .tp-card-delete{ display:flex; }
.tp-card-delete:hover{ box-shadow: var(--glow-grey-strong); }
.tp-rename-input{
  width:100%; background: rgba(255,255,255,0.06); border:1px solid rgba(138,0,203,0.4); border-radius:6px;
  color:var(--c-fg-strong); font-family:inherit; font-size:.7rem; padding: 4px 6px; text-align:center;
  resize:none; line-height:1.3; /* Chris 2026-08-18 : devenu un textarea (retours de ligne permis dans le nom) */
}
.tp-add{
  flex:0 0 auto; width:110px; height:100px; border-radius:10px; border:1px dashed rgba(138,0,203,0.4);
  color: var(--c-gold-bright); background: rgba(138,0,203,0.06); font-size:1.4rem; display:none;
  align-items:center; justify-content:center; transition: background .25s;
}
body.edit-mode .tp-add{ display:flex; }
.tp-add:hover{ background: rgba(138,0,203,0.16); }
.tp-empty{ flex:1; text-align:center; font-size:.7rem; color: rgba(242,239,232,0.4); font-style:italic; }

/* ---------------- mode toggle (edit / view) + settings toggle ---------------- */
.mode-toggle{
  width:38px; height:38px; border-radius:50%; flex-shrink:0;
  background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  color: var(--c-gold-bright); display:flex; align-items:center; justify-content:center;
  transition: filter .3s, box-shadow .3s, background .3s;
}
.mode-toggle svg{ width:17px; height:17px; }
.mode-toggle:hover{ filter: drop-shadow(var(--glow-active-drop)); box-shadow: var(--glow-grey-strong); }
.mode-toggle .icon-view{ display:none; }
body.edit-mode .mode-toggle{ filter: drop-shadow(var(--glow-active-drop)); box-shadow: var(--glow-grey-strong); }
body.edit-mode .mode-toggle .icon-edit{ display:none; }
body.edit-mode .mode-toggle .icon-view{ display:block; }

/* ---------------- "+" ajouter à la page (visible en mode édition seulement) ----------------
   Chris 2026-07-29 (v2, corrigé après capture d'écran en direct) :
   - le + doit être SOUS le crayon, pas à côté -- .mode-toggle-wrap porte le
     position:relative qui ancre le + en absolu juste en dessous du bouton
     édition, sans perturber l'alignement des autres icônes de la rangée
     (le wrapper occupe la même taille que le crayon seul dans le flex).
   - le panneau s'étire vers la GAUCHE du +, pas vers le bas.
   - remplace le "truc" CSS grid-template-rows/columns du premier essai (qui
     laissait le contenu visible/mal caché en pratique, confirmé par capture
     d'écran de Chris) par un simple max-width transitionné -- même
     technique déjà éprouvée ailleurs dans ce fichier (.topbar-frame,
     .filmstrip-dock), donc un risque de rendu déjà écarté. */
.mode-toggle-wrap{ position:relative; }
.edit-add-toggle{
  display:none; position:absolute; top:calc(100% + 10px); left:0; z-index:41;
  width:38px; height:38px; border-radius:50%; flex-shrink:0;
  background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  color: var(--c-gold-bright); align-items:center; justify-content:center;
  transition: filter .3s, box-shadow .3s, background .3s;
}
body.edit-mode .edit-add-toggle{ display:flex; }
.edit-add-toggle svg{ width:17px; height:17px; }
.edit-add-toggle:hover{ filter: drop-shadow(var(--glow-active-drop)); box-shadow: var(--glow-grey-strong); }
.edit-add-toggle.active{ filter: drop-shadow(var(--glow-active-drop)); box-shadow: var(--glow-grey-strong); }

/* Chris 2026-08-18 : le crayon vit maintenant au bord GAUCHE de la barre --
   le panneau + s'étire donc vers la droite (left) au lieu de la gauche. */
.edit-add-panel{
  position:absolute; top:calc(100% + 10px); left: calc(100% + 12px); z-index:40;
  max-width:0; overflow:hidden; transition: max-width .35s var(--ease-soft);
  pointer-events:none;
}
.edit-add-panel.open{ max-width:170px; pointer-events:auto; }
.edit-add-panel-inner{
  width:170px; display:flex; flex-direction:column; gap:2px;
  background: var(--c-panel-strong); border:1px solid var(--c-glass-border); border-radius:14px;
  backdrop-filter: blur(20px); padding: 8px; box-shadow: 0 20px 50px rgba(0,0,0,0.5);
}
.edit-add-item{
  background:transparent; border:none;
  text-align:left; padding: 9px 10px; border-radius:9px; font-size:.66rem; letter-spacing:.1em;
  color: var(--c-text-dim); transition: background .2s, color .2s; white-space:nowrap;
}
.edit-add-item:hover{ background: rgba(138,0,203,0.16); color: var(--c-gold-bright); }

/* ---------------- exit-cinema button ----------------
   Lives outside #hud-top on purpose: hud-top (incl. the settings popover
   that turns cinema mode on) is hidden while cinema mode is active, so this
   is the only way back out and must never be hidden by that same rule. */
.exit-cinema-btn{
  display:none; position: fixed; top:22px; right: clamp(20px,4vw,56px); z-index: 60;
  align-items:center; gap:8px; padding: 9px 16px 9px 12px; border-radius:999px;
  background: var(--c-panel); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  color: var(--c-gold-bright); font-family:'Orbitron',sans-serif; font-size:.62rem; letter-spacing:.16em;
  transition: text-shadow .3s, box-shadow .3s;
}
.exit-cinema-btn svg{ width:15px; height:15px; }
.exit-cinema-btn:hover{ text-shadow: var(--glow-white-active); box-shadow: var(--glow-grey-strong); }
body.cinema-mode .exit-cinema-btn{ display:flex; }

/* ============================================================
   HERO
   ============================================================ */
.hero{
  position: relative; z-index: 10; min-height: 100vh;
  display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center;
  padding: 0 24px;
}
.hero-logo-wrap{
  /* Chris 2026-07-26: no longer a button -- boot enters the archive on its
     own, the hero is just an inert backdrop shown for an instant (if at
     all) before enterArchive() hides it. No cursor/hover affordance.
     Chris 2026-07-29: "rien ne bouge" on arrival -- no intro animation,
     already at its final look (moot in practice since enterArchive() hides
     the whole hero instantly, but kept motionless for the rare frame before
     that runs). */
  display:flex; flex-direction:column; align-items:center; gap: clamp(14px, 2.4vw, 22px);
  opacity:1; transform: scale(1);
}
.hero-logo{
  width: clamp(160px, 26vw, 320px); height:auto; display:block;
  filter: drop-shadow(0 0 34px rgba(138,0,203,0.22));
}
.hero-logo-text{
  width: clamp(140px, 20vw, 260px); height:auto; display:block; opacity:.9;
}

/* Chris 2026-07-28: was a graceful .7s fade -- but the hero sits fully
   opaque and inert behind the (opaque) boot screen the whole time, so its
   own separate logo (same asset, but a bigger size than the boot logo --
   see .hero-logo vs .boot-logo-img) was still fading out in the open while
   the boot screen fades away on top of it, reading as a second, larger
   logo flashing right as the boot fade finishes. Hiding it instantly (no
   transition) removes it before the boot screen becomes transparent enough
   to reveal it, since it's never meant to be seen in this flow anyway
   (boot always auto-enters the archive -- see enterArchive() comment). */
.hero.hidden{ opacity:0; visibility:hidden; pointer-events:none; position:fixed; inset:0; }

/* ============================================================
   MAIN STAGE / CAROUSEL
   ============================================================ */
.stage{
  position: fixed; inset:0; z-index: 15;
  display:flex; align-items:center; justify-content:center;
  opacity:0; visibility:hidden; pointer-events:none;
}

/* ---------------- partner spotlight (gal.type === "partner") ---------------
   Chris 2026-07-29: a "partner" gallery entry shows this instead of the
   photo carousel -- still nav'd/closed like any gallery (title + X), just a
   different stage content. Arrows/view-toggle/filmstrip don't need extra
   hiding rules here: they're already gated on .stage.has-photos elsewhere,
   and a partner entry has photos:[] so that class never gets added. */
.partner-spotlight{
  position:absolute; inset:0; display:none;
  flex-direction:column; align-items:center; justify-content:center; gap:28px;
  padding: 0 24px;
}
.stage.partner-mode .partner-spotlight{ display:flex; }
.stage.partner-mode .carousel-viewport{ display:none; }
.partner-frame{
  /* Chris 2026-07-29: logo retire de cette vue, cadre reduit a un seul
     enfant (l'image) -- padding retire pour que l'image touche les coins
     du cadre exactement ("fitter au coin"), image et cadre partagent le
     meme rayon de coin pour que ça se voie comme un seul bloc. */
  display:flex; flex-direction:column; align-items:center;
  padding: 0; border-radius: 18px; max-width: min(720px, 88vw);
  background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey); overflow:hidden;
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.partner-screenshot{
  /* Chris 2026-07-29: taille doublee (retour 100%/46vh) puis logo retire +
     image fittee exactement aux coins du cadre (pas de padding, meme rayon
     que .partner-frame) + opacite remontee a 80% (etait 50%). */
  max-width:100%; max-height: 46vh; width:auto; height:auto; display:block;
  opacity:.8;
  border-radius: 18px; box-shadow: 0 20px 60px rgba(0,0,0,0.45);
}
.partner-cta{
  font-family:'Orbitron',sans-serif; font-size:.7rem; letter-spacing:.18em;
  padding: 12px 28px; border-radius:999px; background: var(--c-glass);
  border:1px solid var(--c-border-glow); color: var(--c-gold-bright);
  box-shadow: var(--glow-grey);
  text-decoration:none; display:inline-block;
  transition: text-shadow .3s, box-shadow .3s, background .3s;
}
.partner-cta:hover{ background: rgba(138,0,203,0.12); text-shadow: var(--glow-white-active); box-shadow: var(--glow-grey-strong); }

/* Chris 2026-07-29: wrapper SANS overflow:hidden (contrairement à
   .partner-frame) -- porte le position:relative pour le bouton de réglages
   et son panneau, qui doivent pouvoir déborder du cadre de l'image. */
.partner-frame-wrap{ position:relative; display:flex; flex-direction:column; align-items:center; }
.partner-image-settings-toggle{
  display:none; position:absolute; top:10px; right:10px; z-index:3;
  width:32px; height:32px; border-radius:50%;
  background: var(--c-panel-strong); border:1px solid var(--c-border-glow);
  color: var(--c-gold-bright); align-items:center; justify-content:center;
  transition: box-shadow .25s;
}
body.edit-mode .stage.partner-mode .partner-image-settings-toggle{ display:flex; }
.partner-image-settings-toggle svg{ width:16px; height:16px; }
.partner-image-settings-toggle:hover, .partner-image-settings-toggle.active{ box-shadow: var(--glow-grey-strong); }
.partner-image-settings{
  position:absolute; top:10px; right: calc(100% + 12px); z-index:3;
  max-width:0; overflow:hidden; transition: max-width .3s var(--ease-soft);
  pointer-events:none;
}
.partner-image-settings.open{ max-width:200px; pointer-events:auto; }
.partner-image-settings-inner{ width:200px; }
.stage.visible{ opacity:1; visibility:visible; pointer-events:auto; }

.gallery-heading{
  position:absolute; top: 96px; left:50%; transform: translateX(-50%);
  display:flex; align-items:center; gap:10px;
  font-family:'Orbitron',sans-serif; font-size:.68rem; letter-spacing:.28em; color: var(--c-gold-bright);
  text-shadow: 0 0 10px rgba(138,0,203,0.35);
  opacity:0; visibility:hidden; transition: opacity .5s var(--ease); z-index:20;
}
.gallery-heading.visible{ opacity:.9; visibility:visible; }
/* Chris 2026-08-18 : un nom de galerie peut contenir des retours de ligne */
.gallery-heading-text{ white-space:pre-line; text-align:center; }
/* Chris 2026-07-28: X next to the open gallery's title -- closes it
   (fold-to-packet animation, see closeGalleryAnimated in script.js) back to
   the empty landing page. Chris 2026-07-28 (2nd pass): "put it in a pastille
   like the rest of the buttons, same size" -- matches .view-toggle exactly
   (36px glass circle, border-glow, glow-grey shadow), the closest icon
   button in this same top:96px row. */
.gallery-heading-close{
  flex-shrink:0; width:36px; height:36px; border-radius:50%;
  background: var(--c-glass); border:1px solid var(--c-border-glow); box-shadow: var(--glow-grey);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  display:flex; align-items:center; justify-content:center;
  cursor:pointer; padding:0;
  font-family:'Orbitron',sans-serif; font-size:.85rem; line-height:1; letter-spacing:0;
  color: var(--c-gold-bright);
  transition: text-shadow .3s, box-shadow .3s, background .3s;
}
.gallery-heading-close:hover{ background: rgba(138,0,203,0.12); text-shadow: var(--glow-white-active); box-shadow: var(--glow-grey-strong); }

.gallery-intro{
  position:absolute; top: 132px; left:50%; transform: translateX(-50%);
  max-width:min(560px, 86vw); text-align:center; padding: 0 12px;
  font-family:'Space Grotesk',sans-serif; font-size:.78rem; line-height:1.6; color: var(--c-text-dim);
  opacity:0; visibility:hidden; transition: opacity .5s var(--ease); z-index:20;
  white-space: pre-wrap;
}
.gallery-intro.visible{ opacity:.85; visibility:visible; }
.gallery-intro.placeholder{ opacity:.4; font-style:italic; }
.gallery-intro.editable{ cursor:pointer; }
.gallery-intro.editable:hover{ color: var(--c-gold-bright); opacity:1; }
.gallery-intro-input{
  position:absolute; top: 132px; left:50%; transform: translateX(-50%); z-index:21;
  width:min(560px, 86vw); min-height: 54px; resize: vertical;
  background: rgba(0,0,0,0.45); border:1px solid rgba(138,0,203,0.4); border-radius:8px;
  color:var(--c-fg-strong); font-family:'Space Grotesk',sans-serif; font-size:.78rem; line-height:1.6; padding: 8px 10px;
  backdrop-filter: blur(10px);
}

/* per-gallery carousel <-> index toggle */
/* Chris 2026-08-18 (v2) : les contrôles de la scène vivent dans la rangée
   .stage-bottom-controls (bas, centrée) -- le position:absolute de base ne
   sert plus qu'au bouton retour-carrousel du HAUT de la vue encadrée. */
.stage-bottom-controls{
  position:absolute; bottom:40px; left:50%; transform:translateX(-50%); z-index:21;
  display:flex; align-items:center; gap:12px;
  opacity:0; pointer-events:none; transition: opacity .8s var(--ease) .3s;
}
.stage.visible.has-photos .stage-bottom-controls,
.stage.visible.partner-mode .stage-bottom-controls{ opacity:1; pointer-events:auto; } /* page partenaire : le X doit rester accessible */
.stage-bottom-controls .view-toggle{ position:static; }
/* (pilule .insta-btn retirée le 2026-08-18 -- l'instagram d'une galerie est
   maintenant un BLOC texte rattaché à la galerie : déplaçable/lien/opacité) */
/* sur une page sans photos (partenaire), seuls les boutons pertinents restent */
.stage:not(.has-photos) .stage-bottom-controls .view-toggle{ display:none; }
.grid-bottom-controls{
  position:fixed; bottom:70px; left:50%; transform:translateX(-50%); z-index:45;
  display:flex; align-items:center; gap:12px;
}
.grid-bottom-controls .view-toggle{ position:static; opacity:.85; pointer-events:auto; }
.view-toggle{
  position:absolute; top: 96px; right: clamp(16px,4vw,60px); z-index:22;
  width:36px; height:36px; border-radius:50%;
  background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  backdrop-filter: blur(14px); color: var(--c-gold-bright);
  display:flex; align-items:center; justify-content:center;
  opacity:0; pointer-events:none; transition: opacity .6s var(--ease) .2s, filter .3s, box-shadow .3s;
}
.view-toggle svg{ width:16px; height:16px; }
/* Chris 2026-07-26: only a real point when a gallery is actually on screen
   -- gated on .has-photos, not just .stage.visible (true even when empty) */
.stage.visible.has-photos .view-toggle{ opacity:.85; pointer-events:auto; }
.view-toggle:hover{ opacity:1; filter: drop-shadow(var(--glow-active-drop)); box-shadow: var(--glow-grey-strong); }
.view-toggle-carousel{ position:absolute; top: 96px; right: clamp(16px,4vw,60px); opacity:.85; z-index:45; }
/* Chris 2026-08-18 (bug corrigé) : ce bouton vit dans #grid-view, pas dans
   .stage -- la règle .stage.visible.has-photos .view-toggle ne le réarmait
   donc jamais : visible mais incliquable (pointer-events:none de base). */
.grid-view.visible .view-toggle-carousel{ opacity:.85; pointer-events:auto; }
body.cinema-mode .view-toggle{ display:none !important; }

/* Chris 2026-08-18 : coins HUD (.corner) retirés -- plus utilisés depuis que
   la lightbox partage la lamelle de verre du carrousel. */

.carousel-viewport{
  position:relative; width:100%; height: 100%;
  display:flex; align-items:center; justify-content:center;
  perspective: 1800px; overflow:hidden;
}
.carousel-track{ position:relative; width:100%; height:100%; transform-style: preserve-3d; }

.card{
  /* width/height are set inline per-card by script.js, sized from the
     photo's real w/h (data/site-data.json) so portrait and landscape
     shots both show uncropped instead of being forced into one fixed box. */
  position:absolute; top:50%; left:50%;
  border-radius: 18px;
  transition: transform 1.15s var(--ease-float), opacity 1s var(--ease-float), width .3s var(--ease-soft), height .3s var(--ease-soft);
  will-change: transform, opacity;
  cursor: pointer;
}
.card-float{
  position:relative; width:100%; height:100%;
}
.card-glass{
  position:absolute; inset:0; border-radius: 18px; overflow:hidden;
  background: var(--c-glass);
  border: 1px solid rgba(230,220,200,0.09);
  backdrop-filter: blur(8px) saturate(1.15);
  -webkit-backdrop-filter: blur(8px) saturate(1.15);
  box-shadow:
    0 26px 70px rgba(0,0,0,0.6),
    0 4px 14px rgba(0,0,0,0.4),
    inset 0 1px 0 rgba(255,255,255,0.16),
    inset 0 -1px 0 rgba(0,0,0,0.35);
}
.card-glass img{ width:100%; height:100%; object-fit:cover; display:block; transform: scale(1.001); }
/* Chris 2026-08-18 (v2) : reflet RETIRÉ à la demande du photographe -- le
   voile diagonal altérait l'editing des photos. Le contour (biseau de bord
   + liseré coloré) est conservé, lui ne touche que les 4px du bord. */
.card-sheen{ display:none; }
/* card-bevel simulates a ~1mm-thick glass pane: a beveled ring lit from the
   top-left (bright specular edge) fading to a shaded, slightly cool edge at
   the bottom-right -- the illusion of physical edge thickness on the glass. */
.card-bevel{
  position:absolute; inset:0; border-radius:18px; pointer-events:none; z-index:2;
  padding: 4px;
  background: linear-gradient(135deg,
    rgba(255,255,255,0.95) 0%,
    rgba(255,255,255,0.4) 10%,
    rgba(255,255,255,0.08) 26%,
    rgba(255,255,255,0.02) 45%,
    rgba(10,8,14,0.1) 62%,
    rgba(10,8,14,0.45) 82%,
    rgba(10,8,14,0.6) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
.card-bevel::after{
  content:''; position:absolute; inset:4px; border-radius:14px; pointer-events:none;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.22);
  mix-blend-mode: overlay;
}
.card-edge{
  position:absolute; inset:0; border-radius:18px; pointer-events:none; padding:2px;
  /* --edge-a/--edge-b : couleurs dominantes de la photo (script.js,
     applyEdgeColors) -- le violet/argent n'est que le repli. */
  background: linear-gradient(140deg, var(--edge-a, rgba(138,0,203,0.75)), rgba(255,255,255,0), var(--edge-b, rgba(227,230,238,0.6)));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity:0; transition: opacity .6s; z-index:3;
}
.card.is-center .card-edge{ opacity: 1; }
.card-index-tag{
  position:absolute; top:12px; left:12px; font-family:'Orbitron',sans-serif; font-size:.6rem; letter-spacing:.15em;
  background: var(--c-panel); border:1px solid var(--c-glass-border); padding:4px 9px; border-radius: 20px;
  backdrop-filter: blur(6px); opacity:0; transition: opacity .5s;
}
.card-glow{
  position:absolute; inset:-2px; border-radius:20px; z-index:-1; opacity:0; transition: opacity .8s;
  background: linear-gradient(135deg, var(--edge-a, var(--c-gold)), var(--edge-b, var(--c-silver)));
  filter: blur(28px);
}
.card.is-center .card-glow{ opacity:.35; }

.arrow-btn{
  position:fixed; top:50%; transform: translateY(-50%); z-index:25;
  width:54px; height:54px; border-radius:50%;
  background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  display:flex; align-items:center; justify-content:center; color:var(--c-gold-bright);
  opacity:0; pointer-events:none; transition: opacity .8s var(--ease) .3s, background .3s, box-shadow .3s, transform .3s var(--ease-soft), filter .3s;
}
.stage.visible.has-photos .arrow-btn{ opacity:.85; pointer-events:auto; }
/* Chris 2026-07-29: flèches de navigation ENTRE partenaires (pas entre
   photos -- une "galerie" partenaire n'a jamais de photos, has-photos ne se
   pose jamais pour ce type).
   Chris 2026-07-29 (bug corrigé après retour live -- "je vois plus les
   flèches du tout") : .arrow-btn de base est position:fixed avec un top:50%
   pensé pour un ancrage aux bords de l'écran (voir .arrow-left/.arrow-right)
   -- en enlevant ces 2 classes pour les faire vivre DANS .partner-nav-row
   (flex, "collées au cadre"), elles restaient quand même position:fixed
   SANS left/right, donc sorties du flux flex et sans position horizontale
   définie -- invisibles/mal placées. Il fallait explicitement repasser en
   position:static ici pour qu'elles redeviennent de vrais enfants flex.
   Sélecteur à 2 classes (.arrow-btn.arrow-btn-partner) pour être sûr de
   gagner sur .arrow-btn:hover/:active même si l'ordre dans ce fichier
   changeait plus tard. */
.arrow-btn-partner{
  position:static; top:auto; transform:none; opacity:0; pointer-events:none;
  transition: opacity .3s ease, background .3s, box-shadow .3s, filter .3s, transform .2s;
}
.stage.visible.partner-mode .arrow-btn-partner{ opacity:.85; pointer-events:auto; }
.arrow-btn.arrow-btn-partner:hover{ transform: scale(1.08); }
.arrow-btn.arrow-btn-partner:active{ transform: scale(0.94); }

/* Chris 2026-07-29 (v2, retour live -- "effet carrousel 3D comme les
   galeries photo, même avec juste 2 partenaires") : pas le même mécanisme
   que le carrousel principal (pool DOM virtualisé pour des centaines de
   photos -- inutile ici, jamais plus qu'une poignée de partenaires), mais
   le même LANGAGE visuel -- perspective + rotateY, voir .carousel-viewport/
   .carousel-track. Le flip lui-même (rotateY 0 -> ±100deg -> swap -> ±100deg
   -> 0) est piloté en JS (gotoAdjacentPartner, script.js), pas en CSS pur --
   il doit attendre que le nouveau contenu soit chargé avant de revenir. */
.partner-nav-row{ display:flex; align-items:center; gap:20px; perspective:1400px; }
.partner-frame-wrap{ transform-style: preserve-3d; will-change: transform, opacity; }
.arrow-btn svg{ width:20px; height:20px; }
.arrow-btn:hover{ opacity:1; background: rgba(255,255,255,0.1); box-shadow: var(--glow-grey-strong); filter: drop-shadow(var(--glow-active-drop)); transform: translateY(-50%) scale(1.08); }
.arrow-btn:active{ transform: translateY(-50%) scale(0.94); }
.arrow-left{ left: clamp(10px, 3vw, 40px); }
.arrow-right{ right: clamp(10px, 3vw, 40px); }

.caption-bar{
  position:absolute; bottom: 108px; left:50%; transform: translateX(-50%);
  text-align:center; z-index:20; opacity:0; visibility:hidden; transition: opacity .8s var(--ease) .3s, visibility .8s;
  pointer-events:none;
}
.caption-glitch{ font-size: clamp(1rem,2vw,1.3rem); letter-spacing:.14em; font-weight:700; }


/* ---------------- edit-mode photo/gallery actions under the carousel ---------------- */
.edit-photo-actions{
  position:absolute; bottom: 60px; left:50%; transform: translateX(-50%);
  display:none; gap:10px; z-index:20;
}
/* Chris 2026-08-21 (vieux bug) : gate sur has-photos (photos réellement
   chargées), pas seulement la visibilité de la stage -- sinon SUPPRIMER
   CETTE PHOTO traîne en mode édition alors qu'il n'y a rien à supprimer.
   Même règle que flèches/grille/filmstrip (DECISIONS 2026-07-26). */
body.edit-mode .stage.visible.has-photos .edit-photo-actions{ display:flex; }
.edit-chip{
  font-family:'Orbitron',sans-serif; font-size:.58rem; letter-spacing:.14em; padding: 8px 14px; border-radius:999px;
  background: rgba(255,60,60,0.08); border:1px solid rgba(255,90,90,0.35); color:#ff9b9b;
  backdrop-filter: blur(10px); transition: background .3s, box-shadow .3s, text-shadow .3s;
}
.edit-chip:hover{ background: rgba(255,60,60,0.18); box-shadow: 0 0 16px rgba(255,60,60,0.2); }
.edit-chip.gold{
  background: rgba(138,0,203,0.08); border-color: var(--c-border-glow); color: var(--c-gold-bright);
  box-shadow: var(--glow-grey);
}
.edit-chip.gold:hover{ background: rgba(138,0,203,0.18); text-shadow: var(--glow-white-active); box-shadow: var(--glow-grey-strong); }

/* ============================================================
   GRID / INDEX VIEW
   ============================================================ */
.grid-view{
  position:fixed; inset:0; z-index: 40; overflow-y:auto;
  background: var(--c-overlay); backdrop-filter: blur(30px); -webkit-backdrop-filter: blur(30px);
  opacity:0; visibility:hidden; pointer-events:none; transition: opacity .5s var(--ease), visibility .5s;
  padding: 120px clamp(20px,5vw,80px) 80px;
}
.grid-view.visible{ opacity:1; visibility:visible; pointer-events:auto; }
.grid-view-header{ text-align:center; margin-bottom: 44px; }
.grid-view-header h2{ font-size: clamp(1.6rem,3.4vw,2.4rem); letter-spacing:.1em; margin:0 0 8px;
  background: linear-gradient(90deg, var(--c-gold), var(--c-silver)); -webkit-background-clip:text; background-clip:text; color:transparent; }
.grid-view-sub{ font-size:.7rem; letter-spacing:.24em; color: var(--c-text-dim); }
.grid-view-grid{
  display:grid; grid-template-columns: repeat(auto-fill, minmax(160px,1fr)); gap: 16px;
  max-width: 1400px; margin: 0 auto;
}
/* Chris 2026-08-18 : la vue encadrée présente chaque photo sur la même
   lamelle de verre que le carrousel (verre + biseau ::before + reflet ::after). */
.grid-item{
  position:relative; aspect-ratio: 2/3; border-radius:16px; cursor:pointer;
  padding: 4px;
  background: var(--c-glass);
  border:1px solid rgba(230,220,200,0.09);
  backdrop-filter: blur(8px) saturate(1.15);
  -webkit-backdrop-filter: blur(8px) saturate(1.15);
  box-shadow:
    0 14px 40px rgba(0,0,0,0.5),
    inset 0 1px 0 rgba(255,255,255,0.14),
    inset 0 -1px 0 rgba(0,0,0,0.3);
  transition: transform .4s var(--ease-soft), box-shadow .4s;
}
/* Chris 2026-08-18 : plus AUCUN filtre sur la photo (le saturate/brightness
   d'origine altérait aussi l'editing) -- rendu pur, même hors survol. */
.grid-item img{
  width:100%; height:100%; object-fit:cover; border-radius:12px;
}
.grid-item::before{
  content:''; position:absolute; inset:0; border-radius:16px; pointer-events:none; z-index:2; padding:2px;
  background: linear-gradient(140deg, var(--edge-a, rgba(138,0,203,0.6)), rgba(255,255,255,0.1), var(--edge-b, rgba(227,230,238,0.5)));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity:0; transition: opacity .4s;
}
/* (reflet ::after retiré le 2026-08-18 -- photo pure, contour conservé) */
.grid-item:hover{ transform: translateY(-6px); box-shadow: 0 20px 55px rgba(138,0,203,0.22), inset 0 1px 0 rgba(255,255,255,0.14); }
.grid-item:hover::before{ opacity:1; }
.grid-item:hover img{ filter:none; }
.grid-item-tag{
  position:absolute; bottom:8px; left:8px; font-family:'Orbitron',sans-serif; font-size:.55rem; letter-spacing:.1em;
  background: var(--c-panel); padding:3px 8px; border-radius: 20px; border:1px solid var(--c-glass-border);
  display:none;
}

/* ============================================================
   LIGHTBOX
   ============================================================ */
.lightbox{
  position:fixed; inset:0; z-index:80; display:flex; align-items:center; justify-content:center;
  background: var(--c-overlay); backdrop-filter: blur(10px);
  opacity:0; visibility:hidden; pointer-events:none; transition: opacity .45s var(--ease), visibility .45s;
}
.lightbox.visible{ opacity:1; visibility:visible; pointer-events:auto; }
/* Chris 2026-08-18 : la photo agrandie vit sur la MÊME lamelle de verre que
   les cartes du carrousel -- verre dépoli + biseau lumineux (::before, anneau
   dégradé masqué) + reflet diagonal (::after). Les anciens coins HUD dorés
   sont retirés (index.html). */
/* Chris 2026-08-18 : agrandi (était 88vw/80vh) -- le plus plein écran
   possible en gardant l'air des boutons de navigation et de la légende. */
.lightbox-frame{
  position:relative; max-width: 96vw; max-height: 92vh;
  padding: 6px; border-radius: 20px;
  background: var(--c-glass);
  border: 1px solid rgba(230,220,200,0.09);
  backdrop-filter: blur(8px) saturate(1.15);
  -webkit-backdrop-filter: blur(8px) saturate(1.15);
  box-shadow:
    0 40px 120px rgba(0,0,0,0.7),
    0 6px 18px rgba(0,0,0,0.45),
    inset 0 1px 0 rgba(255,255,255,0.16),
    inset 0 -1px 0 rgba(0,0,0,0.35);
  transform: scale(.94); transition: transform .45s var(--ease);
}
.lightbox.visible .lightbox-frame{ transform: scale(1); }
.lightbox-frame img{ max-width: calc(96vw - 12px); max-height: calc(92vh - 12px); display:block; border-radius: 15px; }
.lightbox-frame::before{
  content:''; position:absolute; inset:0; border-radius:20px; pointer-events:none; z-index:2; padding:2px;
  background: linear-gradient(140deg, var(--edge-a, rgba(138,0,203,0.75)), rgba(255,255,255,0.15), var(--edge-b, rgba(227,230,238,0.6)));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity:.8;
}
/* (reflet ::after retiré le 2026-08-18 -- photo pure, contour conservé) */
.lightbox-close{
  position:absolute; top: 26px; right: clamp(16px,3vw,40px); background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  color:var(--c-gold-bright); padding:10px 18px; border-radius:999px; font-family:'Orbitron',sans-serif; font-size:.65rem; letter-spacing:.18em;
  backdrop-filter: blur(14px); transition: text-shadow .3s, box-shadow .3s, background .3s;
}
.lightbox-close:hover{ background: rgba(138,0,203,0.12); text-shadow: var(--glow-white-active); box-shadow: var(--glow-grey-strong); }
.lightbox-nav{
  position:absolute; top:50%; transform: translateY(-50%); background: var(--c-glass); border:1px solid var(--c-border-glow);
  box-shadow: var(--glow-grey);
  color:var(--c-gold-bright); width:50px; height:50px; border-radius:50%; font-size:1.6rem; backdrop-filter: blur(14px);
  display:flex; align-items:center; justify-content:center; transition: filter .3s, box-shadow .3s, background .3s;
}
.lightbox-nav svg{ width:20px; height:20px; display:block; }
.lightbox-nav:hover{ background: rgba(138,0,203,0.12); filter: drop-shadow(var(--glow-active-drop)); box-shadow: var(--glow-grey-strong); }
.lightbox-prev{ left: clamp(10px,3vw,40px); }
.lightbox-next{ right: clamp(10px,3vw,40px); }
.lightbox-caption{
  position:absolute; bottom: 30px; left:50%; transform: translateX(-50%);
  font-family:'Orbitron',sans-serif; font-size:.7rem; letter-spacing:.2em; color: var(--c-text-dim);
  display:none;
}
.lightbox-delete{
  display:none; position:absolute; top:26px; left: clamp(16px,3vw,40px);
  font-family:'Orbitron',sans-serif; font-size:.6rem; letter-spacing:.14em; padding: 10px 16px; border-radius:999px;
  background: rgba(255,60,60,0.1); border:1px solid rgba(255,90,90,0.4); color:#ff9b9b; backdrop-filter: blur(14px);
  transition: background .3s, box-shadow .3s;
}
body.edit-mode .lightbox-delete{ display:block; }
.lightbox-delete:hover{ background: rgba(255,60,60,0.2); box-shadow: 0 0 18px rgba(255,60,60,0.2); }

/* ============================================================
   CINEMA MODE — strip everything but the carousel + background
   ============================================================ */
body.cinema-mode .hud-top,
body.cinema-mode .gallery-heading,
body.cinema-mode .gallery-intro,
body.cinema-mode .caption-bar,
body.cinema-mode .stage-bottom-controls,
body.cinema-mode .edit-photo-actions{
  display:none !important;
}

/* ============================================================
   MODALS (new gallery / confirm)
   ============================================================ */
.modal{
  position:fixed; inset:0; z-index:120; display:flex; align-items:center; justify-content:center;
  background: var(--c-overlay); backdrop-filter: blur(14px);
  opacity:0; visibility:hidden; pointer-events:none; transition: opacity .35s var(--ease), visibility .35s;
  padding: 24px;
}
.modal.visible{ opacity:1; visibility:visible; pointer-events:auto; }
.modal-panel{
  width: min(480px, 100%); max-height: 84vh; overflow-y:auto;
  background: var(--c-panel-strong); border:1px solid var(--c-glass-border); border-radius:20px;
  padding: 30px clamp(20px,4vw,34px); box-shadow: 0 30px 90px rgba(0,0,0,0.6);
  transform: scale(.96); transition: transform .35s var(--ease);
}
.modal.visible .modal-panel{ transform: scale(1); }
.modal-panel.small{ width: min(380px, 100%); }
.modal-title{
  font-family:'Orbitron',sans-serif; font-size:1rem; letter-spacing:.14em; margin-bottom: 4px;
  background: linear-gradient(90deg, var(--c-gold), var(--c-silver)); -webkit-background-clip:text; background-clip:text; color:transparent;
}
.modal-sub{ font-size:.62rem; letter-spacing:.2em; color: var(--c-text-dim); margin-bottom: 22px; }
.modal-field{ margin-bottom: 18px; }
.modal-field > span{ display:block; font-size:.62rem; letter-spacing:.14em; color: var(--c-text-dim); margin-bottom: 8px; }
.modal-field input[type="text"], .modal-field input[type="url"]{
  width:100%; background: rgba(255,255,255,0.05); border:1px solid var(--c-glass-border); border-radius:10px;
  padding: 11px 14px; color:var(--c-fg-strong); font-family: inherit; font-size:.9rem;
}
.modal-field input[type="text"]:focus, .modal-field input[type="url"]:focus{ outline:none; border-color: rgba(138,0,203,0.5); }
.modal-btn-row{ display:flex; gap:10px; flex-wrap:wrap; }
.modal-folder-status{ margin-top:8px; font-size:.68rem; color: var(--c-text-dim); line-height:1.6; }
.modal-folder-status .warn{ color:#ffb15c; }
/* Chris 2026-07-29: "coller une capture d'écran (Ctrl+V)" -- petit texte
   discret sous le bouton de choix de fichier. */
.modal-hint{ margin-top:8px; font-size:.62rem; font-style:italic; color: var(--c-text-dim); opacity:.75; }
.modal-preview{ display:flex; flex-wrap:wrap; gap:6px; margin: 10px 0 4px; max-height:120px; overflow-y:auto; }
.modal-preview img{ width:44px; height:60px; object-fit:cover; border-radius:5px; border:1px solid rgba(255,255,255,0.1); }
.modal-progress{ margin: 14px 0 4px; }
.modal-progress-track{ height:4px; border-radius:2px; background: rgba(255,255,255,0.1); overflow:hidden; }
.modal-progress-fill{ height:100%; width:0%; background: linear-gradient(90deg, var(--c-gold), var(--c-silver)); transition: width .2s var(--ease-soft); }
.modal-progress-label{ margin-top:8px; font-size:.62rem; letter-spacing:.12em; color: var(--c-text-dim); }
.modal-confirm-body{ font-size:.85rem; color: var(--c-text-dim); line-height:1.6; margin-bottom: 24px; }
.modal-actions{ display:flex; justify-content:flex-end; gap:10px; margin-top: 24px; }
.modal-btn{
  font-family:'Orbitron',sans-serif; font-size:.64rem; letter-spacing:.14em; padding: 11px 20px; border-radius:999px;
  border:1px solid var(--c-glass-border); background: var(--c-glass); color:var(--c-fg-strong); transition: background .3s, box-shadow .3s, text-shadow .3s;
}
.modal-btn:hover{ background: rgba(255,255,255,0.08); }
.modal-btn:disabled{ opacity:.4; cursor:not-allowed; }
.modal-btn.ghost{ background:transparent; color: var(--c-text-dim); }
.modal-btn.primary{ background: linear-gradient(90deg, rgba(138,0,203,0.25), rgba(227,230,238,0.2)); border-color: var(--c-border-glow); box-shadow: var(--glow-grey); }
.modal-btn.primary:hover{ box-shadow: var(--glow-grey-strong); text-shadow: var(--glow-white-active); }
.modal-btn.danger{ background: rgba(255,60,60,0.15); border-color: rgba(255,90,90,0.4); color:#ff9b9b; }
.modal-btn.danger:hover{ box-shadow: 0 0 20px rgba(255,60,60,0.25); }

/* ============================================================
   TOAST
   ============================================================ */
.toast{
  position:fixed; bottom: 30px; left:50%; transform: translateX(-50%) translateY(20px);
  z-index:200; background: var(--c-panel-strong); border:1px solid var(--c-glass-border); border-radius:12px;
  padding: 12px 20px; font-size:.78rem; color:var(--c-fg-strong); box-shadow: 0 20px 50px rgba(0,0,0,0.5);
  opacity:0; visibility:hidden; pointer-events:none; transition: all .35s var(--ease-soft);
  max-width: min(400px, 86vw); text-align:center;
}
.toast.visible{ opacity:1; visibility:visible; transform: translateX(-50%) translateY(0); }
.toast.error{ border-color: rgba(255,90,90,0.5); color:#ffb3b3; }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 720px){
  .topbar-tabs{ transform: scale(.85); }
  .topbar-tab{ padding: 10px 12px; }
  .mode-toggle, .edit-add-toggle{ width:32px; height:32px; }
  .arrow-btn{ width:44px; height:44px; }
  .caption-bar{ bottom: 96px; }
  .edit-photo-actions{ flex-direction:column; align-items:center; bottom: 50px; }
}

/* ============================================================
   BOOKING (Chris 2026-08-18) -- réutilise l'habillage des modales (.modal /
   .modal-panel / .modal-field / .modal-btn) ; ce bloc n'ajoute que le
   spécifique : sélecteurs d'heures, encadré tarifs, X de fermeture, statut.
   ============================================================ */
.booking-panel{ position:relative; width:min(520px,100%); }
.booking-close{ position:absolute; top:14px; right:14px; }
.booking-botcheck{ display:none; }
.booking-panel select,
.booking-panel input[type="email"],
.booking-panel input[type="date"],
.booking-panel textarea{
  width:100%; background: rgba(255,255,255,0.05); border:1px solid var(--c-glass-border); border-radius:10px;
  padding: 11px 14px; color:var(--c-fg-strong); font-family: inherit; font-size:.9rem;
}
.booking-panel select:focus,
.booking-panel input:focus,
.booking-panel textarea{ outline:none; }
.booking-panel select option{ background: #14101c; color: var(--c-fg-strong); }
.booking-panel input[type="date"]{ color-scheme: dark; } /* calendrier natif en thème sombre */
.booking-panel textarea{ resize:vertical; min-height:80px; }
.booking-hours-row{ display:flex; align-items:center; gap:10px; }
.booking-hours-sep{ color: var(--c-text-dim); flex-shrink:0; }
/* l'offre tarifaire -- vitrine, pas contrat : gros prix dégradé or/argent */
.booking-rates{
  text-align:center; margin: 0 0 22px; padding: 16px 14px 12px;
  background: rgba(138,0,203,0.08); border:1px solid var(--c-border-glow); border-radius:14px;
  box-shadow: var(--glow-grey);
}
.booking-rate-main{ display:flex; align-items:baseline; justify-content:center; gap:10px; }
.booking-rate-price{
  font-family:'Orbitron',sans-serif; font-size:2rem; font-weight:700;
  background: linear-gradient(90deg, var(--c-gold), var(--c-silver)); -webkit-background-clip:text; background-clip:text; color:transparent;
}
.booking-rate-sub{ display:flex; align-items:baseline; justify-content:center; gap:8px; margin-top:2px; }
.booking-rate-price2{
  font-family:'Orbitron',sans-serif; font-size:1.05rem; font-weight:600;
  background: linear-gradient(90deg, var(--c-gold), var(--c-silver)); -webkit-background-clip:text; background-clip:text; color:transparent;
}
.booking-rate-label{ font-size:.6rem; letter-spacing:.18em; color: var(--c-text-dim); }
.booking-rate-notes{ margin-top:10px; font-size:.62rem; letter-spacing:.06em; color: var(--c-text-dim); white-space:pre-line; line-height:1.9; }
/* le légal, en tout petit tout en bas */
.booking-legal{
  margin-top:16px; font-size:.55rem; letter-spacing:.04em; line-height:1.7;
  color: var(--c-text-dim); opacity:.7;
}
.booking-status{ margin-top:12px; font-size:.72rem; line-height:1.6; color:#9fe6a0; }
.booking-status.error{ color:#ffb15c; }

/* ============================================================
   FOOTER / COPYRIGHT (Chris 2026-08-18) -- ligne discrète en bas, texte
   légal complet replié derrière le petit bouton i. Caché en mode cinéma.
   ============================================================ */
.site-footer{
  position:fixed; left:50%; transform:translateX(-50%); bottom:6px; z-index:30;
  display:flex; flex-direction:column; align-items:center; gap:4px;
  text-align:center; max-width:min(92vw, 720px); pointer-events:none;
}
.site-footer-row{ display:flex; align-items:center; gap:8px; pointer-events:auto; }
.site-footer-line{
  font-size:.55rem; letter-spacing:.08em; color: var(--c-text-dim); opacity:.55;
}
.site-footer-info{
  width:16px; height:16px; border-radius:50%; flex-shrink:0;
  background:transparent; border:1px solid var(--c-border-glow); color: var(--c-text-dim);
  font-size:.55rem; line-height:1; display:flex; align-items:center; justify-content:center;
  opacity:.55; transition: opacity .25s, box-shadow .25s;
  font-family:'Space Grotesk',sans-serif; font-style:italic;
}
.site-footer-info:hover{ opacity:1; box-shadow: var(--glow-grey); }
/* Chris 2026-08-18 : mini bouton de langue déplacé ici (la barre du haut
   reste centrée en mobile ; la langue est auto-détectée, ceci est l'issue
   de secours si la détection se trompe). */
.site-footer-lang{
  height:16px; padding:0 7px; border-radius:999px; flex-shrink:0;
  background:transparent; border:1px solid var(--c-border-glow); color: var(--c-text-dim);
  font-family:'Orbitron',sans-serif; font-size:.5rem; letter-spacing:.1em; line-height:1;
  display:flex; align-items:center; justify-content:center;
  opacity:.55; transition: opacity .25s, box-shadow .25s;
}
.site-footer-lang:hover{ opacity:1; box-shadow: var(--glow-grey); }
.site-footer-full{
  pointer-events:auto;
  max-height:0; overflow:hidden; transition: max-height .35s var(--ease-soft), padding .35s;
  font-size:.58rem; letter-spacing:.04em; line-height:1.7; color: var(--c-text-dim);
  background: var(--c-panel-strong); border-radius:12px; padding:0 14px;
  border:0px solid transparent;
}
.site-footer-full.open{
  max-height:200px; padding:10px 14px; margin-bottom:4px;
  border:1px solid var(--c-glass-border);
}
body.cinema-mode .site-footer{ display:none; }

@media (prefers-reduced-motion: reduce){
  *{ animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* SEO (Chris 2026-08-21) : contenu present pour les crawlers mais invisible
   a l'ecran (H1 + index statique genere par publier.py). Technique standard
   "screen-reader only" — pas de display:none (Google l'ignorerait). */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}

/* Perf mobile (Chris 2026-08-21, "lag entre les photos") : les deux gros
   couts GPU du changement de photo sont desactives/allegés SOUS 768px
   seulement -- le PC garde la qualite pleine :
   - fond : blur reduit (la source est deja la miniature floue, voir
     setBackground dans script.js) ;
   - cartes : backdrop-filter (flou temps reel derriere chaque carte,
     recalcule a chaque frame de l'animation 1.15s) remplace par un fond
     semi-opaque fixe ; ombres allegees. */
@media (max-width: 768px){
  .bg-layer{ filter: blur(20px) saturate(1.3) brightness(.55); }
  /* Chris 2026-09-01 (photo centrale découpée par les cartes latérales en
     mobile) : en scène 3D partagée (preserve-3d), le GPU TRANCHE les cartes
     qui s'entrecoupent selon leur profondeur -- le z-index n'y peut rien.
     Sous 768px on aplatit la scène : perspective posée sur la track (chaque
     carte garde exactement la même projection 3D individuelle), mais plus
     d'espace 3D commun => plus aucune découpe possible, l'ordre d'empilement
     (z-index, centrale au-dessus) redevient l'autorité. Le PC garde le
     preserve-3d (le backdrop-filter y aplatit déjà le rendu de fait). */
  .carousel-track{ transform-style: flat; perspective: 1800px; }
  .card-glass{
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: rgba(18,16,24,0.6);
    box-shadow: 0 14px 36px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.12);
  }
}

/* Badge de vue d'edition (Chris 2026-08-21) : rappelle si les reglages de
   blocs en cours s'ecrivent dans la vue MOBILE ou PC. Mode edition seulement. */
#edit-view-badge{
  position:fixed; top:8px; right:8px; z-index:60;
  font-family:'Orbitron',sans-serif; font-size:.6rem; letter-spacing:.12em;
  padding:5px 10px; border-radius:999px; pointer-events:none;
  color:#d9a3ff; border:1px solid var(--c-border-glow-strong);
  background:rgba(10,9,14,0.75);
}
#edit-view-badge.is-mobile{ color:#ffd27a; }

/* Bloc "galerie en vedette" (Chris 2026-08-21) : vignette d'accueil dans le
   style verre du site -- couverture de la galerie + nom, clic visiteur =
   ouvre la galerie dans le carrousel. */
/* Plan A v3 (2026-08-21) : le bloc vedette n'a AUCUN rendu (ni visiteur ni
   édition) -- l'ancienne vignette-marqueur passait pour un bloc résiduel et
   se faisait supprimer par erreur. Gestion via la liste + GALERIE (✓). */
.block-gallery{ display:none !important; }
.edit-add-gal-item.is-featured{ color:var(--c-gold-bright); }
/* titre de scène masqué pour le VISITEUR quand la galerie ouverte est la
   vedette (Chris met son propre bloc texte) ; visible en mode édition
   (le renommage par clic sur le titre doit rester accessible). */
/* v2 (2026-08-21) : featured-open = vedette affichée EN page d'accueil
   (jamais posé quand la même galerie est ouverte via son onglet). Carrousel
   NU, mode édition inclus : ni titre, ni intro, ni rangée du bas, ni chips
   d'édition. Pour éditer les photos : ouvrir la galerie via l'onglet. */
body.featured-open .gallery-heading{ display:none; }
body.featured-open .gallery-intro{ display:none; }
body.featured-open .stage-bottom-controls{ display:none; }
body.featured-open .edit-photo-actions{ display:none !important; }

/* sous-liste du bouton + GALERIE (panneau d'ajout, mode edition) */
.edit-add-gal-list{ display:none; }
.edit-add-gal-list.open{ display:block; max-height:220px; overflow-y:auto; }
.edit-add-gal-item{
  display:block; width:100%; background:transparent; border:none;
  text-align:left; padding:7px 10px 7px 22px; border-radius:9px;
  font-size:.6rem; letter-spacing:.08em; color:var(--c-text-dim);
  transition:background .2s, color .2s; cursor:pointer;
}
.edit-add-gal-item:hover{ background:rgba(138,0,203,0.16); color:var(--c-gold-bright); }

/* Bouton FR/EN deplacable (Chris 2026-08-21) : .lang-floating = position
   personnalisee (site-data.json langBtn), sinon place normale du footer.
   La poignee de redimensionnement n'apparait qu'en mode edition. */
.site-footer-lang.lang-floating{
  position:fixed; z-index:60; transform-origin:center;
  /* Chris 2026-08-21 : look aligné sur le cadre du menu du haut -- contour
     1px fin, coins 14px (plus la pilule 999px), même glow. La taille passe
     par font-size (script.js), donc tout (padding/hauteur) suit en em et
     le trait reste fin à toute taille. */
  height:auto; padding:.5em .9em; border-radius:14px;
  border:1px solid var(--c-border-glow); box-shadow: var(--glow-grey);
}
.lang-resize-handle{
  display:none; position:absolute; right:-10px; top:50%; margin-top:-6px;
  width:12px; height:12px; border-radius:50%;
  background:rgba(138,0,203,0.5); border:1px solid var(--c-border-glow-strong);
  cursor:ew-resize;
}
/* selection du bouton FR/EN (clic en mode edition) : encadre pointille +
   poignee, comme un bloc actif */
body.edit-mode .site-footer-lang.lang-active{
  outline:1px dashed var(--c-border-glow-strong); outline-offset:4px; opacity:1;
}
body.edit-mode .site-footer-lang.lang-active .lang-resize-handle{ display:block; }
body.edit-mode .site-footer-lang{ cursor:move; opacity:1; }

/* Chris 2026-08-21 : le mode carre (grille FULL INDEX) est retire pour les
   visiteurs "pour l'instant" -- seuls carrousel et cinema restent. Le bouton
   ne s'affiche qu'en mode edition (donc jamais sur le site public, ou
   edit-mode n'existe pas). Rebrancher = supprimer cette regle. */
body:not(.edit-mode) .view-toggle{ display:none !important; }

/* drag de reordonnancement des photos en vue grille (mode edition) */
body.edit-mode .grid-item{ cursor:grab; }
.grid-item-dragging{ opacity:.35; outline:1px dashed var(--c-border-glow-strong); }
