/* ACC-240 — Update 3: smartphone landscape — raise 'Collection' slightly */
:root{
  --bg:#3b383a; --fg:#e9e9ec; --fg-dim:#d8d8dc; --border:#cfcfd6;
  --shadow: rgba(0,0,0,.35);

  /* Marges / dimensions validées */
  --m: 22px;
  --frame-top-offset: 84px;
  --frame-portrait-h: 70dvh;
  --frame-landscape-w: 70vw;

  /* Desktop margins */
  --desk-frame-top: 48px;
  --desk-frame-right: 48px;

  /* Paysage placements (base) */
  --y-collection: 52%;
  --y-2d: 66%;
  --y-3d: 86%;
  --ls-gap: var(--m);
  --ls-arrow-bite: 2px;

  /* Portrait tuning (smartphone validé ACC-238) */
  --ptb-gap-add: 16px;
  --ptb-line-h: 24px;
  --ptb-2d-x: 48%;
  --ptb-3d-right: 5%;
  --ptb-arrow-offset: 8px;

  /* Typo mobile (base) — légèrement plus grande */
  --fz-title: clamp(14px, 2.0vmin, 22px);
  --fz-label: clamp(12px, 1.8vmin, 17px);
}

*{ box-sizing:border-box; }
html,body{ height:100%; }
body{ margin:0; background:var(--bg); color:var(--fg); }
.stage{ position:relative; min-height:100dvh; width:100%; }

/* Avatar + titres */
.avatar{
  position:absolute; top: var(--m); left: var(--m);
  width: clamp(32px,4.5vmin,40px); height:auto;
  filter: drop-shadow(0 2px 4px var(--shadow));
  user-select:none; pointer-events:none; z-index:3;
}
.titles{
  position:absolute; top: calc(var(--m) + 4px); left: calc(var(--m) + 60px);
  display:flex; flex-direction:column; gap: 6px; z-index:3;
}
.t-pres{ font-size: var(--fz-title); color:var(--fg-dim); }
.t-contact{ font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* ===== Zone cadre ===== */
.frame-area{
  position:absolute;
  left: var(--m); right: var(--m);
  top: calc(var(--m) + var(--frame-top-offset));
  bottom: var(--m);
  container-type: inline-size; /* pour cqi */
}
.frame{
  position:absolute; left:0; right:0; bottom:0;
  height: var(--frame-portrait-h);
  background:#0a0a0c; border:1px dotted var(--border); border-radius:8px;
  box-shadow: inset 0 10px 30px rgba(0,0,0,.6), 0 8px 22px var(--shadow);
}

/* === Portrait : topbar au-dessus du cadre === */
.ptb{
  position:absolute; left:0; right:0;
  top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add));
  height: var(--ptb-line-h);
  pointer-events:none;
}
.ptb-left, .ptb-2d, .ptb-3d{ position:absolute; bottom:0; line-height:1; }
.ptb-left{ left:0; font-size: var(--fz-title); }
.ptb-2d{ left: var(--ptb-2d-x); transform: translateX(-50%); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ptb-3d{ right: var(--ptb-3d-right); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* Curseur sous 'Visite 2D' */
.ptb-2d::after{
  content:""; position:absolute; left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ===== Landscape (base) ===== */
@media (orientation: landscape){
  .frame-area{ left:auto; right: var(--m); top: var(--m); bottom: var(--m); width: var(--frame-landscape-w); }
  .frame{ inset:0; height:auto; }
  .ptb{ display:none; }
}
.ls-overlay{ position:absolute; left:0; right:0; bottom:0; height:100%; pointer-events:none; display:none; }
@media (orientation: landscape){ .ls-overlay{ display:block; } }

.ls-label{
  position:absolute; left:0;
  transform: translateX(calc(-100% - var(--ls-gap)));
  width:max-content;
}
.ls-collection{ top: var(--y-collection); font-size: var(--fz-title); }
.ls-2d{ top: var(--y-2d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
.ls-3d{ top: var(--y-3d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ls-arrow{
  position:absolute; top: var(--y-2d); left:0;
  transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%);
  width:0; height:0; border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}

/* ===== Smartphone landscape ONLY: raise Collection (52% -> 50%) ===== */
@media (max-width: 979px) and (orientation: landscape){
  :root{
    --y-collection: 50%;
  }
}

/* ===== Desktop landscape (PC): smaller than previous update, same as last step ===== */
@media (min-width: 980px) and (orientation: landscape){
  .t-pres{ font-size: clamp(16px, 1.5vmin, 20px); }
  .t-contact{ font-size: clamp(14px, 1.3vmin, 17px); }

  @container (min-width: 520px){
    .ls-collection{ font-size: clamp(18px, 2.2cqi, 26px); }
    .ls-2d, .ls-3d{ font-size: clamp(16px, 1.8cqi, 23px); }
  }
  @container (min-width: 760px){
    .ls-collection{ font-size: clamp(20px, 2.4cqi, 30px); }
    .ls-2d, .ls-3d{ font-size: clamp(18px, 2.0cqi, 26px); }
  }
}

/* Desktop paysage (positioning inchangé) */
@media (min-width: 980px) and (orientation: landscape){
  .frame-area{ right: var(--desk-frame-right); top: var(--desk-frame-top); bottom: var(--desk-frame-top); width: var(--frame-landscape-w); }
  .avatar{ top: var(--desk-frame-top); left: 24px; width: 40px; }
  .titles{ top: var(--desk-frame-top); left: 96px; }
}

/* 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; }

/* === additions pour bascule 2D/3D ================================ */
.hotspots{ position:absolute; inset:0; z-index:5; pointer-events:none; }
.hot{ position:absolute; width:200px; height:32px; background:transparent; border:0; padding:0; pointer-events:auto; cursor:pointer; }
@media (orientation: landscape){
  .hot-ls-2d{ left:0; top: var(--y-2d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ls-3d{ left:0; top: var(--y-3d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ptb-2d, .hot-ptb-3d{ display:none; }
}
@media (orientation: portrait){
  .hot-ls-2d, .hot-ls-3d{ display:none; }
  .hot-ptb-2d{ left: var(--ptb-2d-x); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(-50%, 50%); width:160px; height:28px; }
  .hot-ptb-3d{ right: var(--ptb-3d-right); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(50%, 50%); width:160px; height:28px; }
}
body.mode-3d .ls-arrow{ top: var(--y-3d); }
body.mode-3d .ptb-2d::after{ display:none; }
body.mode-3d .ptb-3d::after{
  content:""; position:absolute;
  left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ACC-257 — micro-réglages Y uniquement (depuis ACC-254) */
:root{ --ls-arrow-nudge: 0px; } /* défaut */

@media (orientation: landscape) and (max-width: 900px){
  :root{ --ls-arrow-nudge: -4px; } /* smartphone paysage : remonter un peu */
}
@media (orientation: landscape) and (min-width: 1200px){
  :root{ --ls-arrow-nudge: 6px; }  /* PC paysage : descendre un peu */
}
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + var(--ls-arrow-nudge)); }
}

/* ACC-262 — override minimal depuis 257 : descendre le curseur UNIQUEMENT en 3D (paysage) de +10px. */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-263 — ajustement fin : remonter de 3px la position 3D en paysage (=> +7px au total). */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 7px) !important; }
}

/* ACC-264 — ajustements demandés, 3D uniquement
   - Smartphone paysage : remonter de 1px => +6px total
   - PC paysage        : descendre de 3px => +10px total */
@media (orientation: landscape) and (max-width: 900px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 6px) !important; }
}
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-265 — ajustement final : PC paysage = +13px total (descend 1px de plus que ACC-265 précédent). */
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 13px) !important; }
}

/* ACC-265-B — Lock mobile viewport (smartphone), sans rien toucher d'autre */
@media (max-width: 900px){
  html, body{
    position: fixed;
    inset: 0;
    width: 100dvw;
    height: 100dvh;
    overflow: hidden;              /* pas de scroll */
    overscroll-behavior: none;     /* pas de rebond */
    touch-action: none;            /* pas de pan/scroll gestuel */
  }
}


/* ===============================================================
   ACC-272 — Base pseudo-élément (débord possible)
   =============================================================== */
.frame{ background:#0a0a0c !important; overflow:visible; }
.frame::before{
  content:"";
  position:absolute; inset:0;
  background-repeat:no-repeat;
  background-position:center center;
  background-size:contain;
  pointer-events:none;
  transform-origin:center;
}
body.mode-2d .frame::before{ background-image:url("./images/collection.jpg"); }
body.mode-3d .frame::before{ background-image:url("./images/acces3d.jpg"); }


/* ===============================================================
   ACC-275 — Débord +10px par défaut et cadre blanc lumineux
   =============================================================== */
.frame::before{ inset: var(--img-inset, -10px) !important; transform:none !important; }
.frame::after{
  content:"";
  position:absolute;
  pointer-events:none;
  inset: var(--glow-inset, -10px);
  border:2px solid rgba(255,255,255,.95);
  box-shadow: 0 0 6px rgba(255,255,255,.6),
              0 0 14px rgba(255,255,255,.35),
              0 0 28px rgba(255,255,255,.18);
  border-radius:4px;
  opacity:1;
}
@media (orientation: portrait){
  .frame::after{
    inset:auto;
    left: var(--glow-inset, -10px); right: var(--glow-inset, -10px);
    top:50%; transform:translateY(-50%);
    aspect-ratio:1/1;
  }
}
@media (orientation: landscape){
  .frame::after{
    inset:auto;
    top: var(--glow-inset, -10px); bottom: var(--glow-inset, -10px);
    left:50%; transform:translateX(-50%);
    aspect-ratio:1/1;
  }
}


/* ===============================================================
   ACC-276 — Slider tactile (smartphone) + variation taille/voile
   - Sans modifier l'HTML (éléments injectés en JS)
   - Contrôle via variables CSS:
       --img-inset : taille du carré (px, négatif = débord)
       --veil      : 0..1, niveau de voile (grayscale/blur)
       --halo      : 0..1, opacité du cadre lumineux (mobile)
   =============================================================== */

/* Voile progressif sur l'image */
.frame::before{
  filter: grayscale(var(--veil, 0)) blur(calc(var(--veil, 0) * 2px));
  opacity: 1;
}

/* Mobile : halo contrôlé par var --halo (desktop = 1 par défaut) */
@media (max-width: 900px){
  .frame::after{ opacity: var(--halo, 0); transition: opacity .18s ease; }
}

/* ===== Slider visuel ===== */
.touch-slider{ position:absolute; inset:0; z-index:9; pointer-events:auto; touch-action:none; }
.touch-slider .knob{
  position:absolute; width:18px; height:18px; border-radius:50%;
  background:#fff; box-shadow: 0 2px 6px rgba(0,0,0,.5), 0 0 8px rgba(255,255,255,.5);
  transform: translate(-50%, -50%);
}

/* Portrait: track horizontal au-dessus du cadre (proche de la topbar) */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider{ 
    left:0; right:0;
    top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add) - 8px);
    height: 28px;
  }
  .touch-slider .knob{ top: 50%; }
}

