This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
|
||||
// Autoriser uniquement les requêtes POST
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'message' => 'Méthode non autorisée.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Protection anti-spam (honeypot)
|
||||
if (!empty($_POST['website'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Spam détecté.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Récupération et nettoyage des champs
|
||||
$nom = trim(strip_tags($_POST['nom'] ?? ''));
|
||||
$email = trim(strip_tags($_POST['email'] ?? ''));
|
||||
$message = trim(strip_tags($_POST['message'] ?? ''));
|
||||
|
||||
// Validation
|
||||
$errors = [];
|
||||
if (empty($nom)) $errors[] = 'Le nom est requis.';
|
||||
if (empty($email)) $errors[] = "L'adresse email est requise.";
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = "L'adresse email n'est pas valide.";
|
||||
if (empty($message)) $errors[] = 'Le message est requis.';
|
||||
if (strlen($message) > 5000) $errors[] = 'Le message est trop long (5000 caractères max).';
|
||||
|
||||
if (!empty($errors)) {
|
||||
http_response_code(422);
|
||||
echo json_encode(['success' => false, 'message' => implode(' ', $errors)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Destinataire
|
||||
$to = 'contact@la-maison-de-cecile.fr';
|
||||
$subject = '=?UTF-8?B?' . base64_encode('[La Maison de Cécile] Message de ' . $nom) . '?=';
|
||||
|
||||
// Corps du mail
|
||||
$body = "Vous avez reçu un nouveau message via le formulaire de contact.\n\n";
|
||||
$body .= "Nom : {$nom}\n";
|
||||
$body .= "Email : {$email}\n";
|
||||
$body .= "Message:\n{$message}\n";
|
||||
|
||||
// En-têtes
|
||||
$headers = "From: =?UTF-8?B?" . base64_encode($nom) . "?= <no-reply@la-maison-de-cecile.fr>\r\n";
|
||||
$headers .= "Reply-To: {$email}\r\n";
|
||||
$headers .= "MIME-Version: 1.0\r\n";
|
||||
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
||||
$headers .= "Content-Transfer-Encoding: base64\r\n";
|
||||
|
||||
$success = mail($to, $subject, base64_encode($body), $headers);
|
||||
|
||||
if ($success) {
|
||||
echo json_encode(['success' => true, 'message' => 'Votre message a bien été envoyé. Nous vous répondrons sous 24h.']);
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'message' => "Une erreur s'est produite. Veuillez réessayer ou nous contacter par téléphone."]);
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 58 KiB |
+163
-8
@@ -1,9 +1,164 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
role="img"
|
||||
aria-labelledby="title desc">
|
||||
<title id="title">La Maison de Cécile — favicon maison rivière pont</title>
|
||||
<desc id="desc">Icône simple avec maison blanche, toit couleur tuile, pont en arc et rivière bleue en forme de S.</desc>
|
||||
|
||||
<defs>
|
||||
<clipPath id="circleClip">
|
||||
<circle cx="256" cy="256" r="240"/>
|
||||
</clipPath>
|
||||
|
||||
<linearGradient id="backgroundGradient" x1="256" y1="16" x2="256" y2="496" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#7EA35F"/>
|
||||
<stop offset="1" stop-color="#3F703A"/>
|
||||
</linearGradient>
|
||||
|
||||
<linearGradient id="riverGradient" x1="210" y1="230" x2="285" y2="505" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#8CC2C6"/>
|
||||
<stop offset="1" stop-color="#4E8F9A"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Background circle -->
|
||||
<circle cx="256" cy="256" r="240" fill="url(#backgroundGradient)"/>
|
||||
|
||||
<g clip-path="url(#circleClip)">
|
||||
<!-- Distant soft hill -->
|
||||
<path
|
||||
d="M-20 242
|
||||
C70 210 145 220 220 250
|
||||
C315 288 392 240 532 210
|
||||
L532 512 L-20 512 Z"
|
||||
fill="#5D8749"
|
||||
opacity="0.72"/>
|
||||
|
||||
<!-- Left foreground hill -->
|
||||
<path
|
||||
d="M-20 360
|
||||
C65 292 150 282 235 338
|
||||
C170 405 100 455 -20 512 Z"
|
||||
fill="#315F31"/>
|
||||
|
||||
<!-- Right foreground hill -->
|
||||
<path
|
||||
d="M532 350
|
||||
C455 286 360 283 280 338
|
||||
C350 414 430 465 532 512 Z"
|
||||
fill="#315F31"/>
|
||||
|
||||
<!-- River body, S shape -->
|
||||
<path
|
||||
d="M279 247
|
||||
C226 275 224 313 267 337
|
||||
C315 364 323 404 272 430
|
||||
C235 449 206 470 198 512
|
||||
L351 512
|
||||
C373 466 359 431 320 407
|
||||
C280 382 286 358 330 334
|
||||
C381 306 380 264 322 239
|
||||
Z"
|
||||
fill="url(#riverGradient)"/>
|
||||
|
||||
<!-- River white banks/highlights -->
|
||||
<path
|
||||
d="M284 259
|
||||
C238 282 242 309 277 327
|
||||
C326 352 337 400 282 426"
|
||||
fill="none"
|
||||
stroke="#FFFFFF"
|
||||
stroke-width="16"
|
||||
stroke-linecap="round"
|
||||
opacity="0.95"/>
|
||||
|
||||
<path
|
||||
d="M221 452
|
||||
C247 436 280 429 303 406"
|
||||
fill="none"
|
||||
stroke="#FFFFFF"
|
||||
stroke-width="13"
|
||||
stroke-linecap="round"
|
||||
opacity="0.95"/>
|
||||
|
||||
<!-- Bridge deck -->
|
||||
<path
|
||||
d="M82 336
|
||||
C148 300 204 283 256 283
|
||||
C308 283 364 300 430 336
|
||||
L430 373
|
||||
C365 336 309 319 256 319
|
||||
C203 319 147 336 82 373 Z"
|
||||
fill="#E7DFC8"/>
|
||||
|
||||
<!-- Bridge arch cutout -->
|
||||
<path
|
||||
d="M204 372
|
||||
C213 333 299 333 308 372
|
||||
L308 410
|
||||
L204 410 Z"
|
||||
fill="#315F31"/>
|
||||
|
||||
<!-- Subtle bridge outline -->
|
||||
<path
|
||||
d="M87 336
|
||||
C150 302 205 286 256 286
|
||||
C307 286 362 302 425 336"
|
||||
fill="none"
|
||||
stroke="#FFFFFF"
|
||||
stroke-width="8"
|
||||
stroke-linecap="round"
|
||||
opacity="0.95"/>
|
||||
|
||||
<!-- House body -->
|
||||
<rect x="173" y="165" width="166" height="126" rx="6" fill="#FFFFFF"/>
|
||||
|
||||
<!-- Roof fill -->
|
||||
<path
|
||||
d="M151 170
|
||||
L256 78
|
||||
L361 170
|
||||
L343 190
|
||||
L256 113
|
||||
L169 190 Z"
|
||||
fill="#C96F3A"/>
|
||||
|
||||
<!-- Roof underside / clean edge -->
|
||||
<path
|
||||
d="M171 181
|
||||
L256 108
|
||||
L341 181"
|
||||
fill="none"
|
||||
stroke="#B95F32"
|
||||
stroke-width="13"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
|
||||
<!-- Chimney -->
|
||||
<rect x="306" y="102" width="30" height="68" rx="5" fill="#FFFFFF"/>
|
||||
|
||||
<!-- Repaint roof over chimney base for clean overlap -->
|
||||
<path
|
||||
d="M151 170
|
||||
L256 78
|
||||
L361 170"
|
||||
fill="none"
|
||||
stroke="#C96F3A"
|
||||
stroke-width="22"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
|
||||
<!-- Door -->
|
||||
<rect x="207" y="231" width="33" height="60" rx="4" fill="#315F31"/>
|
||||
|
||||
<!-- Window -->
|
||||
<g fill="#315F31">
|
||||
<rect x="272" y="212" width="20" height="20" rx="3"/>
|
||||
<rect x="300" y="212" width="20" height="20" rx="3"/>
|
||||
<rect x="272" y="240" width="20" height="20" rx="3"/>
|
||||
<rect x="300" y="240" width="20" height="20" rx="3"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 749 B After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 412 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 389 KiB |
@@ -7,7 +7,7 @@ import terrasse from '../assets/images/terrasse.jpg';
|
||||
import hamac from '../assets/images/hamac.jpg';
|
||||
---
|
||||
|
||||
<section id="about" class="py-32 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<section id="about" class="py-16 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<div class="max-w-6xl mx-auto px-6">
|
||||
<div class="grid md:grid-cols-2 gap-16 items-center">
|
||||
|
||||
@@ -15,10 +15,10 @@ import hamac from '../assets/images/hamac.jpg';
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-primary mb-5">
|
||||
La maison
|
||||
</span>
|
||||
<h2 class="font-serif text-5xl md:text-6xl font-light leading-tight mb-8">
|
||||
<h2 class="font-display text-5xl md:text-6xl font-light leading-tight mb-8">
|
||||
Entre rivière, prairies et forêts verdoyantes...
|
||||
</h2>
|
||||
<p class="text-dark/70 leading-relaxed mb-4">
|
||||
<p class="text-dark/80 leading-relaxed mb-4">
|
||||
Charmante maison de village surplombant l'Allier, Cécile l'a faite à son image :
|
||||
chaleureuse, vivante, colorée.
|
||||
Vous pouvez profiter de la terrasse abritée et du jardin, accueillant et verdoyant où il fait bon traîner.<br/>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
import { Car, Clock, Clock2, Train } from 'lucide-astro';
|
||||
import { Car, Clock, Train } from 'lucide-astro';
|
||||
---
|
||||
|
||||
<section id="activities" class="py-32 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<section id="activities" class="py-16 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<div class="max-w-6xl mx-auto px-6">
|
||||
|
||||
<div class="mb-14 text-center">
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-primary mb-4">Une étape idéale</span>
|
||||
<h2 class="font-serif text-5xl font-normal">Bienvenue a Pont d'Alleyras</h2>
|
||||
<h2 class="font-display text-5xl font-normal">Bienvenue a Pont d'Alleyras</h2>
|
||||
<p class="text-dark/80 mt-4 max-w-4xl mx-auto ">
|
||||
Niché dans les gorges sauvages du Haut-Allier, au sud de la Haute-Loire et a deux pas de la Lozére,<br/> le village du Pont d'Alleyras est un point de départ idéal pour les randonneurs, cyclistes et amateurs de nature.
|
||||
</p>
|
||||
@@ -109,7 +109,7 @@ import { Car, Clock, Clock2, Train } from 'lucide-astro';
|
||||
le canoë.
|
||||
</p>
|
||||
<a
|
||||
href="https://www.ffck.org/"
|
||||
href="https://tonic-aventure.fr/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-block text-xs tracking-[0.15em] uppercase text-primary border-b border-primary/40 hover:border-primary transition-colors"
|
||||
@@ -132,7 +132,7 @@ import { Car, Clock, Clock2, Train } from 'lucide-astro';
|
||||
Plusieurs circuits balisés autour d'Alleyras, Monistrol-d'Allier et Saugues, accessibles à tous les niveaux, permettent de découvrir la vallée de l'Allier et ses gorges.
|
||||
</p>
|
||||
<a
|
||||
href="https://www.hautligonauvergne.fr/activites/vtt/"
|
||||
href="https://sitesvtt.ffc.fr/sites/velay-volcanique-entre-loire-et-allier-6/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-block text-xs tracking-[0.15em] uppercase text-primary border-b border-primary/40 hover:border-primary transition-colors"
|
||||
@@ -188,7 +188,7 @@ import { Car, Clock, Clock2, Train } from 'lucide-astro';
|
||||
|
||||
<!-- Carte + accès -->
|
||||
<div class="space-y-6">
|
||||
<div class="h-[420px] rounded-sm overflow-hidden">
|
||||
<div class="h-[420px] rounded-md overflow-hidden shadow-lg border border-secondary">
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d440.97773965266185!2d3.6727355223841234!3d44.919259000000004!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x12b3549765f98705%3A0x8bf01e8fb12db201!2s3%20Imp.%20du%20Moulin%2C%2043580%20Alleyras!5e1!3m2!1sfr!2sfr!4v1780157726814!5m2!1sfr!2sfr"
|
||||
width="100%"
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
---
|
||||
const bonuses = [
|
||||
{
|
||||
emoji: "🧘",
|
||||
title: "Yoga",
|
||||
description: "Découvrez le yoga avec une enseignante diplômée et passionnée — 25 ans de pratique à votre service.",
|
||||
},
|
||||
{
|
||||
emoji: "🌿",
|
||||
title: "Plantes comestibles",
|
||||
description: "Partez à la découverte des plantes sauvages et comestibles qui fleurissent autour du domaine.",
|
||||
},
|
||||
{
|
||||
emoji: "🫧",
|
||||
title: "Massages ayurvédiques",
|
||||
description: "Offrez-vous un soin profond et revitalisant avec des massages ayurvédiques traditionnels.",
|
||||
},
|
||||
{
|
||||
emoji: "🥾",
|
||||
title: "Randonnée guidée",
|
||||
description: "Suivez les pas d'une amoureuse des sentiers d'ici, qui vous révèlera les secrets des chemins locaux.",
|
||||
},
|
||||
{
|
||||
emoji: "🎲",
|
||||
title: "Jeux & bibliothèque",
|
||||
description: "Une belle sélection de jeux de société et une bibliothèque accueillante pour les soirées douces.",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<details class="group bonus-details">
|
||||
|
||||
<!-- Ruban cliquable -->
|
||||
<summary class="list-none cursor-pointer select-none">
|
||||
<div class="bonus-ribbon relative flex items-center justify-center py-3 bg-gradient-to-r from-[#f5ede0] via-[#ead5b5] to-[#f5ede0] border-y border-[#d4a574]/40 hover:via-[#e0c49a] transition-colors duration-300">
|
||||
|
||||
<!-- Tirets décoratifs gauche -->
|
||||
|
||||
<div class="bonus-ribbon-content flex flex-row items-center gap-5">
|
||||
<span class="text-5xl">✨</span>
|
||||
<div class="flex flex-col items-center gap-0">
|
||||
<span class="font-serif font-medium text-md tracking-[0.3em] uppercase text-[#995f11]">Les petits plus</span>
|
||||
<!-- + / × -->
|
||||
<span class="bonus-icon text-[#995f11] text-2xl font-bold leading-none transition-transform duration-300 group-open:rotate-45 inline-block">+</span>
|
||||
</div>
|
||||
<span class="text-5xl">✨</span>
|
||||
</div>
|
||||
|
||||
<!-- Tirets décoratifs droite -->
|
||||
<span class="hidden sm:block absolute right-8 top-1/2 -translate-y-1/2 text-[#c4956a]/40 tracking-widest text-xs">· · · · · · · ·</span>
|
||||
</div>
|
||||
</summary>
|
||||
|
||||
<!-- Contenu avec animation -->
|
||||
<div class="bonus-body">
|
||||
<div class="bonus-inner bg-gradient-to-b from-[#fdf6ed] to-[#f5ede0] border-b border-[#d4a574]/30">
|
||||
<div class="max-w-6xl mx-auto px-6 py-14">
|
||||
|
||||
<!-- En-tête -->
|
||||
<div class="text-center mb-10">
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-[#c4956a] mb-4">Selon les saisons & disponibilités</span>
|
||||
<h2 class="font-display text-5xl text-[#8b6a3e] mb-3">Les surprises de votre séjour</h2>
|
||||
<p class="text-dark/80 max-w-xl mx-auto text-sm leading-relaxed">
|
||||
En fonction des emplois du temps et des saisons, votre hôte vous propose quelques pépites pour enrichir votre séjour.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Cartes bonus -->
|
||||
<div class="flex flex-wrap justify-center gap-5">
|
||||
{bonuses.map((b) => (
|
||||
<div class="group/card w-full sm:w-[calc(50%-10px)] lg:w-[calc(33.333%-14px)] bg-white/60 border border-[#d4a574]/30 p-6 flex flex-col items-center text-center hover:bg-white/90 hover:border-[#d4a574]/60 hover:shadow-md transition-all duration-300">
|
||||
<div class="text-8xl mb-4">{b.emoji}</div>
|
||||
<h3 class="font-serif text-lg text-dark mb-2">{b.title}</h3>
|
||||
<p class="text-dark/60 text-sm leading-relaxed">{b.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p class="text-center text-[#c4956a]/90 text-xs mt-10 tracking-[0.25em] uppercase">Sur demande · selon disponibilités de votre hôte</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</details>
|
||||
|
||||
<style>
|
||||
/* Ouverture du contenu */
|
||||
.bonus-body {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
transition: grid-template-rows 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
details[open].bonus-details .bonus-body {
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.bonus-inner {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Battement de coeur sur tout le contenu du bandeau */
|
||||
@keyframes heartbeat {
|
||||
0%, 100% { transform: scale(1); }
|
||||
25% { transform: scale(1.10); }
|
||||
50% { transform: scale(1); }
|
||||
75% { transform: scale(1.10); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
.bonus-ribbon-content {
|
||||
animation: heartbeat 2s ease-in-out infinite;
|
||||
}
|
||||
details[open] .bonus-ribbon-content {
|
||||
animation: none;
|
||||
}
|
||||
details[open] .bonus-icon {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,8 @@
|
||||
<section id="contact" class="py-32 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
---
|
||||
import { Phone, Mail} from 'lucide-astro';
|
||||
---
|
||||
|
||||
<section id="contact" class="py-16 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<div class="max-w-6xl mx-auto px-6">
|
||||
<div class="grid md:grid-cols-2 gap-16" >
|
||||
|
||||
@@ -7,10 +11,10 @@
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-primary mb-5">
|
||||
Contact
|
||||
</span>
|
||||
<h2 class="font-serif text-5xl md:text-6xl font-light leading-tight mb-8">
|
||||
Réservez<br/>votre séjour
|
||||
<h2 class="font-display text-5xl md:text-6xl font-light leading-tight mb-8">
|
||||
Réservez votre séjour
|
||||
</h2>
|
||||
<p class="text-dark/70 leading-relaxed mb-5">
|
||||
<p class="text-dark/80 leading-relaxed mb-5">
|
||||
Une question ou une demande de réservation ?
|
||||
N'hésitez pas à nous contacter, nous répondons sous 24h.
|
||||
</p>
|
||||
@@ -26,35 +30,46 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="text-primary font-serif text-xl">→</span>
|
||||
<span>contact@lamaisondececile.fr</span>
|
||||
<span>contact@la-maison-de-cecile.fr</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Formulaire -->
|
||||
<div class="flex items-center justify-center">
|
||||
<form class="space-y-4 ">
|
||||
<form id="contact-form" class="space-y-4 w-full" novalidate>
|
||||
<!-- Honeypot anti-spam (caché) -->
|
||||
<input type="text" name="website" class="hidden" tabindex="-1" autocomplete="off" />
|
||||
|
||||
<input
|
||||
type="text"
|
||||
name="nom"
|
||||
placeholder="Votre nom"
|
||||
required
|
||||
class="w-full bg-white border border-secondary px-4 py-3 text-dark placeholder:text-dark/40 focus:outline-none focus:border-primary transition-colors"
|
||||
/>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Votre adresse email"
|
||||
required
|
||||
class="w-full bg-white border border-secondary px-4 py-3 text-dark placeholder:text-dark/40 focus:outline-none focus:border-primary transition-colors"
|
||||
/>
|
||||
<textarea
|
||||
name="message"
|
||||
rows="5"
|
||||
placeholder="Votre message (dates souhaitées, nombre de personnes, activités souhaitées...)"
|
||||
required
|
||||
class="w-full bg-white border border-secondary px-4 py-3 text-dark placeholder:text-dark/40 focus:outline-none focus:border-primary transition-colors resize-none"
|
||||
></textarea>
|
||||
|
||||
<!-- Message de retour -->
|
||||
<p id="form-feedback" class="hidden text-sm px-1"></p>
|
||||
|
||||
<button
|
||||
id="form-submit"
|
||||
type="submit"
|
||||
class="w-full bg-primary text-white py-4 text-xs tracking-[0.25em] uppercase hover:bg-primary/80 transition-colors"
|
||||
class="w-full bg-primary text-white py-4 text-xs tracking-[0.25em] border border-secondary rounded-md shadow-lg uppercase hover:bg-primary/80 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Envoyer le message
|
||||
</button>
|
||||
@@ -64,3 +79,41 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
const form = document.getElementById('contact-form') as HTMLFormElement;
|
||||
const feedback = document.getElementById('form-feedback') as HTMLParagraphElement;
|
||||
const submit = document.getElementById('form-submit') as HTMLButtonElement;
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
submit.disabled = true;
|
||||
submit.textContent = 'Envoi en cours…';
|
||||
feedback.className = 'hidden text-sm px-1';
|
||||
|
||||
try {
|
||||
const res = await fetch('/contact.php', {
|
||||
method: 'POST',
|
||||
body: new FormData(form),
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
feedback.textContent = data.message;
|
||||
feedback.classList.remove('hidden');
|
||||
|
||||
if (data.success) {
|
||||
feedback.classList.add('text-green-700');
|
||||
form.reset();
|
||||
} else {
|
||||
feedback.classList.add('text-red-600');
|
||||
}
|
||||
} catch {
|
||||
feedback.textContent = 'Erreur réseau. Veuillez réessayer.';
|
||||
feedback.classList.remove('hidden');
|
||||
feedback.classList.add('text-red-600');
|
||||
} finally {
|
||||
submit.disabled = false;
|
||||
submit.textContent = 'Envoyer le message';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -3,12 +3,12 @@ import { Image } from 'astro:assets';
|
||||
import food from '../assets/images/food.png';
|
||||
---
|
||||
|
||||
<section id="food" class="py-32 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<section id="food" class="py-16 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<div class="max-w-6xl mx-auto px-6">
|
||||
<div class="grid md:grid-cols-2 gap-16 items-center">
|
||||
|
||||
<!-- Image -->
|
||||
<div class="relative order-2 md:order-1">
|
||||
<div class="relative order-2 md:order-1 shadow-lg">
|
||||
<Image
|
||||
src={food}
|
||||
alt="Les petits plats de Cécile, une cuisine inspirée par de nombreux voyages, les saisons et les produits du marché."
|
||||
@@ -22,14 +22,14 @@ import food from '../assets/images/food.png';
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-primary mb-5">
|
||||
La table
|
||||
</span>
|
||||
<h2 class="font-serif text-5xl md:text-6xl font-light leading-tight mb-8">
|
||||
<h2 class="font-display text-5xl md:text-6xl font-light leading-tight mb-8">
|
||||
Cuisine du marché<br/>et du jardin
|
||||
</h2>
|
||||
<p class="text-dark/70 leading-relaxed mb-6">
|
||||
<p class="text-dark/80 leading-relaxed mb-6">
|
||||
Le matin, le copieux petit-déjeuner est fait maison : pain, yaourt, confitures,
|
||||
fruits de saison, infusion du jardin.
|
||||
</p>
|
||||
<p class="text-dark/70 leading-relaxed mb-8">
|
||||
<p class="text-dark/80 leading-relaxed mb-8">
|
||||
Le soir, Cécile vous propose un repas partagé selon ce qu'elle
|
||||
a trouvé au marché ou cueillit dans les bois alentour, inspirés par ses voyages.
|
||||
Simple, vivant, sincère.
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
<div class="max-w-6xl mx-auto px-6 flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
<span class="font-serif text-xl text-white/70">La Maison de Cécile</span>
|
||||
<span class="text-white/30 text-sm">© 2026 · Tous droits réservés</span>
|
||||
<span class="text-white/40 text-sm">Soyez gentil avec ma maman ❤️</span>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -29,20 +29,20 @@ const photos = [
|
||||
];
|
||||
---
|
||||
|
||||
<section id="gallery" class="py-32 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<section id="gallery" class="py-16 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
<div class="max-w-6xl mx-auto px-6">
|
||||
|
||||
<div class="mb-14 text-center">
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-primary mb-4">Galerie</span>
|
||||
<h2 class="font-serif text-5xl font-light">Découvrez le lieu</h2>
|
||||
<span class="block text-md tracking-[0.3em] text-primary mb-4 font-display">Galerie</span>
|
||||
<h2 class="font-display text-5xl font-light">Découvrez le lieu</h2>
|
||||
</div>
|
||||
|
||||
<!-- CSS columns : les photos gardent leurs proportions naturelles,
|
||||
s'empilent automatiquement, aucun calcul de span nécessaire. -->
|
||||
<div class="columns-2 md:columns-3 gap-3">
|
||||
<div class="columns-2 md:columns-3 gap-2">
|
||||
{photos.map((photo, i) => (
|
||||
<div
|
||||
class="break-inside-avoid mb-3 cursor-pointer group relative overflow-hidden"
|
||||
class="break-inside-avoid mb-3 cursor-pointer group relative overflow-hidden rounded-sm shadow-lg border border-secondary"
|
||||
data-lightbox={i}
|
||||
data-caption={photo.caption}
|
||||
role="button"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<header class="fixed top-0 left-0 right-0 z-50 bg-cream/95 backdrop-blur-sm border-b border-secondary/60">
|
||||
<header class="fixed top-0 left-0 right-0 z-50 bg-cream/95 backdrop-blur-sm border-b border-secondary/60 shadow-md">
|
||||
<div class="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
|
||||
<a href="#" class="font-display text-3xl text-dark">
|
||||
<a href="#" class="font-display text-4xl text-dark">
|
||||
La Maison de Cécile
|
||||
</a>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<a href="#food" class="text-xs tracking-[0.2em] uppercase text-dark/60 hover:text-primary transition-colors">La table</a>
|
||||
<a href="#activities" class="text-xs tracking-[0.2em] uppercase text-dark/60 hover:text-primary transition-colors">Activités</a>
|
||||
<a href="#pricing" class="text-xs tracking-[0.2em] uppercase text-dark/60 hover:text-primary transition-colors">Tarifs</a>
|
||||
<a href="#contact" class="text-xs tracking-[0.2em] uppercase bg-primary text-white px-6 py-2.5 hover:bg-primary/80 transition-colors">
|
||||
<a href="#contact" class="text-xs tracking-[0.2em] uppercase bg-primary border border-secondary rounded-md text-white px-6 py-2.5 hover:bg-primary/80 transition-colors">
|
||||
Me contacter
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
<section id="pricing" class="py-32 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
---
|
||||
import constructionMedium from '../assets/images/construction_medium.png';
|
||||
import constructionSmall from '../assets/images/construction_small.png';
|
||||
---
|
||||
|
||||
<section id="pricing" class="relative py-16 scroll-mt-20 bg-gradient-to-b from-[#f7f3e8] via-[#f2efdf] to-[#e4ecd2] border-y border-[#d9d2c3]/70">
|
||||
|
||||
<!-- Filtre "en construction" -->
|
||||
<div class="absolute inset-0 z-10 pointer-events-none">
|
||||
<!-- Mobile -->
|
||||
<img src={constructionSmall.src} alt="En construction" class="sm:hidden absolute inset-0 w-full h-full object-cover object-top" />
|
||||
<!-- Desktop -->
|
||||
<img src={constructionMedium.src} alt="En construction" class="hidden sm:block absolute inset-0 w-full h-full object-cover object-center" />
|
||||
<div class="absolute inset-0 bg-black/30"></div>
|
||||
</div>
|
||||
<div class="max-w-6xl mx-auto px-6">
|
||||
|
||||
<!-- En-tête -->
|
||||
@@ -6,10 +20,10 @@
|
||||
<span class="block text-xs tracking-[0.3em] uppercase text-primary mb-5">
|
||||
Les tarifs
|
||||
</span>
|
||||
<h2 class="font-serif text-5xl md:text-6xl font-light leading-tight mb-6">
|
||||
<h2 class="font-display text-5xl md:text-6xl font-light leading-tight mb-6">
|
||||
Mes formules
|
||||
</h2>
|
||||
<p class="text-dark/60 max-w-4xl mx-auto leading-relaxed">
|
||||
<p class="text-dark/80 max-w-4xl mx-auto leading-relaxed">
|
||||
Je vous accueille dans une maison joliement restaurée et chaleureuse, pour un séjour ressourçant en pleine nature. <br/>
|
||||
Deux formules d'hébergement s'offrent à vous : la location complète du gîte, ou la réservation d'une chambre d'hôtes.
|
||||
</p>
|
||||
@@ -19,7 +33,7 @@
|
||||
<div class="grid md:grid-cols-2 gap-8 mb-12">
|
||||
|
||||
<!-- Gîte -->
|
||||
<div class="border border-secondary bg-white">
|
||||
<div class="border border-secondary bg-white shadow-lg">
|
||||
<div class="px-8 pt-8 pb-6 border-b border-secondary">
|
||||
<span class="block text-xs tracking-[0.2em] uppercase text-primary mb-2">Location complète</span>
|
||||
<h3 class="font-serif text-3xl font-light text-dark">Gîte</h3>
|
||||
@@ -56,7 +70,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Chambre d'hôtes -->
|
||||
<div class="border border-secondary bg-white">
|
||||
<div class="border border-secondary bg-white shadow-lg">
|
||||
<div class="px-8 pt-8 pb-6 border-b border-secondary">
|
||||
<span class="block text-xs tracking-[0.2em] uppercase text-primary mb-2">Par chambre</span>
|
||||
<h3 class="font-serif text-3xl font-light text-dark">Chambre d'hôtes</h3>
|
||||
|
||||
@@ -15,6 +15,8 @@ const {
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
|
||||
<title>{title}</title>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import Gallery from '../components/Gallery.astro';
|
||||
import Food from '../components/Food.astro';
|
||||
import Pricing from '../components/Pricing.astro';
|
||||
import Activities from '../components/Activities.astro';
|
||||
import Bonus from '../components/Bonus.astro';
|
||||
import Contact from '../components/Contact.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
---
|
||||
@@ -21,6 +22,7 @@ import Footer from '../components/Footer.astro';
|
||||
<Food />
|
||||
<Pricing />
|
||||
<Activities />
|
||||
<Bonus />
|
||||
<Contact />
|
||||
</main>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
--color-dark: #1f1f1f;
|
||||
--font-display: 'Parisienne', cursive;
|
||||
--font-serif: 'Marcellus', serif;
|
||||
--font-sans: 'Source Sans 3', sans-serif;
|
||||
--font-sans: 'Cormorant Garamond', sans-serif;
|
||||
}
|
||||
|
||||
html {
|
||||
|
||||
Reference in New Issue
Block a user