/* Outil « Visite 3D depuis un plan » (Bêta) — upload + viewer.
   Token-driven (var(--vefa-*) chargés globalement via base.html). */
/* Tokens raccordés au set commun tokens.css — même valeur, source unique */

:root {
  --fp3d-accent: #db2777;
  --fp3d-accent-dark: #9d174d;
  --fp3d-accent-soft: rgba(219, 39, 119, 0.08);
  --fp3d-iso-roof: #fce7f3;
  --fp3d-iso-wall-l: #f9a8d4;
  --fp3d-iso-wall-r: #db2777;
  --fp3d-iso-window: var(--vefa-bg);
}

/* --- Pastille Bêta --- */
.fp3d-beta-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--fp3d-accent-dark);
  background: rgba(219, 39, 119, 0.10);
  border: 1px solid rgba(219, 39, 119, 0.25);
  margin-bottom: 0.75rem;
}

/* --- Alerte erreur --- */
.fp3d-alert {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  padding: 0.85rem 1rem;
  border-radius: 12px;
  margin-bottom: 1rem;
  font-size: 0.92rem;
  line-height: 1.45;
}
.fp3d-alert--error {
  color: #842029;
  background: #f8d7da;
  border: 1px solid #f1aeb5;
}
.fp3d-alert i { margin-top: 0.15rem; }

/* ====================== PAGE D'UPLOAD (mockup 2026-07) ====================== */