/* Paysage smartphone: track vertical le long du bord gauche du cadre */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider{ 
    width: 28px;
    left: calc(-1 * var(--ls-gap) - 8px);
    top: 0; bottom: 0;
  }
  .touch-slider .knob{ left: 50%; }
}


/* ACC-295 — Triangles visibles UNIQUEMENT quand le swipe est en position (2D / 0 / 3D) */
.ptb-cursor, .ls-cursor{ pointer-events:none; z-index:7; position:absolute; display:none; }
.ptb-cursor{ top:100%; transform: translateX(-50%); margin-top: var(--ptb-arrow-offset); }
.ptb-cursor::before{
  content:""; display:block; width:0; height:0;
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}
.ls-cursor{ left:0; transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%); }
.ls-cursor::before{
  content:""; display:block; width:0; height:0;
  border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}
/* Utility to toggle visibility */
.show{ display:block !important; }


/* ACC-305 — Masquer les triangles statiques quand on est au point neutre */
body.at-mid .ptb-2d::after,
body.at-mid .ptb-3d::after{ display:none !important; }


/* ACC-307 — Smartphone paysage : décaler 'Visite 2D' au centre du cadre noir */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-2d: 50%; } /* ne touche à rien d'autre */
}


/* ACC-308 — Smartphone paysage : remonter 'Collection' de 10px (sans rien d'autre) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 10px); } /* part de 50% validé et le remonte de 10px */
}


/* ACC-309 — Smartphone paysage : remonter 'Collection' de 15px supplémentaires (total -25px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 25px); }
}


/* ACC-310 — Smartphone paysage : remonter 'Collection' de 10px supplémentaires (total -35px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 35px); }
}

}

/* ===============================================================
   ACC-314 — Smartphone paysage : masquer le triangle statique au neutre
   (cache .ls-arrow à l'état neutre uniquement en paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-arrow{ display: none !important; }
}

/* ===============================================================
   ACC-315 — Smartphone paysage : masquer les triangles statiques Visite2D et Visite3D au neutre
   (cache .ls-2d::after et .ls-3d::after uniquement en état neutre, paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-2d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-317 — Smartphone paysage : masquer aussi le triangle 3D au neutre
   (supprime l'affichage du triangle "Visite 3D" quand swipe au point milieu)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ptb-3d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-318 — Smartphone paysage : au neutre, n'afficher QUE le curseur central
   (spécifique à .ls-0-cursor ; supprime tout fallback hasardeux)
   =============================================================== */
@media (pointer:coarse) and (orientation: landscape){
  body.at-mid .ls-cursor{ display: none !important; }              /* cache tous les curseurs dynamiques */
  body.at-mid .ls-cursor.ls-0-cursor{ display: block !important; } /* ne montre que le neutre */
  body.at-mid .ls-arrow{ display: none !important; }               /* triangle statique masqué au neutre */
}


/* ===============================================================
   ACC-318-DRAG-PC4 — Curseur visible (PC uniquement via JS)
   - Slider collé au bord GAUCHE du cadre, calculé en JS
   - Pas d'impact mobile: le JS ne crée pas le slider en pointer:coarse
   =============================================================== */
.pc-slider4{ position:absolute; width: 22px; pointer-events:auto; z-index: 50; }
.pc-slider4 .pc-track{ position:absolute; left:50%; transform:translateX(-50%); top:0; bottom:0; width:2px;
  background: transparent; border-radius:2px; }
.pc-slider4 .pc-track::before{ content:\"\"; position:absolute; left:0; right:0; top: var(--pc-range-top, 24%); bottom: var(--pc-range-bottom, 24%); background: rgba(255,255,255,.32); box-shadow: 0 0 8px rgba(255,255,255,.28); border-radius:2px; pointer-events:none; }
.pc-slider4 .pc-thumb{ position:absolute; left:50%; transform: translate(-50%, -50%); width: 16px; height: 28px;
  border-radius: 9px; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.5); opacity:.95; }

/* ACC-323 — Halo desktop via --halo */
@media (pointer: fine){
  .frame::after{ opacity: var(--halo, 1); transition: opacity .18s ease; }
}


/* ===============================================================
   ACC-349 — Smartphone : triangle attaché au point de swipe avec règles distinctes
   - Portrait  : triangle sur la bordure HAUTE du cadre, pointe VERS LE BAS (vers l'image), aligné horizontalement.
   - Paysage   : triangle sur la bordure GAUCHE  du cadre, pointe VERS LA DROITE (vers l'image), aligné verticalement.
   - Visibilité: UNIQUEMENT en mode-2d ou mode-3d ; MASQUÉ au neutre (at-mid).
   - Ancien triangle smartphone désactivé.
   =============================================================== */
@media (pointer:coarse){
  /* Désactivation des triangles statiques smartphone */
  .ptb-2d::after, .ptb-3d::after{ display:none !important; }

  /* Base: caché par défaut */
  .touch-slider .knob::after{ display:none; }
  body.mode-2d .touch-slider .knob::after,
  body.mode-3d .touch-slider .knob::after{ display:block; }
  body.at-mid .touch-slider .knob::after{ display:none !important; }
}

/* === Portrait : sommet de l'image en haut → triangle sur la bordure HAUTE, pointe vers le BAS === */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    content:""; position:absolute;
    left:50%; transform: translateX(-50%);
    top: var(--tri-top, 0px); /* calculé en JS */
    width:0; height:0;
    border-left:6px solid transparent;
    border-right:6px solid transparent;
    border-bottom:8px solid var(--fg); /* pointe vers le bas (image) */
  }
}

/* === Paysage : image à droite → triangle sur la bordure GAUCHE, pointe vers la DROITE === */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider .knob::after{
    content:""; position:absolute;
    top:50%; transform: translateY(-50%);
    left: var(--tri-left, 0px); /* calculé en JS */
    width:0; height:0;
    border-top:6px solid transparent;
    border-bottom:6px solid transparent;
    border-right:8px solid var(--fg); /* pointe vers la droite (image) */
  }
}/* ACC-240 — Update 3: smartphone landscape — raise 'Collection' slightly */
:root{
  --bg:#3b383a; --fg:#e9e9ec; --fg-dim:#d8d8dc; --border:#cfcfd6;
  --shadow: rgba(0,0,0,.35);

  /* Marges / dimensions validées */
  --m: 22px;
  --frame-top-offset: 84px;
  --frame-portrait-h: 70dvh;
  --frame-landscape-w: 70vw;

  /* Desktop margins */
  --desk-frame-top: 48px;
  --desk-frame-right: 48px;

  /* Paysage placements (base) */
  --y-collection: 52%;
  --y-2d: 66%;
  --y-3d: 86%;
  --ls-gap: var(--m);
  --ls-arrow-bite: 2px;

  /* Portrait tuning (smartphone validé ACC-238) */
  --ptb-gap-add: 16px;
  --ptb-line-h: 24px;
  --ptb-2d-x: 48%;
  --ptb-3d-right: 5%;
  --ptb-arrow-offset: 8px;

  /* Typo mobile (base) — légèrement plus grande */
  --fz-title: clamp(14px, 2.0vmin, 22px);
  --fz-label: clamp(12px, 1.8vmin, 17px);
}

*{ box-sizing:border-box; }
html,body{ height:100%; }
body{ margin:0; background:var(--bg); color:var(--fg); }
.stage{ position:relative; min-height:100dvh; width:100%; }

