Files
photobooth/frontend/index.html
Jules f49d5511ef Pellicule : marge de coupe plus large + warmup LiveView apres capture
La coupe physique du K60 n'est jamais parfaitement centree, donc une marge
noire trop fine fait perdre la pellicule d'un cote du strip dedouble. Marge
de coupe (perforations) elargie de 34 a 55px (~4.6mm) de chaque cote.

Ajoute aussi un warmup LiveView (_chauffer_liveview) juste apres la remontee
du miroir post-capture : consomme les ~1-2s de stabilisation pendant le
spinner de traitement plutot que de laisser le preview du countdown suivant
figé sur l'ancienne photo.
2026-06-21 23:47:06 +02:00

749 lines
38 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Photobooth</title>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta name="google" content="notranslate">
<meta http-equiv="Content-Language" content="fr">
<link rel="stylesheet" href="/css/style.css?v=4">
<link rel="stylesheet" href="/css/themes.css">
</head>
<body>
<div id="app">
<!-- Bandeau erreur imprimante (tous écrans) -->
<div id="printer-erreur" class="printer-erreur cache">
<span class="printer-erreur-icon">&#128424;</span>
<span id="printer-erreur-msg">Problème imprimante</span>
<button onclick="document.getElementById('printer-erreur').classList.add('cache')">&#10005;</button>
</div>
<!-- Overlay erreur camera -->
<div id="camera-erreur" class="camera-erreur cache">
<div class="camera-erreur-icon">&#128247;</div>
<p>Probleme de communication avec l'appareil photo</p>
<span class="camera-erreur-sub">Reconnexion en cours...</span>
<button onclick="document.getElementById('camera-erreur').classList.add('cache'); afficherEcran('accueil')" style="margin-top:2rem;padding:1rem 2rem;font-size:1.5rem;border-radius:1rem;border:none;background:#e91e63;color:#fff;cursor:pointer;">Retour accueil</button>
</div>
<!-- Ecran d'accueil -->
<section id="ecran-accueil" class="ecran actif">
<!-- Fond video/gif en boucle -->
<video id="accueil-video" class="accueil-media cache" muted loop playsinline></video>
<img id="accueil-gif" class="accueil-media cache">
<div class="accueil-contenu">
<img id="accueil-logo" class="accueil-logo cache" src="" alt="">
<h1 id="nom-evenement">Photobooth</h1>
<p class="accueil-instruction">Touchez pour commencer</p>
<div id="accueil-animation-defaut" class="accueil-animation">
<div class="cercle-pulse"></div>
</div>
</div>
<div id="compteur-accueil" class="compteur-accueil cache">
<span id="compteur-restant">400</span> / <span id="compteur-limite">400</span>
</div>
<!-- Booth : code + QR en bas a gauche -->
<div id="booth-info" class="booth-info cache">
<img id="booth-qr" class="booth-qr" src="">
<span id="booth-code" class="booth-code"></span>
</div>
<!-- Icone admin coin bas-droit -->
<div id="btn-admin" class="btn-admin" onclick="ouvrirAdmin()">&#9881;</div>
<!-- Icone photostation coin bas-gauche (visible seulement si installée) -->
<div id="btn-photostation" class="btn-photostation cache" onclick="ouvrirPhotostation()">&#128444;</div>
</section>
<!-- Choix du mode -->
<section id="ecran-mode" class="ecran">
<h2>Choisissez votre mode</h2>
<div class="grille-modes">
<button class="btn-mode" data-mode="simple">
<div class="mode-icone mode-icone-large">&#128247;</div>
<span>Photo</span>
</button>
<button class="btn-mode" data-mode="multi" id="btn-multi">
<div class="mode-icone mode-icone-large">&#127902;</div>
<span>Pellicule</span>
</button>
</div>
<button class="btn-retour" onclick="allerA('accueil')">Retour</button>
</section>
<!-- Choix de cadre avant capture -->
<section id="ecran-cadre-choix" class="ecran">
<h2>Choisissez un cadre</h2>
<div id="grille-cadres-choix" class="grille-cadres-choix">
<div class="cadre-choix-item cadre-choix-aucun" onclick="lancerSansCadre()">
<div class="cadre-choix-vide"></div>
<span>Sans cadre</span>
</div>
</div>
<button class="btn-retour" onclick="allerA('mode')">Retour</button>
</section>
<!-- Compte a rebours + Capture -->
<section id="ecran-capture" class="ecran">
<div id="preview-live" class="preview-live">
<img id="img-preview" src="" alt="Preview">
<div id="cadre-guide-recadrage" class="cadre-guide-recadrage cache"></div>
<div id="preview-erreur-camera" class="preview-erreur-camera cache">
<div class="preview-erreur-icon">&#128247;</div>
<p>Appareil photo deconnecte</p>
<span>Reconnexion en cours...</span>
</div>
</div>
<div id="compte-a-rebours" class="compte-a-rebours cache">
<span id="chiffre-car">3</span>
</div>
<div id="flash-blanc" class="flash-blanc cache"></div>
<div id="capture-en-cours" class="capture-en-cours cache">
<div class="capture-spinner"></div>
<span>Capture en cours...</span>
</div>
<div class="capture-info">
<span id="capture-compteur"></span>
</div>
</section>
<!-- Preview photo + Filtres -->
<section id="ecran-preview" class="ecran">
<div class="preview-photo-container">
<img id="photo-resultat" src="" alt="Photo">
<img id="cadre-overlay-preview" class="cadre-overlay cache" src="" alt="">
</div>
<div id="barre-filtres" class="barre-filtres">
</div>
<div id="barre-overlays" class="barre-overlays cache">
</div>
<div id="barre-fonds" class="barre-fonds cache">
</div>
<div class="preview-actions">
<button class="btn-action" onclick="allerA('partage')">Valider</button>
<button class="btn-secondaire" onclick="recommencer()">Reprendre</button>
</div>
</section>
<!-- Partage -->
<section id="ecran-partage" class="ecran">
<h2>Partagez votre photo !</h2>
<div class="photo-miniature">
<img id="photo-partage" src="" alt="Photo">
</div>
<div class="grille-partage">
<button class="btn-partage" id="btn-imprimer" onclick="ouvrirImpression()">
<div class="partage-icone">&#128424;</div>
<span>Imprimer</span>
</button>
<button class="btn-partage" id="btn-email" onclick="ouvrirEmail()">
<div class="partage-icone">&#128231;</div>
<span>Email</span>
</button>
<button class="btn-partage" id="btn-qr" onclick="afficherQR()">
<div class="partage-icone">&#128274;</div>
<span>QR Code</span>
</button>
</div>
<div id="form-impression" class="form-impression cache">
<div class="exemplaires-choix">
<button class="btn-exemplaire" onclick="changerExemplaires(-1)">-</button>
<span id="nb-exemplaires">1</span>
<button class="btn-exemplaire" onclick="changerExemplaires(1)">+</button>
</div>
<span class="exemplaires-label">exemplaire(s)</span>
<button class="btn-action" onclick="lancerImpression()">Imprimer</button>
<button class="btn-secondaire" onclick="fermerImpression()">Annuler</button>
</div>
<div id="form-email" class="form-email cache">
<input type="email" id="input-email" placeholder="votre@email.com" autocomplete="off" readonly>
<div class="clavier-virtuel" id="clavier-email">
<div class="clavier-ligne">
<button onclick="clavierTape('1')">1</button>
<button onclick="clavierTape('2')">2</button>
<button onclick="clavierTape('3')">3</button>
<button onclick="clavierTape('4')">4</button>
<button onclick="clavierTape('5')">5</button>
<button onclick="clavierTape('6')">6</button>
<button onclick="clavierTape('7')">7</button>
<button onclick="clavierTape('8')">8</button>
<button onclick="clavierTape('9')">9</button>
<button onclick="clavierTape('0')">0</button>
</div>
<div class="clavier-ligne">
<button onclick="clavierTape('a')">a</button>
<button onclick="clavierTape('z')">z</button>
<button onclick="clavierTape('e')">e</button>
<button onclick="clavierTape('r')">r</button>
<button onclick="clavierTape('t')">t</button>
<button onclick="clavierTape('y')">y</button>
<button onclick="clavierTape('u')">u</button>
<button onclick="clavierTape('i')">i</button>
<button onclick="clavierTape('o')">o</button>
<button onclick="clavierTape('p')">p</button>
</div>
<div class="clavier-ligne">
<button onclick="clavierTape('q')">q</button>
<button onclick="clavierTape('s')">s</button>
<button onclick="clavierTape('d')">d</button>
<button onclick="clavierTape('f')">f</button>
<button onclick="clavierTape('g')">g</button>
<button onclick="clavierTape('h')">h</button>
<button onclick="clavierTape('j')">j</button>
<button onclick="clavierTape('k')">k</button>
<button onclick="clavierTape('l')">l</button>
<button onclick="clavierTape('m')">m</button>
</div>
<div class="clavier-ligne">
<button onclick="clavierTape('w')">w</button>
<button onclick="clavierTape('x')">x</button>
<button onclick="clavierTape('c')">c</button>
<button onclick="clavierTape('v')">v</button>
<button onclick="clavierTape('b')">b</button>
<button onclick="clavierTape('n')">n</button>
<button onclick="clavierTape('@')">@</button>
<button onclick="clavierTape('.')">.</button>
<button onclick="clavierTape('-')">-</button>
<button onclick="clavierTape('_')">_</button>
</div>
<div class="clavier-ligne clavier-speciales">
<button class="clavier-wide" onclick="clavierEffacer()">&#9003;</button>
<button class="clavier-wide" onclick="clavierTape('@gmail.com')">@gmail</button>
<button class="clavier-wide" onclick="clavierTape('@hotmail.com')">@hotmail</button>
<button class="clavier-wide" onclick="clavierTape('.com')">.com</button>
<button class="clavier-wide" onclick="clavierTape('.fr')">.fr</button>
</div>
</div>
<div style="display:flex;gap:1rem;margin-top:0.5rem">
<button class="btn-action" onclick="envoyerEmail()">Envoyer</button>
<button class="btn-secondaire" onclick="fermerEmail()">Annuler</button>
</div>
</div>
<div id="zone-qr" class="zone-qr cache">
<img id="img-qr" src="" alt="QR Code">
</div>
<div id="statut-partage" class="statut-partage cache"></div>
<div class="partage-bas">
<button class="btn-action" onclick="allerA('accueil')">Terminer</button>
<button class="btn-secondaire" onclick="recommencer()">Nouvelle photo</button>
</div>
</section>
<!-- Galerie -->
<section id="ecran-galerie" class="ecran">
<h2>Galerie</h2>
<div id="grille-galerie" class="grille-galerie"></div>
<button class="btn-retour" onclick="allerA('accueil')">Retour</button>
</section>
<!-- Choix admin : wizard ou parametres -->
<section id="ecran-admin-choix" class="ecran" onclick="event.stopPropagation()">
<h2>Administration</h2>
<div class="grille-modes">
<button class="btn-mode" onclick="ouvrirWizard()">
<div class="mode-icone mode-icone-large">&#9889;</div>
<span>Nouvel evenement</span>
</button>
<button class="btn-mode" onclick="allerA('admin')">
<div class="mode-icone mode-icone-large">&#9881;</div>
<span>Parametres</span>
</button>
</div>
<div style="display:flex;gap:1rem;margin-top:1rem">
<button class="btn-secondaire" onclick="location.reload()">Recharger</button>
<button class="btn-secondaire" onclick="quitterNavigateur()">Quitter</button>
</div>
<button class="btn-retour" onclick="allerA('accueil')">Retour</button>
</section>
<!-- Wizard evenement -->
<section id="ecran-wizard" class="ecran">
<div class="wizard-header">
<button class="btn-fermer" onclick="allerA('accueil')">&times;</button>
<div class="wizard-progress" id="wizard-progress"></div>
</div>
<!-- Etape 1 : Nom -->
<div class="wizard-step actif" data-step="1">
<h2>Nom de l'evenement</h2>
<input type="text" id="wiz-nom" class="wizard-input" placeholder="Mariage Julie & Thomas" autocomplete="off">
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 2 : Theme -->
<div class="wizard-step" data-step="2">
<h2>Theme visuel</h2>
<div class="wizard-choix">
<button class="wizard-card" data-val="base" onclick="wizardChoisir(this, 'theme')">
<div class="wizard-card-icon" style="background:#1a1a2e;color:#e91e63">&#9790;</div>
<span>Sombre</span>
</button>
<button class="wizard-card" data-val="sikapics" onclick="wizardChoisir(this, 'theme')">
<div class="wizard-card-icon" style="background:#fbe7e8;color:#c31f48">&#10047;</div>
<span>SikaPics</span>
</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 3 : Modes photo -->
<div class="wizard-step" data-step="3">
<h2>Modes photo</h2>
<div class="wizard-choix">
<button class="wizard-card wizard-toggle actif" data-val="simple" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#128247;</div>
<span>Photo</span>
</button>
<button class="wizard-card wizard-toggle actif" data-val="multi" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#127902;</div>
<span>Pellicule</span>
</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 4 : Nombre de photos pellicule -->
<div class="wizard-step" data-step="4">
<h2>Photos par pellicule</h2>
<div class="wizard-nombre">
<button class="wizard-nb-btn" onclick="wizardNbPhotos(-1)">-</button>
<span id="wiz-nb-photos" class="wizard-nb-val">4</span>
<button class="wizard-nb-btn" onclick="wizardNbPhotos(1)">+</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 5 : Fonctions partage -->
<div class="wizard-step" data-step="5">
<h2>Partage</h2>
<div class="wizard-choix wizard-choix-wrap">
<button class="wizard-card wizard-toggle" data-val="impression" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#128424;</div>
<span>Impression</span>
</button>
<button class="wizard-card wizard-toggle" data-val="email" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#9993;</div>
<span>Email</span>
</button>
<button class="wizard-card wizard-toggle" data-val="galerie_live" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#127760;</div>
<span>Galerie live</span>
</button>
<button class="wizard-card wizard-toggle" data-val="qr" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#9641;</div>
<span>QR Code</span>
</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 6 : Resume -->
<div class="wizard-step" data-step="6">
<h2>C'est pret !</h2>
<div id="wiz-resume" class="wizard-resume"></div>
<button class="wizard-btn-next wizard-btn-go" onclick="wizardTerminer()">Lancer le photobooth</button>
<button class="btn-secondaire" onclick="allerA('admin')">Parametres avances</button>
</div>
</section>
<!-- Menu Admin / Backoffice (avance) -->
<section id="ecran-admin" class="ecran">
<div class="admin-header">
<h2>Parametres avances</h2>
<button class="btn-fermer" onclick="allerA('accueil')">&times;</button>
</div>
<div class="admin-contenu">
<div class="admin-onglets">
<button class="onglet actif" data-onglet="materiel">Materiel</button>
<button class="onglet" data-onglet="compteur-admin">Compteur</button>
<button class="onglet" data-onglet="destinations-admin">Destinations</button>
<button class="onglet" data-onglet="personnalisation">Personnalisation</button>
<button class="onglet" data-onglet="evenement">Evenement</button>
<button class="onglet" data-onglet="fonctions">Fonctions</button>
<button class="onglet" data-onglet="infos" onclick="chargerInfosSysteme()">Infos</button>
</div>
<!-- Panneau Materiel (Camera + Imprimante) -->
<div class="admin-panneau actif" id="panneau-materiel">
<h3>Appareil photo</h3>
<div class="champ">
<label>Statut</label>
<span id="admin-camera-statut" class="statut-badge">--</span>
<button class="btn-secondaire btn-petit" onclick="reconnecterCamera()">Reconnecter</button>
</div>
<div class="champ">
<label>Appareil detecte</label>
<select id="admin-appareil"><option value="">Detection...</option></select>
</div>
<div class="champ">
<label>Compte a rebours (secondes)</label>
<input type="number" id="admin-car" min="1" max="10" value="3">
</div>
<div class="champ">
<label class="toggle"><input type="checkbox" id="tog-flash-integre" checked><span class="toggle-slider"></span> Flash intégré Canon (décocher = flash Off)</label>
</div>
<h3>Imprimante</h3>
<div class="champ">
<label>Imprimante</label>
<select id="admin-imprimante"><option value="">Detection...</option></select>
<button class="btn-secondaire btn-petit" onclick="rafraichirImprimantes()">Rafraichir</button>
</div>
<div class="champ">
<label>Format papier</label>
<select id="admin-format-papier">
<option value="15x20">15&times;20 cm</option>
<option value="10x15">10&times;15 cm</option>
<option value="10x15-2up">10&times;15 cm &mdash; 2 strips</option>
</select>
</div>
<div class="champ">
<label>Orientation photo</label>
<div class="radio-group">
<label><input type="radio" name="admin-orientation" value="portrait"> Portrait</label>
<label><input type="radio" name="admin-orientation" value="paysage"> Paysage</label>
</div>
</div>
<div class="champ">
<label>Nombre max d'exemplaires</label>
<input type="number" id="admin-copies-max" min="1" max="20" value="5">
</div>
<button class="btn-action" onclick="sauvegarderMateriel()">Sauvegarder</button>
<div class="champ" style="margin-top:1rem;display:flex;gap:0.8rem;flex-wrap:wrap">
<button class="btn-danger" onclick="evacuerBourrage()">&#9888; Annuler jobs</button>
<button class="btn-secondaire" onclick="resetUsb()">&#8635; Réinit. USB</button>
<button class="btn-secondaire" onclick="couperPapier()">&#9988; Couper papier</button>
</div>
<div id="imprimante-statut-detail" class="champ" style="display:none">
<div id="imprimante-erreur-msg" style="background:rgba(244,67,54,0.1);border-radius:8px;padding:0.8rem;color:#f44336;font-size:0.85rem;margin-top:0.5rem"></div>
</div>
</div>
<!-- Panneau Compteur -->
<div class="admin-panneau" id="panneau-compteur-admin">
<h3>Compteur de photos</h3>
<div class="champ">
<label class="toggle"><input type="checkbox" id="tog-compteur-actif"><span class="toggle-slider"></span> Compteur actif</label>
</div>
<div class="compteur-display">
<div class="compteur-gros">
<span id="admin-compteur-restant" class="compteur-nombre">400</span>
<span class="compteur-sep">/</span>
<span id="admin-compteur-limite-display" class="compteur-nombre petit">400</span>
</div>
<span class="compteur-label">photos restantes</span>
</div>
<div class="champ">
<label>Limite totale</label>
<input type="number" id="admin-compteur-limite" min="1" max="9999" value="400">
</div>
<div class="champ-row">
<button class="btn-action" onclick="sauvegarderCompteur()">Sauvegarder</button>
<button class="btn-danger" onclick="resetCompteur()">Remettre a zero</button>
</div>
</div>
<!-- Panneau Destinations -->
<div class="admin-panneau" id="panneau-destinations-admin">
<h3>Ou sauvegarder les photos ?</h3>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-dest-memoire" checked><span class="toggle-slider"></span> Memoire interne</label>
<label class="toggle"><input type="checkbox" id="tog-dest-usb"><span class="toggle-slider"></span> Cle USB</label>
</div>
<div id="dest-usb-details" class="sous-config cache">
<div class="champ">
<label>Chemin USB</label>
<div class="champ-row">
<select id="admin-chemin-usb"><option value="/media/usb">/media/usb</option></select>
<button class="btn-secondaire btn-petit" onclick="detecterUSB()">Detecter</button>
</div>
</div>
</div>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-dest-ftp"><span class="toggle-slider"></span> Serveur FTP</label>
</div>
<div id="dest-ftp-details" class="sous-config cache">
<div class="champ"><label>Hote FTP</label><input type="text" id="admin-ftp-host" placeholder="ftp.exemple.com"></div>
<div class="champ"><label>Port</label><input type="number" id="admin-ftp-port" value="21"></div>
<div class="champ"><label>Utilisateur</label><input type="text" id="admin-ftp-user"></div>
<div class="champ"><label>Mot de passe</label><input type="password" id="admin-ftp-pass"></div>
<div class="champ"><label>Chemin distant</label><input type="text" id="admin-ftp-chemin" value="/photobooth"></div>
</div>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-dest-web"><span class="toggle-slider"></span> Site internet</label>
</div>
<div id="dest-web-details" class="sous-config cache">
<div class="champ"><label>URL d'upload</label><input type="text" id="admin-web-url" placeholder="https://..."></div>
</div>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-dest-email-auto"><span class="toggle-slider"></span> Email automatique</label>
</div>
<h3>Quelles photos sauvegarder ?</h3>
<div class="radio-groupe">
<label class="radio"><input type="radio" name="sauv-mode" id="sauv-tout" value="tout" checked><span class="radio-mark"></span> Toutes les photos</label>
<label class="radio"><input type="radio" name="sauv-mode" id="sauv-imprimees" value="imprimees"><span class="radio-mark"></span> Uniquement les photos imprimees</label>
</div>
<button class="btn-action" onclick="sauvegarderDestinations()">Sauvegarder</button>
</div>
<!-- Panneau Personnalisation (Cadres + Fonds + Animations) -->
<div class="admin-panneau" id="panneau-personnalisation">
<h3>Cadres d'impression</h3>
<p class="aide">Selectionnez un cadre PNG par format. Le cadre est applique sur chaque impression. Laissez vide pour imprimer sans cadre.</p>
<div class="cadres-formats">
<div class="cadres-format-bloc" id="cadres-bloc-strip">
<h4>Strip (5&times;15 cm)</h4>
<div class="cadres-liste" id="cadres-liste-strip"></div>
<div class="champ cadres-upload">
<input type="file" id="input-cadre-strip" accept=".png" class="input-fichier">
<button class="btn-secondaire btn-petit" onclick="uploaderCadreFormat('strip')">Importer</button>
</div>
</div>
<div class="cadres-format-bloc" id="cadres-bloc-10x15">
<h4>10&times;15 cm</h4>
<div class="cadres-liste" id="cadres-liste-10x15"></div>
<div class="champ cadres-upload">
<input type="file" id="input-cadre-10x15" accept=".png" class="input-fichier">
<button class="btn-secondaire btn-petit" onclick="uploaderCadreFormat('10x15')">Importer</button>
</div>
</div>
<div class="cadres-format-bloc" id="cadres-bloc-15x20">
<h4>15&times;20 cm</h4>
<div class="cadres-liste" id="cadres-liste-15x20"></div>
<div class="champ cadres-upload">
<input type="file" id="input-cadre-15x20" accept=".png" class="input-fichier">
<button class="btn-secondaire btn-petit" onclick="uploaderCadreFormat('15x20')">Importer</button>
</div>
</div>
</div>
<h3>Cadres / Overlays photo</h3>
<p class="aide">Cochez les cadres a proposer aux utilisateurs en live.</p>
<div id="liste-cadres" class="liste-cadres">
<p class="texte-secondaire">Aucun cadre importe</p>
</div>
<div class="champ">
<input type="file" id="input-cadre" accept=".png" class="input-fichier">
<button class="btn-action" onclick="uploaderCadre()">Importer un cadre</button>
</div>
<h3>Fonds (chroma key)</h3>
<p class="aide">Importez des images de fond pour le mode fond vert.</p>
<div id="liste-fonds" class="liste-fonds">
<p class="texte-secondaire">Aucun fond importe</p>
</div>
<div class="champ">
<input type="file" id="input-fond" accept=".jpg,.jpeg,.png" class="input-fichier">
<button class="btn-action" onclick="uploaderFond()">Importer un fond</button>
</div>
<h3>Animations 3-2-1</h3>
<p class="aide">Si plusieurs sont cochees, une sera choisie au hasard.</p>
<div id="liste-animations" class="liste-animations">
</div>
<h4>Animations personnalisees (video/GIF)</h4>
<div id="liste-animations-custom" class="liste-animations">
</div>
<div class="champ">
<input type="file" id="input-animation" accept=".gif,.mp4,.webm" class="input-fichier">
<button class="btn-action" onclick="uploaderAnimation()">Importer</button>
</div>
<div class="animation-preview">
<h4>Apercu</h4>
<div id="preview-animation" class="preview-animation-box">
<span id="preview-anim-chiffre" class="anim-chiffre">3</span>
<video id="preview-anim-video" class="preview-anim-video cache" muted playsinline></video>
</div>
<button class="btn-secondaire" onclick="testerAnimationPreview()">Tester</button>
</div>
</div>
<!-- Panneau Evenement -->
<div class="admin-panneau" id="panneau-evenement">
<div class="champ">
<label>Theme visuel</label>
<select id="admin-theme" onchange="changerTheme(this.value)">
<option value="base">Base (Sombre moderne)</option>
<option value="sikapics">SikaPics (Rose elegant)</option>
</select>
</div>
<div class="champ">
<label>Nom de l'evenement</label>
<input type="text" id="admin-nom-event" placeholder="Mon Evenement">
</div>
<div class="champ">
<label>Video/GIF d'accueil (boucle)</label>
<div class="champ-row">
<select id="admin-media-accueil">
<option value="">Aucun (animation par defaut)</option>
</select>
<button class="btn-secondaire btn-petit" onclick="rafraichirMediaAccueil()">Rafraichir</button>
</div>
<input type="file" id="input-media-accueil" accept=".gif,.mp4,.webm" class="input-fichier">
<button class="btn-secondaire btn-petit" onclick="uploaderMediaAccueil()">Importer</button>
</div>
<div class="champ">
<label>Couleur primaire</label>
<input type="color" id="admin-couleur-primaire" value="#e91e63">
</div>
<div class="champ">
<label>Couleur secondaire</label>
<input type="color" id="admin-couleur-secondaire" value="#ffffff">
</div>
<button class="btn-action" onclick="sauvegarderEvenement()">Sauvegarder</button>
</div>
<!-- Panneau Fonctions (toggles + email + booth + galerie + systeme) -->
<div class="admin-panneau" id="panneau-fonctions">
<h3>Modes photo</h3>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-photo-simple" checked><span class="toggle-slider"></span> Photo simple</label>
<label class="toggle"><input type="checkbox" id="tog-multi-shot"><span class="toggle-slider"></span> Pellicule (multi-shot)</label>
<label class="toggle"><input type="checkbox" id="tog-filtres"><span class="toggle-slider"></span> Filtres</label>
<label class="toggle"><input type="checkbox" id="tog-overlays"><span class="toggle-slider"></span> Overlays / Cadres</label>
<label class="toggle"><input type="checkbox" id="tog-chroma-key"><span class="toggle-slider"></span> Chroma key (fond vert)</label>
</div>
<h3>Partage</h3>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-impression"><span class="toggle-slider"></span> Impression</label>
<label class="toggle"><input type="checkbox" id="tog-email"><span class="toggle-slider"></span> Email</label>
<label class="toggle"><input type="checkbox" id="tog-qr-code"><span class="toggle-slider"></span> QR Code</label>
<label class="toggle"><input type="checkbox" id="tog-galerie"><span class="toggle-slider"></span> Galerie locale</label>
</div>
<h3>Email SMTP</h3>
<div class="champ"><label>Serveur SMTP</label><input type="text" id="admin-smtp-host" placeholder="smtp.gmail.com"></div>
<div class="champ"><label>Port</label><input type="number" id="admin-smtp-port" value="587"></div>
<div class="champ"><label>Utilisateur</label><input type="text" id="admin-smtp-user" placeholder="user@gmail.com"></div>
<div class="champ"><label>Mot de passe</label><input type="password" id="admin-smtp-pass"></div>
<div class="champ"><label>Expediteur</label><input type="text" id="admin-expediteur" placeholder="photobooth@event.com"></div>
<button class="btn-action" onclick="sauvegarderEmail()">Sauvegarder email</button>
<h3>Galerie Live</h3>
<p class="aide">Photos envoyees en temps reel. QR code + code sur l'ecran d'accueil.</p>
<div class="champ">
<label class="toggle"><input type="checkbox" id="admin-booth-actif" onchange="sauvegarderBooth()"><span class="toggle-slider"></span> Galerie live active</label>
</div>
<div class="champ"><label>URL du serveur</label><input type="text" id="admin-booth-url" placeholder="https://booth.copydev.fr" value="https://booth.copydev.fr"></div>
<div class="champ"><label>Cle API</label><input type="text" id="admin-booth-apikey" placeholder="booth-photobooth-2026" value="booth-photobooth-2026"></div>
<div class="champ"><label>ID evenement</label><input type="text" id="admin-booth-eventid" placeholder="default" value="default"></div>
<div class="champ">
<label>Code invites : <span id="admin-booth-password" style="font-size:1.5rem;font-weight:bold;letter-spacing:4px">--</span></label>
</div>
<button class="btn-action" onclick="sauvegarderBooth()">Sauvegarder booth</button>
<button class="btn-secondaire" onclick="regenererBoothPassword()">Nouveau code</button>
<h3>Galerie locale</h3>
<div class="champ">
<label>Photos prises : <span id="admin-nb-photos">0</span> | Exports : <span id="admin-nb-exports">0</span></label>
</div>
<div class="champ">
<label>URL galerie en ligne</label>
<input type="text" id="admin-url-galerie" placeholder="https://...">
</div>
<button class="btn-action" onclick="sauvegarderGalerie()">Sauvegarder URL</button>
<button class="btn-danger" onclick="confirmerViderGalerie()">Vider toute la galerie</button>
<h3>Systeme</h3>
<button class="btn-action" onclick="location.reload()">Mettre a jour l'affichage</button>
<button class="btn-secondaire" onclick="quitterNavigateur()">Quitter le navigateur</button>
<button class="btn-danger" onclick="confirmerRedemarrage()">Redemarrer le systeme</button>
<button class="btn-danger" onclick="confirmerExtinction()">Eteindre le systeme</button>
</div>
<!-- Panneau Infos systeme -->
<div class="admin-panneau" id="panneau-infos">
<div class="infos-systeme-header">
<h3>Informations systeme</h3>
<button class="btn-action btn-petit" onclick="chargerInfosSysteme()">&#8635; Actualiser</button>
</div>
<div id="infos-systeme-contenu" class="infos-systeme-contenu">
<p class="infos-chargement">Chargement...</p>
</div>
<div class="infos-systeme-header" style="margin-top:1.5rem">
<h3>Diagnostic camera</h3>
<button class="btn-action btn-petit" onclick="chargerDiagCamera()">&#8635; Tester</button>
</div>
<div id="diag-camera-contenu" style="font-family:monospace;font-size:0.75rem;background:#111;color:#0f0;padding:0.75rem;border-radius:6px;white-space:pre-wrap;max-height:300px;overflow-y:auto">
Appuyer sur Tester...
</div>
</div>
</div>
</section>
<!-- Popup sélection cadre impression -->
<div id="popup-cadre-impression" class="popup-overlay cache">
<div class="popup-box popup-box-cadre">
<h3>Cadre d'impression</h3>
<div id="grille-cadres-impression" class="grille-cadres-choix grille-cadres-popup"></div>
<div class="popup-actions">
<button class="btn-action" onclick="confirmerCadreImpression()">Confirmer</button>
<button class="btn-secondaire" onclick="annulerCadreImpression()">Annuler</button>
</div>
</div>
</div>
<!-- Popup PIN photostation -->
<div id="popup-pin-photostation" class="popup-overlay cache">
<div class="popup-box popup-box-pave">
<h3>Station d'impression</h3>
<p class="aide">Entrez le code PIN</p>
<div id="pin-photostation-affichage" class="mdp-affichage" style="font-size:2rem;letter-spacing:0.5rem;margin:1rem 0">&#9675;&#9675;&#9675;&#9675;</div>
<div id="pin-photostation-erreur" class="mdp-erreur cache">Code incorrect</div>
<div class="pave-numerique">
<button class="pave-touche" onclick="pinPhotostationTouche('1')">1</button>
<button class="pave-touche" onclick="pinPhotostationTouche('2')">2</button>
<button class="pave-touche" onclick="pinPhotostationTouche('3')">3</button>
<button class="pave-touche" onclick="pinPhotostationTouche('4')">4</button>
<button class="pave-touche" onclick="pinPhotostationTouche('5')">5</button>
<button class="pave-touche" onclick="pinPhotostationTouche('6')">6</button>
<button class="pave-touche" onclick="pinPhotostationTouche('7')">7</button>
<button class="pave-touche" onclick="pinPhotostationTouche('8')">8</button>
<button class="pave-touche" onclick="pinPhotostationTouche('9')">9</button>
<button class="pave-touche" onclick="pinPhotostationEffacer()">&#8592;</button>
<button class="pave-touche" onclick="pinPhotostationTouche('0')">0</button>
<button class="pave-touche" onclick="fermerPopupPhotostation()">&#10005;</button>
</div>
</div>
</div>
<!-- Popup mot de passe admin -->
<div id="popup-mdp" class="popup-overlay cache">
<div class="popup-box popup-box-pave">
<h3>Acces administration</h3>
<input type="password" id="input-mdp-admin" placeholder="&#9679;&#9679;&#9679;&#9679;" inputmode="none" autocomplete="off" readonly>
<div class="pave-numerique">
<button class="pave-touche" onclick="paveTouche('1')">1</button>
<button class="pave-touche" onclick="paveTouche('2')">2</button>
<button class="pave-touche" onclick="paveTouche('3')">3</button>
<button class="pave-touche" onclick="paveTouche('4')">4</button>
<button class="pave-touche" onclick="paveTouche('5')">5</button>
<button class="pave-touche" onclick="paveTouche('6')">6</button>
<button class="pave-touche" onclick="paveTouche('7')">7</button>
<button class="pave-touche" onclick="paveTouche('8')">8</button>
<button class="pave-touche" onclick="paveTouche('9')">9</button>
<button class="pave-touche pave-effacer" onclick="paveEffacer()">&#9003;</button>
<button class="pave-touche" onclick="paveTouche('0')">0</button>
<button class="pave-touche pave-valider" onclick="validerMdpAdmin()">&#10003;</button>
</div>
<p id="mdp-erreur" class="mdp-erreur cache">Mot de passe incorrect</p>
<button class="btn-secondaire" onclick="fermerPopupMdp()">Annuler</button>
</div>
</div>
</div>
<script src="/js/websocket.js?v=3"></script>
<script src="/js/app.js?v=4"></script>
<script src="/js/camera.js?v=10"></script>
<script src="/js/effects.js?v=3"></script>
<script src="/js/gallery.js?v=3"></script>
<script src="/js/share.js?v=5"></script>
<script src="/js/admin.js?v=4"></script>
</body>
</html>