.fp3d-page {
  background: linear-gradient(180deg, #fdf2f8 0%, #fef6fb 35%, var(--vefa-bg, #fff) 100%);
}

/* --- Hero --- */
.fp3d-hero {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 1.5rem;
  padding: 1rem 0 2rem;
}
.fp3d-hero__title {
  font-size: clamp(1.7rem, 3vw, 2.3rem);
  font-weight: 800;
  color: var(--vefa-text-strong, #1f2733);
  margin: 0.15rem 0 0.6rem;
}
.fp3d-hero__subtitle {
  max-width: 620px;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--vefa-text-muted, #55606e);
  margin-bottom: 1rem;
}
.fp3d-reassurance {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.fp3d-reassurance__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--fp3d-accent-dark);
  background: #fff;
  border: 1px solid rgba(219, 39, 119, 0.18);
  box-shadow: var(--vefa-shadow-sm, 0 1px 3px rgba(15, 23, 42, 0.06));
}
.fp3d-reassurance__chip i { color: var(--fp3d-accent); }

.fp3d-hero__art {
  justify-self: end;
  opacity: 0.9;
}
.fp3d-iso {
  width: clamp(160px, 22vw, 260px);
  height: auto;
  filter: drop-shadow(0 12px 24px rgba(219, 39, 119, 0.18));
}
@media (max-width: 991px) {
  .fp3d-hero { grid-template-columns: 1fr; }
  .fp3d-hero__art { justify-self: center; opacity: 0.6; order: -1; }
  .fp3d-iso { width: 140px; }
}

/* --- Cartes blanches arrondies --- */
.fp3d-card {
  background: var(--vefa-surface, #fff);
  border-radius: var(--vefa-radius-xl, 24px);
  box-shadow: var(--vefa-shadow-md, 0 4px 6px -1px rgba(15, 23, 42, 0.06));
  padding: clamp(1.25rem, 3vw, 2rem);
  height: 100%;
}
.fp3d-columns { align-items: stretch; }

.fp3d-step-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--vefa-text-strong, #1f2733);
  margin: 0 0 0.9rem;
}
.fp3d-step-hint {
  font-size: 0.9rem;
  color: var(--vefa-text-muted, #55606e);
  margin: -0.4rem 0 0.9rem;
}

/* --- Zone de dépôt --- */
.fp3d-upload-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.25rem;
  align-items: stretch;
}
.fp3d-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.5rem;
  padding: 2.4rem 1.25rem;
  border: 2px dashed rgba(219, 39, 119, 0.35);
  border-radius: 18px;
  background: var(--fp3d-accent-soft);
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
.fp3d-drop:hover { border-color: var(--fp3d-accent); background: rgba(219, 39, 119, 0.12); }
.fp3d-drop--over { border-color: var(--fp3d-accent); background: rgba(219, 39, 119, 0.16); transform: translateY(-2px); }
.fp3d-drop--filled { border-style: solid; border-color: var(--fp3d-accent); background: #fff; }
.fp3d-drop--invalid { border-color: var(--vefa-danger, #dc2626); background: var(--vefa-danger-soft, rgba(220,38,38,.08)); }
.fp3d-drop__input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.fp3d-drop__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: #fff;
  color: var(--fp3d-accent);
  font-size: 1.4rem;
  box-shadow: var(--vefa-shadow-sm, 0 1px 3px rgba(15, 23, 42, 0.08));
}
.fp3d-drop__title { font-weight: 700; color: var(--vefa-text, #1f2733); }
.fp3d-drop__hint { font-size: 0.82rem; color: var(--vefa-text-muted, #6b7785); }

.fp3d-example {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 140px;
  padding: 0.85rem;
  border-radius: 16px;
  background: var(--vefa-bg-soft, #f8fafc);
  border: 1px solid var(--vefa-border, #e2e8f0);
}
.fp3d-example__label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--vefa-text-subtle, #94a3b8);
}
.fp3d-example__svg { width: 100%; height: auto; }
@media (max-width: 640px) {
  .fp3d-upload-row { grid-template-columns: 1fr; }
  .fp3d-example { width: 100%; flex-direction: row; justify-content: flex-start; }
  .fp3d-example__svg { width: 90px; height: auto; flex-shrink: 0; }
}

/* --- Séparateur "Optionnel" --- */
.fp3d-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.75rem 0 1.25rem;
  color: var(--vefa-text-subtle, #94a3b8);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.fp3d-divider::before,
.fp3d-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--vefa-border, #e2e8f0);
}

/* --- Échelle par référence --- */
.fp3d-ref-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
.fp3d-ref-field { display: flex; flex-direction: column; gap: 0.35rem; }
.fp3d-ref-length-input {
  position: relative;
  display: flex;
  align-items: center;
}
.fp3d-ref-length-input .vefa-sim-form-input { padding-right: 2.2rem; }
.fp3d-ref-length-suffix {
  position: absolute;
  right: 0.9rem;
  font-size: 0.85rem;
  color: var(--vefa-text-muted, #6b7785);
  pointer-events: none;
}
.fp3d-ref-hint {
  margin: 0.75rem 0 0;
  padding: 0.65rem 0.85rem;
  border-radius: 10px;
  background: var(--fp3d-accent-soft);
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--fp3d-accent-dark);
}
.fp3d-ref-hint i { margin-right: 0.3rem; }
@media (max-width: 640px) {
  .fp3d-ref-row { grid-template-columns: 1fr; }
}

/* --- CTA principal --- */
.fp3d-cta-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  width: 100%;
  margin-top: 1.5rem;
  padding: 0.95rem 1rem;
  border: 0;
  border-radius: var(--vefa-radius-lg, 16px);
  font-size: 1.05rem;
  font-weight: 700;
  color: #fff;
  text-decoration: none;
  background: linear-gradient(135deg, var(--vefa-accent, #ff4000) 0%, #ff7a45 100%);
  box-shadow: 0 10px 24px -8px rgba(255, 64, 0, 0.45);
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease, filter .15s ease;
}
.fp3d-cta-btn:hover {
  filter: brightness(1.03);
  transform: translateY(-1px);
  color: #fff;
}
.fp3d-cta-btn:disabled { opacity: 0.7; cursor: wait; transform: none; }
.fp3d-cta-note {
  margin-top: 0.75rem;
  font-size: 0.78rem;
  text-align: center;
  color: var(--vefa-text-subtle, #94a3b8);
}
.fp3d-cta-note i { margin-right: 0.25rem; }

/* --- Invité : CTA création de compte --- */
.fp3d-signup {
  padding: 1.5rem;
  border-radius: 16px;
  border: 1px dashed rgba(219, 39, 119, 0.35);
  background: var(--fp3d-accent-soft);
}
.fp3d-signup__text {
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--vefa-text, #1f2733);
  margin-bottom: 1rem;
}
.fp3d-signup__text i { color: var(--fp3d-accent); margin-right: 0.35rem; }

/* --- "Comment ça marche" --- */
.fp3d-how__title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--vefa-text-strong, #1f2733);
  margin: 0 0 1.1rem;
}
.fp3d-steps {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  position: relative;
}
.fp3d-steps__item {
  position: relative;
  display: flex;
  gap: 0.85rem;
  padding-bottom: 1.4rem;
}
.fp3d-steps__item:last-child { padding-bottom: 0; }
.fp3d-steps__item:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 15px;
  top: 34px;
  bottom: -2px;
  width: 2px;
  background: rgba(219, 39, 119, 0.25);
}
.fp3d-steps__dot {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--fp3d-accent);
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  z-index: 1;
}
.fp3d-steps__item strong { display: block; color: var(--vefa-text, #1f2733); margin-bottom: 0.2rem; }
.fp3d-steps__item p { margin: 0; font-size: 0.87rem; line-height: 1.5; color: var(--vefa-text-muted, #6b7785); }

/* Encarts colorés : plans qui marchent / à éviter / bêta */
.fp3d-guide {
  margin: 0.85rem 0 0;
  display: grid;
  gap: 0.55rem;
}
.fp3d-guide p {
  margin: 0;
  padding: 0.6rem 0.8rem;
  border-radius: 10px;
  font-size: 0.85rem;
  line-height: 1.45;
}
.fp3d-guide__ok {
  background: rgba(22, 163, 74, 0.08);
  border-left: 3px solid var(--vefa-success, #16a34a);
}
.fp3d-guide__ok i { color: var(--vefa-success, #16a34a); margin-right: 0.35rem; }
.fp3d-guide__ko {
  background: rgba(245, 158, 11, 0.1);
  border-left: 3px solid var(--vefa-warning, #f59e0b);
}
.fp3d-guide__ko i { color: var(--vefa-warning, #f59e0b); margin-right: 0.35rem; }
.fp3d-guide__beta {
  background: var(--fp3d-accent-soft);
  border-left: 3px solid var(--fp3d-accent);
}
.fp3d-guide__beta i { color: var(--fp3d-accent); margin-right: 0.35rem; }

/* Rétro-compat : ancien bloc "note" (encore référencé par des styles hérités) */
.fp3d-how__note {
  margin-top: 0.75rem;
  padding: 0.7rem 0.85rem;
  border-radius: 10px;
  background: var(--fp3d-accent-soft);
  font-size: 0.88rem;
  line-height: 1.45;
}
.fp3d-how__note i { color: var(--fp3d-accent); margin-right: 0.3rem; }

/* --- Bandeau bas pleine largeur --- */
.fp3d-benefits {
  margin-top: 3rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--vefa-border, #e2e8f0);
}
.fp3d-benefits__intro {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.75rem;
  align-items: center;
  margin-bottom: 2rem;
}
.fp3d-benefits__intro h2 {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--vefa-text-strong, #1f2733);
}
.fp3d-benefits__intro p { color: var(--vefa-text-muted, #55606e); line-height: 1.6; }
.fp3d-benefits__art { flex-shrink: 0; }
.fp3d-benefits__art .fp3d-iso--compact { width: 130px; height: auto; }
@media (max-width: 767px) {
  .fp3d-benefits__intro { grid-template-columns: 1fr; text-align: center; }
  .fp3d-benefits__art { justify-self: center; }
}

.fp3d-benefits__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
}
@media (max-width: 991px) {
  .fp3d-benefits__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .fp3d-benefits__grid { grid-template-columns: 1fr; }
}
.fp3d-benefit {
  padding: 1.25rem;
  border-radius: 16px;
  background: var(--vefa-bg-soft, #f8fafc);
  text-align: center;
}
.fp3d-benefit i {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--fp3d-accent-soft);
  color: var(--fp3d-accent);
  font-size: 1.15rem;
  margin-bottom: 0.75rem;
}
.fp3d-benefit h3 { font-size: 0.98rem; font-weight: 700; margin-bottom: 0.4rem; }
.fp3d-benefit p { font-size: 0.84rem; line-height: 1.5; color: var(--vefa-text-muted, #6b7785); margin: 0; }

/* ============================ VIEWER ============================ */
.fp3d-viewer-page {
  max-width: 1200px;
  margin: 0 auto;
  padding: 1rem clamp(0.75rem, 3vw, 2rem) 2rem;
}

.fp3d-viewer-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  padding: 0.75rem 0;
}
.fp3d-viewer-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  text-decoration: none;
}
.fp3d-viewer-back:hover { color: var(--fp3d-accent); }
.fp3d-viewer-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.85rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-viewer-meta .fp3d-beta-pill { margin-bottom: 0; }
.fp3d-viewer-file { font-weight: 600; color: var(--vefa-text, #1f2733); }
.fp3d-viewer-modes { margin-left: auto; display: flex; gap: 0.5rem; }
.fp3d-mode-btn {
  border: 0;
  border-radius: 9px;
  padding: 0.55rem 1rem;
  font-weight: 600;
  cursor: pointer;
  color: #fff;
  background: var(--fp3d-accent);
}
.fp3d-mode-btn:hover { filter: brightness(1.05); }

/* --- Sélecteur de page (PDF multipage, Lot 13 tâche 1) -------------------- */
.fp3d-pages-form { margin-top: 1rem; }
.fp3d-pages-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.fp3d-pages-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 12px;
  background: var(--vefa-bg, #fff);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.fp3d-pages-choice:has(.fp3d-pages-choice__radio:checked) {
  border-color: var(--fp3d-accent);
  box-shadow: 0 0 0 2px var(--fp3d-accent-soft);
}
.fp3d-pages-choice__radio { accent-color: var(--fp3d-accent); }
.fp3d-pages-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 8px;
  overflow: hidden;
  background: var(--vefa-bg-muted, #f1f4f8);
}
.fp3d-pages-thumb img { width: 100%; height: 100%; object-fit: contain; cursor: zoom-in; }
.fp3d-pages-thumb__missing { font-size: 1.6rem; color: var(--vefa-muted, #6b7785); }
.fp3d-pages-choice__label { font-weight: 600; font-size: 0.85rem; color: var(--vefa-text, #1f2733); }
.fp3d-pages-submit { display: inline-flex; align-items: center; gap: 0.5rem; }

/* Lot 14 (P2), tâche 6 : lightbox simple (sans lib) sur les vignettes du
   sélecteur de page, aperçu agrandissable au clic, fermeture Échap/clic. */
.fp3d-pages-lightbox {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  background: var(--vefa-overlay, rgba(15, 23, 42, 0.5));
}
.fp3d-pages-lightbox[hidden] { display: none; }
.fp3d-pages-lightbox__img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  background: var(--vefa-bg, #fff);
  box-shadow: var(--vefa-shadow-xl, 0 20px 35px -10px rgba(15, 23, 42, 0.15));
}
.fp3d-pages-lightbox__close {
  position: absolute;
  top: 1rem;
  right: 1.25rem;
  width: 2.25rem;
  height: 2.25rem;
  border: none;
  border-radius: 999px;
  background: var(--vefa-surface-glass-strong, rgba(255, 255, 255, 0.9));
  color: var(--vefa-text, #1f2733);
  font-size: 1.1rem;
  cursor: pointer;
}

.fp3d-canvas-wrap {
  position: relative;
  width: 100%;
  height: min(70vh, 620px);
  min-height: 360px;
  border-radius: 16px;
  overflow: hidden;
  background: #1a1f29;
  box-shadow: var(--vefa-shadow-md, 0 10px 30px rgba(16, 24, 40, 0.18));
}
.fp3d-canvas-wrap canvas { display: block; width: 100%; height: 100%; }

/* Chip nom de pièce (Lot 6.4) — bas-gauche du viewport, visible seulement en
   mode Visite (toggle `hidden` par floorplan_studio.js). Discret : petit,
   fond sombre translucide, jamais interactif (pointer-events none).
   `bottom: 68px` : dégage la barre `.fp3d-seg-bar` (segmented control
   Plan 2D/3D/Visite, ancrée `bottom: 14px` + ~44px de haut) qui traverse
   toute la largeur du viewport — sans ce décalage le chip se retrouvait
   sous les boutons de mode, invisible en pratique. */
.fp3d-room-chip-hud {
  position: absolute;
  left: 12px;
  bottom: 68px;
  z-index: 6;
  color: #fff;
  background: rgba(20, 24, 33, 0.72);
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  pointer-events: none;
  backdrop-filter: blur(2px);
  transition: opacity 0.2s ease;
}
.fp3d-room-chip-hud[hidden] { display: none; }

/* Étiquette d'échec ancrée au curseur (Lot 5, tâche 1) : apparaît AU POINT
   cliqué/touché (souris ou tactile), disparaît seule après ~2,5 s (JS,
   showPointerHint). `transform: translate(-50%, -100%)` centre la bulle
   au-dessus du point sans avoir à mesurer sa largeur ; `overflow: hidden` sur
   `.fp3d-canvas-wrap` (ancêtre) suffit à absorber un débordement en coin
   d'écran. Rouge (danger) : c'est toujours un message d'échec, jamais neutre
   comme le chip de pièce ci-dessus. */
.fp3d-pointer-hint {
  position: absolute;
  z-index: 7;
  transform: translate(-50%, -100%);
  background: var(--vefa-danger, #dc2626);
  color: var(--vefa-text-on-primary, #fff);
  font-size: 0.78rem;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: 999px;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 4px 10px rgba(16, 24, 40, 0.22);
}
.fp3d-pointer-hint[hidden] { display: none; }

/* Lot 1 quick wins UX, chantier 3 — barre d'aide courte (résumé) + bouton
   « ? » qui rouvre le détail (#fp3d-help-full ci-dessous). Le conteneur
   redevient interactif (pointer-events: auto) uniquement sur le bouton — le
   texte reste non cliquable comme avant, pour ne pas gêner le drag 3D
   dessous. */
.fp3d-help {
  position: absolute;
  top: 12px;
  left: 12px;
  right: 12px;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: var(--vefa-space-2, 8px);
  color: #fff;
  background: rgba(20, 24, 33, 0.78);
  padding: 8px 12px;
  border-radius: var(--vefa-radius-md, 10px);
  font-size: 0.8rem;
  line-height: 1.4;
  pointer-events: none;
}
#fp3d-help-short { flex: 1; min-width: 0; }
/* Lot 18 : équivalent 2D de #fp3d-help-short (cf. #fp3d-help-2d, gabarit),
   même traitement flex pour que le texte s'enroule plutôt que déborder. */
#fp3d-help-2d-text { flex: 1; min-width: 0; }
.fp3d-help-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 0.85rem;
  cursor: pointer;
  pointer-events: auto;
}
.fp3d-help-toggle:hover,
.fp3d-help-toggle.is-active { background: var(--fp3d-accent); }

/* Panneau d'aide détaillé (repliable) : réutilise le même habillage sombre,
   affiché juste sous la barre courte. Contient le rappel complet des
   commandes + le hint d'édition dynamique (#fp3d-help-edit-hint, préservé
   depuis updateEditModeUi). */
.fp3d-help-full {
  position: absolute;
  top: 52px;
  left: 12px;
  right: 12px;
  z-index: 4;
  color: #fff;
  background: rgba(20, 24, 33, 0.9);
  padding: 10px 36px 10px 12px;
  border-radius: var(--vefa-radius-md, 10px);
  font-size: 0.8rem;
  line-height: 1.45;
}
.fp3d-help-full[hidden] { display: none; }
.fp3d-help-full p { margin: 0 0 0.35rem; }
.fp3d-help-full p:last-child { margin-bottom: 0; }
.fp3d-help-full__close {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  cursor: pointer;
}
.fp3d-help-full__close:hover { background: var(--fp3d-accent); }
.fp3d-lock {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: none;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1rem;
  background: rgba(8, 10, 14, 0.55);
  color: #fff;
  font-size: 1.05rem;
  cursor: pointer;
}

.fp3d-viewer-disclaimer {
  margin-top: 0.9rem;
  font-size: 0.83rem;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-viewer-disclaimer i { color: var(--fp3d-accent); margin-right: 0.3rem; }

@media (max-width: 640px) {
  .fp3d-viewer-modes { margin-left: 0; width: 100%; }
  .fp3d-mode-btn { flex: 1; }
  .fp3d-help { font-size: 0.72rem; }
}

/* ===================== Sauvegarde & Mes plans 3D ===================== */
.fp3d-alert--ok {
  color: #0f5132;
  background: #d1e7dd;
  border: 1px solid #a3cfbb;
}
.fp3d-alert--info {
  color: #084298;
  background: #cfe2ff;
  border: 1px solid #9ec5fe;
}
/* --- Lot 6 (P0) : bandeau doublon, discret (une ligne, ton neutre), pas
   une alerte (rien n'est cassé), juste une information, cf. `_viewer_context`
   / `duplicate_plan`. Réutilise les tokens communs plutôt que `.fp3d-alert`
   (trop appuyé pour ce message non bloquant). --- */
.fp3d-dup-notice {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  margin-bottom: 0.75rem;
  border-radius: 10px;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--vefa-text-muted, #475569);
  background: var(--vefa-primary-soft, rgba(52, 152, 219, 0.08));
  border: 1px solid var(--vefa-border, #e2e8f0);
}
.fp3d-dup-notice i { color: var(--vefa-primary, #3498db); }
.fp3d-dup-notice a {
  color: var(--vefa-link, var(--vefa-primary, #3498db));
  font-weight: 600;
  text-decoration: underline;
}
.fp3d-dup-notice a:hover { color: var(--vefa-link-hover, var(--vefa-primary-dark, #2980b9)); }
.fp3d-save-bar {
  margin-top: 0.9rem;
  padding: 0.85rem 1rem;
  border-radius: 12px;
  background: var(--vefa-surface, #fff);
  border: 1px solid var(--vefa-border, #d5dbe2);
}
.fp3d-save-name {
  flex: 1 1 220px;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 9px;
  font-size: 0.95rem;
}
.fp3d-save-consent {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  color: var(--vefa-muted, #6b7785);
  margin: 0;
}
.fp3d-save-ok {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: #1a7f47;
  flex: 0 0 auto;
}
.fp3d-save-ok i { color: #1a7f47; }
.fp3d-save-link {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--fp3d-accent);
  text-decoration: none;
}
.fp3d-save-link:hover { text-decoration: underline; }

.fp3d-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1.1rem;
}
.fp3d-card {
  background: var(--vefa-surface, #fff);
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 14px;
  overflow: hidden;
  transition: transform .15s ease, box-shadow .15s ease;
}
.fp3d-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--vefa-shadow-md, 0 10px 24px rgba(16,24,40,.12));
}
.fp3d-card__thumb {
  display: block;
  aspect-ratio: 4/3;
  background: #f1f4f7;
}
.fp3d-card__thumb img { width: 100%; height: 100%; object-fit: contain; }
.fp3d-card__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 2rem;
  color: var(--vefa-muted, #9aa6b2);
}
.fp3d-card__body { padding: 0.7rem 0.85rem 0.85rem; }
.fp3d-card__name {
  display: block;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  text-decoration: none;
  margin-bottom: 0.15rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fp3d-card__name:hover { color: var(--fp3d-accent); }
.fp3d-card__meta {
  display: block;
  font-size: 0.8rem;
  color: var(--vefa-muted, #6b7785);
  margin-bottom: 0.5rem;
}
.fp3d-card__delete {
  border: 0;
  background: none;
  padding: 0;
  font-size: 0.8rem;
  color: #b42525;
  cursor: pointer;
}
.fp3d-card__delete:hover { text-decoration: underline; }
.fp3d-my-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: 0.6rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--fp3d-accent);
  text-decoration: none;
}
.fp3d-my-link:hover { text-decoration: underline; }

/* ===================== Écran de validation (éditeur 2D) ===================== */
.fp3d-validate-title {
  font-size: 1.45rem;
  font-weight: 800;
  margin: 0.4rem 0 0.2rem;
  color: var(--vefa-text, #1f2733);
}
.fp3d-validate-hint {
  font-size: 0.92rem;
  color: var(--vefa-muted, #6b7785);
  margin-bottom: 0.8rem;
}
.fp3d-chip {
  font-weight: 700;
  padding: 0 0.3rem;
  border-radius: 5px;
}
.fp3d-chip--wall { background: rgba(230,20,20,.12); color: #b42525; }
.fp3d-chip--door { background: rgba(20,60,230,.12); color: #1d3fd1; }
.fp3d-chip--window { background: rgba(10,170,60,.14); color: #0d7a36; }
.fp3d-chip--french { background: rgba(160,0,220,.13); color: #8400b8; }

.fp3d-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  align-items: center;
  padding: 0.55rem;
  background: var(--vefa-surface, #fff);
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 12px;
  /* la barre d'outils SUIT le scroll : le plan est haut, sans ça on remonte
     sans arrêt pour changer d'outil */
  position: sticky;
  top: 8px;
  z-index: 40;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.07);
}
.fp3d-toolbar-spacer { flex: 1; }

/* contrôle d'épaisseur du mur sélectionné (équivalent de la poignée carrée) */
.fp3d-thickness {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #4a5562);
  padding: 0.15rem 0.45rem;
  border: 1px dashed var(--vefa-border, #d5dbe2);
  border-radius: 10px;
}
.fp3d-thickness b { min-width: 4.2em; text-align: center; font-variant-numeric: tabular-nums; }
.fp3d-thickness button {
  width: 1.7rem; height: 1.7rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
  background: #fff;
  font-weight: 700;
  cursor: pointer;
  line-height: 1;
}
.fp3d-thickness button:hover { border-color: var(--fp3d-accent); color: var(--fp3d-accent); }

/* Contrôle « Ouverture » (sens des portes) — même style que l'épaisseur. */
.fp3d-swing {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #4a5562);
  padding: 0.15rem 0.45rem;
  border: 1px dashed var(--vefa-border, #d5dbe2);
  border-radius: 10px;
}
.fp3d-swing button {
  height: 1.7rem; padding: 0 0.55rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
  background: #fff;
  font-weight: 600;
  cursor: pointer;
  line-height: 1;
}
.fp3d-swing button:hover { border-color: var(--fp3d-accent); color: var(--fp3d-accent); }
.fp3d-swing button.is-active {
  background: var(--fp3d-accent, #e0367a);
  border-color: var(--fp3d-accent, #e0367a);
  color: #fff;
}
.fp3d-swing-side { display: inline-flex; align-items: center; gap: 0.3rem; }

/* Contrôle « Type » (mur / barrière + style) — même style que l'épaisseur
   et l'ouverture (toolbar contextuelle d'un mur sélectionné). */
.fp3d-wallkind {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #4a5562);
  padding: 0.15rem 0.45rem;
  border: 1px dashed var(--vefa-border, #d5dbe2);
  border-radius: 10px;
}
.fp3d-wallkind button {
  height: 1.7rem; padding: 0 0.55rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
  background: #fff;
  font-weight: 600;
  cursor: pointer;
  line-height: 1;
}
.fp3d-wallkind button:hover { border-color: var(--fp3d-accent); color: var(--fp3d-accent); }
.fp3d-wallkind button.is-active {
  background: var(--fp3d-accent, #e0367a);
  border-color: var(--fp3d-accent, #e0367a);
  color: #fff;
}
.fp3d-wallkind-style { display: inline-flex; align-items: center; gap: 0.3rem; }

/* Indicateur 2D du débattement / glissement dans l'éditeur. */
.fp3d-swing-ind {
  stroke: var(--fp3d-accent, #e0367a);
  stroke-width: 2.5;
  stroke-dasharray: 6 4;
  stroke-linecap: round;
  fill: none;
  pointer-events: none;
}
.fp3d-tool {
  border: 1px solid var(--vefa-border, #d5dbe2);
  background: #fff;
  border-radius: 9px;
  padding: 0.45rem 0.8rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  cursor: pointer;
}
/* le <form> ne doit pas casser l'alignement flex de la barre : son bouton
   .fp3d-tool participe directement à la rangée. */
.fp3d-tool-form { display: contents; }
.fp3d-tool:hover { border-color: var(--fp3d-accent); color: var(--fp3d-accent); }
.fp3d-tool.is-active {
  background: var(--fp3d-accent);
  border-color: var(--fp3d-accent);
  color: #fff;
}
.fp3d-tool--danger { color: #b42525; }
.fp3d-tool--danger:hover { border-color: #b42525; color: #b42525; }
.fp3d-tool:disabled { opacity: 0.45; cursor: not-allowed; }

.fp3d-mode-hint {
  margin: 0.4rem 0 0.6rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #6b7785);
  min-height: 1.2em;
}
.fp3d-mode-hint.is-flash { color: #b42525; font-weight: 600; }

.fp3d-stage-wrap {
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 14px;
  overflow: auto;
  background: #fff;
  max-height: 78vh;
}
.fp3d-stage { display: block; width: 100%; height: auto; }
.fp3d-stage.is-crosshair { cursor: crosshair; }
/* Lot 18 (navigation cohérente 2D/3D) : affordance du glisser gauche qui
   déplace la vue en outil Sélection, même convention que .fp3d-crop-viewport
   plus haut (is-pannable/is-panning). */
.fp3d-stage.is-pannable { cursor: grab; }
.fp3d-stage.is-panning { cursor: grabbing; }

.fp3d-el { opacity: 0.55; pointer-events: none; }   /* l'interaction passe par .fp3d-hit */
/* Couleurs en tokens (Lot 21) : --vefa-fp3d-* (website/static/website/css/tokens.css)
   est LE point de vérité, repris à l'identique par la pastille de la carte
   « élément sélectionné » et par la légende permanente du panneau 2D
   (gabarit floorplan_3d_studio.html) : changer une couleur ici la change
   partout, sans intervention côté carte/légende. */
.fp3d-el--wall { stroke: var(--vefa-fp3d-wall, #e61414); }
.fp3d-el--door { stroke: var(--vefa-fp3d-door, #143ce6); opacity: 0.75; }
.fp3d-el--window { stroke: var(--vefa-fp3d-window, #0aaa3c); opacity: 0.75; }
.fp3d-el--french { stroke: var(--vefa-fp3d-french, #a000dc); opacity: 0.8; }
/* Barrière (garde-corps) : trait mur pointillé + plus fin (largeur gérée en
   JS via line()) pour se distinguer d'un mur plein au premier coup d'œil. */
.fp3d-el--barrier { stroke-dasharray: 6 4; }
/* Sélection (Lot 21, tâche 4) : l'ombre portée unique d'origine se voyait à
   peine sur un trait de quelques pixels au milieu d'un plan chargé (retour
   Sabri, point 5). Renforcée en halo à deux passes : un liseré clair au plus
   près du trait (le détache d'un fond sombre ou d'un autre trait voisin),
   puis un halo plus large dans l'accent du studio (même couleur que
   .fp3d-tool.is-active : signal « sélectionné » cohérent dans tout le
   panneau, volontairement distinct des couleurs par TYPE ci-dessus). Ne
   touche ni à stroke-width ni à la géométrie : .fp3d-hit (zone de clic
   élargie, règle plus bas) reste strictement inchangée. */
.fp3d-el.is-selected {
  opacity: 1;
  filter:
    drop-shadow(0 0 1.5px var(--vefa-bg, #fff))
    drop-shadow(0 0 3px var(--fp3d-accent))
    drop-shadow(0 0 6px var(--fp3d-accent));
}
/* zone de clic élargie invisible : les traits visibles ne font que ~5 px écran */
.fp3d-hit {
  stroke: transparent;
  fill: none;
  pointer-events: stroke;
  cursor: pointer;
  touch-action: none;
}
/* poignées d'extension/réduction de l'élément sélectionné */
.fp3d-handle {
  fill: #fff;
  stroke: var(--fp3d-accent);
  stroke-width: 2.5;
  cursor: grab;
  touch-action: none;
}
.fp3d-handle:active { cursor: grabbing; }
.fp3d-handle--square { fill: var(--fp3d-accent); stroke: #fff; }
.fp3d-preview { stroke: var(--fp3d-accent); opacity: 0.85; }
.fp3d-preview--scale { stroke: #7c3aed; }
/* Halo d'aimantation sur l'extrémité de mur ciblée, AVANT le clic (Lot 13,
   tâche 4) : jamais interactif (le clic doit toujours atteindre le stage). */
.fp3d-snap-halo {
  fill: var(--fp3d-accent-soft);
  stroke: var(--fp3d-accent);
  stroke-width: 2;
  opacity: 0.85;
  pointer-events: none;
}

/* --- Carte « élément sélectionné » (Lot 21, tâche 1) ---------------------
   Traduit `selected` en langage clair (mur/porte/fenêtre/porte-fenêtre/
   barrière) : le trait de couleur seul ne le disait à personne (retour
   Sabri). TOUJOURS rendue, jamais `hidden` : seuls le texte et la classe de
   la pastille changent entre l'état vide et un élément sélectionné, pour ne
   jamais faire sauter la mise en page du panneau (peuplée par
   floorplan_editor.js, syncSelectionCard(), appelée à chaque render()).
   Placée dans le gabarit juste avant .fp3d-thickness/.fp3d-swing/
   .fp3d-wallkind/.fp3d-open-dims, qu'elle introduit : ne pas déplacer ces
   réglages contextuels existants. */
.fp3d-sel-card {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 12px;
  background: var(--vefa-surface, #fff);
}
.fp3d-sel-card__dot {
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  margin-top: 0.2rem;
  border-radius: 50%;
}
/* Les 4 modificateurs reprennent EXACTEMENT --vefa-fp3d-* (tokens.css),
   mêmes tokens que .fp3d-el--* et .fp3d-legend__dot--* : un seul endroit à
   changer si une couleur bouge un jour. */
.fp3d-sel-card__dot--wall { background: var(--vefa-fp3d-wall); }
.fp3d-sel-card__dot--door { background: var(--vefa-fp3d-door); }
.fp3d-sel-card__dot--window { background: var(--vefa-fp3d-window); }
.fp3d-sel-card__dot--french { background: var(--vefa-fp3d-french); }
/* Barrière : anneau pointillé de la couleur du mur (plutôt qu'un aplat), qui
   fait écho au trait pointillé .fp3d-el--barrier sur le plan. */
.fp3d-sel-card__dot--barrier {
  background: none;
  border: 2px dashed var(--vefa-fp3d-wall);
}
/* État vide : anneau neutre, jamais une des 4 couleurs ci-dessus (aucune
   confusion possible avec un type réel). */
.fp3d-sel-card__dot--empty {
  background: none;
  border: 2px dashed var(--vefa-border, #d5dbe2);
}
.fp3d-sel-card__body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.fp3d-sel-card__title {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
}
.fp3d-sel-card__dims {
  font-size: 0.8rem;
  color: var(--vefa-muted, #6b7785);
  font-variant-numeric: tabular-nums;
}

/* --- Légende permanente des couleurs du plan (Lot 21, tâche 2) -----------
   Discrète, toujours visible (100 % statique, aucun JS) : réponse directe à
   « l'utilisateur sait pas que ligne verte correspond à une porte ou une
   fenêtre » (retour Sabri). Même famille visuelle que .fp3d-room-chip
   (fond doux, texte réduit) pour rester à sa place dans le panneau. */
.fp3d-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.7rem;
  padding: 0.35rem 0.6rem;
  border-radius: 10px;
  background: var(--vefa-bg-muted, #f1f5f9);
  font-size: 0.76rem;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-legend__item { display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap; }
.fp3d-legend__dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; }
.fp3d-legend__dot--wall { background: var(--vefa-fp3d-wall); }
.fp3d-legend__dot--door { background: var(--vefa-fp3d-door); }
.fp3d-legend__dot--window { background: var(--vefa-fp3d-window); }
.fp3d-legend__dot--french { background: var(--vefa-fp3d-french); }
.fp3d-legend__dot--barrier { background: none; border: 1.5px dashed var(--vefa-fp3d-wall); }

/* --- Pièces détectées (surfaces par pièce, écran de validation) ---------- */
.fp3d-rooms {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.2rem 0 0.4rem;
}
.fp3d-room-chip {
  font-size: 0.78rem;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  background: rgba(219, 39, 119, 0.08);
  color: var(--fp3d-accent-dark);
  border: 1px solid rgba(219, 39, 119, 0.25);
  white-space: nowrap;
}
.fp3d-room-chip--ext {
  background: var(--vefa-bg-muted, #f1f4f8);
  color: var(--vefa-muted, #6b7785);
  border-color: var(--vefa-border, #d5dbe2);
}
.fp3d-room-chip--total {
  background: var(--fp3d-accent);
  border-color: var(--fp3d-accent);
  color: #fff;
  font-weight: 600;
}
/* Nommage des pièces (Lot 13, tâche 5) : signale que le chip est cliquable
   (le total n'a jamais cette classe, cf. floorplan_editor.js renderRoomPanel). */
.fp3d-room-chip--nameable { cursor: pointer; }
.fp3d-room-chip--nameable:hover { filter: brightness(0.96); }
/* Signal discret d'incohérence nom/surface (Lot 2, tâche 3) : teinte + icône,
   jamais de blocage. */
.fp3d-room-chip--flag {
  background: var(--vefa-warning-soft, rgba(245, 158, 11, 0.12));
  border-color: var(--vefa-warning, #f59e0b);
}
.fp3d-room-chip__flag-icon {
  color: var(--vefa-warning, #f59e0b);
  margin-right: 0.3em;
  font-size: 0.75em;
}

/* Indicateur discret d'autosave du panneau 2D (Lot 2, tâche 1). */
.fp3d-save-status--2d { display: block; margin: -0.1rem 0 0.4rem; min-height: 1.1em; }
.fp3d-save-status.is-error { color: var(--vefa-danger, #dc2626); font-weight: 600; }

/* --- Contours ouverts : pastille de signal + action "fermer" (Lot 2, t.2) - */
.fp3d-open-badge {
  fill: var(--vefa-danger, #dc2626);
  stroke: var(--vefa-bg, #fff);
  stroke-width: 2;
  opacity: 0.85;
  pointer-events: none;
  animation: fp3d-open-pulse 1.6s ease-in-out infinite;
}
@keyframes fp3d-open-pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 0.95; }
}
.fp3d-open-close-line {
  stroke: var(--vefa-success, #16a34a);
  fill: none;
  opacity: 0.55;
  pointer-events: none;
}
.fp3d-open-close-badge { cursor: pointer; }
.fp3d-open-close-badge__bg {
  fill: var(--vefa-success, #16a34a);
  stroke: var(--vefa-bg, #fff);
  stroke-width: 2;
}
.fp3d-open-close-badge:hover .fp3d-open-close-badge__bg { fill: #12833c; } /* hex-ok, vert succès foncé, pas de token dédié */
.fp3d-open-close-badge__icon {
  fill: var(--vefa-bg, #fff);
  font-weight: 700;
  pointer-events: none;
  user-select: none;
}

/* --- Écran de cadrage (cadrage utilisateur, plans multi-panneaux) -------- */
.fp3d-crop-scale {
  margin: 0 0 0.7rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-crop-scale > summary {
  cursor: pointer;
  color: var(--fp3d-accent);
  font-weight: 600;
  list-style: none;
}
.fp3d-crop-scale > summary::-webkit-details-marker { display: none; }
.fp3d-crop-scale > summary::before { content: "\f054"; font-family: "Font Awesome 6 Free";
  font-weight: 900; font-size: 0.7rem; margin-right: 0.4rem; display: inline-block; }
.fp3d-crop-scale[open] > summary::before { transform: rotate(90deg); }
.fp3d-crop-scale-field { display: block; margin: 0.5rem 0 0.2rem; }
.fp3d-crop-scale-field input {
  width: 5rem; padding: 0.3rem 0.5rem; margin: 0 0.3rem;
  border: 1px solid var(--vefa-border, #d5dbe2); border-radius: 8px;
}
.fp3d-crop-scale-help { color: var(--vefa-muted, #6b7785); }

/* Lot 3 (cadrage), page en colonne : barre d'outils avec sa PROPRE hauteur
   (jamais en overlay du plan) puis viewport qui prend tout l'espace restant
   de l'écran, calculé en JS (`fitToScreen`, floorplan_crop.js) pour que le
   plan ENTIER tienne sans scroll, molette/mobile inclus. `.fp3d-crop-page`
   scope les dérogations à `.fp3d-toolbar` (partagée avec l'éditeur 2D du
   Studio, cf. floorplan_3d_studio.html + floorplan_editor.js) sans toucher
   sa règle de base. */
.fp3d-crop-page .fp3d-validate-title { margin: 0.2rem 0 0.3rem; }
.fp3d-crop-page .fp3d-validate-hint { margin: 0 0 0.6rem; }
.fp3d-crop-layout {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.fp3d-crop-page .fp3d-toolbar {
  /* dérogation à la barre COLLANTE partagée (.fp3d-toolbar de base,
     `position: sticky`) : ici la barre est un bloc normal avec sa propre
     hauteur réservée, jamais un overlay du plan (exigence 1.1). */
  position: static;
}
.fp3d-crop-zoom {
  display: inline-flex;
  gap: 0.3rem;
}
.fp3d-crop-viewport {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 14px;
  background: var(--vefa-bg-muted, #f1f5f9);
  touch-action: none;
}
.fp3d-crop-viewport.is-pannable { cursor: grab; }
.fp3d-crop-viewport.is-panning { cursor: grabbing; }
.fp3d-crop-stage {
  position: relative;
  flex: none;
  overflow: visible;
  background: #fff;
  cursor: crosshair;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.fp3d-crop-viewport.is-pannable .fp3d-crop-stage,
.fp3d-crop-viewport.is-panning .fp3d-crop-stage { cursor: inherit; }
.fp3d-crop-img { display: block; width: 100%; height: 100%; pointer-events: none; }
.fp3d-crop-rect {
  position: absolute;
  border: 2px solid var(--fp3d-accent);
  background: rgba(219, 39, 119, 0.14);
  /* masque assombrissant l'extérieur de la sélection (exigence 1.3) : un
     spread énorme sur le rect lui-même, clippé par .fp3d-crop-viewport
     (overflow: hidden) : « ce qui est gardé » est littéralement ce qui
     reste clair à l'écran, quels que soient le zoom/le pan courants. */
  box-shadow: 0 0 0 9999px rgba(15, 23, 42, 0.32);
  pointer-events: none;
}
.fp3d-crop-form { margin: 0; }

/* Poignées de redimensionnement (exigence 1.2) : 8 poignées (coins +
   milieux), positionnées en JS sur le rect NORMALISÉ courant. Pastille
   visible réduite + zone de clic invisible élargie via ::before (inset
   négatif) pour respecter les 44px minimum en pointeur coarse sans
   agrandir le rendu visuel (mêmes couleurs que le rect : --fp3d-accent). */
.fp3d-crop-handles[hidden] { display: none; }
.fp3d-crop-handle {
  position: absolute;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  background: var(--vefa-bg, #fff);
  border: 2px solid var(--fp3d-accent);
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.25);
  touch-action: none;
}
.fp3d-crop-handle::before {
  content: "";
  position: absolute;
  inset: -11px; /* zone de clic 44x44 sans agrandir la pastille visible */
}
.fp3d-crop-handle[data-handle="nw"], .fp3d-crop-handle[data-handle="se"] { cursor: nwse-resize; }
.fp3d-crop-handle[data-handle="ne"], .fp3d-crop-handle[data-handle="sw"] { cursor: nesw-resize; }
.fp3d-crop-handle[data-handle="n"], .fp3d-crop-handle[data-handle="s"] { cursor: ns-resize; }
.fp3d-crop-handle[data-handle="e"], .fp3d-crop-handle[data-handle="w"] { cursor: ew-resize; }
/* Déplacement du rectangle entier (exigence 1.2) : PAS de poignée centrale
   dédiée : .fp3d-crop-rect garde `pointer-events: none` (nécessaire pour que
   le masque n'intercepte rien) et floorplan_crop.js détecte le déplacement
   par coordonnées (pointerdown à l'intérieur des bornes courantes du
   rectangle, hors poignée) plutôt que par ciblage DOM. `.fp3d-crop-stage`
   affiche `cursor: move` quand le pointeur survole le corps du rectangle
   (classe posée en JS) pour rester cohérent visuellement.
   Curseur ADDITIONNEL de survol : posé en JS via .is-move-target. */
.fp3d-crop-stage.is-move-target { cursor: move; }

@media (max-width: 640px) {
  .fp3d-crop-page .fp3d-validate-hint { font-size: 0.82rem; }
  .fp3d-crop-page .fp3d-crop-scale { font-size: 0.8rem; }
}

/* CTA invité : la génération de la maquette 3D nécessite un compte. */
.fp3d-signup {
  text-align: center;
  padding: 20px 14px;
  border: 1px dashed var(--fp3d-accent, #db2777);
  border-radius: 14px;
  background: rgba(219, 39, 119, 0.05);
}
.fp3d-signup__text {
  margin: 0 0 16px;
  color: var(--vefa-text-muted, #475569);
  line-height: 1.6;
}
.fp3d-signup__text i {
  color: var(--fp3d-accent, #db2777);
  margin-right: 4px;
}

/* --- Panneau de matériaux (Lot A2) ------------------------------------- */
.fp3d-mat-panel {
  position: absolute;
  top: 56px;
  right: 12px;
  z-index: 6;
  width: 260px;
  max-height: calc(100% - 72px);
  overflow-y: auto;
  padding: 12px 14px 14px;
  background: rgba(20, 24, 33, 0.92);
  color: #eef1f5;
  border-radius: 12px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);
  font-size: 0.86rem;
}
.fp3d-mat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 700;
  margin-bottom: 10px;
}
.fp3d-mat-close {
  background: none;
  border: none;
  color: #cfd6dd;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.fp3d-mat-close:hover { color: #fff; }
.fp3d-mat-sec {
  margin: 12px 0 6px;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #9aa4b0;
}
.fp3d-mat-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 7px;
}
.fp3d-mat-row > span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fp3d-mat-row select {
  flex: 0 0 108px;
  padding: 4px 6px;
  border-radius: 7px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: #2a3140;
  color: #eef1f5;
  font-size: 0.82rem;
}
.fp3d-mat-row input[type="color"] {
  flex: 0 0 40px;
  height: 26px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 6px;
  background: none;
  cursor: pointer;
}
.fp3d-mat-save { width: 100%; margin-top: 12px; }
.fp3d-mat-save:disabled { opacity: 0.6; cursor: wait; }
.fp3d-mat-status {
  display: block;
  margin-top: 8px;
  font-size: 0.78rem;
  color: #9fd8b0;
  text-align: center;
}
.fp3d-mat-login {
  display: block;
  margin-top: 12px;
  font-size: 0.8rem;
  color: var(--fp3d-accent, #db2777);
  text-decoration: underline;
}

/* --- Bibliothèque de textures sols (Lot 4a-1) — grille de vignettes par pièce */
.fp3d-mat-room {
  margin-bottom: 10px;
}
.fp3d-mat-room > span {
  display: block;
  margin-bottom: 5px;
  font-size: 0.82rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fp3d-mat-swatches {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}
.fp3d-swatch {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 6px;
  border: 2px solid rgba(255, 255, 255, 0.18);
  background-size: cover;
  background-position: center;
  cursor: pointer;
  padding: 0;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.fp3d-swatch:hover { transform: scale(1.05); }
.fp3d-swatch.is-active {
  border-color: var(--fp3d-accent, #db2777);
  box-shadow: 0 0 0 1px var(--fp3d-accent, #db2777);
}
.fp3d-swatch--chene-clair    { background-image: url("../textures/floors/chene-clair.1dab1c14776e.webp"); }
.fp3d-swatch--chene-fume     { background-image: url("../textures/floors/chene-fume.c9636b9c3e65.webp"); }
.fp3d-swatch--chevron        { background-image: url("../textures/floors/chevron.119af9cd3996.webp"); }
.fp3d-swatch--carrelage-60   { background-image: url("../textures/floors/carrelage-60.6aa05c720bff.webp"); }
.fp3d-swatch--travertin      { background-image: url("../textures/floors/travertin.d619b14ea28b.webp"); }
.fp3d-swatch--beton-cire     { background-image: url("../textures/floors/beton-cire.cc3c824523d0.webp"); }
.fp3d-swatch--moquette       { background-image: url("../textures/floors/moquette.ba70c85d5058.webp"); }
.fp3d-swatch--terrazzo       { background-image: url("../textures/floors/terrazzo.5f419c1c752c.webp"); }

@media (max-width: 640px) {
  .fp3d-mat-panel { width: calc(100% - 24px); max-height: 60%; }
}

/* --- Badge de sens d'ouverture (éditeur) : distinct des poignées de redim --- */
.fp3d-swing-badge { cursor: pointer; }
.fp3d-swing-badge__bg {
  fill: var(--fp3d-accent, #db2777);
  stroke: #fff;
  stroke-width: 2;
}
.fp3d-swing-badge:hover .fp3d-swing-badge__bg { fill: var(--fp3d-accent-dark, #9d174d); }
.fp3d-swing-badge__icon {
  fill: #fff;
  font-weight: 700;
  pointer-events: none;
  user-select: none;
}

/* Panneau « Dimensions » d'une ouverture sélectionnée (éditeur). */
.fp3d-open-dims {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--vefa-muted, #4a5562);
  padding: 0.15rem 0.5rem;
  border: 1px dashed var(--vefa-border, #d5dbe2);
  border-radius: 10px;
}
.fp3d-open-dims label {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  margin: 0;
  font-weight: 600;
}
.fp3d-open-dims input[type="number"] {
  width: 3.6rem;
  height: 1.7rem;
  padding: 0 0.35rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
  background: #fff;
  font-size: 0.85rem;
  text-align: right;
}
.fp3d-open-dims input[type="number"]:focus {
  outline: none;
  border-color: var(--fp3d-accent, #e0367a);
}
.fp3d-open-dims input[type="number"]:disabled { background: #f0f2f5; color: #9aa4b0; }

/* ===================== Écran d'attente (extraction async — Lot 2) ===================== */
.fp3d-processing-card {
  max-width: 520px;
  margin: 0 auto;
  text-align: center;
  padding: 2.5rem 1.5rem;
}
.fp3d-processing-spinner {
  width: 48px;
  height: 48px;
  margin: 0.5rem auto 1.25rem;
  border-radius: 50%;
  border: 4px solid rgba(219, 39, 119, 0.15);
  border-top-color: var(--fp3d-accent, #db2777);
  animation: fp3d-spin 0.9s linear infinite;
}
@keyframes fp3d-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .fp3d-processing-spinner { animation-duration: 2.4s; }
}

/* ============================ STUDIO (Lot 4a-2) ============================ */
/* Une page unique : viewport (3D three.js OU stage SVG éditeur) + panneau
   latéral contextuel + segmented control bas. Tokens --vefa-* + accent rose
   --fp3d-accent, cohérent avec la page d'upload refondue. */
/* Lot 16 : le Studio est un OUTIL plein écran, pas un article de blog. 1400px
   enfermait la maquette 3D avec des marges vides sur un écran large (retour
   Sabri : « l'écran donne l'impression d'être tronqué »). 1920px suit
   l'écran sur un desktop courant tout en bornant la topbar sur un écran 4K.
   Portée : cette règle ne s'applique QU'à .fp3d-studio-page, aucune autre
   page du site n'est concernée. */
.fp3d-studio-page {
  max-width: 1920px;
  margin: 0 auto;
  padding: 0.75rem clamp(0.75rem, 2vw, 1.5rem) 1.5rem;
}

/* STUDIO — topbar compacte (Lot 2a) : 2 zones flex — `.fp3d-topbar__ctx`
   (retour + fil d'ariane + nom + état de sauvegarde compact) et
   `.fp3d-topbar__actions` (Variante / Actions / Détails / Mettre à jour).
   Remplace l'ancien fil d'ariane éclaté (dims + save 3 états inline) : sur
   mobile 390px la maquette apparaît après ≤ 2 lignes de contexte. */
.fp3d-studio-topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  padding: 0.5rem 0 0.75rem;
}
.fp3d-topbar__ctx {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem 0.8rem;
  min-width: 0;
}
.fp3d-topbar__ctx .fp3d-save-ok { font-size: 0.85rem; }
.fp3d-studio-crumb__trail {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.9rem;
  min-width: 0;
}
.fp3d-studio-crumb__trail a {
  color: var(--vefa-muted, #6b7785);
  text-decoration: none;
  font-weight: 600;
}
.fp3d-studio-crumb__trail a:hover { color: var(--fp3d-accent); }
.fp3d-studio-crumb__sep { color: var(--vefa-border, #d5dbe2); }
.fp3d-studio-crumb__name {
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* --- chip d'état du plan (Lot 10, tâche 3) : Brouillon / Dans Mes plans 3D,
   distinct de l'indicateur d'auto-save du panneau (#fp3d-save-status,
   « Modifications enregistrées ») : remplace l'ancien .fp3d-save-ok,
   ambigu avec ce dernier (retour testeur). */
.fp3d-plan-status-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  flex: 0 0 auto;
  border: 1px solid var(--vefa-border, #e2e8f0);
  color: var(--vefa-text-muted, #475569);
  background: var(--vefa-bg-soft, #f8fafc);
  white-space: nowrap;
}
.fp3d-plan-status-chip.is-saved {
  color: var(--vefa-success, #16a34a);
  border-color: var(--vefa-success, #16a34a);
  background: var(--vefa-success-soft, rgba(22, 163, 74, 0.1));
}
.fp3d-topbar__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.6rem;
  margin-left: auto;
}
.fp3d-topbar__actions .fp3d-tool-form { display: inline-flex; }
/* ≤480px : la rangée d'actions doit tenir sur UNE ligne (critère Lot 2a :
   ≤2 lignes de contexte avant la maquette) — la variante passe en icône
   seule (le nom reste lisible dans son menu) et les gaps se resserrent. */
@media (max-width: 480px) {
  .fp3d-topbar__actions { gap: 0.35rem 0.4rem; }
  #fp3d-variant-name { display: none; }
  .fp3d-topbar__actions .fp3d-variant__btn { padding-left: 0.55rem; padding-right: 0.55rem; }
}
.fp3d-save-form-inline { display: inline-flex; align-items: center; gap: 0.5rem; }
.fp3d-save-form--compact .fp3d-mode-btn { padding: 0.42rem 0.8rem; font-size: 0.85rem; }

/* --- bouton « Mettre à jour »/« Enregistrer » : niveau secondaire (contour) —
   la couleur pleine (.fp3d-mode-btn de base) reste réservée à l'état actif du
   sélecteur de modes (2D/3D/Visite). --- */
.fp3d-mode-btn--secondary {
  background: transparent;
  color: var(--vefa-text, #1f2733);
  border: 1px solid var(--vefa-border, #d5dbe2);
}
.fp3d-mode-btn--secondary:hover { border-color: var(--fp3d-accent); color: var(--fp3d-accent-dark); }

/* --- panneau « Détails » : disclosure du même pattern que le menu Variante
   (coquille .fp3d-variant__menu réutilisée), contenu empilé verticalement. --- */
.fp3d-details { position: relative; display: inline-flex; }
.fp3d-details__panel {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  /* min-width hérité de .fp3d-variant__menu (240px, déclaré plus bas dans ce
     fichier — priorité par ordre de source à spécificité égale) */
}
.fp3d-details__panel .fp3d-viewer-stat {
  font-size: 0.82rem;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-details__panel .fp3d-beta-pill { margin-bottom: 0; align-self: flex-start; }
.fp3d-details__field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-details__field .fp3d-save-name { flex: none; width: 100%; }
.fp3d-details__link {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--fp3d-accent-dark);
  text-decoration: none;
}
.fp3d-details__link:hover { text-decoration: underline; }

/* --- corps : viewport + panneau ---
   Lot 16 : hauteur MESUREE par le JS (updateStudioBodyHeight,
   floorplan_studio.js) et écrite dans --fp3d-body-h sur .fp3d-studio-page.
   L'ancienne constante calc(100vh - 230px) supposait un en-tête de site, une
   topbar de studio et des bandeaux (programme, doublon) de hauteur fixe :
   faux dès qu'un bandeau optionnel apparaît (cf. brief). Le repli
   calc(100dvh - 230px) ne sert qu'avant la première mesure JS (pas de saut
   visible au chargement) ; 100dvh gère nativement la barre d'adresse mobile,
   déjà mieux que 100vh. */
.fp3d-studio-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 0.9rem;
  align-items: stretch;
  height: var(--fp3d-body-h, calc(100dvh - 230px));
  min-height: 480px;
}
/* Plein écran (Lot 16) : c'est .fp3d-studio-body (viewport ET panneau) qui
   devient l'élément plein écran (cf. floorplan_studio.js), jamais le seul
   viewport, sinon le panneau de personnalisation reste invisible et le
   bouton Édition n'ouvre plus rien. Le navigateur donne à l'élément plein
   écran les dimensions de l'écran mais ignore notre grille : sans ce
   height:100% explicite, la hauteur mesurée d'avant plein écran (calc(),
   variable) continue de s'appliquer et laisse une bande morte en bas. */
.fp3d-studio-body:fullscreen {
  height: 100%;
  width: 100%;
  /* Fond explicite : l'élément plein écran sort de .fp3d-studio-page (donc
     de son fond de page ambiant) et hérite sinon du blanc par défaut du
     navigateur, visible dans la gouttière de la grille (gap: 0.9rem). */
  background: var(--vefa-bg-page, #f4f7fa);
}
.fp3d-studio-viewport {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  background: #1a1f29;
  box-shadow: var(--vefa-shadow-md, 0 10px 30px rgba(16, 24, 40, 0.18));
  min-height: 0;
}
.fp3d-studio-viewport .fp3d-canvas-wrap {
  position: absolute;
  inset: 0;
  height: auto;
  min-height: 0;
  border-radius: 0;
  box-shadow: none;
}
.fp3d-studio-stage {
  position: absolute;
  inset: 0;
  margin: 0;
  /* Lot 22 (cf. PLAN_STUDIO3D_LOT22_PAN_COMPLET.md) : plus de défilement
     natif ici. Avant : `overflow: auto` faisait coexister un 2e mécanisme de
     navigation (le scroll de ce conteneur) avec le glisser qui pilote le
     viewBox du SVG (clampView/panByScreen, floorplan_editor.js), jamais
     synchronisés et jamais actionné par le scroll natif : jusqu'à 249 px de
     plan restaient durablement hors d'atteinte à la souris dès que le plan
     est plus "haut" que ce conteneur (`.fp3d-stage` a `height: auto`, sa
     boîte rendue peut dépasser cette hauteur). Le viewBox devient le SEUL
     mécanisme : `computePanBounds` (floorplan_editor.js) compense la
     fraction de boîte non visible pour que les 4 bords du plan restent
     atteignables au glisser, à tout zoom. */
  overflow: hidden;
  background: #fff;
  border-radius: 0;
}
/* Correctif du cadrage initial (retour Sabri : « quand on ouvre le plan 2D,
   on doit avoir la vue globale, la c'est zoome sur une chambre »). La regle
   de base `.fp3d-stage { height: auto }` fait suivre au SVG le rapport
   d'aspect de son viewBox : sur un plan plus haut que large, sa boite
   depassait ce conteneur. Tant que le conteneur avait `overflow: auto` ca se
   voyait peu (on pouvait defiler) ; depuis que le Lot 22 l'a passe en
   `hidden`, le bas du plan etait simplement COUPE au chargement (mesure :
   73,5 % de la hauteur visible seulement). En donnant au SVG la hauteur
   pleine du conteneur, le `preserveAspectRatio` par defaut
   (`xMidYMid meet`) met le plan ENTIER en boite, centre : la vue globale est
   retrouvee, et il n'existe plus aucune zone hors d'atteinte (le facteur de
   correction de `computePanBounds` vaut alors 1, il devient inoffensif).
   Portee volontairement limitee au studio : l'ecran de validation autonome
   (`.fp3d-stage-wrap` seul, avec son `max-height: 78vh`) n'est pas concerne. */
.fp3d-studio-stage .fp3d-stage {
  height: 100%;
}
.fp3d-studio-stage[hidden] { display: none; }
.fp3d-canvas-wrap[hidden] { display: none; }
.fp3d-viewer-empty {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem;
  color: #e6e9ee;
  background: rgba(20, 24, 33, 0.6);
}

/* --- segmented control bas centré (+ undo/redo à gauche, plein écran à droite) --- */
.fp3d-seg-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  z-index: 5;
  display: flex;
  align-items: center;
  padding: 0 14px;
  pointer-events: none;
  /* Lot 11, tâche 3 : transition du glissement hors champ ci-dessous, posée
     ici (règle de base) pour que le RETOUR à la normale (fin de pose) soit
     lui aussi animé, pas un simple saut. */
  transition: transform 0.18s ease, opacity 0.18s ease;
}
/* Lot 11, tâche 3 : barre de mode escamotée pendant une pose (placement actif
   OU drag d'un meuble déjà posé, classe posée sur la racine du studio par
   floorplan_studio.js/onPosingActiveChange), retour testeur « la barre
   inférieure peut recouvrir précisément la zone où l'utilisateur doit poser
   un meuble ». Glisse hors champ (transform, pas seulement `opacity`) ET
   coupe l'interaction, même mécanique que `.fp3d-sheet-open` plus bas (cran
   `full` du sheet mobile) : les deux classes peuvent cohabiter, chacune
   masque indépendamment. Règle unique hors media query : le glissement
   fonctionne à l'identique en position `absolute` (bureau) et `fixed`
   (mobile, cf. media plus bas), aucune duplication nécessaire.
   200px (pas un pourcentage de la propre hauteur de la barre, ~48 px,
   insuffisant) : mesuré en QA E2E à 375 px (`position: fixed; bottom:
   132px`, cf. media plus bas) pour que le RECTANGLE de la barre passe
   entièrement sous le bas du canvas, pas seulement son opacité. Vérifié par
   calcul de non-chevauchement des rects (getBoundingClientRect), cf. brief
   tâche 3 « mesurer les rects ». */
.fp3d-posing .fp3d-seg-bar {
  transform: translateY(200px);
  opacity: 0;
  pointer-events: none;
}
.fp3d-posing .fp3d-seg-bar * { pointer-events: none !important; }
.fp3d-seg-side {
  flex: 1;
  display: flex;
  gap: 0.4rem;
}
.fp3d-seg-side--right { justify-content: flex-end; }
.fp3d-seg-side .fp3d-tool,
.fp3d-seg .fp3d-seg__btn { pointer-events: auto; }
.fp3d-seg-side .fp3d-tool {
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--vefa-border, #d5dbe2);
  box-shadow: 0 4px 14px rgba(16, 24, 40, 0.22);
}
.fp3d-seg {
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 6px 20px rgba(16, 24, 40, 0.28);
}
.fp3d-seg__btn {
  border: 0;
  border-radius: 999px;
  padding: 0.45rem 1rem;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
}
.fp3d-seg__btn:hover { background: var(--fp3d-accent-soft); color: var(--fp3d-accent-dark); }
.fp3d-seg__btn.is-active { background: var(--fp3d-accent); color: #fff; }
.fp3d-seg__btn i { margin-right: 0.3rem; }
.fp3d-seg__btn:disabled { opacity: 0.6; cursor: wait; }

/* --- pilule « Mode Édition », à côté du segmented control (chantier toggle
   édition studio 3D) : même échelle que .fp3d-seg-side .fp3d-tool (chip
   blanche flottante), remplie accent quand active. Masquée en Plan 2D
   (JS updateCaptureUiVisibility) et sur petits écrans le libellé se réduit à
   l'icône seule (cf. media queries plus bas). */
.fp3d-seg-group { display: inline-flex; align-items: center; gap: 0.4rem; pointer-events: none; }
.fp3d-seg-group .fp3d-seg,
.fp3d-seg-group .fp3d-edit-toggle { pointer-events: auto; }
.fp3d-edit-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border: 0;
  border-radius: 999px;
  padding: 0.45rem 0.9rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 6px 20px rgba(16, 24, 40, 0.28);
  cursor: pointer;
  white-space: nowrap;
}
.fp3d-edit-toggle:hover { background: var(--fp3d-accent-soft); color: var(--fp3d-accent-dark); }
.fp3d-edit-toggle.is-active {
  background: var(--fp3d-accent);
  border-color: var(--fp3d-accent);
  color: #fff;
  box-shadow: 0 6px 20px rgba(219, 39, 119, 0.35);
}

/* --- pilule « Pose libre » (Lot 10, tâche 2), panneau Meubles : même forme
   que .fp3d-edit-toggle ci-dessus mais teinte accent VEFA (orange) quand
   active, cohérente avec le fantôme/l'empreinte orange du mode (JS,
   GHOST_FREE_COLOR = --vefa-accent). */
.fp3d-free-placement-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 999px;
  padding: 0.4rem 0.8rem;
  margin-bottom: 0.6rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  background: var(--vefa-bg, #fff);
  cursor: pointer;
}
.fp3d-free-placement-toggle:hover { border-color: var(--vefa-accent, #ff4000); }
.fp3d-free-placement-toggle.is-active {
  background: var(--vefa-accent, #ff4000);
  border-color: var(--vefa-accent, #ff4000);
  color: var(--vefa-text-on-primary, #fff);
}

/* --- panneau latéral droit contextuel --- */
.fp3d-studio-panel {
  background: var(--vefa-surface, #fff);
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 16px;
  padding: 0.9rem;
  overflow-y: auto;
  min-height: 0;
}
.fp3d-panel-head {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding-bottom: 0.65rem;
  border-bottom: 1px solid var(--vefa-border, #e4e8ee);
  margin-bottom: 0.65rem;
}
.fp3d-panel-head__title {
  font-weight: 800;
  font-size: 1.02rem;
  color: var(--vefa-text, #1f2733);
}
.fp3d-panel-head__sub { font-size: 0.8rem; color: var(--vefa-muted, #6b7785); }
.fp3d-ptabs {
  display: flex;
  /* wrap = filet de sécurité (zoom navigateur, police système large) : un
     onglet passe à la ligne plutôt que d'être TRONQUÉ par le bord du panneau
     (bug constaté : « Meubles » coupé en « Meub » à 5 onglets). */
  flex-wrap: wrap;
  gap: 3px;
  padding: 3px;
  background: var(--vefa-bg-muted, #f1f3f6);
  border-radius: 10px;
  margin-bottom: 0.75rem;
}
.fp3d-ptab {
  flex: 1;
  border: 0;
  border-radius: 8px;
  /* 5 onglets (« Ensoleillement » compris) doivent tenir dans les 320px du
     panneau — padding horizontal et corps resserrés en conséquence. */
  padding: 0.4rem 0.15rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--vefa-muted, #6b7785);
  background: transparent;
  cursor: pointer;
}
.fp3d-ptab.is-active {
  background: #fff;
  color: var(--fp3d-accent-dark);
  box-shadow: 0 1px 4px rgba(16, 24, 40, 0.12);
}
.fp3d-panel-hint {
  font-size: 0.8rem;
  color: var(--vefa-muted, #6b7785);
  line-height: 1.45;
  margin: 0 0 0.6rem;
}
.fp3d-mat-swatches--panel {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.fp3d-mat-swatches--panel .fp3d-swatch {
  width: 100%;
  aspect-ratio: 1;
  height: auto;
}
.fp3d-swatch:disabled { opacity: 0.45; cursor: not-allowed; }
.fp3d-wall-scope {
  display: flex;
  gap: 6px;
  margin-bottom: 0.7rem;
}
.fp3d-chip-btn {
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 999px;
  background: #fff;
  padding: 0.32rem 0.75rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  cursor: pointer;
}
.fp3d-chip-btn:hover { border-color: var(--fp3d-accent); }
.fp3d-chip-btn.is-active {
  background: var(--fp3d-accent);
  border-color: var(--fp3d-accent);
  color: #fff;
}
.fp3d-chip-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.fp3d-cswatches {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}
.fp3d-cswatch {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 10px;
  background: #fff;
  padding: 0.35rem 0.5rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  cursor: pointer;
  text-align: left;
}
.fp3d-cswatch:hover { border-color: var(--fp3d-accent); }
.fp3d-cswatch.is-active {
  border-color: var(--fp3d-accent);
  box-shadow: 0 0 0 2px var(--fp3d-accent-soft);
}
.fp3d-cswatch__dot {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid rgba(16, 24, 40, 0.18);
}
.fp3d-cswatch__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fp3d-cswatch__dot {
  background-size: cover;
  background-position: center;
}
.fp3d-cswatches--texture { margin-top: 0.5rem; }
.fp3d-sky-list { display: flex; flex-wrap: wrap; gap: 6px; }

/* Pastille « Autre » (couleur murale libre) — <label> autour d'un
   <input type=color>, même contrat visuel qu'un .fp3d-cswatch classique
   (dot + nom), le dot natif du picker est retaillé en rond via
   .fp3d-cswatch__dot--input (même technique que .fp3d-finish-color-other
   côté meubles). */
.fp3d-cswatch--other { cursor: pointer; }
.fp3d-cswatch__dot--input {
  padding: 0;
  border: 1px solid rgba(16, 24, 40, 0.18);
  background: none;
  cursor: pointer;
  overflow: hidden;
}
.fp3d-cswatch__dot--input::-webkit-color-swatch-wrapper { padding: 0; }
.fp3d-cswatch__dot--input::-webkit-color-swatch { border: 0; border-radius: 50%; }

/* Pastille « Aucune » (retrait de la teinte de sol, chantier « teinte des
   textures de sol » 2026-07) — barre oblique sur fond neutre : signale une
   ABSENCE de couleur, là où les autres dots en affichent une. */
.fp3d-cswatch__dot--none {
  background-color: #fff;
  background-image: linear-gradient(
    to top left, transparent calc(50% - 1px),
    rgba(16, 24, 40, 0.45) calc(50% - 1px), rgba(16, 24, 40, 0.45) calc(50% + 1px),
    transparent calc(50% + 1px));
}

/* ---- Presets « Styles » (Lot 2 — ambiance intérieure en 1 clic) ---------- */
.fp3d-style-presets { margin-bottom: 1rem; }
.fp3d-style-preset-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.fp3d-style-preset {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 10px;
  background: #fff;
  padding: 0.4rem 0.55rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  cursor: pointer;
  text-align: left;
}
.fp3d-style-preset:hover { border-color: var(--fp3d-accent); }
.fp3d-style-preset.is-active {
  border-color: var(--fp3d-accent);
  box-shadow: 0 0 0 2px var(--fp3d-accent-soft);
}
.fp3d-style-preset__swatches {
  flex: 0 0 auto;
  display: flex;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid rgba(16, 24, 40, 0.18);
}
.fp3d-style-preset__swatch {
  width: 16px;
  height: 28px;
  background-size: cover;
  background-position: center;
}
.fp3d-style-preset__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fp3d-panel-foot { margin-top: 0.8rem; min-height: 1.2rem; }
.fp3d-save-status {
  font-size: 0.78rem;
  color: var(--vefa-muted, #6b7785);
}

/* ---- Onglet Ensoleillement (Lot 7) --------------------------------------- */
.fp3d-panel-hint--tight { margin: 0.7rem 0 0.4rem; font-weight: 700; color: var(--vefa-text, #1f2733); }
.fp3d-compass {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}
.fp3d-compass__btn {
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 10px;
  background: #fff;
  padding: 0.4rem 0.2rem;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  cursor: pointer;
}
.fp3d-compass__btn:hover { border-color: var(--fp3d-accent); }
.fp3d-compass__btn.is-active {
  background: var(--fp3d-accent);
  border-color: var(--fp3d-accent);
  color: #fff;
}
.fp3d-stepper {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.3rem;
}
.fp3d-stepper__val {
  flex: 1;
  text-align: center;
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--vefa-text, #1f2733);
}
.fp3d-chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 0.2rem; }
.fp3d-hour-slider {
  width: 100%;
  margin: 0.3rem 0 0.8rem;
  accent-color: var(--fp3d-accent);
}
.fp3d-panel-honesty {
  margin-top: 0.9rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--vefa-border, #e4e8ee);
}
.fp3d-panel-honesty i { color: var(--fp3d-accent); margin-right: 0.25rem; }

/* ---- Lot 8 — chip « Nuit » + hint « Posez des luminaires » -------------- */
.fp3d-chip-btn--night i { margin-right: 0.25rem; }
.fp3d-chip-btn--night.is-active,
.fp3d-chip-btn--night:hover {
  background: #1f2a44;
  border-color: #1f2a44;
  color: #fff;
}
.fp3d-night-hint {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  margin: 0.5rem 0 0.2rem;
  padding: 0.55rem 0.7rem;
  border: 1px dashed var(--fp3d-accent, #db2777);
  border-radius: 10px;
  background: var(--fp3d-accent-soft, rgba(219, 39, 119, 0.08));
  color: var(--fp3d-accent-dark, #9d174d);
  font-size: 0.78rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}
.fp3d-night-hint:hover { background: rgba(219, 39, 119, 0.14); }
.fp3d-night-hint i { color: #eab308; font-size: 0.9rem; }
.fp3d-night-hint[hidden] { display: none; }

/* ---- Lot 8 (Studio UX v2) : hint découvrabilité « vue de dessus » -------
   Même gabarit que .fp3d-night-hint ci-dessus (discret, cliquable, texte
   court), teinte info/astuce (tokens globaux --vefa-*, pas les --fp3d-*
   locaux de ce fichier : convention retenue pour tout ajout récent, cf.
   .fp3d-dup-notice / .fp3d-furn-thumb__placed-badge). */
.fp3d-top-view-hint {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  margin: 0.5rem 0 0.2rem;
  padding: 0.55rem 0.7rem;
  border: 1px dashed var(--vefa-primary, #3498db);
  border-radius: 10px;
  background: var(--vefa-primary-soft, rgba(52, 152, 219, 0.08));
  color: var(--vefa-primary-dark, #2980b9);
  font-size: 0.78rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}
.fp3d-top-view-hint:hover { background: var(--vefa-primary-soft-strong, rgba(52, 152, 219, 0.16)); }
.fp3d-top-view-hint i { color: var(--vefa-primary, #3498db); font-size: 0.9rem; }
.fp3d-top-view-hint[hidden] { display: none; }

/* Boussole overlay (Lot 7) — discrète, haut-droite du viewport, visible en
   2D ET 3D/Visite. Cachée tant que l'orientation n'a jamais été touchée. */
.fp3d-compass-hud {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 6;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(20, 24, 33, 0.72);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 800;
  pointer-events: none;
  backdrop-filter: blur(2px);
}
.fp3d-compass-hud[hidden] { display: none; }
.fp3d-compass-hud__needle {
  display: inline-block;
  transition: transform 0.25s ease;
}

/* ---- Onglet Meubles (Lot 5a) -------------------------------------------- */
/* Recherche catalogue (Lot 5, tâche 4) : en tête de panneau, au-dessus de
   #fp3d-furn-catalog (jamais effacée par un re-rendu du catalogue). */
.fp3d-furn-search {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 10px;
  padding: 0.4rem 0.65rem;
  margin-bottom: 0.7rem;
  color: var(--vefa-muted, #6b7785);
}
.fp3d-furn-search__input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  font-size: 0.85rem;
  color: var(--vefa-text, #1f2733);
}
.fp3d-furn-search__input::placeholder { color: var(--vefa-muted, #9aa4b0); }
.fp3d-furn-catalog { display: flex; flex-direction: column; gap: 0.9rem; }
.fp3d-furn-cat-group__title {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--vefa-muted, #6b7785);
  margin: 0 0 0.4rem;
}
.fp3d-furn-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.fp3d-furn-thumb {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 10px;
  background: #fff;
  padding: 0.5rem 0.3rem;
  cursor: pointer;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  text-align: center;
  line-height: 1.15;
}
.fp3d-furn-thumb:hover { border-color: var(--fp3d-accent); }
.fp3d-furn-thumb.is-placing {
  border-color: var(--fp3d-accent);
  box-shadow: 0 0 0 2px var(--fp3d-accent-soft);
}
.fp3d-furn-thumb__icon {
  position: relative;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: var(--fp3d-accent-soft, #fde8e2);
  color: var(--fp3d-accent-dark, #c0392b);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}
.fp3d-furn-selected {
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 10px;
  padding: 0.6rem 0.7rem;
  margin-bottom: 0.8rem;
  background: #fbfaf8;
}
.fp3d-furn-selected__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 0.4rem;
}
/* ---- Lot 8 — interrupteur Allumé/Éteint (meuble luminaire sélectionné) --- */
.fp3d-furn-light-toggle {
  display: flex;
  gap: 6px;
  margin-bottom: 0.5rem;
}
.fp3d-furn-light-toggle .fp3d-chip-btn { flex: 1; justify-content: center; display: flex; align-items: center; gap: 0.3rem; }
#fp3d-furn-light-on.is-active {
  background: #eab308;
  border-color: #eab308;
  color: #201400;
}
#fp3d-furn-light-off.is-active {
  background: var(--vefa-text, #1f2733);
  border-color: var(--vefa-text, #1f2733);
  color: #fff;
}
/* Badge 💡 sur les vignettes de luminaires (manifest emits_light). */
.fp3d-furn-thumb__light-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  font-size: 0.7rem;
  line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
}
/* Badge « posé » (Lot 5, tâche 4) : compteur discret sur la vignette d'un
   item déjà présent dans spec.furniture, coin opposé au badge lumineux
   ci-dessus pour ne jamais les superposer. Mis à jour en direct à la pose et
   à la suppression (JS, refreshFurnitureBadges). */
.fp3d-furn-thumb__placed-badge {
  position: absolute;
  top: -4px;
  left: -4px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--vefa-success, #16a34a);
  color: var(--vefa-text-on-primary, #fff);
  font-size: 0.6rem;
  font-weight: 800;
  line-height: 15px;
  text-align: center;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
/* ---- Onglet Meubles, sections 5b (Mes meubles / Communauté) -------------- */
.fp3d-furn-section-title {
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--vefa-text, #1f2733);
  border-top: 1px solid var(--vefa-border, #d5dbe2);
  padding-top: 0.7rem;
  margin: 0.2rem 0 0.1rem;
}
.fp3d-furn-catalog .fp3d-furn-section-title:first-child { border-top: 0; padding-top: 0; }
.fp3d-furn-mine {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.fp3d-furn-mine .fp3d-furn-thumb { width: 100%; }
.fp3d-furn-badge {
  font-size: 0.58rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #8a6d1a;
  background: #fdf3d7;
  border: 1px solid #ecd9a0;
  border-radius: 6px;
  padding: 1px 4px;
  text-align: center;
}
.fp3d-furn-report {
  border: 0;
  background: none;
  font-size: 0.62rem;
  color: var(--vefa-muted, #6b7785);
  cursor: pointer;
  text-decoration: underline;
  padding: 0;
}
.fp3d-furn-report:hover { color: var(--fp3d-accent-dark, #c0392b); }
.fp3d-furn-report.is-done { text-decoration: none; color: #1a7f47; cursor: default; }
.fp3d-furn-propose { margin-top: 0.4rem; }
.fp3d-furn-propose a { font-weight: 700; color: var(--fp3d-accent-dark, #c0392b); }

/* ---- Personnalisation des meubles (finish, chantier 2026-07) ------------ */
.fp3d-furn-finish {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  margin-bottom: 0.7rem;
}
.fp3d-furn-finish-part {
  border-top: 1px solid var(--vefa-border, #d5dbe2);
  padding-top: 0.55rem;
}
.fp3d-furn-finish-part:first-child { border-top: 0; padding-top: 0; }
/* Sous-titre de famille (« Tissus et cuirs », « Bois », « Métaux ») — chantier
   « piètement & familles », 2026-07. Discret : il complète le titre de partie
   (Revêtement / Piètement / Structure) sans lui voler la vedette. */
.fp3d-furn-finish-family {
  margin: 0 0 0.3rem;
  font-size: 0.72rem;
  color: var(--vefa-text-muted, #6b7684);
}
.fp3d-finish-colors {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0.35rem 0 0.4rem;
}
.fp3d-finish-color-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid rgba(16, 24, 40, 0.18);
  padding: 0;
  cursor: pointer;
}
.fp3d-finish-color-dot.is-active {
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--fp3d-accent);
}
/* Sélecteur de couleur libre (chantier 2026-07) — l'<input type=color> nu se
   lisait comme une pastille BLANCHE de plus au bout de la rangée de teintes :
   rien ne signalait un SÉLECTEUR. Le <label> porte donc une icône pipette et
   un damier (convention « pas de couleur fixe ») ; l'input, transparent, reste
   au-dessus pour que le clic natif ouvre le picker du navigateur.
   `--fp3d-picked` : posé en JS quand une couleur libre est active → la
   pastille montre alors la couleur choisie au lieu du damier. */
.fp3d-finish-color-picker {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--vefa-border, #d5dbe2);
  cursor: pointer;
  overflow: hidden;
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #d5dbe2 25%, transparent 25%, transparent 75%, #d5dbe2 75%),
    linear-gradient(45deg, #d5dbe2 25%, transparent 25%, transparent 75%, #d5dbe2 75%);
  background-size: 8px 8px;
  background-position: 0 0, 4px 4px;
}
.fp3d-finish-color-picker.is-active {
  background-image: none;
  background-color: var(--fp3d-picked, #fff);
  box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--fp3d-accent);
}
.fp3d-finish-color-picker > i {
  position: relative;
  z-index: 0;
  font-size: 10px;
  color: #1f2933;
  text-shadow: 0 0 3px #fff, 0 0 2px #fff;   /* lisible sur teinte foncée */
  pointer-events: none;
}
.fp3d-finish-color-other {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  opacity: 0;          /* invisible mais cliquable : ouvre le picker natif */
  cursor: pointer;
}
/* Le swatch natif de <input type=color> est un rectangle plein cadre —
   masque la bordure interne du navigateur pour tenir dans le rond ci-dessus. */
.fp3d-finish-color-other::-webkit-color-swatch-wrapper { padding: 0; }
.fp3d-finish-color-other::-webkit-color-swatch { border: 0; border-radius: 50%; }
.fp3d-finish-reset {
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
  background: #fff;
  padding: 0.25rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--vefa-muted, #6b7785);
  cursor: pointer;
}
.fp3d-finish-reset:hover:not(:disabled) { border-color: var(--fp3d-accent); color: var(--fp3d-accent-dark, #c0392b); }
.fp3d-finish-reset:disabled { opacity: 0.45; cursor: not-allowed; }

.fp3d-save-status.is-saved { color: #1a7f47; font-weight: 600; }

/* --- panneau 2D : toolbar existante réorganisée verticalement --- */
.fp3d-toolbar--panel {
  position: static;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  margin-bottom: 0.75rem;
}
.fp3d-toolbar--panel .fp3d-tool {
  justify-content: flex-start;
  text-align: left;
  width: 100%;
}
.fp3d-toolbar--panel .fp3d-thickness,
.fp3d-toolbar--panel .fp3d-swing,
.fp3d-toolbar--panel .fp3d-wallkind,
.fp3d-toolbar--panel .fp3d-open-dims {
  margin: 0.2rem 0 0;
}
.fp3d-toolbar--panel .fp3d-open-dims {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.6rem;
}
.fp3d-rooms--panel { margin-top: 0.6rem; }

/* mini-formulaire « Régler l'échelle » (remplace le prompt() natif) */
.fp3d-scale-form {
  margin: 0 0 0.75rem;
  padding: 0.7rem 0.75rem;
  border: 1px solid var(--fp3d-accent);
  border-radius: 12px;
  background: var(--fp3d-accent-soft);
}
.fp3d-scale-form__measured {
  margin: 0 0 0.5rem;
  font-size: 0.83rem;
  color: var(--vefa-text, #1f2733);
}
.fp3d-scale-form__row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.83rem;
  font-weight: 600;
  margin-bottom: 0.55rem;
}
.fp3d-scale-form__input {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.fp3d-scale-form__input input {
  width: 90px;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
}
.fp3d-scale-form__actions { display: flex; gap: 0.5rem; }

/* ==================== LOT 4a-3 : variantes / partage / mobile ============= */

/* --- pill « Variante A ▾ » + menu (topbar) --- */
.fp3d-variant { position: relative; display: inline-flex; }
.fp3d-variant__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 999px;
  background: var(--vefa-surface, #fff);
  padding: 0.32rem 0.75rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--vefa-text, #1f2733);
  cursor: pointer;
  white-space: nowrap;
}
.fp3d-variant__btn:hover { border-color: var(--fp3d-accent); color: var(--fp3d-accent-dark); }
.fp3d-variant__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 1050;
  min-width: 240px;
  padding: 0.4rem;
  background: var(--vefa-surface, #fff);
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(16, 24, 40, 0.2);
}
.fp3d-variant__menu[hidden] { display: none; }
.fp3d-variant__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  border: 0;
  border-radius: 8px;
  background: transparent;
  padding: 0.45rem 0.55rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--vefa-text, #1f2733);
  text-align: left;
  cursor: pointer;
}
.fp3d-variant__item:hover { background: var(--fp3d-accent-soft); }
.fp3d-variant__item.is-active { color: var(--fp3d-accent-dark); }
.fp3d-variant__item .fa-check { margin-left: auto; color: var(--fp3d-accent); }
.fp3d-variant__item:disabled { opacity: 0.45; cursor: not-allowed; }
.fp3d-variant__item--danger { color: #b4232a; }
.fp3d-variant__item--danger:hover { background: rgba(180, 35, 42, 0.08); }
.fp3d-variant__sep {
  margin: 0.35rem 0.2rem;
  border: 0;
  border-top: 1px solid var(--vefa-border, #e4e8ee);
}
.fp3d-variant__rename {
  display: flex;
  gap: 0.4rem;
  padding: 0.3rem 0.4rem;
}
.fp3d-variant__rename input {
  flex: 1;
  min-width: 0;
  padding: 0.32rem 0.5rem;
  border: 1px solid var(--vefa-border, #d5dbe2);
  border-radius: 8px;
  font-size: 0.85rem;
}
.fp3d-variant__rename .fp3d-mode-btn { padding: 0.32rem 0.7rem; font-size: 0.8rem; }

/* --- menu « Actions » (Lot 1 quick wins UX chantier 2, PERMANENT à toutes
   les largeurs depuis le Lot 2a) : réutilise la coquille .fp3d-variant
   (pill + menu), même pattern que Variante/Vue. Capturer/Partager/Publier
   sur le forum/Régénérer y vivent désormais y compris en bureau —
   floorplan_studio.js (setupActionsMenu) déplace les nœuds DOM dedans UNE
   FOIS au boot, plus de dépendance à un seuil matchMedia. --- */
.fp3d-actions { position: relative; display: inline-flex; }
/* items déplacés dans le menu (classe ajoutée par le JS) : ils gardent leur
   id/data-umami-event d'origine mais adoptent l'habillage ligne-de-menu
   (comme .fp3d-variant__item) au lieu de la pilule de topbar — et le
   libellé texte (.fp3d-share-label, masqué ≤991px par ailleurs) redevient
   visible : dans un menu déroulant on veut le texte, pas l'icône seule. */
#fp3d-actions-menu { min-width: 220px; }
#fp3d-actions-menu .fp3d-actions-menu__item {
  display: flex;
  width: 100%;
  justify-content: flex-start;
  border-radius: var(--vefa-radius-sm, 6px);
  background: transparent;
  border-color: transparent;
}
#fp3d-actions-menu .fp3d-actions-menu__item:hover {
  background: var(--fp3d-accent-soft);
  border-color: transparent;
}
#fp3d-actions-menu .fp3d-actions-menu__item .fp3d-share-label,
#fp3d-actions-menu .fp3d-actions-menu__item .fp3d-studio-regen-label { display: inline; }
/* garde-fou (Lot 2a) : un item masqué par mode (#fp3d-capture en 2D, cf.
   updateCaptureUiVisibility) doit rester invisible même une fois déplacé
   dans le menu — sans cette règle, le display:flex ci-dessus (origine
   auteur) gagne sur le display:none UA de [hidden] (origine UA), qui perd
   la bataille de cascade même à spécificité comparable. */
#fp3d-actions-menu .fp3d-actions-menu__item[hidden] { display: none; }

/* --- joystick virtuel (visite tactile) --- */
.fp3d-joystick {
  position: absolute;
  left: 18px;
  bottom: 84px;
  width: 118px;
  height: 118px;
  border-radius: 50%;
  background: rgba(20, 24, 33, 0.28);
  border: 2px solid rgba(255, 255, 255, 0.45);
  z-index: 6;
  touch-action: none;
  display: none;
  backdrop-filter: blur(2px);
}
.fp3d-joystick.is-visible { display: block; }
.fp3d-joystick__stick {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 52px;
  height: 52px;
  margin: -26px 0 0 -26px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 4px 14px rgba(16, 24, 40, 0.35);
  pointer-events: none;
}

/* --- éditeur 2D tactile : le stage gère lui-même pan/zoom (viewBox) --- */
#fp3d-stage { touch-action: none; }

/* --- responsive : tablette (panneau empilé sous le viewport) --- */
@media (max-width: 991px) {
  .fp3d-studio-body {
    grid-template-columns: 1fr;
    height: auto;
  }
  .fp3d-studio-viewport { height: 58vh; min-height: 340px; }
  .fp3d-studio-panel { max-height: 46vh; }
  .fp3d-topbar__actions { margin-left: 0; }
  .fp3d-studio-crumb__newlabel,
  .fp3d-studio-regen-label,
  .fp3d-share-label { display: none; }
  .fp3d-seg__btn { padding: 0.42rem 0.7rem; font-size: 0.82rem; }
  .fp3d-edit-toggle { padding: 0.42rem 0.7rem; font-size: 0.82rem; }
}
@media (max-width: 480px) {
  /* libellé masqué, icône seule (même logique que les autres labels compactés
     ci-dessus) : la pilule reste lisible même à côté des 3 pilules de mode */
  .fp3d-edit-toggle { padding: 0.42rem 0.6rem; }
  .fp3d-edit-toggle .fp3d-edit-toggle__label { display: none; }
}

/* STUDIO — sheet 3 crans (Lot 2b) : le panneau devient un BOTTOM SHEET sous
   900 px avec 3 crans — `peek` (~122 px, défaut, base rule ci-dessous),
   `is-half` (~40vh, nouveau) et `is-expanded` (62vh, "full", inchangé).
   Drag/tap sur la poignée, snap au cran le plus proche des 3 au relâchement
   (JS : yForDetent/setSheet dans floorplan_studio.js). .is-dragging coupe la
   transition pendant le geste. Le segmented control passe en fixed
   au-dessus du sheet et ne s'efface QU'EN cran `full` (classe
   fp3d-sheet-open sur la racine — en `half` le sélecteur de modes reste
   visible/utilisable). */
@media (max-width: 899px) {
  .fp3d-studio-page { padding-bottom: 136px; }
  .fp3d-studio-viewport { height: calc(100vh - 320px); min-height: 300px; }
  .fp3d-studio-panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1040;
    max-height: none;
    height: 62vh;
    border-radius: 18px 18px 0 0;
    border-bottom: 0;
    box-shadow: 0 -10px 34px rgba(16, 24, 40, 0.28);
    padding-top: 0;
    transform: translateY(calc(100% - 122px));
    transition: transform 0.24s ease;
    overscroll-behavior: contain;
    will-change: transform;
  }
  .fp3d-studio-panel.is-dragging { transition: none; }
  /* cran `half` (Lot 2b) — ~40vh visibles sur un panneau de hauteur fixe
     62vh : translateY = 62vh − 40vh = 22vh. Le panneau ne couvre alors
     jamais plus de 45 % du viewport (critère audit). */
  .fp3d-studio-panel.is-half { transform: translateY(22vh); }
  .fp3d-studio-panel.is-expanded { transform: translateY(0); }
  /* sélecteur composé : gagne sur le display:none de base (déclaré plus bas) */
  .fp3d-studio-panel .fp3d-sheet-handle { display: flex; }
  /* replié (cran `peek` UNIQUEMENT) : pas de scroll interne (on ne voit que
     l'en-tête + onglets). En `half` et `full` le scroll interne reste actif
     (contenu du panneau plus grand que le cran visible). */
  .fp3d-studio-panel:not(.is-expanded):not(.is-half) { overflow: hidden; }
  /* segmented control : flotte au-dessus du sheet replié */
  .fp3d-seg-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 132px;
    z-index: 1041;
    /* Lot 11, tâche 3 : transform ajouté à la liste (mobile redéfinissait la
       transition sans elle), même glissement animé qu'en bureau à 375 px. */
    transition: opacity 0.2s ease, transform 0.18s ease;
  }
  .fp3d-sheet-open .fp3d-seg-bar { opacity: 0; pointer-events: none; }
  .fp3d-sheet-open .fp3d-seg-bar * { pointer-events: none !important; }
  /* Cran half (Lot 2b) : la seg-bar reste utilisable mais AU-DESSUS du sheet
     (son bottom:132px est calé sur le cran peek — laissée telle quelle, elle
     chevauche les onglets/chips du panneau à ~40vh). */
  .fp3d-sheet-half .fp3d-seg-bar { bottom: calc(40vh + 12px); }
  /* joystick FIXÉ à l'écran (au-dessus du sheet replié + seg bar) : le
     viewport peut déborder sous la ligne de flottaison en mobile, un joystick
     absolu dans le viewport finirait masqué par le sheet */
  .fp3d-joystick {
    position: fixed;
    left: 14px;
    bottom: 188px;
    z-index: 1042;
  }
}

/* poignée de drag du sheet (masquée en desktop) */
.fp3d-sheet-handle {
  display: none;
  position: sticky;
  top: 0;
  z-index: 3;
  justify-content: center;
  align-items: center;
  padding: 10px 0 8px;
  margin: 0 -0.9rem;          /* pleine largeur malgré le padding du panneau */
  background: var(--vefa-surface, #fff);
  touch-action: none;
  cursor: grab;
}
.fp3d-sheet-handle span {
  width: 46px;
  height: 5px;
  border-radius: 999px;
  background: var(--vefa-border, #cfd6de);
}

/* --- tactile : poignées de l'éditeur 2D élargies (complément du sizing JS,
   cf. floorplan_editor.js COARSE — les rayons sont posés en unités viewBox) --- */
@media (pointer: coarse) {
  .fp3d-handle { stroke-width: 2; }
}

/* ==================== LOT 4b : capture + presets caméra + photoréalisme === */

/* --- menu « Vue » (topbar) : réutilise la coquille .fp3d-variant --- */
.fp3d-camview { position: relative; display: inline-flex; }

/* --- bandeau de miniatures de session (bas du viewport 3D/Visite) --- */
.fp3d-capture-strip {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 10px;
  z-index: 5;
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding: 0.4rem;
  background: rgba(20, 24, 33, 0.35);
  border-radius: 12px;
  backdrop-filter: blur(3px);
}
.fp3d-capture-strip[hidden] { display: none; }
.fp3d-capture-thumb {
  position: relative;
  flex: 0 0 auto;
  width: 72px;
  height: 54px;
  border-radius: 8px;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, 0.6);
  cursor: pointer;
  background: #1c2230;
}
.fp3d-capture-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fp3d-capture-thumb:hover { border-color: var(--fp3d-accent); }
.fp3d-capture-thumb__remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  line-height: 18px;
  text-align: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.65rem;
  border: 0;
  cursor: pointer;
}
.fp3d-capture-thumb__photoreal {
  position: absolute;
  bottom: 2px;
  left: 2px;
  right: 2px;
  font-size: 0.6rem;
  padding: 0.15rem 0.2rem;
  border-radius: 5px;
  border: 0;
  background: rgba(219, 39, 119, 0.88);
  color: #fff;
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- modale de comparaison photoréalisme (avant/après) --- */
.fp3d-photoreal-modal { position: fixed; inset: 0; z-index: 2000; }
.fp3d-photoreal-modal[hidden] { display: none; }
.fp3d-photoreal-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(16, 20, 28, 0.6);
}
.fp3d-photoreal-modal__card {
  position: relative;
  z-index: 1;
  max-width: 900px;
  margin: 5vh auto;
  max-height: 90vh;
  overflow-y: auto;
  background: var(--vefa-surface, #fff);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(16, 24, 40, 0.35);
  display: flex;
  flex-direction: column;
}
.fp3d-photoreal-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.1rem;
  border-bottom: 1px solid var(--vefa-border, #e4e8ee);
  font-weight: 700;
}
.fp3d-photoreal-modal__head i.fa-wand-magic-sparkles { color: var(--fp3d-accent); margin-right: 0.4rem; }
.fp3d-photoreal-modal__body { padding: 1.1rem; min-height: 160px; }
.fp3d-photoreal-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2.5rem 0;
  color: var(--vefa-text-muted, #6b7280);
}
.fp3d-photoreal-spinner[hidden] { display: none; }
.fp3d-photoreal-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
.fp3d-photoreal-compare[hidden] { display: none; }
.fp3d-photoreal-compare figure { margin: 0; }
.fp3d-photoreal-compare figcaption {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--vefa-text-muted, #6b7280);
  margin-bottom: 0.35rem;
}
.fp3d-photoreal-compare img {
  width: 100%;
  border-radius: 8px;
  display: block;
}
.fp3d-photoreal-error {
  color: #b4232a;
  font-weight: 600;
}
.fp3d-photoreal-error[hidden] { display: none; }
.fp3d-photoreal-modal__foot {
  padding: 0.8rem 1.1rem;
  border-top: 1px solid var(--vefa-border, #e4e8ee);
  display: flex;
  justify-content: flex-end;
}

@media (max-width: 767px) {
  .fp3d-photoreal-compare { grid-template-columns: 1fr; }
  .fp3d-photoreal-modal__card { margin: 0; max-height: 100vh; border-radius: 0; }
}

/* --- Lot 5c : bouton « Créer depuis une photo » + formulaire de génération --- */
.fp3d-furn-gen-open {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  background: none;
  padding: 0;
  font-weight: 700;
  font-size: inherit;
  color: var(--fp3d-accent-dark, #c0392b);
  cursor: pointer;
}
.fp3d-furn-gen-open:hover { text-decoration: underline; }
#fp3d-furngen-form { display: flex; flex-direction: column; gap: 0.9rem; }
.fp3d-furngen-field { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.88rem; font-weight: 600; }
.fp3d-furngen-field input,
.fp3d-furngen-field select {
  font-weight: 400;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--vefa-border, #e4e8ee);
  border-radius: 8px;
  font-size: 0.92rem;
}
.fp3d-furngen-dims { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; }
.fp3d-furngen-success {
  color: #1a7f37;
  font-weight: 600;
}
.fp3d-furngen-success[hidden] { display: none; }

@media (max-width: 767px) {
  .fp3d-furngen-dims { grid-template-columns: 1fr; }
}

/* ================ LOT 1 QUICK WINS UX — audit Studio 3D (2026-07) ==========
   Chantiers 1 (cibles tactiles + focus-visible) et 5 (normalisation sur les
   tokens --vefa-*). Scope STRICT à la page Studio (#fp3d-studio /
   .fp3d-studio-page) — n'affecte ni l'upload, ni le cadrage, ni le
   traitement. N'écrase JAMAIS --fp3d-accent (palette en attente de décision
   produit). */

/* --- chantier 5 : hauteur/rayon/espacement harmonisés sur les tokens, sans
   toucher aux règles PARTAGÉES avec les autres écrans floorplan (.fp3d-tool
   et .fp3d-mode-btn sont définis plus haut dans ce fichier et servent aussi
   la page d'upload / l'écran de cadrage — on les surcharge ici seulement
   SOUS .fp3d-studio-page, jamais globalement). --- */
.fp3d-studio-page .fp3d-tool,
.fp3d-studio-page .fp3d-mode-btn,
.fp3d-studio-page .fp3d-edit-toggle,
.fp3d-studio-page .fp3d-variant__btn,
.fp3d-studio-page .fp3d-seg__btn,
.fp3d-studio-page .fp3d-help-toggle,
.fp3d-studio-page .fp3d-help-full__close {
  min-height: 40px;
}
.fp3d-studio-page .fp3d-tool,
.fp3d-studio-page .fp3d-variant__btn {
  border-radius: var(--vefa-radius-md, 10px);
}
.fp3d-studio-page .fp3d-ptab {
  border-radius: var(--vefa-radius-sm, 6px);
}
.fp3d-studio-page .fp3d-seg-bar,
.fp3d-studio-page .fp3d-seg-group,
.fp3d-studio-page .fp3d-seg-side {
  gap: var(--vefa-space-2, 8px);
}
.fp3d-studio-page .fp3d-topbar__ctx,
.fp3d-studio-page .fp3d-topbar__actions {
  gap: var(--vefa-space-2, 8px) var(--vefa-space-4, 16px);
}

/* focus-visible : aucun contrôle de la Studio n'en avait — anneau cohérent
   sur tous les éléments interactifs (boutons, liens, "boutons" ARIA comme la
   poignée du sheet, champs). */
.fp3d-studio-page button:focus-visible,
.fp3d-studio-page a:focus-visible,
.fp3d-studio-page [role="button"]:focus-visible,
.fp3d-studio-page input:focus-visible,
.fp3d-studio-page select:focus-visible {
  outline: 2px solid var(--fp3d-accent, #db2777);
  outline-offset: 2px;
}

/* --- chantier 1 : cibles tactiles ≥ 44×44 px sur pointeur grossier, pour
   toutes les actions qui deviennent icône-seule en mobile (Vue, Capturer,
   Partager, Publier forum, Régénérer, Édition, plein écran, undo/redo,
   poignée du sheet). `.fp3d-help-toggle` couvre aussi #fp3d-recenter (LOT 4,
   tâche 1, même classe partagée que le bouton « ? » d'aide, cf.
   floorplan_3d_studio.html). --- */
@media (pointer: coarse) {
  .fp3d-studio-page #fp3d-undo,
  .fp3d-studio-page #fp3d-redo,
  .fp3d-studio-page #fp3d-fullscreen,
  .fp3d-studio-page #fp3d-edit-toggle,
  .fp3d-studio-page #fp3d-capture,
  .fp3d-studio-page #fp3d-share,
  .fp3d-studio-page #fp3d-publish-forum,
  .fp3d-studio-page #fp3d-camview-btn,
  .fp3d-studio-page #fp3d-actions-btn,
  .fp3d-studio-page #fp3d-details-btn,
  .fp3d-studio-page #fp3d-regen-form .fp3d-tool,
  .fp3d-studio-page .fp3d-help-toggle,
  .fp3d-studio-page .fp3d-help-full__close {
    min-width: 44px;
    min-height: 44px;
  }
  /* la poignée elle-même : la zone de drag/tap est toute la div, on agrandit
     son padding vertical plutôt qu'une largeur fixe (pleine largeur du
     panneau par ailleurs). */
  .fp3d-studio-page #fp3d-sheet-handle {
    min-height: 44px;
    padding-top: 16px;
    padding-bottom: 14px;
  }
}

/* STUDIO — flux guidé (Lot 2c) : carte d'état vide (#fp3d-panel-empty-sols /
   -murs, aucune sélection) + catégories de sols repliées en <details>
   natifs (cf. floorplan_studio.js renderPanelState()). Visible/masquée par
   JS via l'attribut `hidden` — aucune classe d'état dédiée nécessaire. */
.fp3d-panel-empty {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin: 0 0 0.8rem;
  padding: 0.7rem 0.85rem;
  border: 1px dashed var(--vefa-border, #d5dbe2);
  border-radius: 12px;
  background: var(--vefa-bg-muted, #f6f7f9);
}
.fp3d-panel-empty[hidden] { display: none; }
.fp3d-panel-empty i {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--fp3d-accent-soft);
  color: var(--fp3d-accent-dark);
  font-size: 0.9rem;
}
.fp3d-panel-empty p {
  margin: 0;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--vefa-text, #1f2733);
}
.fp3d-panel-empty p strong { color: var(--fp3d-accent-dark); }

/* Catégories de sols repliées — le `<summary>` porte déjà la classe
   `.fp3d-panel-hint--tight` (poids/couleur/marges du sous-titre qu'il
   remplace, cf. règle plus haut) ; on n'ajoute ici que le curseur + le
   chevron cliquable. Chevron : même technique déjà en place sur
   `.fp3d-crop-scale > summary` plus haut dans ce fichier (glyphe FA en
   `content`, rotation 90°→pointe vers le bas quand `[open]`). */
.fp3d-floor-cat { margin: 0; }
.fp3d-floor-cat > summary { cursor: pointer; list-style: none; }
.fp3d-floor-cat > summary::-webkit-details-marker { display: none; }
.fp3d-floor-cat > summary::before {
  content: "\f054";
  font-family: "Font Awesome 6 Free";
  font-weight: 900;
  font-size: 0.65rem;
  margin-right: 0.4rem;
  display: inline-block;
  color: var(--vefa-muted, #6b7785);
  transition: transform 0.15s ease;
}
.fp3d-floor-cat[open] > summary::before { transform: rotate(90deg); }
.fp3d-floor-cat > summary:hover { color: var(--fp3d-accent-dark); }
.fp3d-floor-cat > summary:hover::before { color: var(--fp3d-accent); }
.fp3d-floor-cat > .fp3d-mat-swatches--panel { margin-top: 0.2rem; }

/* Honeypot du formulaire d'upload (Lot 3 — génération sans compte) : sorti
   du flux sans display:none ni type=hidden, que les bots ignorent — même
   recette que .optout-form__hp (website/static/website/css/optout.css). */
.fp3d-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