/* Avatar + titres */
.avatar{
  position:absolute; top: var(--m); left: var(--m);
  width: clamp(32px,4.5vmin,40px); height:auto;
  filter: drop-shadow(0 2px 4px var(--shadow));
  user-select:none; pointer-events:none; z-index:3;
}
.titles{
  position:absolute; top: calc(var(--m) + 4px); left: calc(var(--m) + 60px);
  display:flex; flex-direction:column; gap: 6px; z-index:3;
}
.t-pres{ font-size: var(--fz-title); color:var(--fg-dim); }
.t-contact{ font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* ===== Zone cadre ===== */
.frame-area{
  position:absolute;
  left: var(--m); right: var(--m);
  top: calc(var(--m) + var(--frame-top-offset));
  bottom: var(--m);
  container-type: inline-size; /* pour cqi */
}
.frame{
  position:absolute; left:0; right:0; bottom:0;
  height: var(--frame-portrait-h);
  background:#0a0a0c; border:1px dotted var(--border); border-radius:8px;
  box-shadow: inset 0 10px 30px rgba(0,0,0,.6), 0 8px 22px var(--shadow);
}

/* === Portrait : topbar au-dessus du cadre === */
.ptb{
  position:absolute; left:0; right:0;
  top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add));
  height: var(--ptb-line-h);
  pointer-events:none;
}
.ptb-left, .ptb-2d, .ptb-3d{ position:absolute; bottom:0; line-height:1; }
.ptb-left{ left:0; font-size: var(--fz-title); }
.ptb-2d{ left: var(--ptb-2d-x); transform: translateX(-50%); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ptb-3d{ right: var(--ptb-3d-right); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* Curseur sous 'Visite 2D' */
.ptb-2d::after{
  content:""; position:absolute; left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ===== Landscape (base) ===== */
@media (orientation: landscape){
  .frame-area{ left:auto; right: var(--m); top: var(--m); bottom: var(--m); width: var(--frame-landscape-w); }
  .frame{ inset:0; height:auto; }
  .ptb{ display:none; }
}
.ls-overlay{ position:absolute; left:0; right:0; bottom:0; height:100%; pointer-events:none; display:none; }
@media (orientation: landscape){ .ls-overlay{ display:block; } }

.ls-label{
  position:absolute; left:0;
  transform: translateX(calc(-100% - var(--ls-gap)));
  width:max-content;
}
.ls-collection{ top: var(--y-collection); font-size: var(--fz-title); }
.ls-2d{ top: var(--y-2d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
.ls-3d{ top: var(--y-3d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ls-arrow{
  position:absolute; top: var(--y-2d); left:0;
  transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%);
  width:0; height:0; border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}

/* ===== Smartphone landscape ONLY: raise Collection (52% -> 50%) ===== */
@media (max-width: 979px) and (orientation: landscape){
  :root{
    --y-collection: 50%;
  }
}

/* ===== Desktop landscape (PC): smaller than previous update, same as last step ===== */
@media (min-width: 980px) and (orientation: landscape){
  .t-pres{ font-size: clamp(16px, 1.5vmin, 20px); }
  .t-contact{ font-size: clamp(14px, 1.3vmin, 17px); }

  @container (min-width: 520px){
    .ls-collection{ font-size: clamp(18px, 2.2cqi, 26px); }
    .ls-2d, .ls-3d{ font-size: clamp(16px, 1.8cqi, 23px); }
  }
  @container (min-width: 760px){
    .ls-collection{ font-size: clamp(20px, 2.4cqi, 30px); }
    .ls-2d, .ls-3d{ font-size: clamp(18px, 2.0cqi, 26px); }
  }
}

/* Desktop paysage (positioning inchangé) */
@media (min-width: 980px) and (orientation: landscape){
  .frame-area{ right: var(--desk-frame-right); top: var(--desk-frame-top); bottom: var(--desk-frame-top); width: var(--frame-landscape-w); }
  .avatar{ top: var(--desk-frame-top); left: 24px; width: 40px; }
  .titles{ top: var(--desk-frame-top); left: 96px; }
}

/* 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; }

/* === additions pour bascule 2D/3D ================================ */
.hotspots{ position:absolute; inset:0; z-index:5; pointer-events:none; }
.hot{ position:absolute; width:200px; height:32px; background:transparent; border:0; padding:0; pointer-events:auto; cursor:pointer; }
@media (orientation: landscape){
  .hot-ls-2d{ left:0; top: var(--y-2d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ls-3d{ left:0; top: var(--y-3d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ptb-2d, .hot-ptb-3d{ display:none; }
}
@media (orientation: portrait){
  .hot-ls-2d, .hot-ls-3d{ display:none; }
  .hot-ptb-2d{ left: var(--ptb-2d-x); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(-50%, 50%); width:160px; height:28px; }
  .hot-ptb-3d{ right: var(--ptb-3d-right); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(50%, 50%); width:160px; height:28px; }
}
body.mode-3d .ls-arrow{ top: var(--y-3d); }
body.mode-3d .ptb-2d::after{ display:none; }
body.mode-3d .ptb-3d::after{
  content:""; position:absolute;
  left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ACC-257 — micro-réglages Y uniquement (depuis ACC-254) */
:root{ --ls-arrow-nudge: 0px; } /* défaut */

@media (orientation: landscape) and (max-width: 900px){
  :root{ --ls-arrow-nudge: -4px; } /* smartphone paysage : remonter un peu */
}
@media (orientation: landscape) and (min-width: 1200px){
  :root{ --ls-arrow-nudge: 6px; }  /* PC paysage : descendre un peu */
}
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + var(--ls-arrow-nudge)); }
}

/* ACC-262 — override minimal depuis 257 : descendre le curseur UNIQUEMENT en 3D (paysage) de +10px. */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-263 — ajustement fin : remonter de 3px la position 3D en paysage (=> +7px au total). */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 7px) !important; }
}

/* ACC-264 — ajustements demandés, 3D uniquement
   - Smartphone paysage : remonter de 1px => +6px total
   - PC paysage        : descendre de 3px => +10px total */
@media (orientation: landscape) and (max-width: 900px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 6px) !important; }
}
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-265 — ajustement final : PC paysage = +13px total (descend 1px de plus que ACC-265 précédent). */
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 13px) !important; }
}

/* ACC-265-B — Lock mobile viewport (smartphone), sans rien toucher d'autre */
@media (max-width: 900px){
  html, body{
    position: fixed;
    inset: 0;
    width: 100dvw;
    height: 100dvh;
    overflow: hidden;              /* pas de scroll */
    overscroll-behavior: none;     /* pas de rebond */
    touch-action: none;            /* pas de pan/scroll gestuel */
  }
}


/* ===============================================================
   ACC-272 — Base pseudo-élément (débord possible)
   =============================================================== */
.frame{ background:#0a0a0c !important; overflow:visible; }
.frame::before{
  content:"";
  position:absolute; inset:0;
  background-repeat:no-repeat;
  background-position:center center;
  background-size:contain;
  pointer-events:none;
  transform-origin:center;
}
body.mode-2d .frame::before{ background-image:url("./images/collection.jpg"); }
body.mode-3d .frame::before{ background-image:url("./images/acces3d.jpg"); }


/* ===============================================================
   ACC-275 — Débord +10px par défaut et cadre blanc lumineux
   =============================================================== */
.frame::before{ inset: var(--img-inset, -10px) !important; transform:none !important; }
.frame::after{
  content:"";
  position:absolute;
  pointer-events:none;
  inset: var(--glow-inset, -10px);
  border:2px solid rgba(255,255,255,.95);
  box-shadow: 0 0 6px rgba(255,255,255,.6),
              0 0 14px rgba(255,255,255,.35),
              0 0 28px rgba(255,255,255,.18);
  border-radius:4px;
  opacity:1;
}
@media (orientation: portrait){
  .frame::after{
    inset:auto;
    left: var(--glow-inset, -10px); right: var(--glow-inset, -10px);
    top:50%; transform:translateY(-50%);
    aspect-ratio:1/1;
  }
}
@media (orientation: landscape){
  .frame::after{
    inset:auto;
    top: var(--glow-inset, -10px); bottom: var(--glow-inset, -10px);
    left:50%; transform:translateX(-50%);
    aspect-ratio:1/1;
  }
}


/* ===============================================================
   ACC-276 — Slider tactile (smartphone) + variation taille/voile
   - Sans modifier l'HTML (éléments injectés en JS)
   - Contrôle via variables CSS:
       --img-inset : taille du carré (px, négatif = débord)
       --veil      : 0..1, niveau de voile (grayscale/blur)
       --halo      : 0..1, opacité du cadre lumineux (mobile)
   =============================================================== */

/* Voile progressif sur l'image */
.frame::before{
  filter: grayscale(var(--veil, 0)) blur(calc(var(--veil, 0) * 2px));
  opacity: 1;
}

/* Mobile : halo contrôlé par var --halo (desktop = 1 par défaut) */
@media (max-width: 900px){
  .frame::after{ opacity: var(--halo, 0); transition: opacity .18s ease; }
}

/* ===== Slider visuel ===== */
.touch-slider{ position:absolute; inset:0; z-index:9; pointer-events:auto; touch-action:none; }
.touch-slider .knob{
  position:absolute; width:18px; height:18px; border-radius:50%;
  background:#fff; box-shadow: 0 2px 6px rgba(0,0,0,.5), 0 0 8px rgba(255,255,255,.5);
  transform: translate(-50%, -50%);
}

/* Portrait: track horizontal au-dessus du cadre (proche de la topbar) */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider{ 
    left:0; right:0;
    top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add) - 8px);
    height: 28px;
  }
  .touch-slider .knob{ top: 50%; }
}

/* Paysage smartphone: track vertical le long du bord gauche du cadre */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider{ 
    width: 28px;
    left: calc(-1 * var(--ls-gap) - 8px);
    top: 0; bottom: 0;
  }
  .touch-slider .knob{ left: 50%; }
}


/* ACC-295 — Triangles visibles UNIQUEMENT quand le swipe est en position (2D / 0 / 3D) */
.ptb-cursor, .ls-cursor{ pointer-events:none; z-index:7; position:absolute; display:none; }
.ptb-cursor{ top:100%; transform: translateX(-50%); margin-top: var(--ptb-arrow-offset); }
.ptb-cursor::before{
  content:""; display:block; width:0; height:0;
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}
.ls-cursor{ left:0; transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%); }
.ls-cursor::before{
  content:""; display:block; width:0; height:0;
  border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}
/* Utility to toggle visibility */
.show{ display:block !important; }


/* ACC-305 — Masquer les triangles statiques quand on est au point neutre */
body.at-mid .ptb-2d::after,
body.at-mid .ptb-3d::after{ display:none !important; }


/* ACC-307 — Smartphone paysage : décaler 'Visite 2D' au centre du cadre noir */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-2d: 50%; } /* ne touche à rien d'autre */
}


/* ACC-308 — Smartphone paysage : remonter 'Collection' de 10px (sans rien d'autre) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 10px); } /* part de 50% validé et le remonte de 10px */
}


