Warrior Paintball Antibes dispose de 2 hectares repartis sur 6 terrains de jeux entre 2 000 et 5 000m², parmi lesquels vous pourrez choisir en fonction des différents scénarios proposés par nos équipes d’animateurs
Surface idéale
Des terrains plats, parfaits pour courir et franchir les obstacles.
Sécurité Optimale
Filets de protection contre les billes de Paintball à 5 mètres hauteur.
Équité des joueurs
Les terrains sont spécialement conçus pour une parité parfaite entre chaque équipe.
Espace de détente
Un espace dédié avec rafraichissements pour garantir aux spectateurs une journée parfaite. Vous pourrez circuler autour des terrains pour un meilleur spectacle.
Pompeï
Ce terrain plus vaste offre une expérience de jeu avec davantage de joueurs. Les tactiques d’avancée rapide et les combats à distance encouragent différents styles de jeu : certains préféreront camper, tandis que d’autres opteront pour un style plus agressif en rushant. À vous de choisir votre approche !
Les missions
Match à mort par équipes
Le match à mort par équipe, également appelé "Team Deathmatch" est un jeu où deux équipes s'affrontent pour éliminer les joueurs adverses. C'est un scénario intense qui teste les compétences tactiques, la communication et la précision des participants. Le gagnant est déterminé par l'équipe ayant éliminé le plus grand nombre de joueurs adverses.
Highlander
Le mode de jeu Highlander est un scénario où les joueurs s'affrontent en match à mort par équipe jusqu'à ce qu'il ne reste plus que quelques joueurs qui s'affrontent ensuite individuellement, sans équipe. Chaque joueur est responsable de sa propre survie et de l'élimination des autres joueurs en mêlée générale.
VIP
L'objectif consiste à déplacer son V.I.P. d'un point A à un point B du terrain sans que ce dernier soit éliminé par l'équipe adverse. Il peut être équipé d'u marqueur ou non selon les variantes.
Sumatra
Plongez dans l’action de la capture du drapeau sur notre terrain de paintball dynamique. Affrontez-vous en face-à-face avec pour objectif d’être l’équipe la plus rapide à récupérer le drapeau et le ramener sans être touché jusqu’à votre base pour remporter la mission. Révélez votre agilité, votre vitesse et votre esprit d’équipe dans cette quête palpitante. Relevez le défi dès maintenant et vivez une expérience de paintball inoubliable sur notre terrain captivant.
Les missions
Match à mort par équipes
Le match à mort par équipe, également appelé "Team Deathmatch" est un jeu où deux équipes s'affrontent pour éliminer les joueurs adverses. C'est un scénario intense qui teste les compétences tactiques, la communication et la précision des participants. Le gagnant est déterminé par l'équipe ayant éliminé le plus grand nombre de joueurs adverses.
Highlander
Le mode de jeu Highlander est un scénario où les joueurs s'affrontent en match à mort par équipe jusqu'à ce qu'il ne reste plus que quelques joueurs qui s'affrontent ensuite individuellement, sans équipe. Chaque joueur est responsable de sa propre survie et de l'élimination des autres joueurs en mêlée générale.
Drapeau
Le mode de jeu Capture du Drapeau dans le paintball implique deux équipes adverses qui tentent de s'emparer d’un drapeau central et de le ramener à leur propre base sans se faire toucher. C'est un scénario stratégique et compétitif où la coordination d'équipe est essentielle. Plongez dans l'action de la Capture du Drapeau lors de vos parties de paintball et testez vos compétences tactiques et votre esprit d'équipe.
Ghost Town
Explorez notre terrain de paintball unique qui simule une ville de camping abandonnée avec ses bâtiments. Parfait pour le scénario de capture du drapeau, vous devrez rivaliser avec l’autre équipe tout en restant vigilant. Assurez-vous de regarder par-dessus votre épaule pour éviter les surprises. Plongez dans cette expérience immersive et stratégique où l’action et l’adrénaline sont garanties sur ce terrain captivant.
Les missions
Match à mort par équipes
Le match à mort par équipe, également appelé "Team Deathmatch" est un jeu où deux équipes s'affrontent pour éliminer les joueurs adverses. C'est un scénario intense qui teste les compétences tactiques, la communication et la précision des participants. Le gagnant est déterminé par l'équipe ayant éliminé le plus grand nombre de joueurs adverses.
Highlander
Le mode de jeu Highlander est un scénario où les joueurs s'affrontent en match à mort par équipe jusqu'à ce qu'il ne reste plus que quelques joueurs qui s'affrontent ensuite individuellement, sans équipe. Chaque joueur est responsable de sa propre survie et de l'élimination des autres joueurs en mêlée générale.
Drapeau
Le mode de jeu Capture du Drapeau dans le paintball implique deux équipes adverses qui tentent de s'emparer d’un drapeau central et de le ramener à leur propre base sans se faire toucher. C'est un scénario stratégique et compétitif où la coordination d'équipe est essentielle. Plongez dans l'action de la Capture du Drapeau lors de vos parties de paintball et testez vos compétences tactiques et votre esprit d'équipe.
Speed Palette
Découvrez le terrain Speed Palettes, inspiré du speed ball de compétition. Ce terrain parfaitement symétrique offre une expérience équilibrée, idéale pour des parties éliminatoires en paintball. La communication entre les joueurs est favorisée, permettant des stratégies coordonnées. Profitez de cette configuration optimale pour des sessions de paintball type compétition.
Les missions
Match à mort par équipes
Le match à mort par équipe, également appelé "Team Deathmatch" est un jeu où deux équipes s'affrontent pour éliminer les joueurs adverses. C'est un scénario intense qui teste les compétences tactiques, la communication et la précision des participants. Le gagnant est déterminé par l'équipe ayant éliminé le plus grand nombre de joueurs adverses.
Highlander
Le mode de jeu Highlander est un scénario où les joueurs s'affrontent en match à mort par équipe jusqu'à ce qu'il ne reste plus que quelques joueurs qui s'affrontent ensuite individuellement, sans équipe. Chaque joueur est responsable de sa propre survie et de l'élimination des autres joueurs en mêlée générale.
Éliminatoire
Le mode de jeu Éliminatoire dans le paintball consiste à éliminer tous les joueurs de l'équipe adverse pour remporter la partie. C'est un scénario compétitif où la précision, la stratégie et l'esprit d'équipe sont essentiels. Plongez dans des affrontements intenses et testez vos compétences de tir et votre réactivité. Jouez au mode Éliminatoire pour vivre une expérience de paintball palpitante et laissez votre marque sur le terrain.
Chernobyl
Ce terrain légèrement plus grand vous permet un jeu à plus de joueurs. Des tactiques d’avancée plus rapide et un combat plus distant inciteront certains participants à camper et d’autre à rusher. Quel sera votre style ?
Les missions
Match à mort par équipes
Le match à mort par équipe, également appelé "Team Deathmatch" est un jeu où deux équipes s'affrontent pour éliminer les joueurs adverses. Le gagnant est déterminé par l'équipe ayant éliminé le plus grand nombre de joueurs adverses.
Highlander
Le mode de jeu Highlander est un scénario où les joueurs s'affrontent en match à mort par équipe jusqu'à ce qu'il ne reste plus que quelques joueurs qui s'affrontent ensuite individuellement, sans équipe.
Médecin
Le mode de jeu Médecin consiste à désigner un joueur chargé de soigner les coéquipiers touchés. Il offre une dynamique de jeu stratégique axée sur la survie et l'entraide. Expérimentez ce mode de jeu palpitant qui met en avant la coopération d'équipe dans des parties de paintball immersives.
Drapeau
Le mode de jeu Capture du Drapeau implique deux équipes adverses qui tentent de s'emparer d’un drapeau central et de le ramener à leur propre base sans se faire toucher. C'est un scénario stratégique et compétitif où la coordination d'équipe est essentielle.
The Castle
Découvrez notre nouveau terrain, THE CASTLE, , idéal pour une expérience de paintball immersive. Les attaquants et les défenseurs s’affrontent, offrant une dynamique de jeu captivante. Avec des positions en hauteur pour les défenseurs et au sol pour les attaquants. Seuls les stratèges les plus habiles triompheront. Dominez ce terrain stratégique lors de vos parties de paintball en attaque défense. .
Les missions
Match à mort par équipes
Le match à mort par équipe, également appelé "Team Deathmatch" est un jeu où deux équipes s'affrontent pour éliminer les joueurs adverses. Le gagnant est déterminé par l'équipe ayant éliminé le plus grand nombre de joueurs adverses.
Highlander
Le mode de jeu Highlander est un scénario où les joueurs s'affrontent en match à mort par équipe jusqu'à ce qu'il ne reste plus que quelques joueurs qui s'affrontent ensuite individuellement, sans équipe.
Drapeau
Le mode de jeu Capture du Drapeau implique deux équipes adverses qui tentent de s'emparer d’un drapeau central et de le ramener à leur propre base sans se faire toucher. C'est un scénario stratégique et compétitif où la coordination d'équipe est essentielle.
Mêlée Générale
Le mode de jeu Mêlée Générale met tous les joueurs en confrontation directe, sans équipes. C'est un scénario chaotique et intense où chaque joueur se bat individuellement pour survivre et éliminer les autres.
Gérer le consentement aux cookies
Pour offrir les meilleures expériences, nous utilisons des technologies telles que les cookies pour stocker et/ou accéder aux informations des appareils. Le fait de consentir à ces technologies nous permettra de traiter des données telles que le comportement de navigation ou les ID uniques sur ce site. Le fait de ne pas consentir ou de retirer son consentement peut avoir un effet négatif sur certaines caractéristiques et fonctions.
Fonctionnel
Toujours activé
Le stockage ou l’accès technique est strictement nécessaire dans la finalité d’intérêt légitime de permettre l’utilisation d’un service spécifique explicitement demandé par l’abonné ou l’utilisateur, ou dans le seul but d’effectuer la transmission d’une communication sur un réseau de communications électroniques.
Préférences
Le stockage ou l’accès technique est nécessaire dans la finalité d’intérêt légitime de stocker des préférences qui ne sont pas demandées par l’abonné ou l’utilisateur.
Statistiques
Le stockage ou l’accès technique qui est utilisé exclusivement à des fins statistiques.Le stockage ou l’accès technique qui est utilisé exclusivement dans des finalités statistiques anonymes. En l’absence d’une assignation à comparaître, d’une conformité volontaire de la part de votre fournisseur d’accès à internet ou d’enregistrements supplémentaires provenant d’une tierce partie, les informations stockées ou extraites à cette seule fin ne peuvent généralement pas être utilisées pour vous identifier.
Marketing
Le stockage ou l’accès technique est nécessaire pour créer des profils d’utilisateurs afin d’envoyer des publicités, ou pour suivre l’utilisateur sur un site web ou sur plusieurs sites web ayant des finalités marketing similaires.
En soumettant ce formulaire vous acceptez que WarriorPaintBall Antibes, en sa qualité de responsable de traitement, collecte vos données afin de pouvoir répondre à votre message. Pour connaitre et exercer vos droits , notamment de retrait de votre consentement à l’utilisation de données collectées par ce formulaire, veuillez consulter notre politique de confidentialité
Vous avez désormais la possibilité de vos restaurez sur place. Si toutefois vous êtes un groupe nous vous recommandons de nous le mentionner dans la réservation afin de faciliter la préparation pour le jour J. Il est toujours possible de ramener votre propre picnic.
Les packs avec gâteaux incluent bonbons et boissons. Nous nous occuperons des assiettes, couverts et serviettes que si nous gérons le gâteau et des gobelets que si nous gérons les boissons. Vous pouvez emporter des éléments supplémentaires ou de la décoration sans aucun problème.
Nous vous conseillons de rajouter des options pour rendre l’activité encore plus immersive. Les fumigènes sont exceptionnels pour les parties comme la capture du drapeau ou la prise de position.
Pour les groupes de + de 10 personnes ou + de 20 personnes vous bénéficiez de billes offertes ou de réductions. D’avril à Octobre découvrez le pack combo Paintball et Ninja Warrior Antibes.
Nous sélectionnons toujours le type de lanceur en fonction de l’âge du plus jeune joueur du groupe.
Vous souhaitez jouer au paintball ou organiser un événement particulier ? Sélectionnez un évènement …
Surprenez vos proches avec une séance de paintball, chargée d’adrénaline et de stratégie ! Idéal pour les anniversaires, les occasions spéciales ou juste pour le plaisir.
Félicitations ! Votre bon cadeau a été créé avec succès. Nous avons envoyé une copie du bon à votre adresse email ainsi qu’à celle du bénéficiaire. Le bon peut être utilisé selon les préférences du destinataire.
Nous sommes impatients d’accueillir le bénéficiaire et restons à votre disposition pour toute question ou information complémentaire. N’hésitez pas à nous contacter.
Le Gotcha est le plus simple et le plus adapté aux jeunes joueurs de paintball. Plus lent à utiliser car il doit être manuellement recharger il s’apparente à un fusil à pompe et sûr pour les enfants de 7 ans et plus.
Ergonomie
Puissance
Cadence
Précision
De 10 à 17 ans
Ce lanceur semi-automatique de calibre .50 est une excellente option pour les débutants et les adolescents. Son mécanisme permet une fluidité de tir et une stabilité sans pareil. Léger et équilibré, le Précision est l’allié des joueurs recherchant la perfection sur le terrain.
Ergonomie
Puissance
Cadence
BT4 Combat
À partir de 15 ans
Le Lanceur Combat est le compagnon idéal pour les amateurs d’action qui cherchent un équipement fiable et puissant. Le BT4 est le tank du paintball, conçu pour ceux qui aiment être en première ligne. Robuste et fiable, il peut résister aux conditions les plus difficiles
Ergonomie
Puissance
Cadence
Emek
À partir de 16 ans
L’Emek est une combinaison parfaite adaptée à tous les styles de jeu grâce à son système de tir pneumatique offrant une précision et une cadence de tir incroyablement efficaces et extrêmement fiables.
Angie SAS RCS Antibes 883 659 518 N° de TVA Intracommunautaire FR91883659518
Réservation Enregistrée
Votre réservation est enregistrée, vous allez recevoir dans votre email la confirmation de votre réservation et un rappel du rendez-vous avec les détails de votre réservation.
Nous sommes ravis de vous accueillir ! Si vous avez la moindre question ou besoin de plus d’infos, n’hésitez surtout pas à nous contacter.
Le Gotcha est le plus simple et le plus adapté aux jeunes joueurs de paintball. Plus lent à utiliser car il doit être manuellement recharger il s’apparente à un fusil à pompe et sûr pour les enfants de 7 ans et plus.
Ergonomie
Puissance
Cadence
Description
Précision
De 10 à 17 ans
Ce lanceur semi-automatique de calibre .50 est une excellente option pour les débutants et les adolescents. Son mécanisme permet une fluidité de tir et une stabilité sans pareil. Léger et équilibré, le Précision est l’allié des joueurs recherchant la perfection sur le terrain.
Ergonomie
Puissance
Cadence
Équipement
Lanceur
INCLUS
Billes
INCLUS
Masque
INCLUS
Plastron
INCLUS
Combinaison
INCLUS
Gants
OPTION
Protège cou
OPTION
Fumigène
OPTION
Nourriture et boissons
OPTION
Espace de réception
À DISPOSITION
Temps et terrains
Description
BT4 Combat
À partir de 15 ans
Le Lanceur Combat est le compagnon idéal pour les amateurs d’action qui cherchent un équipement fiable et puissant. Le BT4 est le tank du paintball, conçu pour ceux qui aiment être en première ligne. Robuste et fiable, il peut résister aux conditions les plus difficiles
Ergonomie
Puissance
Cadence
Équipement
Lanceur
INCLUS
Billes
INCLUS
Masque
INCLUS
Plastron
INCLUS
Combinaison
INCLUS
Gants
OPTION
Protège cou
OPTION
Fumigène
OPTION
Nourriture et boissons
OPTION
Espace de réception
À DISPOSITION
Temps et terrainns
Description
Emek
À partir de 16 ans
L’Emek est une combinaison parfaite adaptée à tous les styles de jeu grâce à son système de tir pneumatique offrant une précision et une cadence de tir incroyablement efficaces et extrêmement fiables.
Ergonomie
Puissance
Cadence
Équipement
Lanceur
INCLUS
Billes
INCLUS
Masque
INCLUS
Plastron
INCLUS
Combinaison
INCLUS
Gants
OPTION
Protège cou
OPTION
Fumigène
OPTION
Nourriture et boissons
OPTION
Espace de réception
À DISPOSITION
Temps et terrains
// ====================================================
// PIOTNET STRIPE - GESTION UX PAIEMENT - v3.2.0
// Fix : réutilisation transaction_id si paiement non abouti
// Fix : détection bloqueur popup + statut ABANDONED
// ====================================================
document.addEventListener('DOMContentLoaded', function () {
console.log('[PIOTNET-STRIPE] Initialisation v3.2.0');
(function () {
'use strict';
/* ============================
* CONFIGURATION
* ============================ */
const THEME_CONFIG = {
buttonColor: '#C97064',
overlayOpacity: 0.8
};
const CONFIG = {
ERROR_CHECK_INTERVAL: 500,
MAX_WAIT_TIME: 45000,
// Délai adaptatif mobile/desktop
LOADING_DELAY: /Mobi|Android/i.test(navigator.userAgent) ? 800 : 350,
DEBUG_MODE: true,
SERVER_LOGGING: true,
LOG_ENDPOINT: '/wp-admin/admin-ajax.php?action=stripe_payment_log',
// ✅ v3.2.0 : Clé sessionStorage pour persister l'ID de transaction
SESSION_TXN_KEY: 'stripe_pending_txn_id',
SESSION_TXN_EMAIL_KEY: 'stripe_pending_txn_email'
};
window.PIOTNET_CONFIG = CONFIG;
/* ============================
* ÉTAT GLOBAL
* ============================ */
let errorCheckInterval = null;
let timeoutTimer = null;
let isMonitoring = false;
let isProcessingPayment = false;
let currentTransactionId = null;
function debugLog(msg, data = null) {
if (CONFIG.DEBUG_MODE) console.log('[PAYMENT-UX]', msg, data ?? '');
}
/* ============================
* GESTION DU TRANSACTION ID ← NOUVEAU v3.2.0
*
* Principe : si un paiement a été tenté (clic) mais n'a jamais abouti
* (pas de succès, pas d'erreur confirmée), on RÉUTILISE le même ID
* pour le prochain clic au lieu d'en générer un nouveau.
* Cela regroupe les multiples clics dus au bloqueur de popup en
* une seule transaction dans le dashboard.
* ============================ */
function getOrCreateTransactionId(email) {
const existingId = sessionStorage.getItem(CONFIG.SESSION_TXN_KEY);
const existingEmail = sessionStorage.getItem(CONFIG.SESSION_TXN_EMAIL_KEY);
// Réutiliser si même email et transaction pas encore conclue
if (existingId && existingEmail === email) {
debugLog('♻️ Réutilisation du transaction_id existant (popup bloquée probable):', existingId);
return existingId;
}
// Nouveau ID
const newId = 'txn_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
sessionStorage.setItem(CONFIG.SESSION_TXN_KEY, newId);
sessionStorage.setItem(CONFIG.SESSION_TXN_EMAIL_KEY, email || '');
debugLog('🆔 Nouveau transaction_id généré:', newId);
return newId;
}
function clearTransactionId() {
sessionStorage.removeItem(CONFIG.SESSION_TXN_KEY);
sessionStorage.removeItem(CONFIG.SESSION_TXN_EMAIL_KEY);
debugLog('🗑️ Transaction ID effacé (paiement conclu)');
}
/* ============================
* DÉTECTION DU MODE STRIPE
* ============================ */
function detectPaymentMode() {
if (typeof window.STRIPE_MODE_DETECTED !== 'undefined') {
return window.STRIPE_MODE_DETECTED;
}
const scripts = document.querySelectorAll('script');
for (const script of scripts) {
const c = script.textContent || script.innerHTML;
if (c.includes('pk_test_')) return 'test';
if (c.includes('pk_live_')) return 'live';
}
const stripeEls = document.querySelectorAll('[data-stripe-publishable-key],[data-pafe-stripe-key]');
for (const el of stripeEls) {
const key = el.getAttribute('data-stripe-publishable-key') || el.getAttribute('data-pafe-stripe-key');
if (key?.startsWith('pk_test_')) return 'test';
if (key?.startsWith('pk_live_')) return 'live';
}
return 'live';
}
/* ============================
* EXTRACTION DONNÉES CLIENT
* ============================ */
function extractClientData() {
const data = {};
const emailField = document.querySelector('input[type="email"],input[name*="email"],input[id*="email"]');
if (emailField?.value) data.email = emailField.value;
const nameFields = document.querySelectorAll('input[name*="nom"],input[name*="name"],input[id*="nom"],input[id*="name"]');
let fullName = '';
nameFields.forEach(f => {
if (f.value && !f.type.match(/email|tel|number/)) fullName += (fullName ? ' ' : '') + f.value;
});
if (fullName) data.customerName = fullName.trim();
const phoneField = document.querySelector('input[type="tel"],input[name*="phone"],input[name*="telephone"],input[id*="phone"],input[id*="tel"]');
if (phoneField?.value) data.phone = phoneField.value;
data.userAgent = navigator.userAgent;
data.screenResolution = `${window.screen.width}x${window.screen.height}`;
data.viewportSize = `${window.innerWidth}x${window.innerHeight}`;
const ua = navigator.userAgent.toLowerCase();
data.deviceType = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/i.test(ua) ? 'mobile'
: /tablet|ipad/i.test(ua) ? 'tablet' : 'desktop';
data.referrer = document.referrer || 'direct';
const urlParams = new URLSearchParams(window.location.search);
const utmParams = {};
['utm_source','utm_medium','utm_campaign','utm_term','utm_content'].forEach(p => {
if (urlParams.has(p)) utmParams[p] = urlParams.get(p);
});
if (Object.keys(utmParams).length) data.utmParams = utmParams;
if (!sessionStorage.getItem('stripe_session_id')) {
sessionStorage.setItem('stripe_session_id', 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9));
}
data.sessionId = sessionStorage.getItem('stripe_session_id');
data.timestamp = Date.now();
return data;
}
/* ============================
* DÉTECTION TYPE ERREUR
* ============================ */
function detectErrorType(msg) {
const m = msg.toLowerCase();
if (m.includes('declined') || m.includes('refus')) return 'Carte refusée';
if (m.includes('insufficient') || m.includes('fonds')) return 'Fonds insuffisants';
if (m.includes('expired') || m.includes('expir')) return 'Carte expirée';
if (m.includes('cvc') || m.includes('cvv') || m.includes('security code')) return 'Code CVC incorrect';
if (m.includes('invalid number')|| m.includes('numéro invalide')) return 'Numéro invalide';
if (m.includes('authentication')|| m.includes('3d secure')) return 'Authentification 3DS échouée';
if (m.includes('popup') || m.includes('bloqué') || m.includes('blocked')) return 'Popup bloquée';
if (m.includes('timeout') || m.includes('délai')) return 'Timeout';
if (m.includes('network') || m.includes('réseau') || m.includes('connection')) return 'Erreur réseau';
return 'Autre erreur';
}
/* ============================
* LOGGING SERVEUR
* ============================ */
function serverLog(level, message, context = null, extraData = {}) {
debugLog(`[${level.toUpperCase()}] ${message}`, context);
if (!CONFIG.SERVER_LOGGING) return;
const logData = {
level, message, context,
timestamp: new Date().toISOString(),
url: window.location.href,
userAgent: navigator.userAgent,
transactionId: currentTransactionId,
...extraData
};
fetch(CONFIG.LOG_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
body: JSON.stringify(logData),
keepalive: true
}).catch(err => console.error('[PAYMENT-UX] Erreur logging:', err));
}
/* ============================
* DÉTECTION BLOQUEUR POPUP
* ============================ */
function isPopupBlocked() {
try {
const w = window.open('', '_blank', 'width=1,height=1,left=-9999,top=-9999');
if (!w || w.closed) return true;
w.close();
return false;
} catch (e) {
debugLog('Exception test popup:', e.message);
return true;
}
}
/* ============================
* CSS
* ============================ */
function addStyles() {
if (document.getElementById('piotnet-responsive-styles')) return;
const style = document.createElement('style');
style.id = 'piotnet-responsive-styles';
style.textContent = `
@keyframes fadeInCenter{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}100%{opacity:1;transform:translate(-50%,-50%) scale(1)}}
@keyframes fadeOutCenter{0%{opacity:1;transform:translate(-50%,-50%) scale(1)}100%{opacity:0;transform:translate(-50%,-50%) scale(.9)}}
@keyframes spin{to{transform:rotate(360deg)}}
.piotnet-popup-overlay{position:fixed;inset:0;background:rgba(0,0,0,${THEME_CONFIG.overlayOpacity});z-index:999998;display:flex;align-items:center;justify-content:center;padding:20px;box-sizing:border-box}
.piotnet-popup{background:#fff;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.25);max-width:520px;width:100%;max-height:90vh;overflow:hidden;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);animation:fadeInCenter .25s ease-out}
.piotnet-popup.closing{animation:fadeOutCenter .2s ease-in}
.piotnet-popup-header{padding:22px 26px 14px;border-bottom:1px solid #eee;text-align:center;position:relative}
.piotnet-popup-title{font-family:Arial,sans-serif;font-size:18px;font-weight:bold;color:#222;margin:0;text-transform:uppercase;letter-spacing:.4px}
.piotnet-popup-close{position:absolute;top:12px;right:16px;background:none;border:none;font-size:22px;color:#888;cursor:pointer;padding:6px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:50%}
.piotnet-popup-close:hover{background:#f4f4f4;color:#333}
.piotnet-popup-content{padding:22px 24px 26px;text-align:center}
.piotnet-popup-content p{margin:0 0 16px;font-family:Arial,sans-serif;font-size:15px;color:#555;line-height:1.55}
.piotnet-loading-spinner{width:56px;height:56px;margin:18px auto;position:relative}
.piotnet-loading-spinner::before{content:"";position:absolute;inset:0;border:4px solid #e3e3e3;border-top-color:#3498db;border-radius:50%;animation:spin 1s linear infinite}
.piotnet-loading-spinner::after{content:"";position:absolute;top:8px;left:8px;right:8px;bottom:8px;border:4px solid transparent;border-top-color:#27ae60;border-radius:50%;animation:spin 1.25s linear infinite reverse}
.piotnet-error-details{background:#f8f9fa;border:1px solid #dee2e6;border-radius:10px;padding:14px;margin:18px 0;text-align:left}
.piotnet-error-details h4{margin:0 0 6px;font-size:14px;color:#333}
.piotnet-error-details p{margin:0;font-size:14px;color:#666}
.piotnet-popup-warning{background:#fff8e1;border:1px solid #ffe082;border-radius:10px;padding:14px;margin:18px 0;text-align:left}
.piotnet-popup-warning h4{margin:0 0 6px;font-size:14px;color:#f57c00}
.piotnet-popup-warning p{margin:0;font-size:13px;color:#795548;line-height:1.5}
.piotnet-popup-warning ol{margin:8px 0 0 16px;padding:0;font-size:13px;color:#795548;line-height:1.8}
.piotnet-popup-buttons{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
.piotnet-popup .piotnet-popup-button{background:#fff;border:1px solid ${THEME_CONFIG.buttonColor};color:${THEME_CONFIG.buttonColor};padding:10px 20px;border-radius:10px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s;text-transform:uppercase;text-decoration:none}
.piotnet-popup .piotnet-popup-button.primary:hover{background:${THEME_CONFIG.buttonColor};color:#fff}
.piotnet-hide-native-error{display:none !important}
@media(max-width:600px){
.piotnet-popup{max-width:95%;border-radius:12px}
.piotnet-popup-buttons{flex-direction:column}
.piotnet-popup-button{width:100%}
}
`;
document.head.appendChild(style);
}
/* ============================
* TRADUCTIONS STRIPE
* ============================ */
const STRIPE_TRANSLATIONS = {
'Your card was declined.' : 'Votre carte a été refusée.',
'Your card has insufficient funds.' : 'Fonds insuffisants.',
'Your card has expired.' : 'Votre carte a expiré.',
"Your card's security code is incorrect." : 'Code de sécurité incorrect.',
'An error occurred while processing your card.': 'Une erreur est survenue lors du traitement.',
'Your card number is incorrect.' : 'Numéro de carte incorrect.',
'Your card is not supported.' : "Votre carte n'est pas supportée.",
'Processing error' : 'Erreur de traitement'
};
function translateError(message) {
return STRIPE_TRANSLATIONS[message] || message;
}
/* ============================
* HELPERS
* ============================ */
function findParentForm(el) {
let cur = el;
while (cur && cur !== document.body) {
if (cur.tagName === 'FORM') return cur;
cur = cur.parentElement;
}
return null;
}
function isPaymentButtonEnabled(btn) {
return btn && !btn.disabled && !btn.classList.contains('pafe-form-builder-button-disabled');
}
function areStripeElementsComplete() {
const fields = document.querySelectorAll('.StripeElement');
if (!fields.length) return true;
for (const f of fields) {
if (f.classList.contains('StripeElement--empty') || f.classList.contains('StripeElement--invalid')) return false;
}
return true;
}
function isElementVisible(el) {
if (!el) return false;
const s = window.getComputedStyle(el);
if (s.display === 'none' || s.visibility === 'hidden' || s.opacity === '0') return false;
const r = el.getBoundingClientRect();
return !(r.width === 0 && r.height === 0);
}
// Sélecteur élargi — cible tous les boutons Piotnet/PAFE/Elementor
const PAYMENT_BUTTON_SELECTORS = [
'[data-pafe-form-builder-stripe-submit]',
'.pafe-form-builder-button',
'.elementor-button.pafe-form-builder-button'
].join(',');
function getPaymentButton(el) {
return el.closest(PAYMENT_BUTTON_SELECTORS);
}
function isFormValid(form) {
const required = form.querySelectorAll('[required],[aria-required="true"]');
for (const f of required) {
if (f.closest('.StripeElement')) continue;
const empty = (f.type === 'checkbox' || f.type === 'radio') ? !f.checked : !f.value.trim();
if (empty) {
f.scrollIntoView({ behavior: 'smooth', block: 'center' });
if (f.reportValidity) f.reportValidity(); else f.focus();
return false;
}
}
return true;
}
/* ============================
* GESTION DES POPUPS
* ============================ */
function removeAllPopups() {
document.querySelectorAll('.piotnet-popup-overlay').forEach(o => o.remove());
}
function createLoadingPopup() {
removeAllPopups();
const overlay = document.createElement('div');
overlay.className = 'piotnet-popup-overlay';
overlay.innerHTML = `
Traitement en cours...
Veuillez patienter, nous interrogeons votre banque.