en attendant les tarifs
Build & Deploy / build-push-deploy (push) Failing after 5s

This commit is contained in:
2026-06-23 00:01:27 +02:00
parent 9406cadb12
commit a343bb23e9
17 changed files with 450 additions and 44 deletions
+62
View File
@@ -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
View File
@@ -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

+3 -3
View File
@@ -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/>
+6 -6
View File
@@ -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%"
+117
View File
@@ -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>
+61 -8
View File
@@ -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>
@@ -63,4 +78,42 @@
</div>
</div>
</section>
</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>
+5 -5
View File
@@ -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.
+1
View File
@@ -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>
+5 -5
View File
@@ -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"
+3 -3
View File
@@ -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>
+19 -5
View File
@@ -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>
+2
View File
@@ -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>
+2
View File
@@ -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>
+1 -1
View File
@@ -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 {