/* ACC-309 — Smartphone paysage : remonter 'Collection' de 15px supplémentaires (total -25px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 25px); }
}


/* ACC-310 — Smartphone paysage : remonter 'Collection' de 10px supplémentaires (total -35px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 35px); }
}

}

/* ===============================================================
   ACC-314 — Smartphone paysage : masquer le triangle statique au neutre
   (cache .ls-arrow à l'état neutre uniquement en paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-arrow{ display: none !important; }
}

/* ===============================================================
   ACC-315 — Smartphone paysage : masquer les triangles statiques Visite2D et Visite3D au neutre
   (cache .ls-2d::after et .ls-3d::after uniquement en état neutre, paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-2d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-317 — Smartphone paysage : masquer aussi le triangle 3D au neutre
   (supprime l'affichage du triangle "Visite 3D" quand swipe au point milieu)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ptb-3d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-318 — Smartphone paysage : au neutre, n'afficher QUE le curseur central
   (spécifique à .ls-0-cursor ; supprime tout fallback hasardeux)
   =============================================================== */
@media (pointer:coarse) and (orientation: landscape){
  body.at-mid .ls-cursor{ display: none !important; }              /* cache tous les curseurs dynamiques */
  body.at-mid .ls-cursor.ls-0-cursor{ display: block !important; } /* ne montre que le neutre */
  body.at-mid .ls-arrow{ display: none !important; }               /* triangle statique masqué au neutre */
}


/* ===============================================================
   ACC-318-DRAG-PC4 — Curseur visible (PC uniquement via JS)
   - Slider collé au bord GAUCHE du cadre, calculé en JS
   - Pas d'impact mobile: le JS ne crée pas le slider en pointer:coarse
   =============================================================== */
.pc-slider4{ position:absolute; width: 22px; pointer-events:auto; z-index: 50; }
.pc-slider4 .pc-track{ position:absolute; left:50%; transform:translateX(-50%); top:0; bottom:0; width:2px;
  background: transparent; border-radius:2px; }
.pc-slider4 .pc-track::before{ content:\"\"; position:absolute; left:0; right:0; top: var(--pc-range-top, 24%); bottom: var(--pc-range-bottom, 24%); background: rgba(255,255,255,.32); box-shadow: 0 0 8px rgba(255,255,255,.28); border-radius:2px; pointer-events:none; }
.pc-slider4 .pc-thumb{ position:absolute; left:50%; transform: translate(-50%, -50%); width: 16px; height: 28px;
  border-radius: 9px; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.5); opacity:.95; }

/* ACC-323 — Halo desktop via --halo */
@media (pointer: fine){
  .frame::after{ opacity: var(--halo, 1); transition: opacity .18s ease; }
}


/* ===============================================================
   ACC-349 — Smartphone : triangle attaché au point de swipe avec règles distinctes
   - Portrait  : triangle sur la bordure HAUTE du cadre, pointe VERS LE BAS (vers l'image), aligné horizontalement.
   - Paysage   : triangle sur la bordure GAUCHE  du cadre, pointe VERS LA DROITE (vers l'image), aligné verticalement.
   - Visibilité: UNIQUEMENT en mode-2d ou mode-3d ; MASQUÉ au neutre (at-mid).
   - Ancien triangle smartphone désactivé.
   =============================================================== */
@media (pointer:coarse){
  /* Désactivation des triangles statiques smartphone */
  .ptb-2d::after, .ptb-3d::after{ display:none !important; }

  /* Base: caché par défaut */
  .touch-slider .knob::after{ display:none; }
  body.mode-2d .touch-slider .knob::after,
  body.mode-3d .touch-slider .knob::after{ display:block; }
  body.at-mid .touch-slider .knob::after{ display:none !important; }
}

/* === Portrait : sommet de l'image en haut → triangle sur la bordure HAUTE, pointe vers le BAS === */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    content:""; position:absolute;
    left:50%; transform: translateX(-50%);
    top: var(--tri-top, 0px); /* calculé en JS */
    width:0; height:0;
    border-left:6px solid transparent;
    border-right:6px solid transparent;
    border-bottom:8px solid var(--fg); /* pointe vers le bas (image) */
  }
}

/* === Paysage : image à droite → triangle sur la bordure GAUCHE, pointe vers la DROITE === */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider .knob::after{
    content:""; position:absolute;
    top:50%; transform: translateY(-50%);
    left: var(--tri-left, 0px); /* calculé en JS */
    width:0; height:0;
    border-top:6px solid transparent;
    border-bottom:6px solid transparent;
    border-right:8px solid var(--fg); /* pointe vers la droite (image) */
  }
}/* ACC-240 — Update 3: smartphone landscape — raise 'Collection' slightly */
:root{
  --bg:#3b383a; --fg:#e9e9ec; --fg-dim:#d8d8dc; --border:#cfcfd6;
  --shadow: rgba(0,0,0,.35);

  /* Marges / dimensions validées */
  --m: 22px;
  --frame-top-offset: 84px;
  --frame-portrait-h: 70dvh;
  --frame-landscape-w: 70vw;

  /* Desktop margins */
  --desk-frame-top: 48px;
  --desk-frame-right: 48px;

  /* Paysage placements (base) */
  --y-collection: 52%;
  --y-2d: 66%;
  --y-3d: 86%;
  --ls-gap: var(--m);
  --ls-arrow-bite: 2px;

  /* Portrait tuning (smartphone validé ACC-238) */
  --ptb-gap-add: 16px;
  --ptb-line-h: 24px;
  --ptb-2d-x: 48%;
  --ptb-3d-right: 5%;
  --ptb-arrow-offset: 8px;

  /* Typo mobile (base) — légèrement plus grande */
  --fz-title: clamp(14px, 2.0vmin, 22px);
  --fz-label: clamp(12px, 1.8vmin, 17px);
}

*{ box-sizing:border-box; }
html,body{ height:100%; }
body{ margin:0; background:var(--bg); color:var(--fg); }
.stage{ position:relative; min-height:100dvh; width:100%; }

/* Avatar + titres */
.avatar{
  position:absolute; top: var(--m); left: var(--m);
  width: clamp(32px,4.5vmin,40px); height:auto;
  filter: drop-shadow(0 2px 4px var(--shadow));
  user-select:none; pointer-events:none; z-index:3;
}
.titles{
  position:absolute; top: calc(var(--m) + 4px); left: calc(var(--m) + 60px);
  display:flex; flex-direction:column; gap: 6px; z-index:3;
}
.t-pres{ font-size: var(--fz-title); color:var(--fg-dim); }
.t-contact{ font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* ===== Zone cadre ===== */
.frame-area{
  position:absolute;
  left: var(--m); right: var(--m);
  top: calc(var(--m) + var(--frame-top-offset));
  bottom: var(--m);
  container-type: inline-size; /* pour cqi */
}
.frame{
  position:absolute; left:0; right:0; bottom:0;
  height: var(--frame-portrait-h);
  background:#0a0a0c; border:1px dotted var(--border); border-radius:8px;
  box-shadow: inset 0 10px 30px rgba(0,0,0,.6), 0 8px 22px var(--shadow);
}

/* === Portrait : topbar au-dessus du cadre === */
.ptb{
  position:absolute; left:0; right:0;
  top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add));
  height: var(--ptb-line-h);
  pointer-events:none;
}
.ptb-left, .ptb-2d, .ptb-3d{ position:absolute; bottom:0; line-height:1; }
.ptb-left{ left:0; font-size: var(--fz-title); }
.ptb-2d{ left: var(--ptb-2d-x); transform: translateX(-50%); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ptb-3d{ right: var(--ptb-3d-right); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* Curseur sous 'Visite 2D' */
.ptb-2d::after{
  content:""; position:absolute; left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ===== Landscape (base) ===== */
@media (orientation: landscape){
  .frame-area{ left:auto; right: var(--m); top: var(--m); bottom: var(--m); width: var(--frame-landscape-w); }
  .frame{ inset:0; height:auto; }
  .ptb{ display:none; }
}
.ls-overlay{ position:absolute; left:0; right:0; bottom:0; height:100%; pointer-events:none; display:none; }
@media (orientation: landscape){ .ls-overlay{ display:block; } }

.ls-label{
  position:absolute; left:0;
  transform: translateX(calc(-100% - var(--ls-gap)));
  width:max-content;
}
.ls-collection{ top: var(--y-collection); font-size: var(--fz-title); }
.ls-2d{ top: var(--y-2d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
.ls-3d{ top: var(--y-3d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ls-arrow{
  position:absolute; top: var(--y-2d); left:0;
  transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%);
  width:0; height:0; border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}

/* ===== Smartphone landscape ONLY: raise Collection (52% -> 50%) ===== */
@media (max-width: 979px) and (orientation: landscape){
  :root{
    --y-collection: 50%;
  }
}

/* ===== Desktop landscape (PC): smaller than previous update, same as last step ===== */
@media (min-width: 980px) and (orientation: landscape){
  .t-pres{ font-size: clamp(16px, 1.5vmin, 20px); }
  .t-contact{ font-size: clamp(14px, 1.3vmin, 17px); }

  @container (min-width: 520px){
    .ls-collection{ font-size: clamp(18px, 2.2cqi, 26px); }
    .ls-2d, .ls-3d{ font-size: clamp(16px, 1.8cqi, 23px); }
  }
  @container (min-width: 760px){
    .ls-collection{ font-size: clamp(20px, 2.4cqi, 30px); }
    .ls-2d, .ls-3d{ font-size: clamp(18px, 2.0cqi, 26px); }
  }
}

/* Desktop paysage (positioning inchangé) */
@media (min-width: 980px) and (orientation: landscape){
  .frame-area{ right: var(--desk-frame-right); top: var(--desk-frame-top); bottom: var(--desk-frame-top); width: var(--frame-landscape-w); }
  .avatar{ top: var(--desk-frame-top); left: 24px; width: 40px; }
  .titles{ top: var(--desk-frame-top); left: 96px; }
}

/* 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; }

/* === additions pour bascule 2D/3D ================================ */
.hotspots{ position:absolute; inset:0; z-index:5; pointer-events:none; }
.hot{ position:absolute; width:200px; height:32px; background:transparent; border:0; padding:0; pointer-events:auto; cursor:pointer; }
@media (orientation: landscape){
  .hot-ls-2d{ left:0; top: var(--y-2d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ls-3d{ left:0; top: var(--y-3d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ptb-2d, .hot-ptb-3d{ display:none; }
}
@media (orientation: portrait){
  .hot-ls-2d, .hot-ls-3d{ display:none; }
  .hot-ptb-2d{ left: var(--ptb-2d-x); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(-50%, 50%); width:160px; height:28px; }
  .hot-ptb-3d{ right: var(--ptb-3d-right); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(50%, 50%); width:160px; height:28px; }
}
body.mode-3d .ls-arrow{ top: var(--y-3d); }
body.mode-3d .ptb-2d::after{ display:none; }
body.mode-3d .ptb-3d::after{
  content:""; position:absolute;
  left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ACC-257 — micro-réglages Y uniquement (depuis ACC-254) */
:root{ --ls-arrow-nudge: 0px; } /* défaut */

@media (orientation: landscape) and (max-width: 900px){
  :root{ --ls-arrow-nudge: -4px; } /* smartphone paysage : remonter un peu */
}
@media (orientation: landscape) and (min-width: 1200px){
  :root{ --ls-arrow-nudge: 6px; }  /* PC paysage : descendre un peu */
}
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + var(--ls-arrow-nudge)); }
}

/* ACC-262 — override minimal depuis 257 : descendre le curseur UNIQUEMENT en 3D (paysage) de +10px. */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-263 — ajustement fin : remonter de 3px la position 3D en paysage (=> +7px au total). */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 7px) !important; }
}

/* ACC-264 — ajustements demandés, 3D uniquement
   - Smartphone paysage : remonter de 1px => +6px total
   - PC paysage        : descendre de 3px => +10px total */
@media (orientation: landscape) and (max-width: 900px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 6px) !important; }
}
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-265 — ajustement final : PC paysage = +13px total (descend 1px de plus que ACC-265 précédent). */
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 13px) !important; }
}

