feat: scaffold Astro project with layout, nav, hero and concept sections
- Add global ocean-themed styles (Inter + Sora, glassmorphism utilities). - Wire up base layout, sticky nav and footer respecting base path. - Build hero with stylised rock SVG + sonar ambient rings and concept pipeline schematic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.astro/
|
||||
.DS_Store
|
||||
*.log
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.vscode/
|
||||
.idea/
|
||||
18
astro.config.mjs
Normal file
18
astro.config.mjs
Normal file
@@ -0,0 +1,18 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
|
||||
export default defineConfig({
|
||||
site: 'https://laboratoire.freeboxos.fr',
|
||||
base: '/nowyousea/',
|
||||
output: 'static',
|
||||
trailingSlash: 'ignore',
|
||||
integrations: [tailwind({ applyBaseStyles: false })],
|
||||
build: {
|
||||
inlineStylesheets: 'auto',
|
||||
},
|
||||
vite: {
|
||||
build: {
|
||||
cssCodeSplit: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
6650
package-lock.json
generated
Normal file
6650
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
package.json
Normal file
18
package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "site-nowyousea",
|
||||
"type": "module",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^5.15.0",
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"tailwindcss": "^3.4.17"
|
||||
}
|
||||
}
|
||||
14
public/favicon.svg
Normal file
14
public/favicon.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" x2="0" y1="0" y2="1">
|
||||
<stop offset="0" stop-color="#38bdf8"/>
|
||||
<stop offset="1" stop-color="#06b6d4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="64" height="64" rx="14" fill="#050d1a"/>
|
||||
<path d="M6 40c6 0 6-6 12-6s6 6 12 6 6-6 12-6 6 6 12 6 6-6 10-6v14H6z" fill="url(#g)" opacity="0.55"/>
|
||||
<path d="M6 46c6 0 6-6 12-6s6 6 12 6 6-6 12-6 6 6 12 6 6-6 10-6v8H6z" fill="url(#g)"/>
|
||||
<circle cx="32" cy="22" r="4" fill="#e0f2fe"/>
|
||||
<circle cx="32" cy="22" r="9" fill="none" stroke="#38bdf8" stroke-width="1.5" opacity="0.6"/>
|
||||
<circle cx="32" cy="22" r="14" fill="none" stroke="#38bdf8" stroke-width="1" opacity="0.3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 747 B |
3
run-build.sh
Executable file
3
run-build.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd /home/floppyrj45/Projects/site-nowyousea
|
||||
exec claude --dangerously-skip-permissions --print "Lis BRIEF.md intégralement puis exécute toutes les étapes. Le contenu source est dans content/. Build un site Astro SSG vitrine NowYouSea avec base: '/nowyousea/', design océan moderne (bleus nuit + cyan accent), sections Hero, Concept, Pourquoi, 4 configurations (MINI/STD/PRO/EOLIEN), Architecture système, Cas d'usage Port-Navalo, Équipe (Baptiste Moulin CTO, Quentin Ingé Produit, Radu Mihail Business EU), Roadmap, Contact. Interdiction absolue de mentionner Octo'pousse, candidature, concours, IFREMER-jury. Livre: projet Astro complet + npm run build OK + DEPLOY.md avec commandes rsync vers floppyrj45@192.168.0.82:/srv/www/nowyousea/ + snippet Caddy. Commits git au fil de l'eau. Tu as le droit de tout faire (bypass permissions), pas besoin de demander confirmation. Quand le build dist/ est produit, termine en lançant: openclaw system event --text 'Done: site vitrine NowYouSea buildé dans ~/Projects/site-nowyousea/dist' --mode now" 2>&1
|
||||
133
src/components/Concept.astro
Normal file
133
src/components/Concept.astro
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
const steps = [
|
||||
{
|
||||
title: 'Terrain',
|
||||
text: 'Un rocher biomimétique immergé, discret, accueille hydrophone calibré, CTD et capteurs modulaires.',
|
||||
icon: 'rock',
|
||||
},
|
||||
{
|
||||
title: 'Calcul embarqué',
|
||||
text: 'FFT et SPL calculés directement sur la station. On transmet l’indicateur, pas le fichier brut.',
|
||||
icon: 'cpu',
|
||||
},
|
||||
{
|
||||
title: 'Cloud',
|
||||
text: 'Collecte MQTT sécurisée, stockage time-series, moteur d’alertes et inter-calibration.',
|
||||
icon: 'cloud',
|
||||
},
|
||||
{
|
||||
title: 'Dashboard',
|
||||
text: 'Carte live, historique, rapports réglementaires auto-générés, API pour la recherche.',
|
||||
icon: 'dashboard',
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section id="concept" class="section">
|
||||
<div class="container-narrow">
|
||||
<div class="section-title-block">
|
||||
<span class="eyebrow">Concept</span>
|
||||
<h2 class="h-section mt-4">
|
||||
Une station côtière autonome, du capteur au tableau de bord.
|
||||
</h2>
|
||||
<p class="lead mt-6">
|
||||
NowYouSea est un réseau de rochers connectés qui écoutent, mesurent et transmettent
|
||||
en continu. L'intelligence des grandes stations de référence, à la portée d'un port —
|
||||
une version moderne et démocratisée du MAREL, conçue pour le littoral.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Pipeline schematic -->
|
||||
<div class="relative">
|
||||
<!-- Connecting gradient line (desktop only) -->
|
||||
<div class="pointer-events-none absolute left-0 right-0 top-[72px] hidden h-px md:block"
|
||||
aria-hidden="true"
|
||||
style="background: linear-gradient(90deg, transparent, rgba(56,189,248,0.4), rgba(6,182,212,0.55), rgba(56,189,248,0.4), transparent);"></div>
|
||||
|
||||
<ol class="grid gap-5 md:grid-cols-4">
|
||||
{steps.map((step, i) => (
|
||||
<li class="relative">
|
||||
<div class="card h-full">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<span class="inline-flex h-10 w-10 items-center justify-center rounded-lg bg-tide-500/15 text-tide-400 ring-1 ring-tide-400/30">
|
||||
{step.icon === 'rock' && (
|
||||
<svg viewBox="0 0 24 24" class="h-5 w-5" fill="currentColor" aria-hidden="true"><path d="M4 17c0-4 3-6 5-6 1 0 2-3 5-3s4 2 4 4c1 0 2 1 2 3s-2 4-5 4H6c-1 0-2-1-2-2z"/></svg>
|
||||
)}
|
||||
{step.icon === 'cpu' && (
|
||||
<svg viewBox="0 0 24 24" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" aria-hidden="true">
|
||||
<rect x="6" y="6" width="12" height="12" rx="2"/>
|
||||
<rect x="9" y="9" width="6" height="6" rx="1"/>
|
||||
<path d="M4 9h2M4 13h2M18 9h2M18 13h2M9 4v2M13 4v2M9 18v2M13 18v2"/>
|
||||
</svg>
|
||||
)}
|
||||
{step.icon === 'cloud' && (
|
||||
<svg viewBox="0 0 24 24" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M7 17h10a4 4 0 0 0 0-8 6 6 0 0 0-11.7 1.3A3.5 3.5 0 0 0 7 17z"/>
|
||||
</svg>
|
||||
)}
|
||||
{step.icon === 'dashboard' && (
|
||||
<svg viewBox="0 0 24 24" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<rect x="3" y="4" width="18" height="16" rx="2"/>
|
||||
<path d="M3 9h18M8 14h3M8 17h7"/>
|
||||
</svg>
|
||||
)}
|
||||
</span>
|
||||
<span class="font-display text-sm font-medium uppercase tracking-widest text-foam-100/50">
|
||||
0{i + 1}
|
||||
</span>
|
||||
</div>
|
||||
<h3 class="font-display text-xl font-semibold text-foam-50">{step.title}</h3>
|
||||
<p class="mt-3 text-sm leading-relaxed text-foam-100/75">{step.text}</p>
|
||||
</div>
|
||||
{i < steps.length - 1 && (
|
||||
<svg
|
||||
viewBox="0 0 40 24"
|
||||
class="pointer-events-none absolute -right-3 top-1/2 hidden h-6 w-10 -translate-y-1/2 text-tide-400/70 md:block"
|
||||
fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"
|
||||
>
|
||||
<path d="M2 12h34M30 6l6 6-6 6"/>
|
||||
</svg>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<!-- Feature bullets -->
|
||||
<div class="mt-16 grid gap-6 md:grid-cols-3">
|
||||
<div class="flex items-start gap-4">
|
||||
<span class="mt-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-lagoon-500/15 text-lagoon-400">
|
||||
<svg viewBox="0 0 24 24" class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<h4 class="font-semibold text-foam-50">Biomimétique & discret</h4>
|
||||
<p class="mt-1 text-sm text-foam-100/70">
|
||||
Forme de rocher qui se fond dans l'enrochement, sans encombrement maritime ni impact visuel.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-start gap-4">
|
||||
<span class="mt-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-lagoon-500/15 text-lagoon-400">
|
||||
<svg viewBox="0 0 24 24" class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<h4 class="font-semibold text-foam-50">Monitoring-grade</h4>
|
||||
<p class="mt-1 text-sm text-foam-100/70">
|
||||
Précision réglementaire pour la conformité et les alertes, inter-calibrable avec les stations de référence.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-start gap-4">
|
||||
<span class="mt-1 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-lagoon-500/15 text-lagoon-400">
|
||||
<svg viewBox="0 0 24 24" class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<h4 class="font-semibold text-foam-50">Open & interopérable</h4>
|
||||
<p class="mt-1 text-sm text-foam-100/70">
|
||||
API REST, WebSocket, exports CSV et formats compatibles avec les référentiels publics.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
30
src/components/Footer.astro
Normal file
30
src/components/Footer.astro
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
const year = new Date().getFullYear();
|
||||
---
|
||||
|
||||
<footer class="relative border-t border-white/5 py-12 mt-12">
|
||||
<div class="container-narrow flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="inline-flex h-8 w-8 items-center justify-center rounded-md bg-gradient-to-br from-tide-500 to-lagoon-500">
|
||||
<svg viewBox="0 0 24 24" class="h-5 w-5 text-abyss-950" fill="currentColor" aria-hidden="true">
|
||||
<path d="M2 16c2 0 2-2 4-2s2 2 4 2 2-2 4-2 2 2 4 2 2-2 4-2v4H2z"/>
|
||||
<circle cx="12" cy="9" r="2"/>
|
||||
</svg>
|
||||
</span>
|
||||
<div>
|
||||
<div class="font-display font-semibold">NowYouSea</div>
|
||||
<div class="text-xs text-foam-100/60">Le rocher connecté qui écoute l'océan.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav aria-label="Navigation pied de page" class="flex flex-wrap gap-x-6 gap-y-2 text-sm text-foam-100/60">
|
||||
<a href="#concept" class="hover:text-tide-400">Concept</a>
|
||||
<a href="#configurations" class="hover:text-tide-400">Configurations</a>
|
||||
<a href="#architecture" class="hover:text-tide-400">Architecture</a>
|
||||
<a href="#equipe" class="hover:text-tide-400">Équipe</a>
|
||||
<a href="#contact" class="hover:text-tide-400">Contact</a>
|
||||
</nav>
|
||||
|
||||
<div class="text-xs text-foam-100/50">© {year} NowYouSea — Tous droits réservés.</div>
|
||||
</div>
|
||||
</footer>
|
||||
172
src/components/Hero.astro
Normal file
172
src/components/Hero.astro
Normal file
@@ -0,0 +1,172 @@
|
||||
---
|
||||
---
|
||||
|
||||
<section class="relative overflow-hidden pt-16 md:pt-24 pb-24 md:pb-32">
|
||||
<!-- Ambient caustic glow -->
|
||||
<div class="pointer-events-none absolute inset-0 caustic-bg"></div>
|
||||
|
||||
<!-- Decorative SVG backdrop: horizon + underwater layers -->
|
||||
<svg
|
||||
class="pointer-events-none absolute inset-x-0 top-0 h-[540px] w-full opacity-70"
|
||||
viewBox="0 0 1440 540"
|
||||
preserveAspectRatio="none"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="horizon" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#050d1a" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#0a1a2f" stop-opacity="0.85"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="wave" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#0ea5e9" stop-opacity="0.18"/>
|
||||
<stop offset="1" stop-color="#0a1a2f" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="1440" height="540" fill="url(#horizon)"/>
|
||||
<path d="M0 380 C 240 340, 480 420, 720 380 S 1200 320, 1440 380 L1440 540 L0 540 Z" fill="url(#wave)"/>
|
||||
<path d="M0 440 C 300 410, 500 460, 820 430 S 1220 400, 1440 440 L1440 540 L0 540 Z" fill="#0ea5e9" fill-opacity="0.06"/>
|
||||
</svg>
|
||||
|
||||
<div class="container-narrow relative">
|
||||
<div class="grid lg:grid-cols-12 gap-12 items-center">
|
||||
<!-- Copy -->
|
||||
<div class="lg:col-span-7 relative">
|
||||
<span class="eyebrow">Station côtière · Acoustique sous-marine</span>
|
||||
|
||||
<h1 class="h-display mt-6">
|
||||
Le rocher connecté
|
||||
<span class="block bg-gradient-to-r from-foam-50 via-tide-400 to-lagoon-400 bg-clip-text text-transparent">
|
||||
qui écoute l'océan.
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<p class="lead mt-7 max-w-xl">
|
||||
NowYouSea déploie un réseau de stations côtières discrètes, autonomes
|
||||
et abordables — hydrophone calibré, physico-chimie et calcul embarqué —
|
||||
pour donner aux ports et aux gestionnaires d'espaces marins des données
|
||||
continues, du terrain jusqu'au tableau de bord.
|
||||
</p>
|
||||
|
||||
<div class="mt-10 flex flex-wrap items-center gap-3">
|
||||
<a href="#concept" class="btn btn-primary">
|
||||
Découvrir le projet
|
||||
<svg viewBox="0 0 24 24" class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M12 5v14M5 12l7 7 7-7"/>
|
||||
</svg>
|
||||
</a>
|
||||
<a href="#configurations" class="btn btn-ghost">Voir les configurations</a>
|
||||
</div>
|
||||
|
||||
<!-- Key metrics strip -->
|
||||
<dl class="mt-12 grid grid-cols-3 gap-4 max-w-xl">
|
||||
<div class="glass rounded-xl p-4">
|
||||
<dt class="text-xs uppercase tracking-wider text-foam-100/60">Hydrophone</dt>
|
||||
<dd class="mt-1 font-display text-lg font-semibold text-tide-400">63 & 125 Hz</dd>
|
||||
</div>
|
||||
<div class="glass rounded-xl p-4">
|
||||
<dt class="text-xs uppercase tracking-wider text-foam-100/60">Autonomie</dt>
|
||||
<dd class="mt-1 font-display text-lg font-semibold text-tide-400">Solaire 24/7</dd>
|
||||
</div>
|
||||
<div class="glass rounded-xl p-4">
|
||||
<dt class="text-xs uppercase tracking-wider text-foam-100/60">Transmission</dt>
|
||||
<dd class="mt-1 font-display text-lg font-semibold text-tide-400">4G · LoRa</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<!-- Artwork: stylised rock + sonar rings -->
|
||||
<div class="lg:col-span-5 relative flex justify-center">
|
||||
<div class="relative w-full max-w-md aspect-square">
|
||||
<!-- Sonar concentric rings -->
|
||||
<div class="absolute inset-0 flex items-center justify-center">
|
||||
<span class="sonar-ring absolute h-40 w-40 rounded-full border border-tide-400/50"></span>
|
||||
<span class="sonar-ring absolute h-40 w-40 rounded-full border border-tide-400/50" style="animation-delay: 1.2s;"></span>
|
||||
<span class="sonar-ring absolute h-40 w-40 rounded-full border border-lagoon-400/40" style="animation-delay: 2.4s;"></span>
|
||||
</div>
|
||||
|
||||
<!-- Rock SVG -->
|
||||
<svg viewBox="0 0 400 400" class="relative z-10 w-full h-full drop-shadow-[0_25px_35px_rgba(6,182,212,0.25)]" aria-hidden="true">
|
||||
<defs>
|
||||
<radialGradient id="rockGlow" cx="50%" cy="40%" r="60%">
|
||||
<stop offset="0" stop-color="#1a4570"/>
|
||||
<stop offset="0.6" stop-color="#0f2742"/>
|
||||
<stop offset="1" stop-color="#050d1a"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="waterline" x1="0" x2="1" y1="0" y2="0">
|
||||
<stop offset="0" stop-color="#0ea5e9" stop-opacity="0"/>
|
||||
<stop offset="0.5" stop-color="#38bdf8"/>
|
||||
<stop offset="1" stop-color="#06b6d4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- underwater ambient -->
|
||||
<circle cx="200" cy="220" r="180" fill="url(#rockGlow)" opacity="0.65"/>
|
||||
|
||||
<!-- Rock silhouette -->
|
||||
<path d="M90 300
|
||||
C 80 270, 95 240, 115 230
|
||||
C 110 200, 135 175, 165 175
|
||||
C 170 150, 200 140, 225 150
|
||||
C 250 135, 285 145, 300 175
|
||||
C 325 180, 335 210, 320 235
|
||||
C 340 255, 335 290, 310 305
|
||||
C 300 325, 270 335, 240 328
|
||||
C 215 340, 180 340, 155 325
|
||||
C 125 330, 95 320, 90 300 Z"
|
||||
fill="#0f2742" stroke="#1a4570" stroke-width="1.5"/>
|
||||
|
||||
<!-- Rock highlights -->
|
||||
<path d="M135 210 C 160 195, 195 195, 220 210" fill="none" stroke="#215889" stroke-width="1.4" opacity="0.7"/>
|
||||
<path d="M175 260 C 210 250, 240 260, 275 250" fill="none" stroke="#143558" stroke-width="1.2" opacity="0.6"/>
|
||||
|
||||
<!-- Embedded sensor "eye" -->
|
||||
<g transform="translate(215 225)">
|
||||
<circle r="18" fill="#050d1a" stroke="#38bdf8" stroke-width="1.5"/>
|
||||
<circle r="8" fill="#06b6d4"/>
|
||||
<circle r="3" fill="#e0f2fe"/>
|
||||
</g>
|
||||
|
||||
<!-- Solar panel -->
|
||||
<g transform="translate(165 130) rotate(-6)">
|
||||
<rect width="110" height="34" rx="3" fill="#050d1a" stroke="#215889" stroke-width="1"/>
|
||||
<g stroke="#143558" stroke-width="0.8">
|
||||
<line x1="0" y1="11" x2="110" y2="11"/>
|
||||
<line x1="0" y1="22" x2="110" y2="22"/>
|
||||
<line x1="27" y1="0" x2="27" y2="34"/>
|
||||
<line x1="55" y1="0" x2="55" y2="34"/>
|
||||
<line x1="82" y1="0" x2="82" y2="34"/>
|
||||
</g>
|
||||
<rect width="110" height="34" rx="3" fill="url(#waterline)" opacity="0.15"/>
|
||||
</g>
|
||||
|
||||
<!-- Antenna -->
|
||||
<g stroke="#38bdf8" stroke-width="1.6" stroke-linecap="round">
|
||||
<line x1="250" y1="135" x2="250" y2="95"/>
|
||||
<circle cx="250" cy="90" r="3" fill="#38bdf8"/>
|
||||
</g>
|
||||
|
||||
<!-- Waterline -->
|
||||
<path d="M20 160 Q 100 145 200 160 T 380 160" stroke="url(#waterline)" stroke-width="1.3" fill="none" opacity="0.9"/>
|
||||
<path d="M20 170 Q 110 158 210 172 T 380 170" stroke="#0ea5e9" stroke-width="0.8" fill="none" opacity="0.4"/>
|
||||
|
||||
<!-- Sound ripples coming from rock -->
|
||||
<g stroke="#38bdf8" fill="none" opacity="0.55">
|
||||
<circle cx="215" cy="225" r="46" stroke-dasharray="2 3"/>
|
||||
<circle cx="215" cy="225" r="70" stroke-dasharray="2 5" opacity="0.35"/>
|
||||
</g>
|
||||
|
||||
<!-- Seabed hints -->
|
||||
<g fill="#0a1a2f" opacity="0.9">
|
||||
<ellipse cx="120" cy="348" rx="30" ry="6"/>
|
||||
<ellipse cx="220" cy="360" rx="70" ry="7"/>
|
||||
<ellipse cx="320" cy="352" rx="35" ry="5"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- subtle bottom fade line -->
|
||||
<div class="absolute bottom-0 left-0 right-0 h-px divider"></div>
|
||||
</section>
|
||||
45
src/components/Nav.astro
Normal file
45
src/components/Nav.astro
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
const base = import.meta.env.BASE_URL;
|
||||
const items = [
|
||||
{ href: '#concept', label: 'Concept' },
|
||||
{ href: '#pourquoi', label: 'Pourquoi' },
|
||||
{ href: '#configurations', label: 'Configurations' },
|
||||
{ href: '#architecture', label: 'Architecture' },
|
||||
{ href: '#cas-dusage', label: "Cas d'usage" },
|
||||
{ href: '#equipe', label: 'Équipe' },
|
||||
{ href: '#roadmap', label: 'Feuille de route' },
|
||||
{ href: '#contact', label: 'Contact' },
|
||||
];
|
||||
---
|
||||
|
||||
<header class="sticky top-0 z-40 border-b border-white/5 bg-abyss-950/75 backdrop-blur">
|
||||
<div class="container-narrow flex h-16 items-center justify-between">
|
||||
<a href={base} class="flex items-center gap-2.5" aria-label="NowYouSea — retour à l'accueil">
|
||||
<span class="relative inline-flex h-8 w-8 items-center justify-center rounded-md bg-gradient-to-br from-tide-500 to-lagoon-500 shadow-glow">
|
||||
<svg viewBox="0 0 24 24" class="h-5 w-5 text-abyss-950" fill="currentColor" aria-hidden="true">
|
||||
<path d="M2 16c2 0 2-2 4-2s2 2 4 2 2-2 4-2 2 2 4 2 2-2 4-2v4H2z"/>
|
||||
<circle cx="12" cy="9" r="2"/>
|
||||
<path d="M7 9a5 5 0 0 1 10 0" stroke="currentColor" stroke-width="1.5" fill="none" opacity=".65"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="font-display text-base font-semibold tracking-tight">NowYouSea</span>
|
||||
</a>
|
||||
|
||||
<nav aria-label="Navigation principale" class="hidden lg:block">
|
||||
<ul class="flex items-center gap-7 text-sm text-foam-100/75">
|
||||
{items.map((item) => (
|
||||
<li>
|
||||
<a href={item.href} class="hover:text-tide-400">{item.label}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<a href="#contact" class="btn btn-primary hidden md:inline-flex">
|
||||
Demander une démo
|
||||
<svg viewBox="0 0 24 24" class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M5 12h14M13 5l7 7-7 7"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
60
src/layouts/Layout.astro
Normal file
60
src/layouts/Layout.astro
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
import '../styles/global.css';
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
title = "NowYouSea — Le rocher connecté qui écoute l'océan",
|
||||
description = "Réseau de stations côtières acoustiques low-cost pour la surveillance du milieu marin. Hydrophone, physico-chimie et calcul embarqué, du terrain au dashboard.",
|
||||
} = Astro.props;
|
||||
|
||||
const base = import.meta.env.BASE_URL;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="fr" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content={description} />
|
||||
<meta name="theme-color" content="#050d1a" />
|
||||
<meta name="color-scheme" content="dark" />
|
||||
<link rel="icon" type="image/svg+xml" href={`${base}favicon.svg`} />
|
||||
<link rel="preconnect" href="https://rsms.me/" />
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700&display=swap" />
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<a
|
||||
href="#main"
|
||||
class="sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-50 focus:rounded focus:bg-tide-500 focus:px-4 focus:py-2 focus:text-abyss-950"
|
||||
>
|
||||
Aller au contenu
|
||||
</a>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global>
|
||||
html {
|
||||
font-family: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
||||
font-feature-settings: 'cv11', 'ss01', 'ss03';
|
||||
}
|
||||
@supports (font-variation-settings: normal) {
|
||||
html {
|
||||
font-family: 'Inter var', ui-sans-serif, system-ui, sans-serif;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
135
src/styles/global.css
Normal file
135
src/styles/global.css
Normal file
@@ -0,0 +1,135 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-abyss-950 text-foam-50 font-sans;
|
||||
background-image:
|
||||
radial-gradient(1200px 600px at 10% -10%, rgba(6, 182, 212, 0.10), transparent 60%),
|
||||
radial-gradient(1000px 500px at 110% 10%, rgba(14, 165, 233, 0.08), transparent 60%),
|
||||
linear-gradient(180deg, #050d1a 0%, #0a1a2f 100%);
|
||||
background-attachment: fixed;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
@apply font-display tracking-tight;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@apply bg-lagoon-500/40 text-foam-50;
|
||||
}
|
||||
|
||||
a {
|
||||
@apply transition-colors;
|
||||
}
|
||||
|
||||
/* Respect reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.001ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.001ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.container-narrow {
|
||||
@apply mx-auto w-full max-w-6xl px-6 md:px-10;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
@apply inline-flex items-center gap-2 text-xs font-medium uppercase tracking-[0.2em] text-lagoon-400;
|
||||
}
|
||||
|
||||
.eyebrow::before {
|
||||
content: "";
|
||||
@apply inline-block h-px w-8 bg-lagoon-400/60;
|
||||
}
|
||||
|
||||
.h-display {
|
||||
@apply font-display font-semibold tracking-tight text-4xl md:text-5xl lg:text-6xl leading-[1.05];
|
||||
}
|
||||
|
||||
.h-section {
|
||||
@apply font-display font-semibold tracking-tight text-3xl md:text-4xl lg:text-5xl leading-[1.1];
|
||||
}
|
||||
|
||||
.lead {
|
||||
@apply text-lg md:text-xl text-foam-100/80 leading-relaxed;
|
||||
}
|
||||
|
||||
.glass {
|
||||
@apply bg-white/[0.03] backdrop-blur-sm border border-white/[0.07];
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply glass rounded-2xl p-6 md:p-8 shadow-card;
|
||||
}
|
||||
|
||||
.btn {
|
||||
@apply inline-flex items-center gap-2 rounded-full px-5 py-3 text-sm font-medium transition;
|
||||
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tide-400 focus-visible:ring-offset-2 focus-visible:ring-offset-abyss-950;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply bg-tide-500 text-abyss-950 hover:bg-tide-400;
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
@apply border border-white/15 text-foam-50 hover:border-tide-400/60 hover:text-tide-400;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, rgba(56, 189, 248, 0.35), transparent);
|
||||
}
|
||||
|
||||
.section {
|
||||
@apply relative py-20 md:py-28;
|
||||
}
|
||||
|
||||
.section-title-block {
|
||||
@apply mb-12 md:mb-16 max-w-3xl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decorative caustic glow used as subtle ambient light */
|
||||
.caustic-bg {
|
||||
background-image:
|
||||
radial-gradient(circle at 20% 10%, rgba(6, 182, 212, 0.12), transparent 55%),
|
||||
radial-gradient(circle at 80% 80%, rgba(14, 165, 233, 0.10), transparent 55%);
|
||||
}
|
||||
|
||||
/* Animated horizon line */
|
||||
@keyframes drift {
|
||||
0%, 100% { transform: translateX(0) translateY(0); }
|
||||
50% { transform: translateX(12px) translateY(-6px); }
|
||||
}
|
||||
|
||||
.drift-slow {
|
||||
animation: drift 14s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Sonar ring */
|
||||
@keyframes sonar-ring {
|
||||
0% { transform: scale(0.8); opacity: 0.65; }
|
||||
100% { transform: scale(2.8); opacity: 0; }
|
||||
}
|
||||
|
||||
.sonar-ring {
|
||||
animation: sonar-ring 3.6s ease-out infinite;
|
||||
}
|
||||
72
tailwind.config.mjs
Normal file
72
tailwind.config.mjs
Normal file
@@ -0,0 +1,72 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
abyss: {
|
||||
950: '#050d1a',
|
||||
900: '#0a1a2f',
|
||||
800: '#0f2742',
|
||||
700: '#143558',
|
||||
600: '#1a4570',
|
||||
500: '#215889',
|
||||
},
|
||||
tide: {
|
||||
400: '#38bdf8',
|
||||
500: '#0ea5e9',
|
||||
600: '#0284c7',
|
||||
},
|
||||
foam: {
|
||||
50: '#f0f9ff',
|
||||
100: '#e0f2fe',
|
||||
200: '#bae6fd',
|
||||
},
|
||||
lagoon: {
|
||||
400: '#22d3ee',
|
||||
500: '#06b6d4',
|
||||
600: '#0891b2',
|
||||
},
|
||||
galet: {
|
||||
300: '#94a3b8',
|
||||
400: '#64748b',
|
||||
500: '#475569',
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
||||
display: ['Sora', 'Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
||||
},
|
||||
boxShadow: {
|
||||
glow: '0 0 40px -10px rgba(14, 165, 233, 0.35)',
|
||||
'glow-lg': '0 0 80px -10px rgba(6, 182, 212, 0.45)',
|
||||
card: '0 8px 30px rgba(5, 13, 26, 0.45)',
|
||||
},
|
||||
backgroundImage: {
|
||||
'abyss-grad': 'linear-gradient(180deg, #050d1a 0%, #0a1a2f 40%, #0f2742 100%)',
|
||||
'caustic': 'radial-gradient(circle at 20% 10%, rgba(6,182,212,0.15), transparent 50%), radial-gradient(circle at 80% 80%, rgba(14,165,233,0.12), transparent 50%)',
|
||||
},
|
||||
keyframes: {
|
||||
'float-slow': {
|
||||
'0%, 100%': { transform: 'translateY(0px)' },
|
||||
'50%': { transform: 'translateY(-12px)' },
|
||||
},
|
||||
'shimmer': {
|
||||
'0%': { backgroundPosition: '-200% 0' },
|
||||
'100%': { backgroundPosition: '200% 0' },
|
||||
},
|
||||
'sonar': {
|
||||
'0%': { transform: 'scale(1)', opacity: '0.6' },
|
||||
'100%': { transform: 'scale(3)', opacity: '0' },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
'float-slow': 'float-slow 8s ease-in-out infinite',
|
||||
'shimmer': 'shimmer 6s linear infinite',
|
||||
'sonar': 'sonar 3s ease-out infinite',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
9
tsconfig.json
Normal file
9
tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": ["src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user