<?php
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\SandboxExtension;
use Twig\Markup;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityNotAllowedTagError;
use Twig\Sandbox\SecurityNotAllowedFilterError;
use Twig\Sandbox\SecurityNotAllowedFunctionError;
use Twig\Source;
use Twig\Template;
use Twig\TemplateWrapper;
/* Parent/LoginParent.html.twig */
class __TwigTemplate_37bb9239606940e257554a0bc0386491 extends Template
{
private Source $source;
/**
* @var array<string, Template>
*/
private array $macros = [];
public function __construct(Environment $env)
{
parent::__construct($env);
$this->source = $this->getSourceContext();
$this->blocks = [
'title' => [$this, 'block_title'],
'stylesheets' => [$this, 'block_stylesheets'],
'Header' => [$this, 'block_Header'],
'Content' => [$this, 'block_Content'],
'Footer' => [$this, 'block_Footer'],
'javascript' => [$this, 'block_javascript'],
];
}
protected function doGetParent(array $context): bool|string|Template|TemplateWrapper
{
// line 1
return "Accueil/layoutAccueil.html.twig";
}
protected function doDisplay(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Parent/LoginParent.html.twig"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "Parent/LoginParent.html.twig"));
$this->parent = $this->load("Accueil/layoutAccueil.html.twig", 1);
yield from $this->parent->unwrap()->yield($context, array_merge($this->blocks, $blocks));
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
}
// line 3
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_title(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
yield "Connexion Parent — 5sur5séjour";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 5
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_stylesheets(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "stylesheets"));
// line 6
yield from $this->yieldParentBlock("stylesheets", $context, $blocks);
yield "
<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css\">
<style>
/* ========================================
5SUR5 PARENT LOGIN - CLEAN TWO-COLUMN
Stripe/Notion Quality · No Slider
======================================== */
:root {
--pl-teal: #41A2AA;
--pl-teal-dark: #359BA3;
--pl-teal-light: rgba(65, 162, 170, 0.06);
--pl-orange: #F09E7A;
--pl-orange-dark: #E8865E;
--pl-text: #1A1A2E;
--pl-text-secondary: #5A6178;
--pl-text-muted: #8E95A9;
--pl-bg: #FFFFFF;
--pl-bg-hero: #F8FAFB;
--pl-border: #E5E9F0;
--pl-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
--pl-radius: 16px;
}
* {
box-sizing: border-box;
}
.pl-page {
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* ========================================
MAIN CONTAINER - TWO COLUMNS
======================================== */
.pl-main {
flex: 1;
display: flex;
min-height: calc(100vh - 160px);
}
/* ========================================
LEFT COLUMN - HERO
======================================== */
.pl-hero {
width: 35%;
background: var(--pl-bg-hero);
padding: 40px;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
}
.pl-hero-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
max-width: 420px;
}
.pl-hero h1 {
font-size: 32px;
font-weight: 700;
color: var(--pl-text);
line-height: 1.25;
margin: 0 0 16px;
letter-spacing: -0.02em;
}
.pl-hero-subtitle {
font-size: 17px;
color: var(--pl-text-secondary);
line-height: 1.6;
margin: 0 0 32px;
}
/* Features List - Premium Style */
.pl-features {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 18px;
}
.pl-feature {
display: flex;
align-items: flex-start;
gap: 14px;
}
.pl-feature-icon {
width: 44px;
height: 44px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.pl-feature-icon svg {
width: 22px;
height: 22px;
color: #fff;
}
.pl-feature-icon.teal { background: var(--pl-teal); }
.pl-feature-icon.orange { background: var(--pl-orange); }
.pl-feature-icon.coral { background: #F56040; }
.pl-feature-icon.brown { background: #c47d5e; }
.pl-feature-text {
padding-top: 2px;
}
.pl-feature-title {
font-size: 14px;
font-weight: 600;
color: var(--pl-text);
margin: 0 0 3px;
}
.pl-feature-desc {
font-size: 13px;
color: var(--pl-text-muted);
margin: 0;
line-height: 1.4;
}
/* Hero image */
.pl-hero-image {
margin-top: auto;
border-radius: 12px;
overflow: hidden;
}
.pl-hero-image img {
width: 100%;
height: auto;
display: block;
border-radius: 12px;
}
/* Hero decorative illustration */
.pl-hero-illustration {
margin-top: auto;
padding-top: 40px;
position: relative;
}
.pl-hero-illustration svg {
width: 100%;
max-width: 320px;
height: auto;
opacity: 0.9;
}
/* Floating badges */
.pl-floating-badges {
position: absolute;
inset: 0;
pointer-events: none;
}
.pl-badge {
position: absolute;
background: #fff;
border-radius: 12px;
padding: 10px 14px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
font-weight: 500;
color: var(--pl-text);
animation: plFloat 3s ease-in-out infinite;
}
.pl-badge-icon {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.pl-badge-icon svg {
width: 18px;
height: 18px;
color: #fff;
}
.pl-badge-icon.teal { background: var(--pl-teal); }
.pl-badge-icon.orange { background: var(--pl-orange); }
.pl-badge-icon.coral { background: #F56040; }
.pl-badge-1 {
top: 20%;
right: -10px;
animation-delay: 0s;
}
.pl-badge-2 {
bottom: 30%;
left: -5px;
animation-delay: 1s;
}
.pl-badge-3 {
bottom: 10%;
right: 10%;
animation-delay: 2s;
}
@keyframes plFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
/* Entry animations */
.pl-hero-content {
animation: plSlideRight 0.6s ease-out;
}
.pl-card {
animation: plSlideUp 0.5s ease-out;
}
@keyframes plSlideRight {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes plSlideUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Feature items staggered animation */
.pl-feature {
opacity: 0;
animation: plFadeIn 0.4s ease forwards;
}
.pl-feature:nth-child(1) { animation-delay: 0.1s; }
.pl-feature:nth-child(2) { animation-delay: 0.2s; }
.pl-feature:nth-child(3) { animation-delay: 0.3s; }
.pl-feature:nth-child(4) { animation-delay: 0.4s; }
/* ========================================
RIGHT COLUMN - FORM
======================================== */
.pl-form-section {
width: 58%;
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
background: var(--pl-bg);
}
.pl-card {
width: 100%;
max-width: 420px;
background: var(--pl-bg);
border-radius: var(--pl-radius);
box-shadow: var(--pl-shadow);
border: 1px solid var(--pl-border);
overflow: hidden;
}
/* Tabs */
.pl-tabs {
display: flex;
border-bottom: 1px solid var(--pl-border);
}
.pl-tab {
flex: 1;
padding: 18px 16px;
font-size: 14px;
font-weight: 600;
color: var(--pl-text-muted);
background: var(--pl-bg-hero);
border: none;
cursor: pointer;
position: relative;
transition: all 0.2s ease;
}
.pl-tab:hover {
color: var(--pl-text-secondary);
}
.pl-tab.active {
color: var(--pl-teal);
background: var(--pl-bg);
}
.pl-tab.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: var(--pl-teal);
}
.pl-tab:focus-visible {
outline: 2px solid var(--pl-teal);
outline-offset: -2px;
}
.pl-btn:focus-visible,
.pl-social-btn:focus-visible {
outline: 2px solid var(--pl-teal);
outline-offset: 2px;
}
/* Tab panels */
.pl-panel {
padding: 28px;
display: none;
}
.pl-panel.active {
display: block;
animation: plFadeIn 0.25s ease;
}
@keyframes plFadeIn {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
/* Form elements */
.pl-form-group {
margin-bottom: 18px;
}
.pl-label {
display: block;
font-size: 13px;
font-weight: 500;
color: var(--pl-text);
margin-bottom: 6px;
}
.pl-input {
width: 100%;
padding: 12px 14px;
font-size: 15px;
font-family: inherit;
color: var(--pl-text);
background: var(--pl-bg);
border: 1px solid var(--pl-border);
border-radius: 8px;
transition: all 0.2s ease;
outline: none;
}
.pl-input::placeholder {
color: var(--pl-text-muted);
}
.pl-input:hover {
border-color: #D0D6E0;
}
.pl-input:focus {
border-color: var(--pl-teal);
box-shadow: 0 0 0 3px var(--pl-teal-light);
}
.pl-input.is-invalid {
border-color: #EF4444;
background: #FEF2F2;
}
.pl-input.is-valid {
border-color: #10B981;
background: rgba(16, 185, 129, 0.04);
}
.pl-hint {
font-size: 12px;
color: var(--pl-text-muted);
margin-top: 5px;
display: flex;
align-items: center;
gap: 4px;
}
/* Password wrapper */
.pl-password-wrap {
position: relative;
}
.pl-password-wrap .pl-input {
padding-right: 44px;
}
.pl-eye-btn {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
padding: 4px;
cursor: pointer;
color: var(--pl-text-muted);
transition: color 0.2s ease;
}
.pl-eye-btn:hover {
color: var(--pl-teal);
}
/* Row for name fields */
.pl-row {
display: flex;
gap: 12px;
}
.pl-row .pl-form-group {
flex: 1;
}
/* Primary button */
.pl-btn {
width: 100%;
padding: 14px 20px;
font-size: 15px;
font-weight: 600;
font-family: inherit;
color: #FFF;
background: linear-gradient(135deg, var(--pl-teal) 0%, var(--pl-teal-dark) 100%);
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease, transform 0.15s ease;
box-shadow: 0 2px 8px rgba(65, 162, 170, 0.3);
}
.pl-btn:hover {
background: linear-gradient(135deg, var(--pl-teal-dark) 0%, #2E8E96 100%);
box-shadow: 0 4px 16px rgba(65, 162, 170, 0.4);
transform: translateY(-1px);
}
.pl-btn:active {
transform: scale(0.98);
}
.pl-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.pl-btn-secondary {
background: linear-gradient(135deg, var(--pl-orange) 0%, var(--pl-orange-dark) 100%);
box-shadow: 0 2px 8px rgba(240, 158, 122, 0.3);
}
.pl-btn-secondary:hover {
background: linear-gradient(135deg, var(--pl-orange-dark) 0%, #D67A50 100%);
box-shadow: 0 4px 16px rgba(240, 158, 122, 0.4);
}
/* Button loading state */
.pl-btn-loading {
position: relative;
color: transparent !important;
}
.pl-btn-loading::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
top: 50%;
left: 50%;
margin-left: -10px;
margin-top: -10px;
border: 2px solid rgba(255,255,255,0.3);
border-top-color: #fff;
border-radius: 50%;
animation: plSpin 0.6s linear infinite;
}
/* Forgot link */
.pl-forgot {
display: inline-block;
font-size: 13px;
color: var(--pl-orange);
margin-top: 12px;
text-decoration: none;
transition: color 0.2s ease;
}
.pl-forgot:hover {
color: var(--pl-orange-dark);
text-decoration: underline;
}
/* Divider */
.pl-divider {
display: flex;
align-items: center;
margin: 24px 0;
gap: 14px;
}
.pl-divider-line {
flex: 1;
height: 1px;
background: var(--pl-border);
}
.pl-divider-text {
font-size: 12px;
font-weight: 500;
color: var(--pl-text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
/* Social buttons */
.pl-socials {
display: flex;
flex-direction: column;
gap: 10px;
}
.pl-social-btn {
width: 100%;
padding: 11px 16px;
font-size: 14px;
font-weight: 500;
font-family: inherit;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease, transform 0.15s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
text-decoration: none;
}
.pl-social-btn img {
width: 18px;
height: 18px;
}
.pl-social-google {
background: var(--pl-bg);
color: var(--pl-text);
border: 1px solid var(--pl-border);
}
.pl-social-google:hover {
background: var(--pl-bg-hero);
border-color: #D0D6E0;
}
.pl-social-facebook {
background: #1877F2;
color: #FFF;
border: 1px solid #1877F2;
}
.pl-social-facebook:hover {
background: #166FE5;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(24, 119, 242, 0.3);
}
.pl-social-google:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* Notification prefs (compact) */
.pl-notif-box {
background: var(--pl-bg-hero);
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 18px;
}
.pl-notif-label {
font-size: 12px;
font-weight: 500;
color: var(--pl-text-secondary);
margin-bottom: 8px;
}
.pl-notif-opts {
display: flex;
gap: 20px;
}
.pl-checkbox {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--pl-text);
cursor: pointer;
}
.pl-checkbox input {
width: 16px;
height: 16px;
accent-color: var(--pl-teal);
cursor: pointer;
}
/* Form note */
.pl-note {
font-size: 12px;
color: var(--pl-text-muted);
text-align: center;
margin-top: 14px;
line-height: 1.5;
}
/* CGU / RGPD consent block */
.pl-consent-box {
background: var(--pl-bg-hero);
border: 1px solid var(--pl-border);
border-radius: 10px;
padding: 14px 16px;
margin-bottom: 18px;
transition: border-color 0.2s ease;
}
.pl-consent-box.is-invalid {
border-color: #EF4444;
background: #FEF2F2;
}
.pl-consent-box .pl-checkbox {
font-size: 13px;
line-height: 1.5;
align-items: flex-start;
}
.pl-consent-box .pl-checkbox input {
margin-top: 2px;
flex-shrink: 0;
}
.pl-consent-link {
color: var(--pl-teal);
text-decoration: underline;
cursor: pointer;
font-weight: 500;
transition: color 0.2s ease;
}
.pl-consent-link:hover {
color: var(--pl-teal-dark);
}
.pl-consent-hint {
font-size: 11px;
color: var(--pl-text-muted);
margin-top: 6px;
padding-left: 22px;
display: flex;
align-items: center;
gap: 4px;
}
/* CGU modal overlay */
.pl-modal-overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
z-index: 10000;
display: none;
align-items: center;
justify-content: center;
padding: 20px;
animation: plFadeIn 0.2s ease;
}
.pl-modal-overlay.active {
display: flex;
}
.pl-modal {
background: #fff;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.2);
max-width: 640px;
width: 100%;
max-height: 80vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.pl-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 24px;
border-bottom: 1px solid var(--pl-border);
flex-shrink: 0;
}
.pl-modal-header h3 {
font-size: 16px;
font-weight: 700;
color: var(--pl-text);
margin: 0;
}
.pl-modal-close {
width: 32px;
height: 32px;
border-radius: 8px;
border: none;
background: var(--pl-bg-hero);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--pl-text-secondary);
transition: all 0.2s ease;
}
.pl-modal-close:hover {
background: #EEF0F4;
color: var(--pl-text);
}
.pl-modal-body {
padding: 24px;
overflow-y: auto;
font-size: 13px;
line-height: 1.7;
color: var(--pl-text-secondary);
}
.pl-modal-body h4 {
font-size: 14px;
font-weight: 600;
color: var(--pl-text);
margin: 18px 0 8px;
}
.pl-modal-body h4:first-child {
margin-top: 0;
}
.pl-modal-body ul {
padding-left: 20px;
margin: 8px 0;
}
.pl-modal-body ul li {
margin-bottom: 4px;
}
.pl-modal-footer {
padding: 14px 24px;
border-top: 1px solid var(--pl-border);
display: flex;
justify-content: flex-end;
flex-shrink: 0;
}
.pl-modal-footer .pl-btn {
width: auto;
padding: 10px 28px;
font-size: 13px;
}
.pl-input-code {
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
font-size: 18px;
font-weight: 600;
letter-spacing: 2px;
text-transform: uppercase;
text-align: center;
padding: 14px 16px;
background: linear-gradient(135deg, rgba(65, 162, 170, 0.04), rgba(240, 158, 122, 0.04));
border: 2px solid var(--pl-border);
}
.pl-input-code:focus {
border-color: var(--pl-teal);
background: var(--pl-bg);
}
.pl-input-code::placeholder {
font-weight: 400;
letter-spacing: 1px;
color: var(--pl-text-muted);
}
.pl-optional {
font-weight: 400;
color: var(--pl-text-muted);
}
.pl-required {
color: #EF4444;
margin-left: 2px;
}
/* Error alert */
.pl-error {
background: #FEF2F2;
border: 1px solid #FECACA;
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 18px;
font-size: 13px;
color: #991B1B;
display: flex;
align-items: center;
gap: 8px;
}
.pl-error svg {
flex-shrink: 0;
color: #EF4444;
}
/* ========================================
FOOTER TRUST BAR
======================================== */
.pl-footer-trust {
background: var(--pl-bg-hero);
border-top: 1px solid var(--pl-border);
padding: 16px 24px;
display: flex;
justify-content: center;
gap: 32px;
}
.pl-footer-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--pl-text-muted);
}
.pl-footer-item svg {
width: 16px;
height: 16px;
color: var(--pl-teal);
}
/* ========================================
LOADER
======================================== */
.pl-loader {
position: fixed;
inset: 0;
background: rgba(255,255,255,0.95);
z-index: 9999;
display: none;
align-items: center;
justify-content: center;
}
.pl-loader.active {
display: flex;
}
.pl-loader-inner {
text-align: center;
}
.pl-spinner {
width: 40px;
height: 40px;
border: 3px solid var(--pl-border);
border-top-color: var(--pl-teal);
border-radius: 50%;
animation: plSpin 0.7s linear infinite;
}
@keyframes plSpin {
to { transform: rotate(360deg); }
}
.pl-loader-text {
margin-top: 16px;
font-size: 15px;
font-weight: 600;
color: var(--pl-text);
}
.pl-loader-sub {
margin-top: 6px;
font-size: 13px;
color: var(--pl-text-secondary);
}
/* ========================================
RESPONSIVE - MOBILE
======================================== */
@media (max-width: 900px) {
.pl-main {
flex-direction: column;
min-height: auto;
}
.pl-hero {
width: 100%;
padding: 32px 24px;
}
.pl-hero-content {
max-width: 100%;
animation: none;
}
.pl-hero h1 {
font-size: 26px;
}
.pl-hero-subtitle {
font-size: 15px;
margin-bottom: 24px;
}
.pl-features {
gap: 14px;
}
.pl-feature {
animation: none;
opacity: 1;
}
.pl-feature-icon {
width: 38px;
height: 38px;
}
.pl-feature-icon svg {
width: 18px;
height: 18px;
}
.pl-feature-title {
font-size: 13px;
}
.pl-feature-desc {
font-size: 12px;
}
.pl-hero-illustration {
display: none;
}
.pl-form-section {
width: 100%;
padding: 24px 16px 40px;
}
.pl-card {
max-width: 100%;
box-shadow: none;
border: none;
animation: none;
}
.pl-panel {
padding: 24px 20px;
}
.pl-row {
flex-direction: column;
gap: 0;
}
.pl-footer-trust {
flex-wrap: wrap;
gap: 16px 24px;
justify-content: center;
}
}
@media (max-width: 480px) {
.pl-hero {
padding: 24px 20px;
}
.pl-hero h1 {
font-size: 22px;
}
.pl-tab {
padding: 14px 12px;
font-size: 13px;
}
}
</style>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 1009
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_Header(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "Header"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "Header"));
// line 1010
yield from $this->yieldParentBlock("Header", $context, $blocks);
yield "
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 1013
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_Content(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "Content"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "Content"));
// line 1014
yield "<div class=\"pl-page\">
<!-- Loader -->
<div class=\"pl-loader\" id=\"plLoader\">
<div class=\"pl-loader-inner\">
<div class=\"pl-spinner\"></div>
<p class=\"pl-loader-text\">Création de votre compte...</p>
<p class=\"pl-loader-sub\">Préparation de votre espace parent</p>
</div>
</div>
<!-- Main two-column layout -->
<main class=\"pl-main\">
<!-- LEFT: Hero -->
<section class=\"pl-hero\">
<div class=\"pl-hero-content\">
<h1>Suivez le séjour de votre enfant en toute sérénité.</h1>
<p class=\"pl-hero-subtitle\">Photos, vidéos et messages vocaux, dans un espace privé réservé aux familles.</p>
<ul class=\"pl-features\">
<li class=\"pl-feature\">
<span class=\"pl-feature-icon orange\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>
<circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/>
<polyline points=\"21 15 16 10 5 21\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Photos & vidéos en direct</p>
<p class=\"pl-feature-desc\">Visualisez les moments du séjour en toute confidentialité</p>
</div>
</li>
<li class=\"pl-feature\">
<span class=\"pl-feature-icon teal\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Messages vocaux</p>
<p class=\"pl-feature-desc\">Accédez à l’ensemble des messages vocaux enregistrés, en illimité.</p>
</div>
</li>
<li class=\"pl-feature\">
<span class=\"pl-feature-icon coral\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M20 12v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-6\"/>
<rect x=\"6\" y=\"5\" width=\"12\" height=\"7\"/>
<path d=\"M12 3v5\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Souvenirs personnalisés</p>
<p class=\"pl-feature-desc\">Créez albums, livres et cadeaux uniques du séjour</p>
</div>
</li>
<li class=\"pl-feature\">
<span class=\"pl-feature-icon brown\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>
<path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Notifications instantanées</p>
<p class=\"pl-feature-desc\">Restez informé à chaque nouvelle publication</p>
</div>
</li>
</ul>
<!-- Decorative illustration -->
<div class=\"pl-hero-illustration\">
<svg viewBox=\"0 0 400 280\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">
<!-- Background shapes -->
<ellipse cx=\"200\" cy=\"250\" rx=\"180\" ry=\"20\" fill=\"#E5E9F0\" opacity=\"0.5\"/>
<!-- Phone mockup -->
<rect x=\"140\" y=\"30\" width=\"120\" height=\"200\" rx=\"16\" fill=\"#1A1A2E\"/>
<rect x=\"146\" y=\"40\" width=\"108\" height=\"180\" rx=\"12\" fill=\"#fff\"/>
<!-- Phone content - photos grid -->
<rect x=\"152\" y=\"55\" width=\"48\" height=\"48\" rx=\"6\" fill=\"#F09E7A\" opacity=\"0.3\"/>
<rect x=\"152\" y=\"55\" width=\"48\" height=\"48\" rx=\"6\" fill=\"url(#imgGrad1)\"/>
<rect x=\"204\" y=\"55\" width=\"44\" height=\"48\" rx=\"6\" fill=\"#41A2AA\" opacity=\"0.3\"/>
<rect x=\"204\" y=\"55\" width=\"44\" height=\"48\" rx=\"6\" fill=\"url(#imgGrad2)\"/>
<rect x=\"152\" y=\"107\" width=\"96\" height=\"60\" rx=\"6\" fill=\"#F56040\" opacity=\"0.2\"/>
<rect x=\"152\" y=\"107\" width=\"96\" height=\"60\" rx=\"6\" fill=\"url(#imgGrad3)\"/>
<!-- Photo icons -->
<circle cx=\"176\" cy=\"79\" r=\"12\" fill=\"#F09E7A\"/>
<path d=\"M170 82l4-5 3 3 5-6 6 8H170z\" fill=\"#fff\"/>
<circle cx=\"226\" cy=\"79\" r=\"10\" fill=\"#41A2AA\"/>
<polygon points=\"221,82 226,74 231,82\" fill=\"#fff\"/>
<!-- Play button on video -->
<circle cx=\"200\" cy=\"137\" r=\"14\" fill=\"rgba(255,255,255,0.9)\"/>
<polygon points=\"196,131 196,143 208,137\" fill=\"#F56040\"/>
<!-- Notification bar -->
<rect x=\"152\" y=\"175\" width=\"96\" height=\"38\" rx=\"8\" fill=\"#F8FAFB\"/>
<circle cx=\"168\" cy=\"194\" r=\"10\" fill=\"#41A2AA\"/>
<path d=\"M165 194l2 2 4-4\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>
<rect x=\"184\" y=\"188\" width=\"50\" height=\"6\" rx=\"3\" fill=\"#E5E9F0\"/>
<rect x=\"184\" y=\"198\" width=\"35\" height=\"4\" rx=\"2\" fill=\"#E5E9F0\"/>
<!-- Phone notch -->
<rect x=\"175\" y=\"34\" width=\"50\" height=\"4\" rx=\"2\" fill=\"#1A1A2E\"/>
<!-- Decorative elements around -->
<circle cx=\"80\" cy=\"80\" r=\"8\" fill=\"#F09E7A\" opacity=\"0.6\"/>
<circle cx=\"320\" cy=\"100\" r=\"6\" fill=\"#41A2AA\" opacity=\"0.5\"/>
<circle cx=\"340\" cy=\"180\" r=\"10\" fill=\"#F56040\" opacity=\"0.4\"/>
<circle cx=\"60\" cy=\"180\" r=\"5\" fill=\"#41A2AA\" opacity=\"0.4\"/>
<!-- Hearts/love -->
<path d=\"M300 60c-2-4-8-4-10 0-2-4-8-4-10 0 0 6 10 12 10 12s10-6 10-12z\" fill=\"#F09E7A\" opacity=\"0.7\"/>
<!-- Stars -->
<path d=\"M70 120l2 4 4 1-3 3 1 4-4-2-4 2 1-4-3-3 4-1 2-4z\" fill=\"#FFD93D\" opacity=\"0.8\"/>
<path d=\"M350 140l1.5 3 3 .5-2 2 .5 3-3-1.5-3 1.5.5-3-2-2 3-.5 1.5-3z\" fill=\"#FFD93D\" opacity=\"0.6\"/>
<!-- Gradients -->
<defs>
<linearGradient id=\"imgGrad1\" x1=\"152\" y1=\"55\" x2=\"200\" y2=\"103\">
<stop offset=\"0%\" stop-color=\"#F09E7A\" stop-opacity=\"0.4\"/>
<stop offset=\"100%\" stop-color=\"#F56040\" stop-opacity=\"0.3\"/>
</linearGradient>
<linearGradient id=\"imgGrad2\" x1=\"204\" y1=\"55\" x2=\"248\" y2=\"103\">
<stop offset=\"0%\" stop-color=\"#41A2AA\" stop-opacity=\"0.4\"/>
<stop offset=\"100%\" stop-color=\"#359BA3\" stop-opacity=\"0.3\"/>
</linearGradient>
<linearGradient id=\"imgGrad3\" x1=\"152\" y1=\"107\" x2=\"248\" y2=\"167\">
<stop offset=\"0%\" stop-color=\"#F56040\" stop-opacity=\"0.3\"/>
<stop offset=\"100%\" stop-color=\"#F09E7A\" stop-opacity=\"0.2\"/>
</linearGradient>
</defs>
</svg>
<!-- Floating notification badges -->
<div class=\"pl-floating-badges\">
<div class=\"pl-badge pl-badge-1\">
<span class=\"pl-badge-icon orange\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>
<circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/>
<polyline points=\"21 15 16 10 5 21\"/>
</svg>
</span>
<span>+12 photos</span>
</div>
<div class=\"pl-badge pl-badge-2\">
<span class=\"pl-badge-icon teal\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/>
<polyline points=\"22 4 12 14.01 9 11.01\"/>
</svg>
</span>
<span>Bien arrivés !</span>
</div>
</div>
</div>
</div>
</section>
<!-- RIGHT: Form -->
<section class=\"pl-form-section\">
<div class=\"pl-card\">
<!-- Tabs -->
<div class=\"pl-tabs\" role=\"tablist\">
<button class=\"pl-tab active\" role=\"tab\" data-tab=\"login\" aria-selected=\"true\">Se connecter</button>
<button class=\"pl-tab\" role=\"tab\" data-tab=\"register\" aria-selected=\"false\">Créer un compte</button>
</div>
<!-- LOGIN PANEL -->
<div class=\"pl-panel active\" id=\"panel-login\" role=\"tabpanel\">
";
// line 1189
if ((($tmp = (isset($context["error"]) || array_key_exists("error", $context) ? $context["error"] : (function () { throw new RuntimeError('Variable "error" does not exist.', 1189, $this->source); })())) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 1190
yield " <div class=\"pl-error\">
<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<circle cx=\"12\" cy=\"12\" r=\"10\"/>
<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/>
<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>
</svg>
Identifiant ou mot de passe incorrect.
</div>
";
}
// line 1199
yield "
<form method=\"post\" action=\"";
// line 1200
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("app_back_Parent");
yield "\" id=\"loginForm\" autocomplete=\"off\">
<!-- Code Séjour - Required for direct access -->
<div class=\"pl-form-group\">
<label class=\"pl-label\">
Code séjour
<span class=\"pl-required\">*</span>
</label>
<input type=\"text\"
class=\"pl-input pl-input-code\"
name=\"code_sejour\"
id=\"loginCode\"
placeholder=\" XX000000\"
maxlength=\"8\"
autocomplete=\"one-time-code\"
data-lpignore=\"true\"
data-form-type=\"other\"
required>
<p class=\"pl-hint\">
<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<circle cx=\"12\" cy=\"12\" r=\"10\"/>
<path d=\"M12 16v-4\"/>
<path d=\"M12 8h.01\"/>
</svg>
Code reçu par l'école ou l'organisateur du séjour
</p>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Adresse e-mail</label>
<input type=\"email\" class=\"pl-input\" name=\"email\" id=\"loginEmail\" value=\"";
// line 1229
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape((isset($context["last_username"]) || array_key_exists("last_username", $context) ? $context["last_username"] : (function () { throw new RuntimeError('Variable "last_username" does not exist.', 1229, $this->source); })()), "html", null, true);
yield "\" placeholder=\"votre@email.com\" autocomplete=\"username\" required>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Mot de passe</label>
<div class=\"pl-password-wrap\">
<input type=\"password\" class=\"pl-input\" name=\"password\" id=\"loginPwd\" placeholder=\"••••••••\" autocomplete=\"current-password\" required>
<button type=\"button\" class=\"pl-eye-btn\" data-target=\"loginPwd\" aria-label=\"Afficher\">
<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>
<circle cx=\"12\" cy=\"12\" r=\"3\"/>
</svg>
</button>
</div>
</div>
<input type=\"hidden\" name=\"_csrf_token\" value=\"";
// line 1245
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->env->getRuntime('Symfony\Component\Form\FormRenderer')->renderCsrfToken("authenticate"), "html", null, true);
yield "\">
<button type=\"submit\" class=\"pl-btn\">Se connecter</button>
<a href=\"";
// line 1248
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("forgotPassparent");
yield "\" class=\"pl-forgot\">Vous avez oublié votre mot de passe ?</a>
</form>
<div class=\"pl-divider\">
<span class=\"pl-divider-line\"></span>
<span class=\"pl-divider-text\">ou</span>
<span class=\"pl-divider-line\"></span>
</div>
<div class=\"pl-socials\">
<a href=\"";
// line 1258
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("connect_google_start");
yield "\" class=\"pl-social-btn pl-social-google\">
<img src=\"";
// line 1259
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("/images/icons-google.png"), "html", null, true);
yield "\" alt=\"\">
Continuer avec Google
</a>
<a href=\"";
// line 1262
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("connect_facebook_start");
yield "\" class=\"pl-social-btn pl-social-facebook\">
<img src=\"";
// line 1263
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("/images/icons-facebook.png"), "html", null, true);
yield "\" alt=\"\">
Continuer avec Facebook
</a>
</div>
</div>
<!-- REGISTER PANEL -->
<div class=\"pl-panel\" id=\"panel-register\" role=\"tabpanel\">
<form id=\"registerForm\" onsubmit=\"return false;\" autocomplete=\"off\">
<div class=\"pl-row\">
<div class=\"pl-form-group\">
<label class=\"pl-label\">Nom</label>
<input type=\"text\" class=\"pl-input\" id=\"regNom\" name=\"family-name\" placeholder=\"Votre nom\" autocomplete=\"family-name\" required>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Prénom</label>
<input type=\"text\" class=\"pl-input\" id=\"regPrenom\" name=\"given-name\" placeholder=\"Votre prénom\" autocomplete=\"given-name\" required>
</div>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Adresse e-mail</label>
<input type=\"email\" class=\"pl-input\" id=\"regEmail\" name=\"email\" placeholder=\"votre@email.com\" autocomplete=\"email\" required>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Mot de passe</label>
<div class=\"pl-password-wrap\">
<input type=\"password\" class=\"pl-input\" id=\"regPwd\" name=\"new-password\" placeholder=\"Minimum 6 caractères\" autocomplete=\"new-password\" required>
<button type=\"button\" class=\"pl-eye-btn\" data-target=\"regPwd\" aria-label=\"Afficher\">
<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>
<circle cx=\"12\" cy=\"12\" r=\"3\"/>
</svg>
</button>
</div>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Confirmer le mot de passe</label>
<div class=\"pl-password-wrap\">
<input type=\"password\" class=\"pl-input\" id=\"regPwdConfirm\" name=\"confirm-password\" placeholder=\"Retapez votre mot de passe\" autocomplete=\"new-password\" required>
<button type=\"button\" class=\"pl-eye-btn\" data-target=\"regPwdConfirm\" aria-label=\"Afficher\">
<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>
<circle cx=\"12\" cy=\"12\" r=\"3\"/>
</svg>
</button>
</div>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Téléphone portable</label>
<input type=\"tel\" class=\"pl-input\" id=\"regPhone\" placeholder=\"06 12 34 56 78\" required>
</div>
<div class=\"pl-notif-box\">
<p class=\"pl-notif-label\">Recevoir les notifications :</p>
<div class=\"pl-notif-opts\">
<label class=\"pl-checkbox\">
<input type=\"checkbox\" id=\"notifSms\" checked>
SMS
</label>
<label class=\"pl-checkbox\">
<input type=\"checkbox\" id=\"notifEmail\" checked>
E-mail
</label>
</div>
</div>
<div class=\"pl-consent-box\" id=\"consentBox\">
<label class=\"pl-checkbox\">
<input type=\"checkbox\" id=\"acceptCgu\">
J'accepte les <span class=\"pl-consent-link\" onclick=\"openCguModal(event)\">Conditions Générales d'Utilisation</span> et la <span class=\"pl-consent-link\" onclick=\"openPolitiqueModal(event)\">Politique de Confidentialité</span> <span class=\"pl-required\">*</span>
</label>
<p class=\"pl-consent-hint\">
<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"/></svg>
Données hébergées en France, conformité RGPD
</p>
</div>
<button type=\"button\" class=\"pl-btn pl-btn-secondary\" onclick=\"handleRegister()\">Créer mon compte Parent</button>
<p class=\"pl-note\">Vous pourrez modifier vos informations et vos préférences de notifications à tout moment.</p>
</form>
<div class=\"pl-divider\">
<span class=\"pl-divider-line\"></span>
<span class=\"pl-divider-text\">ou</span>
<span class=\"pl-divider-line\"></span>
</div>
<div class=\"pl-socials\">
<a href=\"";
// line 1356
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("connect_google_start");
yield "\" class=\"pl-social-btn pl-social-google\">
<img src=\"";
// line 1357
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("/images/icons-google.png"), "html", null, true);
yield "\" alt=\"\">
Continuer avec Google
</a>
<a href=\"";
// line 1360
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("connect_facebook_start");
yield "\" class=\"pl-social-btn pl-social-facebook\">
<img src=\"";
// line 1361
yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['Symfony\Bridge\Twig\Extension\AssetExtension']->getAssetUrl("/images/icons-facebook.png"), "html", null, true);
yield "\" alt=\"\">
Continuer avec Facebook
</a>
</div>
</div>
</div>
</section>
</main>
<!-- CGU Modal -->
<div class=\"pl-modal-overlay\" id=\"cguModal\">
<div class=\"pl-modal\">
<div class=\"pl-modal-header\">
<h3>Conditions Générales d'Utilisation</h3>
<button class=\"pl-modal-close\" onclick=\"closeCguModal()\">
<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>
</button>
</div>
<div class=\"pl-modal-body\">
<h4>1. Objet</h4>
<p>Les présentes Conditions Générales d'Utilisation (CGU) régissent l'accès et l'utilisation de la plateforme 5sur5séjour par les utilisateurs « Parents ». L'inscription implique l'acceptation pleine et entière des présentes conditions.</p>
<h4>2. Accès au service</h4>
<p>L'accès à l'espace Parent nécessite un code séjour fourni par l'accompagnateur ou l'organisateur du séjour. Le Parent crée un compte personnel pour consulter les photos, vidéos et messages vocaux déposés pendant le séjour de son enfant.</p>
<h4>3. Données personnelles collectées</h4>
<ul>
<li>Nom, prénom, adresse e-mail, numéro de téléphone portable</li>
<li>Préférences de notification (SMS, e-mail)</li>
<li>Données de connexion et d'utilisation de la plateforme</li>
</ul>
<h4>4. Finalités du traitement</h4>
<p>Vos données sont utilisées exclusivement pour :</p>
<ul>
<li>Créer et gérer votre compte Parent</li>
<li>Vous donner accès aux contenus du séjour de votre enfant</li>
<li>Vous envoyer des notifications (nouvelles photos, messages, commandes)</li>
<li>Assurer le bon fonctionnement et la sécurité du service</li>
</ul>
<h4>5. Durée de conservation</h4>
<p>Les données personnelles sont conservées pendant la durée d'utilisation du service. Les contenus de séjour (photos, vidéos) sont automatiquement supprimés 2 mois après la fin du séjour. Votre compte est supprimé après 2 ans d'inactivité.</p>
<h4>6. Droits de l'utilisateur</h4>
<p>Conformément au RGPD (Règlement UE 2016/679), vous disposez d'un droit d'accès, de rectification, de suppression, de limitation et de portabilité de vos données. Vous pouvez exercer ces droits par e-mail à <strong>contact@5sur5sejour.com</strong>.</p>
<h4>7. Hébergement et sécurité</h4>
<p>Toutes les données sont hébergées en France (OVH, 2 rue Kellermann, 59100 Roubaix). La plateforme utilise un chiffrement SSL et des mesures de sécurité conformes aux standards en vigueur.</p>
<h4>8. Responsable du traitement</h4>
<p>TRUST CONSEILS — 199 Avenue Francis de Pressensé, 69200 Vénissieux.<br>Contact : <strong>contact@5sur5sejour.com</strong> — Tél. : 05 36 28 29 30</p>
</div>
<div class=\"pl-modal-footer\">
<button class=\"pl-btn\" onclick=\"closeCguModal()\">J'ai compris</button>
</div>
</div>
</div>
<!-- Politique Modal -->
<div class=\"pl-modal-overlay\" id=\"politiqueModal\">
<div class=\"pl-modal\">
<div class=\"pl-modal-header\">
<h3>Politique de Confidentialité</h3>
<button class=\"pl-modal-close\" onclick=\"closePolitiqueModal()\">
<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>
</button>
</div>
<div class=\"pl-modal-body\">
<h4>Charte d'utilisation des données personnelles</h4>
<p>La présente politique de confidentialité s'applique à la plateforme 5sur5séjour (5sur5sejour.com), éditée par TRUST CONSEILS.</p>
<h4>Données collectées</h4>
<p>Dans le cadre de l'utilisation du service, nous collectons les données suivantes : nom, prénom, adresse e-mail, numéro de téléphone, données de connexion. Ces données sont nécessaires au fonctionnement du service.</p>
<h4>Base légale du traitement</h4>
<p>Le traitement de vos données repose sur votre consentement (acceptation des présentes conditions lors de l'inscription) et sur l'exécution du contrat de service.</p>
<h4>Destinataires des données</h4>
<p>Vos données personnelles ne sont jamais vendues ni partagées avec des tiers à des fins commerciales. Elles sont accessibles uniquement aux équipes de TRUST CONSEILS dans le cadre strict du fonctionnement du service.</p>
<h4>Transferts de données</h4>
<p>Aucun transfert de données hors de l'Union Européenne n'est effectué. L'ensemble des données est hébergé en France.</p>
<h4>Cookies</h4>
<p>La plateforme utilise des cookies strictement nécessaires au fonctionnement du service (session, authentification). Aucun cookie publicitaire n'est utilisé.</p>
<h4>Vos droits</h4>
<p>Conformément au RGPD et à la loi Informatique et Libertés, vous disposez des droits suivants :</p>
<ul>
<li><strong>Droit d'accès</strong> : obtenir une copie de vos données</li>
<li><strong>Droit de rectification</strong> : corriger vos informations</li>
<li><strong>Droit de suppression</strong> : demander l'effacement de vos données</li>
<li><strong>Droit d'opposition</strong> : vous opposer au traitement</li>
<li><strong>Droit à la portabilité</strong> : recevoir vos données dans un format structuré</li>
<li><strong>Droit de retrait du consentement</strong> : à tout moment</li>
</ul>
<p>Pour exercer vos droits : <strong>contact@5sur5sejour.com</strong></p>
<p>Pour en savoir plus : <a href=\"https://www.cnil.fr/\" target=\"_blank\" rel=\"noopener\" style=\"color:var(--pl-teal);\">www.cnil.fr</a></p>
</div>
<div class=\"pl-modal-footer\">
<button class=\"pl-btn\" onclick=\"closePolitiqueModal()\">J'ai compris</button>
</div>
</div>
</div>
<!-- Footer trust bar -->
<footer class=\"pl-footer-trust\">
<span class=\"pl-footer-item\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"/>
<path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>
</svg>
Connexion sécurisée
</span>
<span class=\"pl-footer-item\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"/>
</svg>
Données protégées
</span>
<span class=\"pl-footer-item\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<circle cx=\"12\" cy=\"12\" r=\"10\"/>
<line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\"/>
<path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"/>
</svg>
Hébergé en France
</span>
</footer>
</div>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 1494
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_Footer(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "Footer"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "Footer"));
// line 1495
yield from $this->yieldParentBlock("Footer", $context, $blocks);
yield "
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
// line 1498
/**
* @return iterable<null|scalar|\Stringable>
*/
public function block_javascript(array $context, array $blocks = []): iterable
{
$macros = $this->macros;
$__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
$__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascript"));
$__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "javascript"));
// line 1499
yield from $this->yieldParentBlock("javascript", $context, $blocks);
yield "
<script src=\"https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js\"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Tab switching
const tabs = document.querySelectorAll('.pl-tab');
const panels = document.querySelectorAll('.pl-panel');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = tab.dataset.tab;
tabs.forEach(t => {
t.classList.remove('active');
t.setAttribute('aria-selected', 'false');
});
tab.classList.add('active');
tab.setAttribute('aria-selected', 'true');
panels.forEach(p => p.classList.remove('active'));
document.getElementById('panel-' + target).classList.add('active');
});
});
// Clear autofilled code séjour field on page load (browser autofill fix)
const codeInput = document.getElementById('loginCode');
if (codeInput) {
// Clear any incorrect autofill value
setTimeout(() => {
const currentValue = codeInput.value;
// If the value doesn't match code séjour format (2 letters + 6 digits), clear it
if (currentValue && !/^[A-Z]{2}[0-9]{6}\$/.test(currentValue.toUpperCase())) {
codeInput.value = '';
}
}, 100);
}
// Password toggle
document.querySelectorAll('.pl-eye-btn').forEach(btn => {
btn.addEventListener('click', () => {
const input = document.getElementById(btn.dataset.target);
const isPassword = input.type === 'password';
input.type = isPassword ? 'text' : 'password';
btn.querySelector('svg').style.opacity = isPassword ? '0.5' : '1';
});
});
// Auto-format code séjour (uppercase) and validation
if (codeInput) {
codeInput.addEventListener('input', (e) => {
let value = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
e.target.value = value;
// Visual feedback when complete
if (value.length === 8) {
e.target.style.borderColor = '#41A2AA';
e.target.style.background = 'rgba(65, 162, 170, 0.06)';
} else {
e.target.style.borderColor = '';
e.target.style.background = '';
}
});
// Validate on form submit
document.getElementById('loginForm').addEventListener('submit', function(e) {
const codePattern = /^[A-Z]{2}[0-9]{6}\$/;
if (!codePattern.test(codeInput.value)) {
e.preventDefault();
codeInput.classList.add('is-invalid');
Swal.fire({
icon: 'error',
title: 'Code séjour invalide',
html: '<p style=\"margin-bottom:8px;\">Le code doit contenir :</p><p style=\"color:#5A6178;font-size:14px;\"><strong>2 lettres</strong> + <strong>6 chiffres</strong><br>Exemple : <span style=\"color:#41A2AA;font-weight:600;\">XX000000</span></p>',
confirmButtonColor: '#41a2aa'
});
} else {
// Show loading state on button
const btn = this.querySelector('button[type=\"submit\"]');
btn.classList.add('pl-btn-loading');
btn.disabled = true;
}
});
}
// Add visual feedback when email is valid
const emailInputs = document.querySelectorAll('input[type=\"email\"]');
emailInputs.forEach(input => {
input.addEventListener('blur', function() {
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+\$/;
if (this.value && emailRegex.test(this.value)) {
this.classList.add('is-valid');
this.classList.remove('is-invalid');
} else if (this.value) {
this.classList.add('is-invalid');
this.classList.remove('is-valid');
}
});
input.addEventListener('input', function() {
this.classList.remove('is-valid', 'is-invalid');
});
});
// Login error
";
// line 1602
if ((($tmp = (isset($context["error"]) || array_key_exists("error", $context) ? $context["error"] : (function () { throw new RuntimeError('Variable "error" does not exist.', 1602, $this->source); })())) && $tmp instanceof Markup ? (string) $tmp : $tmp)) {
// line 1603
yield " Swal.fire({
icon: 'error',
title: 'Erreur de connexion',
text: 'Identifiant ou mot de passe incorrect.',
confirmButtonColor: '#41a2aa'
});
";
}
// line 1610
yield "});
// Modal CGU / Politique
function openCguModal(e) { e && e.preventDefault(); document.getElementById('cguModal').classList.add('active'); document.body.style.overflow = 'hidden'; }
function closeCguModal() { document.getElementById('cguModal').classList.remove('active'); document.body.style.overflow = ''; }
function openPolitiqueModal(e) { e && e.preventDefault(); document.getElementById('politiqueModal').classList.add('active'); document.body.style.overflow = 'hidden'; }
function closePolitiqueModal() { document.getElementById('politiqueModal').classList.remove('active'); document.body.style.overflow = ''; }
document.querySelectorAll('.pl-modal-overlay').forEach(function(overlay) {
overlay.addEventListener('click', function(e) {
if (e.target === overlay) {
overlay.classList.remove('active');
document.body.style.overflow = '';
}
});
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') { closeCguModal(); closePolitiqueModal(); }
});
// Registration
function handleRegister() {
const loader = document.getElementById('plLoader');
const fields = {
nom: document.getElementById('regNom'),
prenom: document.getElementById('regPrenom'),
email: document.getElementById('regEmail'),
pwd: document.getElementById('regPwd'),
pwdConfirm: document.getElementById('regPwdConfirm'),
phone: document.getElementById('regPhone')
};
// Reset
Object.values(fields).forEach(f => f.classList.remove('is-invalid'));
document.getElementById('consentBox').classList.remove('is-invalid');
// Validate
let valid = true;
if (!fields.nom.value.trim()) { fields.nom.classList.add('is-invalid'); valid = false; }
if (!fields.prenom.value.trim()) { fields.prenom.classList.add('is-invalid'); valid = false; }
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+\$/;
if (!emailRegex.test(fields.email.value)) { fields.email.classList.add('is-invalid'); valid = false; }
if (fields.pwd.value.length < 6) {
fields.pwd.classList.add('is-invalid');
Swal.fire({ icon: 'warning', title: 'Mot de passe trop court', text: 'Minimum 6 caractères.', confirmButtonColor: '#41a2aa' });
return;
}
if (fields.pwd.value !== fields.pwdConfirm.value) {
fields.pwdConfirm.classList.add('is-invalid');
Swal.fire({ icon: 'warning', title: 'Erreur', text: 'Les mots de passe ne correspondent pas.', confirmButtonColor: '#41a2aa' });
return;
}
if (!fields.phone.value.trim()) { fields.phone.classList.add('is-invalid'); valid = false; }
if (!document.getElementById('acceptCgu').checked) {
document.getElementById('consentBox').classList.add('is-invalid');
Swal.fire({
icon: 'warning',
title: 'Conditions requises',
html: 'Vous devez accepter les <strong>Conditions Générales d\\'Utilisation</strong> et la <strong>Politique de Confidentialité</strong> pour créer votre compte.',
confirmButtonColor: '#41a2aa'
});
return;
}
if (!valid) return;
loader.classList.add('active');
const data = {
nomparent: fields.nom.value.trim(),
prenomparent: fields.prenom.value.trim(),
mailparent: fields.email.value.trim(),
numtel: fields.phone.value.trim(),
passwordparent: fields.pwd.value,
confirmpassword: fields.pwdConfirm.value,
sms: document.getElementById('notifSms').checked ? 1 : 0,
mailnotif: document.getElementById('notifEmail').checked ? 1 : 0
};
fetch(\"";
// line 1696
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("parent_register");
yield "\", {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(data)
})
.then(r => r.text())
.then(text => {
loader.classList.remove('active');
let code = '';
try {
const parsed = JSON.parse(text);
code = typeof parsed === 'string' ? parsed : (parsed && parsed.code !== undefined ? String(parsed.code) : '');
} catch (e) {
code = text.trim();
}
if (code === 'eror') {
fields.email.classList.add('is-invalid');
Swal.fire({
icon: false,
title: '🔐 Vous avez déjà un compte',
text: 'Cette adresse est déjà associée à un compte parent. Vous pouvez vous connecter ou réinitialiser votre mot de passe si besoin.',
footer: '<a href=\"";
// line 1718
yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("forgotPassparent");
yield "\" style=\"color:#F09E7A;\">Mot de passe oublié ?</a>',
confirmButtonColor: '#41a2aa'
});
} else if (code === 'erorpasswordconfirm') {
fields.pwdConfirm.classList.add('is-invalid');
Swal.fire({ icon: 'error', title: 'Erreur', text: 'Les mots de passe ne correspondent pas.', confirmButtonColor: '#41a2aa' });
} else if (code === 'done') {
Swal.fire({
icon: 'success',
title: '🎉 Bienvenue !',
html: '<p>Votre compte parent est presque prêt.</p><p style=\"color:#5A6178;font-size:14px;\">📩 Un e-mail vous a été envoyé pour activer votre compte.</p>',
confirmButtonText: 'Compris',
confirmButtonColor: '#41a2aa'
}).then(() => location.reload());
} else {
Swal.fire({ icon: 'error', title: 'Erreur', text: 'Une réponse inattendue a été reçue. Veuillez réessayer.', confirmButtonColor: '#41a2aa' });
}
})
.catch(() => {
loader.classList.remove('active');
Swal.fire({ icon: 'error', title: 'Erreur', text: 'Un problème est survenu. Veuillez réessayer.', confirmButtonColor: '#F09E7A' });
});
}
</script>
";
$__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
$__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
yield from [];
}
/**
* @codeCoverageIgnore
*/
public function getTemplateName(): string
{
return "Parent/LoginParent.html.twig";
}
/**
* @codeCoverageIgnore
*/
public function isTraitable(): bool
{
return false;
}
/**
* @codeCoverageIgnore
*/
public function getDebugInfo(): array
{
return array ( 1955 => 1718, 1930 => 1696, 1842 => 1610, 1833 => 1603, 1831 => 1602, 1725 => 1499, 1712 => 1498, 1699 => 1495, 1686 => 1494, 1543 => 1361, 1539 => 1360, 1533 => 1357, 1529 => 1356, 1433 => 1263, 1429 => 1262, 1423 => 1259, 1419 => 1258, 1406 => 1248, 1400 => 1245, 1381 => 1229, 1349 => 1200, 1346 => 1199, 1335 => 1190, 1333 => 1189, 1156 => 1014, 1143 => 1013, 1130 => 1010, 1117 => 1009, 104 => 6, 91 => 5, 68 => 3, 45 => 1,);
}
public function getSourceContext(): Source
{
return new Source("{% extends 'Accueil/layoutAccueil.html.twig' %}
{% block title %}Connexion Parent — 5sur5séjour{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css\">
<style>
/* ========================================
5SUR5 PARENT LOGIN - CLEAN TWO-COLUMN
Stripe/Notion Quality · No Slider
======================================== */
:root {
--pl-teal: #41A2AA;
--pl-teal-dark: #359BA3;
--pl-teal-light: rgba(65, 162, 170, 0.06);
--pl-orange: #F09E7A;
--pl-orange-dark: #E8865E;
--pl-text: #1A1A2E;
--pl-text-secondary: #5A6178;
--pl-text-muted: #8E95A9;
--pl-bg: #FFFFFF;
--pl-bg-hero: #F8FAFB;
--pl-border: #E5E9F0;
--pl-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
--pl-radius: 16px;
}
* {
box-sizing: border-box;
}
.pl-page {
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* ========================================
MAIN CONTAINER - TWO COLUMNS
======================================== */
.pl-main {
flex: 1;
display: flex;
min-height: calc(100vh - 160px);
}
/* ========================================
LEFT COLUMN - HERO
======================================== */
.pl-hero {
width: 35%;
background: var(--pl-bg-hero);
padding: 40px;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
}
.pl-hero-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
max-width: 420px;
}
.pl-hero h1 {
font-size: 32px;
font-weight: 700;
color: var(--pl-text);
line-height: 1.25;
margin: 0 0 16px;
letter-spacing: -0.02em;
}
.pl-hero-subtitle {
font-size: 17px;
color: var(--pl-text-secondary);
line-height: 1.6;
margin: 0 0 32px;
}
/* Features List - Premium Style */
.pl-features {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 18px;
}
.pl-feature {
display: flex;
align-items: flex-start;
gap: 14px;
}
.pl-feature-icon {
width: 44px;
height: 44px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.pl-feature-icon svg {
width: 22px;
height: 22px;
color: #fff;
}
.pl-feature-icon.teal { background: var(--pl-teal); }
.pl-feature-icon.orange { background: var(--pl-orange); }
.pl-feature-icon.coral { background: #F56040; }
.pl-feature-icon.brown { background: #c47d5e; }
.pl-feature-text {
padding-top: 2px;
}
.pl-feature-title {
font-size: 14px;
font-weight: 600;
color: var(--pl-text);
margin: 0 0 3px;
}
.pl-feature-desc {
font-size: 13px;
color: var(--pl-text-muted);
margin: 0;
line-height: 1.4;
}
/* Hero image */
.pl-hero-image {
margin-top: auto;
border-radius: 12px;
overflow: hidden;
}
.pl-hero-image img {
width: 100%;
height: auto;
display: block;
border-radius: 12px;
}
/* Hero decorative illustration */
.pl-hero-illustration {
margin-top: auto;
padding-top: 40px;
position: relative;
}
.pl-hero-illustration svg {
width: 100%;
max-width: 320px;
height: auto;
opacity: 0.9;
}
/* Floating badges */
.pl-floating-badges {
position: absolute;
inset: 0;
pointer-events: none;
}
.pl-badge {
position: absolute;
background: #fff;
border-radius: 12px;
padding: 10px 14px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
font-weight: 500;
color: var(--pl-text);
animation: plFloat 3s ease-in-out infinite;
}
.pl-badge-icon {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.pl-badge-icon svg {
width: 18px;
height: 18px;
color: #fff;
}
.pl-badge-icon.teal { background: var(--pl-teal); }
.pl-badge-icon.orange { background: var(--pl-orange); }
.pl-badge-icon.coral { background: #F56040; }
.pl-badge-1 {
top: 20%;
right: -10px;
animation-delay: 0s;
}
.pl-badge-2 {
bottom: 30%;
left: -5px;
animation-delay: 1s;
}
.pl-badge-3 {
bottom: 10%;
right: 10%;
animation-delay: 2s;
}
@keyframes plFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
/* Entry animations */
.pl-hero-content {
animation: plSlideRight 0.6s ease-out;
}
.pl-card {
animation: plSlideUp 0.5s ease-out;
}
@keyframes plSlideRight {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes plSlideUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Feature items staggered animation */
.pl-feature {
opacity: 0;
animation: plFadeIn 0.4s ease forwards;
}
.pl-feature:nth-child(1) { animation-delay: 0.1s; }
.pl-feature:nth-child(2) { animation-delay: 0.2s; }
.pl-feature:nth-child(3) { animation-delay: 0.3s; }
.pl-feature:nth-child(4) { animation-delay: 0.4s; }
/* ========================================
RIGHT COLUMN - FORM
======================================== */
.pl-form-section {
width: 58%;
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
background: var(--pl-bg);
}
.pl-card {
width: 100%;
max-width: 420px;
background: var(--pl-bg);
border-radius: var(--pl-radius);
box-shadow: var(--pl-shadow);
border: 1px solid var(--pl-border);
overflow: hidden;
}
/* Tabs */
.pl-tabs {
display: flex;
border-bottom: 1px solid var(--pl-border);
}
.pl-tab {
flex: 1;
padding: 18px 16px;
font-size: 14px;
font-weight: 600;
color: var(--pl-text-muted);
background: var(--pl-bg-hero);
border: none;
cursor: pointer;
position: relative;
transition: all 0.2s ease;
}
.pl-tab:hover {
color: var(--pl-text-secondary);
}
.pl-tab.active {
color: var(--pl-teal);
background: var(--pl-bg);
}
.pl-tab.active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: var(--pl-teal);
}
.pl-tab:focus-visible {
outline: 2px solid var(--pl-teal);
outline-offset: -2px;
}
.pl-btn:focus-visible,
.pl-social-btn:focus-visible {
outline: 2px solid var(--pl-teal);
outline-offset: 2px;
}
/* Tab panels */
.pl-panel {
padding: 28px;
display: none;
}
.pl-panel.active {
display: block;
animation: plFadeIn 0.25s ease;
}
@keyframes plFadeIn {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
/* Form elements */
.pl-form-group {
margin-bottom: 18px;
}
.pl-label {
display: block;
font-size: 13px;
font-weight: 500;
color: var(--pl-text);
margin-bottom: 6px;
}
.pl-input {
width: 100%;
padding: 12px 14px;
font-size: 15px;
font-family: inherit;
color: var(--pl-text);
background: var(--pl-bg);
border: 1px solid var(--pl-border);
border-radius: 8px;
transition: all 0.2s ease;
outline: none;
}
.pl-input::placeholder {
color: var(--pl-text-muted);
}
.pl-input:hover {
border-color: #D0D6E0;
}
.pl-input:focus {
border-color: var(--pl-teal);
box-shadow: 0 0 0 3px var(--pl-teal-light);
}
.pl-input.is-invalid {
border-color: #EF4444;
background: #FEF2F2;
}
.pl-input.is-valid {
border-color: #10B981;
background: rgba(16, 185, 129, 0.04);
}
.pl-hint {
font-size: 12px;
color: var(--pl-text-muted);
margin-top: 5px;
display: flex;
align-items: center;
gap: 4px;
}
/* Password wrapper */
.pl-password-wrap {
position: relative;
}
.pl-password-wrap .pl-input {
padding-right: 44px;
}
.pl-eye-btn {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
padding: 4px;
cursor: pointer;
color: var(--pl-text-muted);
transition: color 0.2s ease;
}
.pl-eye-btn:hover {
color: var(--pl-teal);
}
/* Row for name fields */
.pl-row {
display: flex;
gap: 12px;
}
.pl-row .pl-form-group {
flex: 1;
}
/* Primary button */
.pl-btn {
width: 100%;
padding: 14px 20px;
font-size: 15px;
font-weight: 600;
font-family: inherit;
color: #FFF;
background: linear-gradient(135deg, var(--pl-teal) 0%, var(--pl-teal-dark) 100%);
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease, transform 0.15s ease;
box-shadow: 0 2px 8px rgba(65, 162, 170, 0.3);
}
.pl-btn:hover {
background: linear-gradient(135deg, var(--pl-teal-dark) 0%, #2E8E96 100%);
box-shadow: 0 4px 16px rgba(65, 162, 170, 0.4);
transform: translateY(-1px);
}
.pl-btn:active {
transform: scale(0.98);
}
.pl-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.pl-btn-secondary {
background: linear-gradient(135deg, var(--pl-orange) 0%, var(--pl-orange-dark) 100%);
box-shadow: 0 2px 8px rgba(240, 158, 122, 0.3);
}
.pl-btn-secondary:hover {
background: linear-gradient(135deg, var(--pl-orange-dark) 0%, #D67A50 100%);
box-shadow: 0 4px 16px rgba(240, 158, 122, 0.4);
}
/* Button loading state */
.pl-btn-loading {
position: relative;
color: transparent !important;
}
.pl-btn-loading::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
top: 50%;
left: 50%;
margin-left: -10px;
margin-top: -10px;
border: 2px solid rgba(255,255,255,0.3);
border-top-color: #fff;
border-radius: 50%;
animation: plSpin 0.6s linear infinite;
}
/* Forgot link */
.pl-forgot {
display: inline-block;
font-size: 13px;
color: var(--pl-orange);
margin-top: 12px;
text-decoration: none;
transition: color 0.2s ease;
}
.pl-forgot:hover {
color: var(--pl-orange-dark);
text-decoration: underline;
}
/* Divider */
.pl-divider {
display: flex;
align-items: center;
margin: 24px 0;
gap: 14px;
}
.pl-divider-line {
flex: 1;
height: 1px;
background: var(--pl-border);
}
.pl-divider-text {
font-size: 12px;
font-weight: 500;
color: var(--pl-text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
/* Social buttons */
.pl-socials {
display: flex;
flex-direction: column;
gap: 10px;
}
.pl-social-btn {
width: 100%;
padding: 11px 16px;
font-size: 14px;
font-weight: 500;
font-family: inherit;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease, transform 0.15s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
text-decoration: none;
}
.pl-social-btn img {
width: 18px;
height: 18px;
}
.pl-social-google {
background: var(--pl-bg);
color: var(--pl-text);
border: 1px solid var(--pl-border);
}
.pl-social-google:hover {
background: var(--pl-bg-hero);
border-color: #D0D6E0;
}
.pl-social-facebook {
background: #1877F2;
color: #FFF;
border: 1px solid #1877F2;
}
.pl-social-facebook:hover {
background: #166FE5;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(24, 119, 242, 0.3);
}
.pl-social-google:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* Notification prefs (compact) */
.pl-notif-box {
background: var(--pl-bg-hero);
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 18px;
}
.pl-notif-label {
font-size: 12px;
font-weight: 500;
color: var(--pl-text-secondary);
margin-bottom: 8px;
}
.pl-notif-opts {
display: flex;
gap: 20px;
}
.pl-checkbox {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--pl-text);
cursor: pointer;
}
.pl-checkbox input {
width: 16px;
height: 16px;
accent-color: var(--pl-teal);
cursor: pointer;
}
/* Form note */
.pl-note {
font-size: 12px;
color: var(--pl-text-muted);
text-align: center;
margin-top: 14px;
line-height: 1.5;
}
/* CGU / RGPD consent block */
.pl-consent-box {
background: var(--pl-bg-hero);
border: 1px solid var(--pl-border);
border-radius: 10px;
padding: 14px 16px;
margin-bottom: 18px;
transition: border-color 0.2s ease;
}
.pl-consent-box.is-invalid {
border-color: #EF4444;
background: #FEF2F2;
}
.pl-consent-box .pl-checkbox {
font-size: 13px;
line-height: 1.5;
align-items: flex-start;
}
.pl-consent-box .pl-checkbox input {
margin-top: 2px;
flex-shrink: 0;
}
.pl-consent-link {
color: var(--pl-teal);
text-decoration: underline;
cursor: pointer;
font-weight: 500;
transition: color 0.2s ease;
}
.pl-consent-link:hover {
color: var(--pl-teal-dark);
}
.pl-consent-hint {
font-size: 11px;
color: var(--pl-text-muted);
margin-top: 6px;
padding-left: 22px;
display: flex;
align-items: center;
gap: 4px;
}
/* CGU modal overlay */
.pl-modal-overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
z-index: 10000;
display: none;
align-items: center;
justify-content: center;
padding: 20px;
animation: plFadeIn 0.2s ease;
}
.pl-modal-overlay.active {
display: flex;
}
.pl-modal {
background: #fff;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0,0,0,0.2);
max-width: 640px;
width: 100%;
max-height: 80vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.pl-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 18px 24px;
border-bottom: 1px solid var(--pl-border);
flex-shrink: 0;
}
.pl-modal-header h3 {
font-size: 16px;
font-weight: 700;
color: var(--pl-text);
margin: 0;
}
.pl-modal-close {
width: 32px;
height: 32px;
border-radius: 8px;
border: none;
background: var(--pl-bg-hero);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--pl-text-secondary);
transition: all 0.2s ease;
}
.pl-modal-close:hover {
background: #EEF0F4;
color: var(--pl-text);
}
.pl-modal-body {
padding: 24px;
overflow-y: auto;
font-size: 13px;
line-height: 1.7;
color: var(--pl-text-secondary);
}
.pl-modal-body h4 {
font-size: 14px;
font-weight: 600;
color: var(--pl-text);
margin: 18px 0 8px;
}
.pl-modal-body h4:first-child {
margin-top: 0;
}
.pl-modal-body ul {
padding-left: 20px;
margin: 8px 0;
}
.pl-modal-body ul li {
margin-bottom: 4px;
}
.pl-modal-footer {
padding: 14px 24px;
border-top: 1px solid var(--pl-border);
display: flex;
justify-content: flex-end;
flex-shrink: 0;
}
.pl-modal-footer .pl-btn {
width: auto;
padding: 10px 28px;
font-size: 13px;
}
.pl-input-code {
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
font-size: 18px;
font-weight: 600;
letter-spacing: 2px;
text-transform: uppercase;
text-align: center;
padding: 14px 16px;
background: linear-gradient(135deg, rgba(65, 162, 170, 0.04), rgba(240, 158, 122, 0.04));
border: 2px solid var(--pl-border);
}
.pl-input-code:focus {
border-color: var(--pl-teal);
background: var(--pl-bg);
}
.pl-input-code::placeholder {
font-weight: 400;
letter-spacing: 1px;
color: var(--pl-text-muted);
}
.pl-optional {
font-weight: 400;
color: var(--pl-text-muted);
}
.pl-required {
color: #EF4444;
margin-left: 2px;
}
/* Error alert */
.pl-error {
background: #FEF2F2;
border: 1px solid #FECACA;
border-radius: 8px;
padding: 12px 14px;
margin-bottom: 18px;
font-size: 13px;
color: #991B1B;
display: flex;
align-items: center;
gap: 8px;
}
.pl-error svg {
flex-shrink: 0;
color: #EF4444;
}
/* ========================================
FOOTER TRUST BAR
======================================== */
.pl-footer-trust {
background: var(--pl-bg-hero);
border-top: 1px solid var(--pl-border);
padding: 16px 24px;
display: flex;
justify-content: center;
gap: 32px;
}
.pl-footer-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--pl-text-muted);
}
.pl-footer-item svg {
width: 16px;
height: 16px;
color: var(--pl-teal);
}
/* ========================================
LOADER
======================================== */
.pl-loader {
position: fixed;
inset: 0;
background: rgba(255,255,255,0.95);
z-index: 9999;
display: none;
align-items: center;
justify-content: center;
}
.pl-loader.active {
display: flex;
}
.pl-loader-inner {
text-align: center;
}
.pl-spinner {
width: 40px;
height: 40px;
border: 3px solid var(--pl-border);
border-top-color: var(--pl-teal);
border-radius: 50%;
animation: plSpin 0.7s linear infinite;
}
@keyframes plSpin {
to { transform: rotate(360deg); }
}
.pl-loader-text {
margin-top: 16px;
font-size: 15px;
font-weight: 600;
color: var(--pl-text);
}
.pl-loader-sub {
margin-top: 6px;
font-size: 13px;
color: var(--pl-text-secondary);
}
/* ========================================
RESPONSIVE - MOBILE
======================================== */
@media (max-width: 900px) {
.pl-main {
flex-direction: column;
min-height: auto;
}
.pl-hero {
width: 100%;
padding: 32px 24px;
}
.pl-hero-content {
max-width: 100%;
animation: none;
}
.pl-hero h1 {
font-size: 26px;
}
.pl-hero-subtitle {
font-size: 15px;
margin-bottom: 24px;
}
.pl-features {
gap: 14px;
}
.pl-feature {
animation: none;
opacity: 1;
}
.pl-feature-icon {
width: 38px;
height: 38px;
}
.pl-feature-icon svg {
width: 18px;
height: 18px;
}
.pl-feature-title {
font-size: 13px;
}
.pl-feature-desc {
font-size: 12px;
}
.pl-hero-illustration {
display: none;
}
.pl-form-section {
width: 100%;
padding: 24px 16px 40px;
}
.pl-card {
max-width: 100%;
box-shadow: none;
border: none;
animation: none;
}
.pl-panel {
padding: 24px 20px;
}
.pl-row {
flex-direction: column;
gap: 0;
}
.pl-footer-trust {
flex-wrap: wrap;
gap: 16px 24px;
justify-content: center;
}
}
@media (max-width: 480px) {
.pl-hero {
padding: 24px 20px;
}
.pl-hero h1 {
font-size: 22px;
}
.pl-tab {
padding: 14px 12px;
font-size: 13px;
}
}
</style>
{% endblock %}
{% block Header %}
{{ parent() }}
{% endblock %}
{% block Content %}
<div class=\"pl-page\">
<!-- Loader -->
<div class=\"pl-loader\" id=\"plLoader\">
<div class=\"pl-loader-inner\">
<div class=\"pl-spinner\"></div>
<p class=\"pl-loader-text\">Création de votre compte...</p>
<p class=\"pl-loader-sub\">Préparation de votre espace parent</p>
</div>
</div>
<!-- Main two-column layout -->
<main class=\"pl-main\">
<!-- LEFT: Hero -->
<section class=\"pl-hero\">
<div class=\"pl-hero-content\">
<h1>Suivez le séjour de votre enfant en toute sérénité.</h1>
<p class=\"pl-hero-subtitle\">Photos, vidéos et messages vocaux, dans un espace privé réservé aux familles.</p>
<ul class=\"pl-features\">
<li class=\"pl-feature\">
<span class=\"pl-feature-icon orange\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>
<circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/>
<polyline points=\"21 15 16 10 5 21\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Photos & vidéos en direct</p>
<p class=\"pl-feature-desc\">Visualisez les moments du séjour en toute confidentialité</p>
</div>
</li>
<li class=\"pl-feature\">
<span class=\"pl-feature-icon teal\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Messages vocaux</p>
<p class=\"pl-feature-desc\">Accédez à l’ensemble des messages vocaux enregistrés, en illimité.</p>
</div>
</li>
<li class=\"pl-feature\">
<span class=\"pl-feature-icon coral\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M20 12v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-6\"/>
<rect x=\"6\" y=\"5\" width=\"12\" height=\"7\"/>
<path d=\"M12 3v5\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Souvenirs personnalisés</p>
<p class=\"pl-feature-desc\">Créez albums, livres et cadeaux uniques du séjour</p>
</div>
</li>
<li class=\"pl-feature\">
<span class=\"pl-feature-icon brown\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"/>
<path d=\"M13.73 21a2 2 0 0 1-3.46 0\"/>
</svg>
</span>
<div class=\"pl-feature-text\">
<p class=\"pl-feature-title\">Notifications instantanées</p>
<p class=\"pl-feature-desc\">Restez informé à chaque nouvelle publication</p>
</div>
</li>
</ul>
<!-- Decorative illustration -->
<div class=\"pl-hero-illustration\">
<svg viewBox=\"0 0 400 280\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">
<!-- Background shapes -->
<ellipse cx=\"200\" cy=\"250\" rx=\"180\" ry=\"20\" fill=\"#E5E9F0\" opacity=\"0.5\"/>
<!-- Phone mockup -->
<rect x=\"140\" y=\"30\" width=\"120\" height=\"200\" rx=\"16\" fill=\"#1A1A2E\"/>
<rect x=\"146\" y=\"40\" width=\"108\" height=\"180\" rx=\"12\" fill=\"#fff\"/>
<!-- Phone content - photos grid -->
<rect x=\"152\" y=\"55\" width=\"48\" height=\"48\" rx=\"6\" fill=\"#F09E7A\" opacity=\"0.3\"/>
<rect x=\"152\" y=\"55\" width=\"48\" height=\"48\" rx=\"6\" fill=\"url(#imgGrad1)\"/>
<rect x=\"204\" y=\"55\" width=\"44\" height=\"48\" rx=\"6\" fill=\"#41A2AA\" opacity=\"0.3\"/>
<rect x=\"204\" y=\"55\" width=\"44\" height=\"48\" rx=\"6\" fill=\"url(#imgGrad2)\"/>
<rect x=\"152\" y=\"107\" width=\"96\" height=\"60\" rx=\"6\" fill=\"#F56040\" opacity=\"0.2\"/>
<rect x=\"152\" y=\"107\" width=\"96\" height=\"60\" rx=\"6\" fill=\"url(#imgGrad3)\"/>
<!-- Photo icons -->
<circle cx=\"176\" cy=\"79\" r=\"12\" fill=\"#F09E7A\"/>
<path d=\"M170 82l4-5 3 3 5-6 6 8H170z\" fill=\"#fff\"/>
<circle cx=\"226\" cy=\"79\" r=\"10\" fill=\"#41A2AA\"/>
<polygon points=\"221,82 226,74 231,82\" fill=\"#fff\"/>
<!-- Play button on video -->
<circle cx=\"200\" cy=\"137\" r=\"14\" fill=\"rgba(255,255,255,0.9)\"/>
<polygon points=\"196,131 196,143 208,137\" fill=\"#F56040\"/>
<!-- Notification bar -->
<rect x=\"152\" y=\"175\" width=\"96\" height=\"38\" rx=\"8\" fill=\"#F8FAFB\"/>
<circle cx=\"168\" cy=\"194\" r=\"10\" fill=\"#41A2AA\"/>
<path d=\"M165 194l2 2 4-4\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>
<rect x=\"184\" y=\"188\" width=\"50\" height=\"6\" rx=\"3\" fill=\"#E5E9F0\"/>
<rect x=\"184\" y=\"198\" width=\"35\" height=\"4\" rx=\"2\" fill=\"#E5E9F0\"/>
<!-- Phone notch -->
<rect x=\"175\" y=\"34\" width=\"50\" height=\"4\" rx=\"2\" fill=\"#1A1A2E\"/>
<!-- Decorative elements around -->
<circle cx=\"80\" cy=\"80\" r=\"8\" fill=\"#F09E7A\" opacity=\"0.6\"/>
<circle cx=\"320\" cy=\"100\" r=\"6\" fill=\"#41A2AA\" opacity=\"0.5\"/>
<circle cx=\"340\" cy=\"180\" r=\"10\" fill=\"#F56040\" opacity=\"0.4\"/>
<circle cx=\"60\" cy=\"180\" r=\"5\" fill=\"#41A2AA\" opacity=\"0.4\"/>
<!-- Hearts/love -->
<path d=\"M300 60c-2-4-8-4-10 0-2-4-8-4-10 0 0 6 10 12 10 12s10-6 10-12z\" fill=\"#F09E7A\" opacity=\"0.7\"/>
<!-- Stars -->
<path d=\"M70 120l2 4 4 1-3 3 1 4-4-2-4 2 1-4-3-3 4-1 2-4z\" fill=\"#FFD93D\" opacity=\"0.8\"/>
<path d=\"M350 140l1.5 3 3 .5-2 2 .5 3-3-1.5-3 1.5.5-3-2-2 3-.5 1.5-3z\" fill=\"#FFD93D\" opacity=\"0.6\"/>
<!-- Gradients -->
<defs>
<linearGradient id=\"imgGrad1\" x1=\"152\" y1=\"55\" x2=\"200\" y2=\"103\">
<stop offset=\"0%\" stop-color=\"#F09E7A\" stop-opacity=\"0.4\"/>
<stop offset=\"100%\" stop-color=\"#F56040\" stop-opacity=\"0.3\"/>
</linearGradient>
<linearGradient id=\"imgGrad2\" x1=\"204\" y1=\"55\" x2=\"248\" y2=\"103\">
<stop offset=\"0%\" stop-color=\"#41A2AA\" stop-opacity=\"0.4\"/>
<stop offset=\"100%\" stop-color=\"#359BA3\" stop-opacity=\"0.3\"/>
</linearGradient>
<linearGradient id=\"imgGrad3\" x1=\"152\" y1=\"107\" x2=\"248\" y2=\"167\">
<stop offset=\"0%\" stop-color=\"#F56040\" stop-opacity=\"0.3\"/>
<stop offset=\"100%\" stop-color=\"#F09E7A\" stop-opacity=\"0.2\"/>
</linearGradient>
</defs>
</svg>
<!-- Floating notification badges -->
<div class=\"pl-floating-badges\">
<div class=\"pl-badge pl-badge-1\">
<span class=\"pl-badge-icon orange\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>
<circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/>
<polyline points=\"21 15 16 10 5 21\"/>
</svg>
</span>
<span>+12 photos</span>
</div>
<div class=\"pl-badge pl-badge-2\">
<span class=\"pl-badge-icon teal\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"/>
<polyline points=\"22 4 12 14.01 9 11.01\"/>
</svg>
</span>
<span>Bien arrivés !</span>
</div>
</div>
</div>
</div>
</section>
<!-- RIGHT: Form -->
<section class=\"pl-form-section\">
<div class=\"pl-card\">
<!-- Tabs -->
<div class=\"pl-tabs\" role=\"tablist\">
<button class=\"pl-tab active\" role=\"tab\" data-tab=\"login\" aria-selected=\"true\">Se connecter</button>
<button class=\"pl-tab\" role=\"tab\" data-tab=\"register\" aria-selected=\"false\">Créer un compte</button>
</div>
<!-- LOGIN PANEL -->
<div class=\"pl-panel active\" id=\"panel-login\" role=\"tabpanel\">
{% if error %}
<div class=\"pl-error\">
<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<circle cx=\"12\" cy=\"12\" r=\"10\"/>
<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/>
<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>
</svg>
Identifiant ou mot de passe incorrect.
</div>
{% endif %}
<form method=\"post\" action=\"{{ path('app_back_Parent') }}\" id=\"loginForm\" autocomplete=\"off\">
<!-- Code Séjour - Required for direct access -->
<div class=\"pl-form-group\">
<label class=\"pl-label\">
Code séjour
<span class=\"pl-required\">*</span>
</label>
<input type=\"text\"
class=\"pl-input pl-input-code\"
name=\"code_sejour\"
id=\"loginCode\"
placeholder=\" XX000000\"
maxlength=\"8\"
autocomplete=\"one-time-code\"
data-lpignore=\"true\"
data-form-type=\"other\"
required>
<p class=\"pl-hint\">
<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<circle cx=\"12\" cy=\"12\" r=\"10\"/>
<path d=\"M12 16v-4\"/>
<path d=\"M12 8h.01\"/>
</svg>
Code reçu par l'école ou l'organisateur du séjour
</p>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Adresse e-mail</label>
<input type=\"email\" class=\"pl-input\" name=\"email\" id=\"loginEmail\" value=\"{{ last_username }}\" placeholder=\"votre@email.com\" autocomplete=\"username\" required>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Mot de passe</label>
<div class=\"pl-password-wrap\">
<input type=\"password\" class=\"pl-input\" name=\"password\" id=\"loginPwd\" placeholder=\"••••••••\" autocomplete=\"current-password\" required>
<button type=\"button\" class=\"pl-eye-btn\" data-target=\"loginPwd\" aria-label=\"Afficher\">
<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>
<circle cx=\"12\" cy=\"12\" r=\"3\"/>
</svg>
</button>
</div>
</div>
<input type=\"hidden\" name=\"_csrf_token\" value=\"{{ csrf_token('authenticate') }}\">
<button type=\"submit\" class=\"pl-btn\">Se connecter</button>
<a href=\"{{ path('forgotPassparent') }}\" class=\"pl-forgot\">Vous avez oublié votre mot de passe ?</a>
</form>
<div class=\"pl-divider\">
<span class=\"pl-divider-line\"></span>
<span class=\"pl-divider-text\">ou</span>
<span class=\"pl-divider-line\"></span>
</div>
<div class=\"pl-socials\">
<a href=\"{{ path('connect_google_start') }}\" class=\"pl-social-btn pl-social-google\">
<img src=\"{{ asset('/images/icons-google.png') }}\" alt=\"\">
Continuer avec Google
</a>
<a href=\"{{ path('connect_facebook_start') }}\" class=\"pl-social-btn pl-social-facebook\">
<img src=\"{{ asset('/images/icons-facebook.png') }}\" alt=\"\">
Continuer avec Facebook
</a>
</div>
</div>
<!-- REGISTER PANEL -->
<div class=\"pl-panel\" id=\"panel-register\" role=\"tabpanel\">
<form id=\"registerForm\" onsubmit=\"return false;\" autocomplete=\"off\">
<div class=\"pl-row\">
<div class=\"pl-form-group\">
<label class=\"pl-label\">Nom</label>
<input type=\"text\" class=\"pl-input\" id=\"regNom\" name=\"family-name\" placeholder=\"Votre nom\" autocomplete=\"family-name\" required>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Prénom</label>
<input type=\"text\" class=\"pl-input\" id=\"regPrenom\" name=\"given-name\" placeholder=\"Votre prénom\" autocomplete=\"given-name\" required>
</div>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Adresse e-mail</label>
<input type=\"email\" class=\"pl-input\" id=\"regEmail\" name=\"email\" placeholder=\"votre@email.com\" autocomplete=\"email\" required>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Mot de passe</label>
<div class=\"pl-password-wrap\">
<input type=\"password\" class=\"pl-input\" id=\"regPwd\" name=\"new-password\" placeholder=\"Minimum 6 caractères\" autocomplete=\"new-password\" required>
<button type=\"button\" class=\"pl-eye-btn\" data-target=\"regPwd\" aria-label=\"Afficher\">
<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>
<circle cx=\"12\" cy=\"12\" r=\"3\"/>
</svg>
</button>
</div>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Confirmer le mot de passe</label>
<div class=\"pl-password-wrap\">
<input type=\"password\" class=\"pl-input\" id=\"regPwdConfirm\" name=\"confirm-password\" placeholder=\"Retapez votre mot de passe\" autocomplete=\"new-password\" required>
<button type=\"button\" class=\"pl-eye-btn\" data-target=\"regPwdConfirm\" aria-label=\"Afficher\">
<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>
<circle cx=\"12\" cy=\"12\" r=\"3\"/>
</svg>
</button>
</div>
</div>
<div class=\"pl-form-group\">
<label class=\"pl-label\">Téléphone portable</label>
<input type=\"tel\" class=\"pl-input\" id=\"regPhone\" placeholder=\"06 12 34 56 78\" required>
</div>
<div class=\"pl-notif-box\">
<p class=\"pl-notif-label\">Recevoir les notifications :</p>
<div class=\"pl-notif-opts\">
<label class=\"pl-checkbox\">
<input type=\"checkbox\" id=\"notifSms\" checked>
SMS
</label>
<label class=\"pl-checkbox\">
<input type=\"checkbox\" id=\"notifEmail\" checked>
E-mail
</label>
</div>
</div>
<div class=\"pl-consent-box\" id=\"consentBox\">
<label class=\"pl-checkbox\">
<input type=\"checkbox\" id=\"acceptCgu\">
J'accepte les <span class=\"pl-consent-link\" onclick=\"openCguModal(event)\">Conditions Générales d'Utilisation</span> et la <span class=\"pl-consent-link\" onclick=\"openPolitiqueModal(event)\">Politique de Confidentialité</span> <span class=\"pl-required\">*</span>
</label>
<p class=\"pl-consent-hint\">
<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"/></svg>
Données hébergées en France, conformité RGPD
</p>
</div>
<button type=\"button\" class=\"pl-btn pl-btn-secondary\" onclick=\"handleRegister()\">Créer mon compte Parent</button>
<p class=\"pl-note\">Vous pourrez modifier vos informations et vos préférences de notifications à tout moment.</p>
</form>
<div class=\"pl-divider\">
<span class=\"pl-divider-line\"></span>
<span class=\"pl-divider-text\">ou</span>
<span class=\"pl-divider-line\"></span>
</div>
<div class=\"pl-socials\">
<a href=\"{{ path('connect_google_start') }}\" class=\"pl-social-btn pl-social-google\">
<img src=\"{{ asset('/images/icons-google.png') }}\" alt=\"\">
Continuer avec Google
</a>
<a href=\"{{ path('connect_facebook_start') }}\" class=\"pl-social-btn pl-social-facebook\">
<img src=\"{{ asset('/images/icons-facebook.png') }}\" alt=\"\">
Continuer avec Facebook
</a>
</div>
</div>
</div>
</section>
</main>
<!-- CGU Modal -->
<div class=\"pl-modal-overlay\" id=\"cguModal\">
<div class=\"pl-modal\">
<div class=\"pl-modal-header\">
<h3>Conditions Générales d'Utilisation</h3>
<button class=\"pl-modal-close\" onclick=\"closeCguModal()\">
<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>
</button>
</div>
<div class=\"pl-modal-body\">
<h4>1. Objet</h4>
<p>Les présentes Conditions Générales d'Utilisation (CGU) régissent l'accès et l'utilisation de la plateforme 5sur5séjour par les utilisateurs « Parents ». L'inscription implique l'acceptation pleine et entière des présentes conditions.</p>
<h4>2. Accès au service</h4>
<p>L'accès à l'espace Parent nécessite un code séjour fourni par l'accompagnateur ou l'organisateur du séjour. Le Parent crée un compte personnel pour consulter les photos, vidéos et messages vocaux déposés pendant le séjour de son enfant.</p>
<h4>3. Données personnelles collectées</h4>
<ul>
<li>Nom, prénom, adresse e-mail, numéro de téléphone portable</li>
<li>Préférences de notification (SMS, e-mail)</li>
<li>Données de connexion et d'utilisation de la plateforme</li>
</ul>
<h4>4. Finalités du traitement</h4>
<p>Vos données sont utilisées exclusivement pour :</p>
<ul>
<li>Créer et gérer votre compte Parent</li>
<li>Vous donner accès aux contenus du séjour de votre enfant</li>
<li>Vous envoyer des notifications (nouvelles photos, messages, commandes)</li>
<li>Assurer le bon fonctionnement et la sécurité du service</li>
</ul>
<h4>5. Durée de conservation</h4>
<p>Les données personnelles sont conservées pendant la durée d'utilisation du service. Les contenus de séjour (photos, vidéos) sont automatiquement supprimés 2 mois après la fin du séjour. Votre compte est supprimé après 2 ans d'inactivité.</p>
<h4>6. Droits de l'utilisateur</h4>
<p>Conformément au RGPD (Règlement UE 2016/679), vous disposez d'un droit d'accès, de rectification, de suppression, de limitation et de portabilité de vos données. Vous pouvez exercer ces droits par e-mail à <strong>contact@5sur5sejour.com</strong>.</p>
<h4>7. Hébergement et sécurité</h4>
<p>Toutes les données sont hébergées en France (OVH, 2 rue Kellermann, 59100 Roubaix). La plateforme utilise un chiffrement SSL et des mesures de sécurité conformes aux standards en vigueur.</p>
<h4>8. Responsable du traitement</h4>
<p>TRUST CONSEILS — 199 Avenue Francis de Pressensé, 69200 Vénissieux.<br>Contact : <strong>contact@5sur5sejour.com</strong> — Tél. : 05 36 28 29 30</p>
</div>
<div class=\"pl-modal-footer\">
<button class=\"pl-btn\" onclick=\"closeCguModal()\">J'ai compris</button>
</div>
</div>
</div>
<!-- Politique Modal -->
<div class=\"pl-modal-overlay\" id=\"politiqueModal\">
<div class=\"pl-modal\">
<div class=\"pl-modal-header\">
<h3>Politique de Confidentialité</h3>
<button class=\"pl-modal-close\" onclick=\"closePolitiqueModal()\">
<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>
</button>
</div>
<div class=\"pl-modal-body\">
<h4>Charte d'utilisation des données personnelles</h4>
<p>La présente politique de confidentialité s'applique à la plateforme 5sur5séjour (5sur5sejour.com), éditée par TRUST CONSEILS.</p>
<h4>Données collectées</h4>
<p>Dans le cadre de l'utilisation du service, nous collectons les données suivantes : nom, prénom, adresse e-mail, numéro de téléphone, données de connexion. Ces données sont nécessaires au fonctionnement du service.</p>
<h4>Base légale du traitement</h4>
<p>Le traitement de vos données repose sur votre consentement (acceptation des présentes conditions lors de l'inscription) et sur l'exécution du contrat de service.</p>
<h4>Destinataires des données</h4>
<p>Vos données personnelles ne sont jamais vendues ni partagées avec des tiers à des fins commerciales. Elles sont accessibles uniquement aux équipes de TRUST CONSEILS dans le cadre strict du fonctionnement du service.</p>
<h4>Transferts de données</h4>
<p>Aucun transfert de données hors de l'Union Européenne n'est effectué. L'ensemble des données est hébergé en France.</p>
<h4>Cookies</h4>
<p>La plateforme utilise des cookies strictement nécessaires au fonctionnement du service (session, authentification). Aucun cookie publicitaire n'est utilisé.</p>
<h4>Vos droits</h4>
<p>Conformément au RGPD et à la loi Informatique et Libertés, vous disposez des droits suivants :</p>
<ul>
<li><strong>Droit d'accès</strong> : obtenir une copie de vos données</li>
<li><strong>Droit de rectification</strong> : corriger vos informations</li>
<li><strong>Droit de suppression</strong> : demander l'effacement de vos données</li>
<li><strong>Droit d'opposition</strong> : vous opposer au traitement</li>
<li><strong>Droit à la portabilité</strong> : recevoir vos données dans un format structuré</li>
<li><strong>Droit de retrait du consentement</strong> : à tout moment</li>
</ul>
<p>Pour exercer vos droits : <strong>contact@5sur5sejour.com</strong></p>
<p>Pour en savoir plus : <a href=\"https://www.cnil.fr/\" target=\"_blank\" rel=\"noopener\" style=\"color:var(--pl-teal);\">www.cnil.fr</a></p>
</div>
<div class=\"pl-modal-footer\">
<button class=\"pl-btn\" onclick=\"closePolitiqueModal()\">J'ai compris</button>
</div>
</div>
</div>
<!-- Footer trust bar -->
<footer class=\"pl-footer-trust\">
<span class=\"pl-footer-item\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"/>
<path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>
</svg>
Connexion sécurisée
</span>
<span class=\"pl-footer-item\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"/>
</svg>
Données protégées
</span>
<span class=\"pl-footer-item\">
<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">
<circle cx=\"12\" cy=\"12\" r=\"10\"/>
<line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\"/>
<path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"/>
</svg>
Hébergé en France
</span>
</footer>
</div>
{% endblock %}
{% block Footer %}
{{ parent() }}
{% endblock %}
{% block javascript %}
{{ parent() }}
<script src=\"https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js\"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Tab switching
const tabs = document.querySelectorAll('.pl-tab');
const panels = document.querySelectorAll('.pl-panel');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = tab.dataset.tab;
tabs.forEach(t => {
t.classList.remove('active');
t.setAttribute('aria-selected', 'false');
});
tab.classList.add('active');
tab.setAttribute('aria-selected', 'true');
panels.forEach(p => p.classList.remove('active'));
document.getElementById('panel-' + target).classList.add('active');
});
});
// Clear autofilled code séjour field on page load (browser autofill fix)
const codeInput = document.getElementById('loginCode');
if (codeInput) {
// Clear any incorrect autofill value
setTimeout(() => {
const currentValue = codeInput.value;
// If the value doesn't match code séjour format (2 letters + 6 digits), clear it
if (currentValue && !/^[A-Z]{2}[0-9]{6}\$/.test(currentValue.toUpperCase())) {
codeInput.value = '';
}
}, 100);
}
// Password toggle
document.querySelectorAll('.pl-eye-btn').forEach(btn => {
btn.addEventListener('click', () => {
const input = document.getElementById(btn.dataset.target);
const isPassword = input.type === 'password';
input.type = isPassword ? 'text' : 'password';
btn.querySelector('svg').style.opacity = isPassword ? '0.5' : '1';
});
});
// Auto-format code séjour (uppercase) and validation
if (codeInput) {
codeInput.addEventListener('input', (e) => {
let value = e.target.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
e.target.value = value;
// Visual feedback when complete
if (value.length === 8) {
e.target.style.borderColor = '#41A2AA';
e.target.style.background = 'rgba(65, 162, 170, 0.06)';
} else {
e.target.style.borderColor = '';
e.target.style.background = '';
}
});
// Validate on form submit
document.getElementById('loginForm').addEventListener('submit', function(e) {
const codePattern = /^[A-Z]{2}[0-9]{6}\$/;
if (!codePattern.test(codeInput.value)) {
e.preventDefault();
codeInput.classList.add('is-invalid');
Swal.fire({
icon: 'error',
title: 'Code séjour invalide',
html: '<p style=\"margin-bottom:8px;\">Le code doit contenir :</p><p style=\"color:#5A6178;font-size:14px;\"><strong>2 lettres</strong> + <strong>6 chiffres</strong><br>Exemple : <span style=\"color:#41A2AA;font-weight:600;\">XX000000</span></p>',
confirmButtonColor: '#41a2aa'
});
} else {
// Show loading state on button
const btn = this.querySelector('button[type=\"submit\"]');
btn.classList.add('pl-btn-loading');
btn.disabled = true;
}
});
}
// Add visual feedback when email is valid
const emailInputs = document.querySelectorAll('input[type=\"email\"]');
emailInputs.forEach(input => {
input.addEventListener('blur', function() {
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+\$/;
if (this.value && emailRegex.test(this.value)) {
this.classList.add('is-valid');
this.classList.remove('is-invalid');
} else if (this.value) {
this.classList.add('is-invalid');
this.classList.remove('is-valid');
}
});
input.addEventListener('input', function() {
this.classList.remove('is-valid', 'is-invalid');
});
});
// Login error
{% if error %}
Swal.fire({
icon: 'error',
title: 'Erreur de connexion',
text: 'Identifiant ou mot de passe incorrect.',
confirmButtonColor: '#41a2aa'
});
{% endif %}
});
// Modal CGU / Politique
function openCguModal(e) { e && e.preventDefault(); document.getElementById('cguModal').classList.add('active'); document.body.style.overflow = 'hidden'; }
function closeCguModal() { document.getElementById('cguModal').classList.remove('active'); document.body.style.overflow = ''; }
function openPolitiqueModal(e) { e && e.preventDefault(); document.getElementById('politiqueModal').classList.add('active'); document.body.style.overflow = 'hidden'; }
function closePolitiqueModal() { document.getElementById('politiqueModal').classList.remove('active'); document.body.style.overflow = ''; }
document.querySelectorAll('.pl-modal-overlay').forEach(function(overlay) {
overlay.addEventListener('click', function(e) {
if (e.target === overlay) {
overlay.classList.remove('active');
document.body.style.overflow = '';
}
});
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') { closeCguModal(); closePolitiqueModal(); }
});
// Registration
function handleRegister() {
const loader = document.getElementById('plLoader');
const fields = {
nom: document.getElementById('regNom'),
prenom: document.getElementById('regPrenom'),
email: document.getElementById('regEmail'),
pwd: document.getElementById('regPwd'),
pwdConfirm: document.getElementById('regPwdConfirm'),
phone: document.getElementById('regPhone')
};
// Reset
Object.values(fields).forEach(f => f.classList.remove('is-invalid'));
document.getElementById('consentBox').classList.remove('is-invalid');
// Validate
let valid = true;
if (!fields.nom.value.trim()) { fields.nom.classList.add('is-invalid'); valid = false; }
if (!fields.prenom.value.trim()) { fields.prenom.classList.add('is-invalid'); valid = false; }
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+\$/;
if (!emailRegex.test(fields.email.value)) { fields.email.classList.add('is-invalid'); valid = false; }
if (fields.pwd.value.length < 6) {
fields.pwd.classList.add('is-invalid');
Swal.fire({ icon: 'warning', title: 'Mot de passe trop court', text: 'Minimum 6 caractères.', confirmButtonColor: '#41a2aa' });
return;
}
if (fields.pwd.value !== fields.pwdConfirm.value) {
fields.pwdConfirm.classList.add('is-invalid');
Swal.fire({ icon: 'warning', title: 'Erreur', text: 'Les mots de passe ne correspondent pas.', confirmButtonColor: '#41a2aa' });
return;
}
if (!fields.phone.value.trim()) { fields.phone.classList.add('is-invalid'); valid = false; }
if (!document.getElementById('acceptCgu').checked) {
document.getElementById('consentBox').classList.add('is-invalid');
Swal.fire({
icon: 'warning',
title: 'Conditions requises',
html: 'Vous devez accepter les <strong>Conditions Générales d\\'Utilisation</strong> et la <strong>Politique de Confidentialité</strong> pour créer votre compte.',
confirmButtonColor: '#41a2aa'
});
return;
}
if (!valid) return;
loader.classList.add('active');
const data = {
nomparent: fields.nom.value.trim(),
prenomparent: fields.prenom.value.trim(),
mailparent: fields.email.value.trim(),
numtel: fields.phone.value.trim(),
passwordparent: fields.pwd.value,
confirmpassword: fields.pwdConfirm.value,
sms: document.getElementById('notifSms').checked ? 1 : 0,
mailnotif: document.getElementById('notifEmail').checked ? 1 : 0
};
fetch(\"{{ path('parent_register') }}\", {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(data)
})
.then(r => r.text())
.then(text => {
loader.classList.remove('active');
let code = '';
try {
const parsed = JSON.parse(text);
code = typeof parsed === 'string' ? parsed : (parsed && parsed.code !== undefined ? String(parsed.code) : '');
} catch (e) {
code = text.trim();
}
if (code === 'eror') {
fields.email.classList.add('is-invalid');
Swal.fire({
icon: false,
title: '🔐 Vous avez déjà un compte',
text: 'Cette adresse est déjà associée à un compte parent. Vous pouvez vous connecter ou réinitialiser votre mot de passe si besoin.',
footer: '<a href=\"{{ path(\"forgotPassparent\") }}\" style=\"color:#F09E7A;\">Mot de passe oublié ?</a>',
confirmButtonColor: '#41a2aa'
});
} else if (code === 'erorpasswordconfirm') {
fields.pwdConfirm.classList.add('is-invalid');
Swal.fire({ icon: 'error', title: 'Erreur', text: 'Les mots de passe ne correspondent pas.', confirmButtonColor: '#41a2aa' });
} else if (code === 'done') {
Swal.fire({
icon: 'success',
title: '🎉 Bienvenue !',
html: '<p>Votre compte parent est presque prêt.</p><p style=\"color:#5A6178;font-size:14px;\">📩 Un e-mail vous a été envoyé pour activer votre compte.</p>',
confirmButtonText: 'Compris',
confirmButtonColor: '#41a2aa'
}).then(() => location.reload());
} else {
Swal.fire({ icon: 'error', title: 'Erreur', text: 'Une réponse inattendue a été reçue. Veuillez réessayer.', confirmButtonColor: '#41a2aa' });
}
})
.catch(() => {
loader.classList.remove('active');
Swal.fire({ icon: 'error', title: 'Erreur', text: 'Un problème est survenu. Veuillez réessayer.', confirmButtonColor: '#F09E7A' });
});
}
</script>
{% endblock %}
", "Parent/LoginParent.html.twig", "/var/www/5sur5sejour/templates/Parent/LoginParent.html.twig");
}
}