/* ACC-265-B — Lock mobile viewport (smartphone), sans rien toucher d'autre */
@media (max-width: 900px){
  html, body{
    position: fixed;
    inset: 0;
    width: 100dvw;
    height: 100dvh;
    overflow: hidden;              /* pas de scroll */
    overscroll-behavior: none;     /* pas de rebond */
    touch-action: none;            /* pas de pan/scroll gestuel */
  }
}


/* ===============================================================
   ACC-272 — Base pseudo-élément (débord possible)
   =============================================================== */
.frame{ background:#0a0a0c !important; overflow:visible; }
.frame::before{
  content:"";
  position:absolute; inset:0;
  background-repeat:no-repeat;
  background-position:center center;
  background-size:contain;
  pointer-events:none;
  transform-origin:center;
}
body.mode-2d .frame::before{ background-image:url("./images/collection.jpg"); }
body.mode-3d .frame::before{ background-image:url("./images/acces3d.jpg"); }


/* ===============================================================
   ACC-275 — Débord +10px par défaut et cadre blanc lumineux
   =============================================================== */
.frame::before{ inset: var(--img-inset, -10px) !important; transform:none !important; }
.frame::after{
  content:"";
  position:absolute;
  pointer-events:none;
  inset: var(--glow-inset, -10px);
  border:2px solid rgba(255,255,255,.95);
  box-shadow: 0 0 6px rgba(255,255,255,.6),
              0 0 14px rgba(255,255,255,.35),
              0 0 28px rgba(255,255,255,.18);
  border-radius:4px;
  opacity:1;
}
@media (orientation: portrait){
  .frame::after{
    inset:auto;
    left: var(--glow-inset, -10px); right: var(--glow-inset, -10px);
    top:50%; transform:translateY(-50%);
    aspect-ratio:1/1;
  }
}
@media (orientation: landscape){
  .frame::after{
    inset:auto;
    top: var(--glow-inset, -10px); bottom: var(--glow-inset, -10px);
    left:50%; transform:translateX(-50%);
    aspect-ratio:1/1;
  }
}


/* ===============================================================
   ACC-276 — Slider tactile (smartphone) + variation taille/voile
   - Sans modifier l'HTML (éléments injectés en JS)
   - Contrôle via variables CSS:
       --img-inset : taille du carré (px, négatif = débord)
       --veil      : 0..1, niveau de voile (grayscale/blur)
       --halo      : 0..1, opacité du cadre lumineux (mobile)
   =============================================================== */

/* Voile progressif sur l'image */
.frame::before{
  filter: grayscale(var(--veil, 0)) blur(calc(var(--veil, 0) * 2px));
  opacity: 1;
}

/* Mobile : halo contrôlé par var --halo (desktop = 1 par défaut) */
@media (max-width: 900px){
  .frame::after{ opacity: var(--halo, 0); transition: opacity .18s ease; }
}

/* ===== Slider visuel ===== */
.touch-slider{ position:absolute; inset:0; z-index:9; pointer-events:auto; touch-action:none; }
.touch-slider .knob{
  position:absolute; width:18px; height:18px; border-radius:50%;
  background:#fff; box-shadow: 0 2px 6px rgba(0,0,0,.5), 0 0 8px rgba(255,255,255,.5);
  transform: translate(-50%, -50%);
}

/* Portrait: track horizontal au-dessus du cadre (proche de la topbar) */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider{ 
    left:0; right:0;
    top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add) - 8px);
    height: 28px;
  }
  .touch-slider .knob{ top: 50%; }
}

/* Paysage smartphone: track vertical le long du bord gauche du cadre */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider{ 
    width: 28px;
    left: calc(-1 * var(--ls-gap) - 8px);
    top: 0; bottom: 0;
  }
  .touch-slider .knob{ left: 50%; }
}


/* ACC-295 — Triangles visibles UNIQUEMENT quand le swipe est en position (2D / 0 / 3D) */
.ptb-cursor, .ls-cursor{ pointer-events:none; z-index:7; position:absolute; display:none; }
.ptb-cursor{ top:100%; transform: translateX(-50%); margin-top: var(--ptb-arrow-offset); }
.ptb-cursor::before{
  content:""; display:block; width:0; height:0;
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}
.ls-cursor{ left:0; transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%); }
.ls-cursor::before{
  content:""; display:block; width:0; height:0;
  border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}
/* Utility to toggle visibility */
.show{ display:block !important; }


/* ACC-305 — Masquer les triangles statiques quand on est au point neutre */
body.at-mid .ptb-2d::after,
body.at-mid .ptb-3d::after{ display:none !important; }


/* ACC-307 — Smartphone paysage : décaler 'Visite 2D' au centre du cadre noir */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-2d: 50%; } /* ne touche à rien d'autre */
}


/* ACC-308 — Smartphone paysage : remonter 'Collection' de 10px (sans rien d'autre) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 10px); } /* part de 50% validé et le remonte de 10px */
}


/* ACC-309 — Smartphone paysage : remonter 'Collection' de 15px supplémentaires (total -25px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 25px); }
}


/* ACC-310 — Smartphone paysage : remonter 'Collection' de 10px supplémentaires (total -35px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 35px); }
}

}

/* ===============================================================
   ACC-314 — Smartphone paysage : masquer le triangle statique au neutre
   (cache .ls-arrow à l'état neutre uniquement en paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-arrow{ display: none !important; }
}

/* ===============================================================
   ACC-315 — Smartphone paysage : masquer les triangles statiques Visite2D et Visite3D au neutre
   (cache .ls-2d::after et .ls-3d::after uniquement en état neutre, paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-2d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-317 — Smartphone paysage : masquer aussi le triangle 3D au neutre
   (supprime l'affichage du triangle "Visite 3D" quand swipe au point milieu)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ptb-3d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-318 — Smartphone paysage : au neutre, n'afficher QUE le curseur central
   (spécifique à .ls-0-cursor ; supprime tout fallback hasardeux)
   =============================================================== */
@media (pointer:coarse) and (orientation: landscape){
  body.at-mid .ls-cursor{ display: none !important; }              /* cache tous les curseurs dynamiques */
  body.at-mid .ls-cursor.ls-0-cursor{ display: block !important; } /* ne montre que le neutre */
  body.at-mid .ls-arrow{ display: none !important; }               /* triangle statique masqué au neutre */
}


/* ===============================================================
   ACC-318-DRAG-PC4 — Curseur visible (PC uniquement via JS)
   - Slider collé au bord GAUCHE du cadre, calculé en JS
   - Pas d'impact mobile: le JS ne crée pas le slider en pointer:coarse
   =============================================================== */
.pc-slider4{ position:absolute; width: 22px; pointer-events:auto; z-index: 50; }
.pc-slider4 .pc-track{ position:absolute; left:50%; transform:translateX(-50%); top:0; bottom:0; width:2px;
  background: transparent; border-radius:2px; }
.pc-slider4 .pc-track::before{ content:\"\"; position:absolute; left:0; right:0; top: var(--pc-range-top, 24%); bottom: var(--pc-range-bottom, 24%); background: rgba(255,255,255,.32); box-shadow: 0 0 8px rgba(255,255,255,.28); border-radius:2px; pointer-events:none; }
.pc-slider4 .pc-thumb{ position:absolute; left:50%; transform: translate(-50%, -50%); width: 16px; height: 28px;
  border-radius: 9px; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.5); opacity:.95; }

/* ACC-323 — Halo desktop via --halo */
@media (pointer: fine){
  .frame::after{ opacity: var(--halo, 1); transition: opacity .18s ease; }
}


/* ===============================================================
   ACC-349 — Smartphone : triangle attaché au point de swipe avec règles distinctes
   - Portrait  : triangle sur la bordure HAUTE du cadre, pointe VERS LE BAS (vers l'image), aligné horizontalement.
   - Paysage   : triangle sur la bordure GAUCHE  du cadre, pointe VERS LA DROITE (vers l'image), aligné verticalement.
   - Visibilité: UNIQUEMENT en mode-2d ou mode-3d ; MASQUÉ au neutre (at-mid).
   - Ancien triangle smartphone désactivé.
   =============================================================== */
@media (pointer:coarse){
  /* Désactivation des triangles statiques smartphone */
  .ptb-2d::after, .ptb-3d::after{ display:none !important; }

  /* Base: caché par défaut */
  .touch-slider .knob::after{ display:none; }
  body.mode-2d .touch-slider .knob::after,
  body.mode-3d .touch-slider .knob::after{ display:block; }
  body.at-mid .touch-slider .knob::after{ display:none !important; }
}

/* === Portrait : sommet de l'image en haut → triangle sur la bordure HAUTE, pointe vers le BAS === */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    content:""; position:absolute;
    left:50%; transform: translateX(-50%);
    top: var(--tri-top, 0px); /* calculé en JS */
    width:0; height:0;
    border-left:6px solid transparent;
    border-right:6px solid transparent;
    border-bottom:8px solid var(--fg); /* pointe vers le bas (image) */
  }
}

/* === Paysage : image à droite → triangle sur la bordure GAUCHE, pointe vers la DROITE === */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider .knob::after{
    content:""; position:absolute;
    top:50%; transform: translateY(-50%);
    left: var(--tri-left, 0px); /* calculé en JS */
    width:0; height:0;
    border-top:6px solid transparent;
    border-bottom:6px solid transparent;
    border-right:8px solid var(--fg); /* pointe vers la droite (image) */
  }
}/* ACC-240 — Update 3: smartphone landscape — raise 'Collection' slightly */
:root{
  --bg:#3b383a; --fg:#e9e9ec; --fg-dim:#d8d8dc; --border:#cfcfd6;
  --shadow: rgba(0,0,0,.35);

  /* Marges / dimensions validées */
  --m: 22px;
  --frame-top-offset: 84px;
  --frame-portrait-h: 70dvh;
  --frame-landscape-w: 70vw;

  /* Desktop margins */
  --desk-frame-top: 48px;
  --desk-frame-right: 48px;

  /* Paysage placements (base) */
  --y-collection: 52%;
  --y-2d: 66%;
  --y-3d: 86%;
  --ls-gap: var(--m);
  --ls-arrow-bite: 2px;

  /* Portrait tuning (smartphone validé ACC-238) */
  --ptb-gap-add: 16px;
  --ptb-line-h: 24px;
  --ptb-2d-x: 48%;
  --ptb-3d-right: 5%;
  --ptb-arrow-offset: 8px;

  /* Typo mobile (base) — légèrement plus grande */
  --fz-title: clamp(14px, 2.0vmin, 22px);
  --fz-label: clamp(12px, 1.8vmin, 17px);
}

*{ box-sizing:border-box; }
html,body{ height:100%; }
body{ margin:0; background:var(--bg); color:var(--fg); }
.stage{ position:relative; min-height:100dvh; width:100%; }

/* Avatar + titres */
.avatar{
  position:absolute; top: var(--m); left: var(--m);
  width: clamp(32px,4.5vmin,40px); height:auto;
  filter: drop-shadow(0 2px 4px var(--shadow));
  user-select:none; pointer-events:none; z-index:3;
}
.titles{
  position:absolute; top: calc(var(--m) + 4px); left: calc(var(--m) + 60px);
  display:flex; flex-direction:column; gap: 6px; z-index:3;
}
.t-pres{ font-size: var(--fz-title); color:var(--fg-dim); }
.t-contact{ font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* ===== Zone cadre ===== */
.frame-area{
  position:absolute;
  left: var(--m); right: var(--m);
  top: calc(var(--m) + var(--frame-top-offset));
  bottom: var(--m);
  container-type: inline-size; /* pour cqi */
}
.frame{
  position:absolute; left:0; right:0; bottom:0;
  height: var(--frame-portrait-h);
  background:#0a0a0c; border:1px dotted var(--border); border-radius:8px;
  box-shadow: inset 0 10px 30px rgba(0,0,0,.6), 0 8px 22px var(--shadow);
}

/* === Portrait : topbar au-dessus du cadre === */
.ptb{
  position:absolute; left:0; right:0;
  top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add));
  height: var(--ptb-line-h);
  pointer-events:none;
}
.ptb-left, .ptb-2d, .ptb-3d{ position:absolute; bottom:0; line-height:1; }
.ptb-left{ left:0; font-size: var(--fz-title); }
.ptb-2d{ left: var(--ptb-2d-x); transform: translateX(-50%); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ptb-3d{ right: var(--ptb-3d-right); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }

/* Curseur sous 'Visite 2D' */
.ptb-2d::after{
  content:""; position:absolute; left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ===== Landscape (base) ===== */
@media (orientation: landscape){
  .frame-area{ left:auto; right: var(--m); top: var(--m); bottom: var(--m); width: var(--frame-landscape-w); }
  .frame{ inset:0; height:auto; }
  .ptb{ display:none; }
}
.ls-overlay{ position:absolute; left:0; right:0; bottom:0; height:100%; pointer-events:none; display:none; }
@media (orientation: landscape){ .ls-overlay{ display:block; } }

.ls-label{
  position:absolute; left:0;
  transform: translateX(calc(-100% - var(--ls-gap)));
  width:max-content;
}
.ls-collection{ top: var(--y-collection); font-size: var(--fz-title); }
.ls-2d{ top: var(--y-2d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
.ls-3d{ top: var(--y-3d); font-size: var(--fz-label); font-style: italic; color:var(--fg-dim); }
.ls-arrow{
  position:absolute; top: var(--y-2d); left:0;
  transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%);
  width:0; height:0; border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}

/* ===== Smartphone landscape ONLY: raise Collection (52% -> 50%) ===== */
@media (max-width: 979px) and (orientation: landscape){
  :root{
    --y-collection: 50%;
  }
}

/* ===== Desktop landscape (PC): smaller than previous update, same as last step ===== */
@media (min-width: 980px) and (orientation: landscape){
  .t-pres{ font-size: clamp(16px, 1.5vmin, 20px); }
  .t-contact{ font-size: clamp(14px, 1.3vmin, 17px); }

  @container (min-width: 520px){
    .ls-collection{ font-size: clamp(18px, 2.2cqi, 26px); }
    .ls-2d, .ls-3d{ font-size: clamp(16px, 1.8cqi, 23px); }
  }
  @container (min-width: 760px){
    .ls-collection{ font-size: clamp(20px, 2.4cqi, 30px); }
    .ls-2d, .ls-3d{ font-size: clamp(18px, 2.0cqi, 26px); }
  }
}

/* Desktop paysage (positioning inchangé) */
@media (min-width: 980px) and (orientation: landscape){
  .frame-area{ right: var(--desk-frame-right); top: var(--desk-frame-top); bottom: var(--desk-frame-top); width: var(--frame-landscape-w); }
  .avatar{ top: var(--desk-frame-top); left: 24px; width: 40px; }
  .titles{ top: var(--desk-frame-top); left: 96px; }
}

/* 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; }

/* === additions pour bascule 2D/3D ================================ */
.hotspots{ position:absolute; inset:0; z-index:5; pointer-events:none; }
.hot{ position:absolute; width:200px; height:32px; background:transparent; border:0; padding:0; pointer-events:auto; cursor:pointer; }
@media (orientation: landscape){
  .hot-ls-2d{ left:0; top: var(--y-2d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ls-3d{ left:0; top: var(--y-3d); transform: translate(calc(-100% - var(--ls-gap)), -50%); }
  .hot-ptb-2d, .hot-ptb-3d{ display:none; }
}
@media (orientation: portrait){
  .hot-ls-2d, .hot-ls-3d{ display:none; }
  .hot-ptb-2d{ left: var(--ptb-2d-x); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(-50%, 50%); width:160px; height:28px; }
  .hot-ptb-3d{ right: var(--ptb-3d-right); bottom: calc(var(--frame-portrait-h) + var(--m) + var(--ptb-arrow-offset)); transform: translate(50%, 50%); width:160px; height:28px; }
}
body.mode-3d .ls-arrow{ top: var(--y-3d); }
body.mode-3d .ptb-2d::after{ display:none; }
body.mode-3d .ptb-3d::after{
  content:""; position:absolute;
  left:50%; transform: translateX(-50%);
  top:100%; margin-top: var(--ptb-arrow-offset);
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}

/* ACC-257 — micro-réglages Y uniquement (depuis ACC-254) */
:root{ --ls-arrow-nudge: 0px; } /* défaut */

@media (orientation: landscape) and (max-width: 900px){
  :root{ --ls-arrow-nudge: -4px; } /* smartphone paysage : remonter un peu */
}
@media (orientation: landscape) and (min-width: 1200px){
  :root{ --ls-arrow-nudge: 6px; }  /* PC paysage : descendre un peu */
}
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + var(--ls-arrow-nudge)); }
}

/* ACC-262 — override minimal depuis 257 : descendre le curseur UNIQUEMENT en 3D (paysage) de +10px. */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-263 — ajustement fin : remonter de 3px la position 3D en paysage (=> +7px au total). */
@media (orientation: landscape){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 7px) !important; }
}

/* ACC-264 — ajustements demandés, 3D uniquement
   - Smartphone paysage : remonter de 1px => +6px total
   - PC paysage        : descendre de 3px => +10px total */
@media (orientation: landscape) and (max-width: 900px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 6px) !important; }
}
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 10px) !important; }
}

/* ACC-265 — ajustement final : PC paysage = +13px total (descend 1px de plus que ACC-265 précédent). */
@media (orientation: landscape) and (min-width: 1200px){
  body.mode-3d .ls-arrow{ top: calc(var(--y-3d) + 13px) !important; }
}

/* ACC-265-B — Lock mobile viewport (smartphone), sans rien toucher d'autre */
@media (max-width: 900px){
  html, body{
    position: fixed;
    inset: 0;
    width: 100dvw;
    height: 100dvh;
    overflow: hidden;              /* pas de scroll */
    overscroll-behavior: none;     /* pas de rebond */
    touch-action: none;            /* pas de pan/scroll gestuel */
  }
}


/* ===============================================================
   ACC-272 — Base pseudo-élément (débord possible)
   =============================================================== */
.frame{ background:#0a0a0c !important; overflow:visible; }
.frame::before{
  content:"";
  position:absolute; inset:0;
  background-repeat:no-repeat;
  background-position:center center;
  background-size:contain;
  pointer-events:none;
  transform-origin:center;
}
body.mode-2d .frame::before{ background-image:url("./images/collection.jpg"); }
body.mode-3d .frame::before{ background-image:url("./images/acces3d.jpg"); }


/* ===============================================================
   ACC-275 — Débord +10px par défaut et cadre blanc lumineux
   =============================================================== */
.frame::before{ inset: var(--img-inset, -10px) !important; transform:none !important; }
.frame::after{
  content:"";
  position:absolute;
  pointer-events:none;
  inset: var(--glow-inset, -10px);
  border:2px solid rgba(255,255,255,.95);
  box-shadow: 0 0 6px rgba(255,255,255,.6),
              0 0 14px rgba(255,255,255,.35),
              0 0 28px rgba(255,255,255,.18);
  border-radius:4px;
  opacity:1;
}
@media (orientation: portrait){
  .frame::after{
    inset:auto;
    left: var(--glow-inset, -10px); right: var(--glow-inset, -10px);
    top:50%; transform:translateY(-50%);
    aspect-ratio:1/1;
  }
}
@media (orientation: landscape){
  .frame::after{
    inset:auto;
    top: var(--glow-inset, -10px); bottom: var(--glow-inset, -10px);
    left:50%; transform:translateX(-50%);
    aspect-ratio:1/1;
  }
}


/* ===============================================================
   ACC-276 — Slider tactile (smartphone) + variation taille/voile
   - Sans modifier l'HTML (éléments injectés en JS)
   - Contrôle via variables CSS:
       --img-inset : taille du carré (px, négatif = débord)
       --veil      : 0..1, niveau de voile (grayscale/blur)
       --halo      : 0..1, opacité du cadre lumineux (mobile)
   =============================================================== */

/* Voile progressif sur l'image */
.frame::before{
  filter: grayscale(var(--veil, 0)) blur(calc(var(--veil, 0) * 2px));
  opacity: 1;
}

/* Mobile : halo contrôlé par var --halo (desktop = 1 par défaut) */
@media (max-width: 900px){
  .frame::after{ opacity: var(--halo, 0); transition: opacity .18s ease; }
}

/* ===== Slider visuel ===== */
.touch-slider{ position:absolute; inset:0; z-index:9; pointer-events:auto; touch-action:none; }
.touch-slider .knob{
  position:absolute; width:18px; height:18px; border-radius:50%;
  background:#fff; box-shadow: 0 2px 6px rgba(0,0,0,.5), 0 0 8px rgba(255,255,255,.5);
  transform: translate(-50%, -50%);
}

/* Portrait: track horizontal au-dessus du cadre (proche de la topbar) */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider{ 
    left:0; right:0;
    top: calc(100% - var(--frame-portrait-h) - var(--m) - var(--ptb-gap-add) - 8px);
    height: 28px;
  }
  .touch-slider .knob{ top: 50%; }
}

/* Paysage smartphone: track vertical le long du bord gauche du cadre */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider{ 
    width: 28px;
    left: calc(-1 * var(--ls-gap) - 8px);
    top: 0; bottom: 0;
  }
  .touch-slider .knob{ left: 50%; }
}


/* ACC-295 — Triangles visibles UNIQUEMENT quand le swipe est en position (2D / 0 / 3D) */
.ptb-cursor, .ls-cursor{ pointer-events:none; z-index:7; position:absolute; display:none; }
.ptb-cursor{ top:100%; transform: translateX(-50%); margin-top: var(--ptb-arrow-offset); }
.ptb-cursor::before{
  content:""; display:block; width:0; height:0;
  border-left:6px solid transparent; border-right:6px solid transparent; border-top:8px solid var(--fg);
}
.ls-cursor{ left:0; transform: translate(calc(-100% + var(--ls-arrow-bite)), -50%); }
.ls-cursor::before{
  content:""; display:block; width:0; height:0;
  border-top:6px solid transparent; border-bottom:6px solid transparent; border-left:8px solid var(--fg);
}
/* Utility to toggle visibility */
.show{ display:block !important; }


/* ACC-305 — Masquer les triangles statiques quand on est au point neutre */
body.at-mid .ptb-2d::after,
body.at-mid .ptb-3d::after{ display:none !important; }


/* ACC-307 — Smartphone paysage : décaler 'Visite 2D' au centre du cadre noir */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-2d: 50%; } /* ne touche à rien d'autre */
}


/* ACC-308 — Smartphone paysage : remonter 'Collection' de 10px (sans rien d'autre) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 10px); } /* part de 50% validé et le remonte de 10px */
}


/* ACC-309 — Smartphone paysage : remonter 'Collection' de 15px supplémentaires (total -25px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 25px); }
}


/* ACC-310 — Smartphone paysage : remonter 'Collection' de 10px supplémentaires (total -35px) */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  :root{ --y-collection: calc(50% - 35px); }
}

}

/* ===============================================================
   ACC-314 — Smartphone paysage : masquer le triangle statique au neutre
   (cache .ls-arrow à l'état neutre uniquement en paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-arrow{ display: none !important; }
}

/* ===============================================================
   ACC-315 — Smartphone paysage : masquer les triangles statiques Visite2D et Visite3D au neutre
   (cache .ls-2d::after et .ls-3d::after uniquement en état neutre, paysage smartphone)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ls-2d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-317 — Smartphone paysage : masquer aussi le triangle 3D au neutre
   (supprime l'affichage du triangle "Visite 3D" quand swipe au point milieu)
   =============================================================== */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  body.at-mid .ptb-3d::after,
  body.at-mid .ls-3d::after{ display: none !important; }
}

/* ===============================================================
   ACC-318 — Smartphone paysage : au neutre, n'afficher QUE le curseur central
   (spécifique à .ls-0-cursor ; supprime tout fallback hasardeux)
   =============================================================== */
@media (pointer:coarse) and (orientation: landscape){
  body.at-mid .ls-cursor{ display: none !important; }              /* cache tous les curseurs dynamiques */
  body.at-mid .ls-cursor.ls-0-cursor{ display: block !important; } /* ne montre que le neutre */
  body.at-mid .ls-arrow{ display: none !important; }               /* triangle statique masqué au neutre */
}


/* ===============================================================
   ACC-318-DRAG-PC4 — Curseur visible (PC uniquement via JS)
   - Slider collé au bord GAUCHE du cadre, calculé en JS
   - Pas d'impact mobile: le JS ne crée pas le slider en pointer:coarse
   =============================================================== */
.pc-slider4{ position:absolute; width: 22px; pointer-events:auto; z-index: 50; }
.pc-slider4 .pc-track{ position:absolute; left:50%; transform:translateX(-50%); top:0; bottom:0; width:2px;
  background: transparent; border-radius:2px; }
.pc-slider4 .pc-track::before{ content:\"\"; position:absolute; left:0; right:0; top: var(--pc-range-top, 24%); bottom: var(--pc-range-bottom, 24%); background: rgba(255,255,255,.32); box-shadow: 0 0 8px rgba(255,255,255,.28); border-radius:2px; pointer-events:none; }
.pc-slider4 .pc-thumb{ position:absolute; left:50%; transform: translate(-50%, -50%); width: 16px; height: 28px;
  border-radius: 9px; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.5); opacity:.95; }

/* ACC-323 — Halo desktop via --halo */
@media (pointer: fine){
  .frame::after{ opacity: var(--halo, 1); transition: opacity .18s ease; }
}


/* ===============================================================
   ACC-349 — Smartphone : triangle attaché au point de swipe avec règles distinctes
   - Portrait  : triangle sur la bordure HAUTE du cadre, pointe VERS LE BAS (vers l'image), aligné horizontalement.
   - Paysage   : triangle sur la bordure GAUCHE  du cadre, pointe VERS LA DROITE (vers l'image), aligné verticalement.
   - Visibilité: UNIQUEMENT en mode-2d ou mode-3d ; MASQUÉ au neutre (at-mid).
   - Ancien triangle smartphone désactivé.
   =============================================================== */
@media (pointer:coarse){
  /* Désactivation des triangles statiques smartphone */
  .ptb-2d::after, .ptb-3d::after{ display:none !important; }

  /* Base: caché par défaut */
  .touch-slider .knob::after{ display:none; }
  body.mode-2d .touch-slider .knob::after,
  body.mode-3d .touch-slider .knob::after{ display:block; }
  body.at-mid .touch-slider .knob::after{ display:none !important; }
}

/* === Portrait : sommet de l'image en haut → triangle sur la bordure HAUTE, pointe vers le BAS === */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    content:""; position:absolute;
    left:50%; transform: translateX(-50%);
    top: var(--tri-top, 0px); /* calculé en JS */
    width:0; height:0;
    border-left:6px solid transparent;
    border-right:6px solid transparent;
    border-bottom:8px solid var(--fg); /* pointe vers le bas (image) */
  }
}

/* === Paysage : image à droite → triangle sur la bordure GAUCHE, pointe vers la DROITE === */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  .touch-slider .knob::after{
    content:""; position:absolute;
    top:50%; transform: translateY(-50%);
    left: var(--tri-left, 0px); /* calculé en JS */
    width:0; height:0;
    border-top:6px solid transparent;
    border-bottom:6px solid transparent;
    border-right:8px solid var(--fg); /* pointe vers la droite (image) */
  }
}

/* ===============================================================
   ACC-364 — Correctifs mobiles (depuis ACC-363)
   - Portrait : descendre la pointe du triangle de 5px et mettre le swipe à l'intérieur du cadre.
   - Paysage  : mettre le swipe à l'intérieur du cadre (bord gauche).
   =============================================================== */

/* ----- Portrait smartphone ----- */
@media (pointer:coarse) and (orientation: portrait){
  /* Placer le track horizontal à l'intérieur du cadre (2px sous la bordure haute) */
  .touch-slider{
    left: 0; right: 0;
    top: calc(100% - var(--frame-portrait-h) + 2px) !important;
    height: 28px;
  }
  /* Descendre la flèche de 5px pour que la pointe dépasse sensiblement dans le cadre */
  .touch-slider .knob::after{
    top: calc(var(--tri-top, 0px) + 5px) !important;
  }
  /* Si un curseur portrait statique est utilisé, on l'abaisse également (préventif) */
  .ptb-cursor{ margin-top: calc(var(--ptb-arrow-offset) + 5px) !important; }
}

/* ----- Paysage smartphone ----- */
@media (pointer:coarse) and (max-width: 979px) and (orientation: landscape){
  /* Placer le track vertical à l'intérieur du cadre noir (bord gauche, 2px) */
  .touch-slider{
    left: 2px !important;
    width: 28px;
    top: 0; bottom: 0;
  }
}

/* ===============================================================
   ACC-365 — Correctif minimal depuis ACC-363
   1) PC : aucun changement (retour implicite au comportement ACC-363).
   2) Smartphone — Portrait : pointe du triangle TOUJOURS vers le BAS.
   =============================================================== */
@media (orientation: portrait){
  /* Triangles topbar (2D statique + 3D actif) */
  .ptb-2d::after,
  body.mode-3d .ptb-3d::after{
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important; /* pointe vers le bas */
  }
  /* Curseur portrait éventuellement injecté */
  .ptb-cursor::before{
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important; /* pointe vers le bas */
  }
  /* Triangle lié au knob du slider tactile */
  .touch-slider .knob::after{
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important; /* pointe vers le bas */
    /* on garde l'intérieur du cadre tel qu'en 364 sans toucher au PC */
  }
}

/* ===============================================================
   ACC-366 — Ajustements mobiles (depuis ACC-365)
   1) Portrait smartphone : remonter la pointe du triangle de 3px (elle reste orientée vers le BAS).
   2) Mobile (coarse pointer) : le point de swipe adopte le visuel du curseur PC.
   =============================================================== */

/* 1) Portrait smartphone — triangle un peu plus haut */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    /* on conserve l'orientation vers le BAS (déjà fixée) et on remonte de 3px */
    top: calc(var(--tri-top, 0px) - 3px) !important;
  }
}

/* 2) Mobile — visuel du point de swipe = équivalent du curseur PC */
@media (pointer:coarse){
  .touch-slider .knob{
    width: 16px !important;
    height: 28px !important;
    border-radius: 9px !important;
    background: #fff !important;
    box-shadow: 0 2px 10px rgba(0,0,0,.5) !important;
    opacity: .95 !important;
  }
}

/* ===============================================================
   ACC-367 — Cursor tweaks (mobile only)
   - Portrait (smartphone): rotate knob 45°.
   - Portrait & Landscape (smartphone): slightly reduce knob size.
   =============================================================== */

/* Mobile (toutes orientations) — taille du curseur un peu réduite */
@media (pointer:coarse){
  .touch-slider .knob{
    width: 14px !important;
    height: 24px !important;
    border-radius: 8px !important;
    /* on conserve le style visuel existant (couleur/ombre/opacité
       héritées des versions précédentes) */
  }
}

/* Portrait uniquement — rotation 45° du curseur (sans toucher au reste) */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob{
    transform: translate(-50%, -50%) rotate(45deg) !important;
  }
}

/* ===============================================================
   ACC-368 — Portrait smartphone: knob à 90° + triangle vers le BAS
   (variation minimale depuis ACC-365/367)
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  /* Curseur (point de swipe) pivoté à 90° */
  .touch-slider .knob{
    transform: translate(-50%, -50%) rotate(90deg) !important;
  }
  /* Triangle attaché au knob: pointe VERS LE BAS (sécurité) */
  .touch-slider .knob::after{
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important;
  }
}

/* ===============================================================
   ACC-369 — Portrait smartphone : triangle sur la LIGNE du cadre, pointe vers le BAS
   Variation minimale depuis ACC-368 (PC inchangé).
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  /* On conserve le track tel qu'actuel, mais on repositionne la flèche pour qu'elle
     vienne exactement AU NIVEAU de la bordure haute du rectangle noir. */
  .touch-slider .knob::after{
    /* Orientation vers le BAS (sécurité) */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important;
    /* Placement : remonte légèrement de 2px pour coïncider avec la ligne du cadre */
    top: calc(var(--tri-top, 0px) - 2px) !important;
  }
}

/* ===============================================================
   ACC-370 — Portrait smartphone : triangle sur la ligne du cadre (via var(--tri-top)), pointe VERS LE BAS
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    top: var(--tri-top, 0px) !important; /* alignement exact calculé par le JS */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important; /* pointe vers le BAS */
  }
}

/* ===============================================================
   ACC-371 — Portrait smartphone : triangle sur la ligne du cadre + pointe VERS LE BAS
   (compense le -8px du JS en ajoutant +8px côté CSS)
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    top: calc(var(--tri-top, 0px) + 8px) !important; /* aligne l'apex sur la bordure du cadre */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important;      /* pointe VERS LE BAS */
  }
}

/* ===============================================================
   ACC-372 — Triangle portrait "comme en 365" (avec knob à 90° conservé)
   - Apex exactement sur la ligne du cadre via top: var(--tri-top)
   - Pointe vers le BAS (border-top coloré)
   - Anti-rotation: on compense la rotation du parent (knob à 90°) par rotate(-90deg) sur le ::after
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    left: 50% !important;
    top: var(--tri-top, 0px) !important;           /* même ancrage qu'en 365 */
    transform: translateX(-50%) rotate(-90deg) !important; /* neutralise la rotation du parent */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important;    /* pointe vers le BAS */
  }
}

/* ===============================================================
   ACC-373 — Portrait smartphone : triangle centré au-dessus du knob,
   apex sur la ligne (léger débord vers l'intérieur), pointe VERS LE BAS.
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    /* Placement exact */
    position: absolute !important;
    left: 50% !important;
    top: calc(var(--tri-top, 0px) + 2px) !important; /* apex sur la ligne, débord ~2px vers l'intérieur */
    transform: translateX(-50%) rotate(-90deg) !important; /* neutralise la rotation du parent (90°) */
    z-index: 2 !important; /* au-dessus du knob */
    /* Orientation de la pointe */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important; /* pointe vers le BAS */
  }
}

/* ===============================================================
   ACC-374 — Triangle portrait: centrage + apex sur la ligne (léger débord), ancrage stable
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  .touch-slider .knob::after{
    position: absolute !important;
    left: 50% !important;
    top: calc(var(--tri-top, 0px) + 2px) !important; /* apex juste à l'intérieur du cadre */
    transform: translateX(-50%) rotate(-90deg) !important; /* neutralise la rotation du parent */
    transform-origin: 50% 0% !important; /* ancre l'apex à la ligne du cadre */
    z-index: 2 !important; /* au-dessus du knob */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important; /* pointe vers le BAS */
  }
}

/* ===============================================================
   ACC-375 — Smartphone portrait: knob visuellement à 90° (via ::before), triangle correct au-dessus
   - PC inchangé, paysage inchangé.
   - DOM inchangé.
   =============================================================== */
@media (pointer:coarse) and (orientation: portrait){
  /* 1) Conteneur knob non-rotaté (garde le centrage de position), fond neutre */
  .touch-slider .knob{
    transform: translate(-50%, -50%) !important;   /* supprime la rotation du conteneur */
    background: transparent !important;
    position: relative !important;
  }
  /* 2) Visuel du curseur rotaté à 90° dessiné en ::before (même look que PC réduit) */
  .touch-slider .knob::before{
    content: "" !important;
    position: absolute !important;
    left: 50% !important;
    top: 50% !important;
    width: 14px !important;
    height: 24px !important;
    transform: translate(-50%, -50%) rotate(90deg) !important;
    border-radius: 8px !important;
    background: #fff !important;
    box-shadow: 0 2px 10px rgba(0,0,0,.5) !important;
    opacity: .95 !important;
    z-index: 1 !important; /* sous la flèche */
  }
  /* 3) Triangle en ::after — indépendant, centré au-dessus du knob, apex sur la ligne + léger débord */
  .touch-slider .knob::after{
    content: "" !important;
    position: absolute !important;
    left: 50% !important;
    top: calc(var(--tri-top, 0px) + 2px) !important; /* apex sur la bordure avec léger débord intérieur */
    transform: translateX(-50%) !important;         /* PAS de rotation ici */
    z-index: 2 !important;                          /* au-dessus du visuel du knob */
    border-left: 6px solid transparent !important;
    border-right: 6px solid transparent !important;
    border-bottom: 0 !important;
    border-top: 8px solid var(--fg) !important;     /* pointe vers le BAS */
  }
}


.webgl-buttons {
  position: absolute;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 1rem;
  z-index: 1000;
}

.webgl-buttons button {
  padding: 0.8rem 1.5rem;
  background: rgba(255,255,255,0.1);
  border: 1px solid white;
  color: white;
  font-size: 1rem;
  cursor: pointer;
  backdrop-filter: blur(5px);
}

.webgl-buttons button:hover {
  background: white;
  color: black;
}
