Initial commit
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Ignore all Markdown files
|
||||
*.md
|
||||
5
.htaccess
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Sécurisation minimale
|
||||
Options -Indexes
|
||||
|
||||
# Page 404 personnalisée
|
||||
ErrorDocument 404 omegakube/pages/404.html
|
||||
331
assets/css/404.css
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
:root {
|
||||
--bg-deep: #0a0a0f;
|
||||
--bg-primary: #12121a;
|
||||
--bg-secondary: #1a1a25;
|
||||
--accent-primary: #8b3a62;
|
||||
--accent-secondary: #5e2a8b;
|
||||
--accent-light: #d4a5c9;
|
||||
--text-primary: #ffffff;
|
||||
--text-secondary: #b8b8c8;
|
||||
--text-muted: #6b6b7b;
|
||||
--glass-bg: rgba(255, 255, 255, 0.03);
|
||||
--glass-border: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
background: var(--bg-deep);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bg-grid {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background-image:
|
||||
linear-gradient(rgba(139, 58, 98, 0.03) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(139, 58, 98, 0.03) 1px, transparent 1px);
|
||||
background-size: 50px 50px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-glow {
|
||||
position: fixed;
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
border-radius: 50%;
|
||||
filter: blur(150px);
|
||||
opacity: 0.15;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-glow-1 {
|
||||
top: -200px;
|
||||
left: -200px;
|
||||
background: var(--accent-primary);
|
||||
animation: float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.bg-glow-2 {
|
||||
bottom: -200px;
|
||||
right: -200px;
|
||||
background: var(--accent-secondary);
|
||||
animation: float 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translate(0, 0); }
|
||||
50% { transform: translate(30px, 30px); }
|
||||
}
|
||||
|
||||
.particles {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.particle {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: var(--accent-light);
|
||||
border-radius: 50%;
|
||||
opacity: 0.3;
|
||||
animation: rise 10s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rise {
|
||||
0% { transform: translateY(100vh) scale(0); opacity: 0; }
|
||||
10% { opacity: 0.3; }
|
||||
90% { opacity: 0.3; }
|
||||
100% { transform: translateY(-100vh) scale(1); opacity: 0; }
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
z-index: 10;
|
||||
padding: 2rem;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.error-code {
|
||||
font-size: clamp(8rem, 25vw, 14rem);
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary), var(--accent-light));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
animation: glitch 3s infinite;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: transform 0.3s ease, filter 0.3s ease;
|
||||
}
|
||||
|
||||
.error-code:hover {
|
||||
transform: scale(1.05);
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.error-code:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.error-code::before,
|
||||
.error-code::after {
|
||||
content: '404';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.error-code::before {
|
||||
animation: glitch-1 0.3s infinite linear alternate-reverse;
|
||||
clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
|
||||
}
|
||||
|
||||
.error-code::after {
|
||||
animation: glitch-2 0.3s infinite linear alternate-reverse;
|
||||
clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%);
|
||||
}
|
||||
|
||||
@keyframes glitch {
|
||||
0%, 90%, 100% { transform: translate(0); }
|
||||
92% { transform: translate(-2px, 2px); }
|
||||
94% { transform: translate(2px, -2px); }
|
||||
96% { transform: translate(-2px, -2px); }
|
||||
98% { transform: translate(2px, 2px); }
|
||||
}
|
||||
|
||||
@keyframes glitch-1 {
|
||||
0% { transform: translate(0); }
|
||||
100% { transform: translate(-3px, 1px); }
|
||||
}
|
||||
|
||||
@keyframes glitch-2 {
|
||||
0% { transform: translate(0); }
|
||||
100% { transform: translate(3px, -1px); }
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto 2rem;
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: pulse-icon 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.error-icon svg {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
color: var(--accent-light);
|
||||
}
|
||||
|
||||
@keyframes pulse-icon {
|
||||
0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(139, 58, 98, 0.4); }
|
||||
50% { transform: scale(1.05); box-shadow: 0 0 0 15px rgba(139, 58, 98, 0); }
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-size: 1.75rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: 1rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.7;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.error-message span {
|
||||
color: var(--accent-light);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.875rem 1.75rem;
|
||||
border-radius: 8px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn svg { width: 18px; height: 18px; }
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
|
||||
color: white;
|
||||
box-shadow: 0 4px 20px rgba(139, 58, 98, 0.3);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 30px rgba(139, 58, 98, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid var(--glass-border);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: var(--accent-primary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.portal {
|
||||
position: absolute;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
pointer-events: none;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.portal-left { left: -100px; top: 50%; transform: translateY(-50%); }
|
||||
.portal-right { right: -100px; top: 50%; transform: translateY(-50%); }
|
||||
|
||||
.portal-ring {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border: 2px solid var(--accent-primary);
|
||||
border-radius: 50%;
|
||||
animation: rotate 10s linear infinite;
|
||||
}
|
||||
|
||||
.portal-ring:nth-child(2) { inset: 20px; border-color: var(--accent-secondary); animation-duration: 8s; animation-direction: reverse; }
|
||||
.portal-ring:nth-child(3) { inset: 40px; border-color: var(--accent-light); animation-duration: 6s; }
|
||||
|
||||
@keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 2rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.footer a { color: var(--accent-light); text-decoration: none; transition: color 0.3s ease; }
|
||||
.footer a:hover { color: var(--text-primary); }
|
||||
|
||||
.logo-mini {
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Responsive 404 */
|
||||
@media (max-width: 768px) {
|
||||
.error-code { font-size: clamp(5rem, 20vw, 8rem); }
|
||||
.error-icon { width: 60px; height: 60px; margin-bottom: 1.5rem; }
|
||||
.error-icon svg { width: 30px; height: 30px; }
|
||||
.error-title { font-size: 1.4rem; }
|
||||
.error-message { font-size: 0.9rem; padding: 0 1rem; }
|
||||
.buttons { flex-direction: column; width: 100%; padding: 0 1rem; }
|
||||
.btn { width: 100%; justify-content: center; padding: 1rem 1.5rem; }
|
||||
.portal { display: none; }
|
||||
.footer { bottom: 1rem; font-size: 0.75rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.container { padding: 1rem; }
|
||||
.error-code { font-size: clamp(4rem, 18vw, 6rem); margin-bottom: 0.5rem; }
|
||||
.error-icon { width: 50px; height: 50px; margin-bottom: 1rem; }
|
||||
.error-icon svg { width: 24px; height: 24px; }
|
||||
.error-title { font-size: 1.2rem; }
|
||||
.error-message { font-size: 0.85rem; margin-bottom: 2rem; }
|
||||
.btn { font-size: 0.9rem; padding: 0.875rem 1.25rem; }
|
||||
}
|
||||
|
||||
@media (max-height: 600px) {
|
||||
.error-icon { display: none; }
|
||||
.error-code { margin-bottom: 0.5rem; }
|
||||
.error-title { font-size: 1.2rem; margin-bottom: 0.5rem; }
|
||||
.error-message { margin-bottom: 1.5rem; }
|
||||
}
|
||||
33
assets/css/legal.css
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* assets/css/legal.css - minimal rules for legal pages */
|
||||
|
||||
/* Layout background patterns */
|
||||
.geo-bg { position:absolute; inset:0; background:radial-gradient(#0f1724 0%, transparent 40%); z-index:0; }
|
||||
.grid-pattern { position:absolute; inset:0; background-image: repeating-linear-gradient(45deg, rgba(255,255,255,0.02) 0 1px, transparent 1px 20px); z-index:0; }
|
||||
|
||||
/* Hero */
|
||||
.page-hero { display:flex; align-items:center; justify-content:center; padding:3rem 1rem; background:var(--hero-bg); color:var(--text-on-hero); }
|
||||
.page-hero .hero-content { max-width:1100px; text-align:center; }
|
||||
|
||||
/* Legal content (text-first layout) */
|
||||
.legal-content { padding:2.25rem 1rem; background:transparent; color:var(--text); }
|
||||
.legal-container { max-width:900px; margin:0 auto; display:block; }
|
||||
.legal-section { margin-bottom:1.25rem; }
|
||||
.legal-section h2 { font-size:1.1rem; margin:0 0 .5rem 0; font-weight:700; display:block; }
|
||||
.legal-card { background:transparent; padding:0; border-radius:0; box-shadow:none; border:none; }
|
||||
.legal-card p, .legal-card ul { margin:0 0 .75rem 0; line-height:1.6; color:var(--text); }
|
||||
.page-hero { padding:1.5rem 1rem; background:transparent; color:var(--text); text-align:left; }
|
||||
.page-hero .hero-content h1 { font-size:1.6rem; margin-bottom:.25rem; }
|
||||
.page-hero .hero-content p { margin:0 0 .5rem 0; }
|
||||
|
||||
|
||||
/* Footer */
|
||||
footer .footer-content { display:flex; gap:1rem; flex-wrap:wrap; align-items:center; }
|
||||
.footer-bottom { text-align:center; padding:1rem 0; font-size:.9rem; }
|
||||
|
||||
/* Nav / responsive */
|
||||
#navbar.scrolled { backdrop-filter: blur(4px); box-shadow:0 6px 18px rgba(2,6,23,.12); }
|
||||
.nav-links { display:flex; gap:1rem; list-style:none; }
|
||||
.nav-links a.active, .nav-links a[aria-current="true"] { font-weight:700; color:var(--accent); }
|
||||
.nav-links.active { display:block; }
|
||||
.mobile-toggle { display:none; /* show via media query */ }
|
||||
@media (max-width:880px) { .nav-links { display:none; } .mobile-toggle { display:block; } }
|
||||
3552
assets/css/main.css
Normal file
290
assets/data/projects.json
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
[
|
||||
{
|
||||
"id": 1,
|
||||
"category": "bot",
|
||||
"title": "Medieval RP Bot",
|
||||
"desc": "Un système RP médiéval complet avec économie, métiers, combat stratégique et gestion de royaumes. Développé pour une communauté de 5000+ joueurs actifs.",
|
||||
"gradient": "linear-gradient(135deg, var(--accent-primary), var(--accent-secondary))",
|
||||
"year": "2024",
|
||||
"duration": "3 mois",
|
||||
"features": ["Système d'économie", "Combat tour par tour", "Gestion de royaumes", "Quêtes automatisées", "Inventaire avancé", "Système de métiers"],
|
||||
"tech": ["Python", "Discord.py", "PostgreSQL", "Redis", "FastAPI"],
|
||||
"stats": [{ "value": "5000+", "label": "Joueurs" }, { "value": "150+", "label": "Commandes" }, { "value": "99.9%", "label": "Uptime" }]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"category": "map",
|
||||
"title": "Cyberpunk City",
|
||||
"desc": "Ville futuriste immersive avec 5 quartiers distincts, plus de 100 bâtiments accessibles et un système jour/nuit dynamique. Optimisée pour 50 joueurs.",
|
||||
"gradient": "linear-gradient(135deg, #5E2040, #8b3a62)",
|
||||
"year": "2024",
|
||||
"duration": "2 mois",
|
||||
"features": ["5 quartiers uniques", "100+ bâtiments", "Système jour/nuit", "Zones scriptées", "Éclairage néon", "Optimisé 50 joueurs"],
|
||||
"tech": ["Fortnite Creative", "UEFN", "Verse", "Lighting"],
|
||||
"stats": [{ "value": "50K+", "label": "Parties" }, { "value": "100+", "label": "Bâtiments" }, { "value": "50", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"category": "bot",
|
||||
"title": "Space Station RP",
|
||||
"desc": "Bot Sci-Fi avec économie spatiale, gestion de vaisseaux, exploration de planètes et système de factions interstellaires.",
|
||||
"gradient": "linear-gradient(135deg, #3a1f5e, #8b3a62)",
|
||||
"year": "2024",
|
||||
"duration": "4 mois",
|
||||
"features": ["Économie spatiale", "Gestion de vaisseaux", "Exploration", "Factions", "Combat spatial", "Crafting"],
|
||||
"tech": ["Python", "Discord.py", "MongoDB", "Docker"],
|
||||
"stats": [{ "value": "3000+", "label": "Joueurs" }, { "value": "200+", "label": "Commandes" }, { "value": "50+", "label": "Planètes" }]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"category": "graphisme",
|
||||
"title": "Branding Nova RP",
|
||||
"desc": "Identité visuelle complète incluant logo, bannières, emojis personnalisés et templates pour un serveur RP majeur.",
|
||||
"gradient": "linear-gradient(135deg, #2d1b5e, #5E2040)",
|
||||
"year": "2024",
|
||||
"duration": "3 semaines",
|
||||
"features": ["Logo principal", "Déclinaisons logo", "Bannières Discord", "Emojis custom", "Templates", "Guide de style"],
|
||||
"tech": ["Photoshop", "Illustrator", "After Effects", "Figma"],
|
||||
"stats": [{ "value": "50+", "label": "Éléments" }, { "value": "8", "label": "Bannières" }, { "value": "30+", "label": "Emojis" }]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"category": "map",
|
||||
"title": "Tokyo Night",
|
||||
"desc": "Reconstitution d'un quartier de Tokyo nocturne avec ruelles, néons, boutiques et ambiance authentique pour du RP urbain japonais.",
|
||||
"gradient": "linear-gradient(135deg, #1a3a5e, #3a5e8b)",
|
||||
"year": "2024",
|
||||
"duration": "6 semaines",
|
||||
"features": ["Ruelles détaillées", "Néons japonais", "Boutiques", "Metro", "Appartements", "Rooftops"],
|
||||
"tech": ["Fortnite Creative", "UEFN", "Custom Props"],
|
||||
"stats": [{ "value": "30K+", "label": "Parties" }, { "value": "80+", "label": "Boutiques" }, { "value": "40", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"category": "bot",
|
||||
"title": "Western Frontier",
|
||||
"desc": "Système RP Far West complet avec duels, shérif, hors-la-loi, prospection d'or et gestion de ranch.",
|
||||
"gradient": "linear-gradient(135deg, #5e3a1a, #8b5e3a)",
|
||||
"year": "2023",
|
||||
"duration": "3 mois",
|
||||
"features": ["Système de duels", "Rôles Sheriff/Outlaw", "Prospection d'or", "Gestion de ranch", "Économie western", "Wanted system"],
|
||||
"tech": ["Python", "Discord.py", "SQLite", "PIL"],
|
||||
"stats": [{ "value": "2500+", "label": "Joueurs" }, { "value": "100+", "label": "Commandes" }, { "value": "15+", "label": "Métiers" }]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"category": "graphisme",
|
||||
"title": "EcoVerse Assets",
|
||||
"desc": "Pack complet d'icônes et emojis sur thème écologique/nature pour serveur communautaire gaming.",
|
||||
"gradient": "linear-gradient(135deg, #1a5e3a, #3a8b5e)",
|
||||
"year": "2024",
|
||||
"duration": "2 semaines",
|
||||
"features": ["Pack icônes", "Emojis animés", "Badges ranks", "Séparateurs", "Backgrounds", "Overlays"],
|
||||
"tech": ["Illustrator", "After Effects", "Photoshop"],
|
||||
"stats": [{ "value": "100+", "label": "Icônes" }, { "value": "50+", "label": "Emojis" }, { "value": "20", "label": "Badges" }]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"category": "map",
|
||||
"title": "Apocalypse Zone",
|
||||
"desc": "Monde post-apocalyptique avec zones de survie, bunkers, véhicules abandonnés et ambiance désolée.",
|
||||
"gradient": "linear-gradient(135deg, #5e1a3a, #8b3a5e)",
|
||||
"year": "2023",
|
||||
"duration": "2 mois",
|
||||
"features": ["Zones dévastées", "Bunkers secrets", "Véhicules props", "Camps survivants", "Ressources", "Zone radioactive"],
|
||||
"tech": ["Fortnite Creative", "UEFN", "Environmental Design"],
|
||||
"stats": [{ "value": "25K+", "label": "Parties" }, { "value": "10", "label": "Zones" }, { "value": "30", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"category": "bot",
|
||||
"title": "Academy RP",
|
||||
"desc": "Système scolaire interactif avec cours, examens, clubs, dortoirs et système de réputation étudiant.",
|
||||
"gradient": "linear-gradient(135deg, #3a1a5e, #5e3a8b)",
|
||||
"year": "2024",
|
||||
"duration": "2 mois",
|
||||
"features": ["Système de cours", "Examens", "Clubs étudiants", "Dortoirs", "Réputation", "Events scolaires"],
|
||||
"tech": ["Python", "Discord.py", "PostgreSQL"],
|
||||
"stats": [{ "value": "4000+", "label": "Étudiants" }, { "value": "50+", "label": "Cours" }, { "value": "20+", "label": "Clubs" }]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"category": "graphisme",
|
||||
"title": "Golden Crown",
|
||||
"desc": "Bannières et visuels premium style royal/luxe pour serveur RP médiéval haut de gamme.",
|
||||
"gradient": "linear-gradient(135deg, #5e5e1a, #8b8b3a)",
|
||||
"year": "2024",
|
||||
"duration": "1 mois",
|
||||
"features": ["Bannières premium", "Logo royal", "Ornements", "Cadres dorés", "Typography", "Animations"],
|
||||
"tech": ["Photoshop", "Illustrator", "After Effects"],
|
||||
"stats": [{ "value": "30+", "label": "Visuels" }, { "value": "5", "label": "Animations" }, { "value": "100%", "label": "Satisfaction" }]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"category": "map",
|
||||
"title": "Mystic Village",
|
||||
"desc": "Village fantastique médiéval avec magie, créatures et architecture féerique pour RP fantasy.",
|
||||
"gradient": "linear-gradient(135deg, #1a1a5e, #3a3a8b)",
|
||||
"year": "2023",
|
||||
"duration": "5 semaines",
|
||||
"features": ["Village médiéval", "Tour du mage", "Forêt enchantée", "Taverne", "Marché", "Arène"],
|
||||
"tech": ["Fortnite Creative", "Custom Lighting"],
|
||||
"stats": [{ "value": "20K+", "label": "Parties" }, { "value": "50+", "label": "Bâtiments" }, { "value": "35", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"category": "bot",
|
||||
"title": "Crime City",
|
||||
"desc": "Bot GTA-like avec gangs, territoire, trafics, police et système judiciaire complet.",
|
||||
"gradient": "linear-gradient(135deg, #5e1a1a, #8b3a3a)",
|
||||
"year": "2024",
|
||||
"duration": "4 mois",
|
||||
"features": ["Système de gangs", "Territoires", "Trafics", "Police/Justice", "Prison", "Braquages"],
|
||||
"tech": ["Python", "Discord.py", "PostgreSQL", "Redis"],
|
||||
"stats": [{ "value": "6000+", "label": "Joueurs" }, { "value": "250+", "label": "Commandes" }, { "value": "10+", "label": "Gangs" }]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"category": "bot",
|
||||
"title": "Pirate Bay RP",
|
||||
"desc": "Aventure pirate complète avec navigation, batailles navales, trésors et commerce maritime.",
|
||||
"gradient": "linear-gradient(135deg, #1a4a5e, #3a6a8b)",
|
||||
"year": "2023",
|
||||
"duration": "3 mois",
|
||||
"features": ["Navigation", "Batailles navales", "Chasse au trésor", "Commerce", "Équipages", "Îles secrètes"],
|
||||
"tech": ["Python", "Discord.py", "MongoDB"],
|
||||
"stats": [{ "value": "3500+", "label": "Pirates" }, { "value": "100+", "label": "Îles" }, { "value": "50+", "label": "Navires" }]
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"category": "map",
|
||||
"title": "Neon District",
|
||||
"desc": "Quartier cyberpunk détaillé avec clubs, appartements high-tech et ambiance nocturne.",
|
||||
"gradient": "linear-gradient(135deg, #4a1a5e, #6a3a8b)",
|
||||
"year": "2024",
|
||||
"duration": "4 semaines",
|
||||
"features": ["Nightclubs", "Appartements", "Ruelles néon", "Boutiques tech", "Garages", "Rooftop bars"],
|
||||
"tech": ["Fortnite Creative", "UEFN", "Neon Effects"],
|
||||
"stats": [{ "value": "15K+", "label": "Parties" }, { "value": "60+", "label": "Intérieurs" }, { "value": "25", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"category": "graphisme",
|
||||
"title": "Cyber UI Pack",
|
||||
"desc": "Interface futuriste complète avec HUD, menus et éléments interactifs style sci-fi.",
|
||||
"gradient": "linear-gradient(135deg, #1a5e5e, #3a8b8b)",
|
||||
"year": "2024",
|
||||
"duration": "3 semaines",
|
||||
"features": ["HUD elements", "Menus", "Boutons", "Barres de vie", "Minimap style", "Notifications"],
|
||||
"tech": ["Figma", "Illustrator", "After Effects"],
|
||||
"stats": [{ "value": "80+", "label": "Éléments" }, { "value": "10", "label": "Animations" }, { "value": "3", "label": "Thèmes" }]
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"category": "bot",
|
||||
"title": "Dragon Realm",
|
||||
"desc": "Univers fantasy avec dragons apprivoisables, magie élémentaire et quêtes épiques.",
|
||||
"gradient": "linear-gradient(135deg, #5e2a1a, #8b4a3a)",
|
||||
"year": "2023",
|
||||
"duration": "5 mois",
|
||||
"features": ["Dragons", "Magie élémentaire", "Quêtes épiques", "Guildes", "Donjons", "Boss fights"],
|
||||
"tech": ["Python", "Discord.py", "PostgreSQL", "PIL"],
|
||||
"stats": [{ "value": "4500+", "label": "Joueurs" }, { "value": "30+", "label": "Dragons" }, { "value": "100+", "label": "Quêtes" }]
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"category": "map",
|
||||
"title": "Space Colony",
|
||||
"desc": "Station spatiale habitable avec modules, serres, hangars et vue sur l'espace.",
|
||||
"gradient": "linear-gradient(135deg, #1a2a5e, #3a4a8b)",
|
||||
"year": "2024",
|
||||
"duration": "6 semaines",
|
||||
"features": ["Modules habitables", "Serres spatiales", "Hangars", "Passerelles", "Vue espace", "Gravité zéro"],
|
||||
"tech": ["Fortnite Creative", "UEFN", "Sci-fi Props"],
|
||||
"stats": [{ "value": "12K+", "label": "Parties" }, { "value": "20", "label": "Modules" }, { "value": "20", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"category": "graphisme",
|
||||
"title": "Retro Wave Pack",
|
||||
"desc": "Style années 80 revisité avec néons, grilles et esthétique synthwave.",
|
||||
"gradient": "linear-gradient(135deg, #5e1a4a, #8b3a6a)",
|
||||
"year": "2023",
|
||||
"duration": "2 semaines",
|
||||
"features": ["Bannières retro", "Grilles 80s", "Néons rose/bleu", "Typography", "Sun effects", "VHS overlays"],
|
||||
"tech": ["Photoshop", "After Effects", "Illustrator"],
|
||||
"stats": [{ "value": "40+", "label": "Éléments" }, { "value": "15", "label": "Animations" }, { "value": "5", "label": "Templates" }]
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"category": "bot",
|
||||
"title": "Zombie Survival",
|
||||
"desc": "Système survie zombie avec crafting, bases, hordes et coopération entre survivants.",
|
||||
"gradient": "linear-gradient(135deg, #2a5e1a, #4a8b3a)",
|
||||
"year": "2024",
|
||||
"duration": "3 mois",
|
||||
"features": ["Système de survie", "Crafting", "Construction bases", "Hordes zombies", "Coop", "Ressources"],
|
||||
"tech": ["Python", "Discord.py", "MongoDB", "Redis"],
|
||||
"stats": [{ "value": "5500+", "label": "Survivants" }, { "value": "50+", "label": "Items craft" }, { "value": "1000+", "label": "Bases" }]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"category": "map",
|
||||
"title": "Desert Oasis",
|
||||
"desc": "Monde désertique immersif avec oasis, ruines anciennes et caravanes nomades.",
|
||||
"gradient": "linear-gradient(135deg, #5e4a1a, #8b6a3a)",
|
||||
"year": "2023",
|
||||
"duration": "5 semaines",
|
||||
"features": ["Désert vaste", "Oasis centrale", "Ruines anciennes", "Camp nomade", "Tempêtes sable", "Grottes"],
|
||||
"tech": ["Fortnite Creative", "Environmental FX"],
|
||||
"stats": [{ "value": "18K+", "label": "Parties" }, { "value": "8", "label": "Zones" }, { "value": "30", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"category": "bot",
|
||||
"title": "Mafia Empire",
|
||||
"desc": "Organisation criminelle RP avec familles, territoires, business illégaux et omerta.",
|
||||
"gradient": "linear-gradient(135deg, #3a3a3a, #5a5a5a)",
|
||||
"year": "2024",
|
||||
"duration": "4 mois",
|
||||
"features": ["Familles mafieuses", "Territoires", "Business", "Omerta", "Hiérarchie", "Contrats"],
|
||||
"tech": ["Python", "Discord.py", "PostgreSQL"],
|
||||
"stats": [{ "value": "3800+", "label": "Membres" }, { "value": "8", "label": "Familles" }, { "value": "150+", "label": "Commandes" }]
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"category": "graphisme",
|
||||
"title": "Fantasy Icons",
|
||||
"desc": "200+ icônes médiévales pour items, skills, classes et interface de jeu RP.",
|
||||
"gradient": "linear-gradient(135deg, #4a3a1a, #6a5a3a)",
|
||||
"year": "2024",
|
||||
"duration": "1 mois",
|
||||
"features": ["Icônes items", "Icônes skills", "Icônes classes", "Cadres", "Rarités", "Animations"],
|
||||
"tech": ["Illustrator", "Photoshop"],
|
||||
"stats": [{ "value": "200+", "label": "Icônes" }, { "value": "6", "label": "Rarités" }, { "value": "12", "label": "Classes" }]
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"category": "map",
|
||||
"title": "Underwater City",
|
||||
"desc": "Cité sous-marine style Atlantis avec dômes, tunnels et créatures marines.",
|
||||
"gradient": "linear-gradient(135deg, #1a3a4a, #3a5a6a)",
|
||||
"year": "2024",
|
||||
"duration": "7 semaines",
|
||||
"features": ["Dômes habitables", "Tunnels verre", "Jardins marins", "Palais central", "Sous-marins", "Créatures"],
|
||||
"tech": ["Fortnite Creative", "UEFN", "Underwater FX"],
|
||||
"stats": [{ "value": "22K+", "label": "Parties" }, { "value": "15", "label": "Dômes" }, { "value": "25", "label": "Joueurs max" }]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"category": "bot",
|
||||
"title": "Superhero League",
|
||||
"desc": "Univers super-héros avec pouvoirs, missions, vilains et quartier général.",
|
||||
"gradient": "linear-gradient(135deg, #1a1a4a, #3a3a6a)",
|
||||
"year": "2023",
|
||||
"duration": "4 mois",
|
||||
"features": ["Pouvoirs custom", "Missions", "Vilains IA", "QG héros", "Réputation", "Team-ups"],
|
||||
"tech": ["Python", "Discord.py", "PostgreSQL", "PIL"],
|
||||
"stats": [{ "value": "4200+", "label": "Héros" }, { "value": "80+", "label": "Pouvoirs" }, { "value": "200+", "label": "Missions" }]
|
||||
}
|
||||
]
|
||||
86
assets/data/team.json
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
[
|
||||
{
|
||||
"name": "Alexandre",
|
||||
"role": "Développeur Principal",
|
||||
"avatar": "A",
|
||||
"bio": "Passionné de développement depuis l'adolescence, Alexandre a découvert le monde du RP Discord en 2019. Depuis, il a développé plus de 50 bots pour des communautés allant de quelques centaines à plusieurs milliers de membres. Son expertise couvre les systèmes d'économie, les mécaniques de jeu complexes et l'optimisation des performances.",
|
||||
"stats": [
|
||||
{ "value": "5", "label": "Ans d'exp." },
|
||||
{ "value": "50+", "label": "Projets" },
|
||||
{ "value": "★★★", "label": "Expert" }
|
||||
],
|
||||
"skills": ["Python", "Discord.py", "JavaScript", "Node.js", "MongoDB", "API REST"]
|
||||
},
|
||||
{
|
||||
"name": "Sophie",
|
||||
"role": "Designer Fortnite",
|
||||
"avatar": "S",
|
||||
"bio": "Sophie combine sa passion pour le level design et le storytelling pour créer des environnements Fortnite uniques. Formée en architecture, elle apporte une attention particulière aux détails et à l'ambiance de chaque map. Ses créations ont été jouées par plus de 100 000 joueurs.",
|
||||
"stats": [
|
||||
{ "value": "3", "label": "Ans d'exp." },
|
||||
{ "value": "25+", "label": "Maps" },
|
||||
{ "value": "100K", "label": "Joueurs" }
|
||||
],
|
||||
"skills": ["Fortnite Creative", "UEFN", "Level Design", "3D", "Lighting", "Scripting"]
|
||||
},
|
||||
{
|
||||
"name": "Thomas",
|
||||
"role": "Community Manager",
|
||||
"avatar": "T",
|
||||
"bio": "Thomas est le lien entre OmégaKube et ses communautés. Ancien admin de plusieurs serveurs RP majeurs, il comprend les besoins des joueurs et des staff. Il s'assure que chaque projet répond aux attentes et accompagne les clients dans le développement de leur communauté.",
|
||||
"stats": [
|
||||
{ "value": "4", "label": "Ans d'exp." },
|
||||
{ "value": "20K+", "label": "Membres" },
|
||||
{ "value": "24/7", "label": "Dispo" }
|
||||
],
|
||||
"skills": ["Community Management", "Discord", "Modération", "Events", "Support"]
|
||||
},
|
||||
{
|
||||
"name": "Marie",
|
||||
"role": "Graphiste",
|
||||
"avatar": "M",
|
||||
"bio": "Marie donne vie aux identités visuelles des projets RP. Diplômée en design graphique, elle maîtrise aussi bien la création de logos que le motion design. Son style unique mélange esthétique gaming et professionnalisme pour des visuels qui marquent les esprits.",
|
||||
"stats": [
|
||||
{ "value": "6", "label": "Ans d'exp." },
|
||||
{ "value": "200+", "label": "Créations" },
|
||||
{ "value": "★★★", "label": "Expert" }
|
||||
],
|
||||
"skills": ["Photoshop", "Illustrator", "After Effects", "Figma", "Branding", "UI Design"]
|
||||
},
|
||||
{
|
||||
"name": "Lucas",
|
||||
"role": "Développeur Backend",
|
||||
"avatar": "L",
|
||||
"bio": "Lucas est l'architecte invisible derrière les systèmes les plus robustes d'OmégaKube. Spécialisé dans les bases de données et les API, il conçoit des systèmes d'économie capables de gérer des millions de transactions sans ralentissement.",
|
||||
"stats": [
|
||||
{ "value": "4", "label": "Ans d'exp." },
|
||||
{ "value": "30+", "label": "Systèmes" },
|
||||
{ "value": "99.9%", "label": "Uptime" }
|
||||
],
|
||||
"skills": ["Python", "PostgreSQL", "Redis", "FastAPI", "Docker", "AWS"]
|
||||
},
|
||||
{
|
||||
"name": "Emma",
|
||||
"role": "Scénariste RP",
|
||||
"avatar": "E",
|
||||
"bio": "Emma crée les univers et les histoires qui donnent vie aux sessions RP. Autrice de formation, elle conçoit des scénarios immersifs, des personnages mémorables et des quêtes captivantes. Elle aide aussi les clients à développer le lore de leur serveur.",
|
||||
"stats": [
|
||||
{ "value": "3", "label": "Ans d'exp." },
|
||||
{ "value": "40+", "label": "Scénarios" },
|
||||
{ "value": "∞", "label": "Créativité" }
|
||||
],
|
||||
"skills": ["Écriture", "Worldbuilding", "Game Design", "Narration", "Dialogue"]
|
||||
},
|
||||
{
|
||||
"name": "Julien",
|
||||
"role": "Testeur QA",
|
||||
"avatar": "J",
|
||||
"bio": "Julien est le gardien de la qualité chez OmégaKube. Aucun bug ne lui échappe. Il teste méticuleusement chaque fonctionnalité, chaque commande, chaque interaction pour garantir une expérience sans accroc aux utilisateurs finaux.",
|
||||
"stats": [
|
||||
{ "value": "2", "label": "Ans d'exp." },
|
||||
{ "value": "500+", "label": "Bugs trouvés" },
|
||||
{ "value": "0", "label": "Bug raté" }
|
||||
],
|
||||
"skills": ["Testing", "Bug Tracking", "Documentation", "Discord", "Feedback"]
|
||||
}
|
||||
]
|
||||
BIN
assets/fonts/custom_font_large.otf
Normal file
BIN
assets/fonts/custom_font_small.otf
Normal file
BIN
assets/images/favicon/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/images/favicon/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
assets/images/favicon/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
assets/images/favicon/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 632 B |
BIN
assets/images/favicon/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/images/favicon/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
1
assets/images/favicon/site.webmanifest
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||
BIN
assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
assets/images/old-logo.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
171
assets/js/home.js
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
// Home page specific JS: team carousel + modal
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Fetch team data and render
|
||||
fetch('assets/data/team.json')
|
||||
.then(res => res.json())
|
||||
.then(members => {
|
||||
initTeamSection(members);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to load team data', err);
|
||||
});
|
||||
|
||||
function initTeamSection(members) {
|
||||
const carousel = document.getElementById('team-carousel');
|
||||
const dotsContainer = document.getElementById('carousel-dots');
|
||||
const prevBtn = document.getElementById('carousel-prev');
|
||||
const nextBtn = document.getElementById('carousel-next');
|
||||
|
||||
// Render cards
|
||||
carousel.innerHTML = members.map((m, i) => `
|
||||
<div class="team-card" data-member="${i}">
|
||||
<div class="team-avatar">
|
||||
<div class="team-avatar-inner">${m.avatar}</div>
|
||||
</div>
|
||||
<h4>${m.name}</h4>
|
||||
<p class="team-role">${m.role}</p>
|
||||
<p class="team-desc">${(m.bio || '').split('.').shift()}.</p>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
// Carousel logic
|
||||
const cardsContainer = carousel; // the track
|
||||
let cards = carousel.querySelectorAll('.team-card');
|
||||
let currentIndex = 0;
|
||||
let cardsPerView = 3;
|
||||
let autoPlayInterval;
|
||||
|
||||
function updateCardsPerView() {
|
||||
if (window.innerWidth <= 768) cardsPerView = 1;
|
||||
else if (window.innerWidth <= 1024) cardsPerView = 2;
|
||||
else cardsPerView = 3;
|
||||
}
|
||||
|
||||
function createDots() {
|
||||
dotsContainer.innerHTML = '';
|
||||
const totalDots = Math.max(1, Math.ceil(cards.length / cardsPerView));
|
||||
for (let i = 0; i < totalDots; i++) {
|
||||
const dot = document.createElement('div');
|
||||
dot.classList.add('carousel-dot');
|
||||
if (i === 0) dot.classList.add('active');
|
||||
dot.addEventListener('click', () => goToSlide(i));
|
||||
dotsContainer.appendChild(dot);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCarousel() {
|
||||
cards = carousel.querySelectorAll('.team-card');
|
||||
if (cards.length === 0) return;
|
||||
const cardStyle = window.getComputedStyle(cards[0]);
|
||||
const gap = 32; // matches previous implementation
|
||||
const cardWidth = cards[0].offsetWidth + gap;
|
||||
carousel.style.transform = `translateX(-${currentIndex * cardWidth}px)`;
|
||||
|
||||
const dots = dotsContainer.querySelectorAll('.carousel-dot');
|
||||
const activeDotIndex = Math.floor(currentIndex / cardsPerView);
|
||||
dots.forEach((dot, i) => dot.classList.toggle('active', i === activeDotIndex));
|
||||
}
|
||||
|
||||
function goToSlide(dotIndex) {
|
||||
currentIndex = dotIndex * cardsPerView;
|
||||
if (currentIndex > cards.length - cardsPerView) currentIndex = Math.max(0, cards.length - cardsPerView);
|
||||
updateCarousel();
|
||||
resetAutoPlay();
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
currentIndex++;
|
||||
if (currentIndex > cards.length - cardsPerView) currentIndex = 0;
|
||||
updateCarousel();
|
||||
}
|
||||
|
||||
function prevSlide() {
|
||||
currentIndex--;
|
||||
if (currentIndex < 0) currentIndex = Math.max(0, cards.length - cardsPerView);
|
||||
updateCarousel();
|
||||
}
|
||||
|
||||
function startAutoPlay() {
|
||||
clearInterval(autoPlayInterval);
|
||||
autoPlayInterval = setInterval(nextSlide, 4000);
|
||||
}
|
||||
|
||||
function resetAutoPlay() {
|
||||
clearInterval(autoPlayInterval);
|
||||
startAutoPlay();
|
||||
}
|
||||
|
||||
prevBtn && prevBtn.addEventListener('click', () => { prevSlide(); resetAutoPlay(); });
|
||||
nextBtn && nextBtn.addEventListener('click', () => { nextSlide(); resetAutoPlay(); });
|
||||
|
||||
carousel.addEventListener('mouseenter', () => clearInterval(autoPlayInterval));
|
||||
carousel.addEventListener('mouseleave', startAutoPlay);
|
||||
|
||||
updateCardsPerView();
|
||||
createDots();
|
||||
startAutoPlay();
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
updateCardsPerView();
|
||||
createDots();
|
||||
currentIndex = 0;
|
||||
updateCarousel();
|
||||
});
|
||||
|
||||
// Modal logic
|
||||
const modalOverlay = document.getElementById('team-modal-overlay');
|
||||
const modalClose = document.getElementById('team-modal-close');
|
||||
const modalAvatar = document.getElementById('modal-avatar');
|
||||
const modalName = document.getElementById('modal-name');
|
||||
const modalRole = document.getElementById('modal-role');
|
||||
const modalBio = document.getElementById('modal-bio');
|
||||
const modalStats = document.getElementById('modal-stats');
|
||||
const modalSkills = document.getElementById('modal-skills');
|
||||
const modalSocial = document.getElementById('modal-social');
|
||||
|
||||
function openMemberModal(index) {
|
||||
const member = members[index];
|
||||
if (!member) return;
|
||||
modalAvatar.textContent = member.avatar || member.name.charAt(0);
|
||||
modalName.textContent = member.name;
|
||||
modalRole.textContent = member.role;
|
||||
modalBio.textContent = member.bio;
|
||||
|
||||
modalStats.innerHTML = (member.stats || []).map(stat => `
|
||||
<div class="team-modal-stat">
|
||||
<div class="team-modal-stat-value">${stat.value}</div>
|
||||
<div class="team-modal-stat-label">${stat.label}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
modalSkills.innerHTML = (member.skills || []).map(s => `<span class="team-modal-skill">${s}</span>`).join('');
|
||||
|
||||
modalSocial.innerHTML = `
|
||||
<a href="#" aria-label="Discord"><i data-feather="message-circle"></i></a>
|
||||
<a href="#" aria-label="Twitter"><i data-feather="twitter"></i></a>
|
||||
`;
|
||||
|
||||
if (window.feather && feather.replace) feather.replace();
|
||||
|
||||
modalOverlay.classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeMemberModal() {
|
||||
modalOverlay.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
// Attach click listeners to generated cards
|
||||
carousel.querySelectorAll('.team-card').forEach(card => {
|
||||
card.addEventListener('click', () => {
|
||||
const idx = parseInt(card.dataset.member, 10);
|
||||
openMemberModal(idx);
|
||||
});
|
||||
});
|
||||
|
||||
modalClose && modalClose.addEventListener('click', closeMemberModal);
|
||||
modalOverlay && modalOverlay.addEventListener('click', (e) => { if (e.target === modalOverlay) closeMemberModal(); });
|
||||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && modalOverlay.classList.contains('active')) closeMemberModal(); });
|
||||
}
|
||||
});
|
||||
393
assets/js/main.js
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
// OmégaKube - shared scripts
|
||||
|
||||
// Feather icons loader (centralized)
|
||||
// loads https://unpkg.com/feather-icons when needed and exposes window.ensureFeather()
|
||||
const FEATHER_URL = 'https://unpkg.com/feather-icons';
|
||||
function ensureFeather() {
|
||||
if (window.__featherLoading) return window.__featherLoading;
|
||||
if (window.feather && window.feather.replace) return Promise.resolve(window.feather);
|
||||
window.__featherLoading = new Promise((resolve, reject) => {
|
||||
const s = document.createElement('script');
|
||||
s.src = FEATHER_URL;
|
||||
s.async = true;
|
||||
s.onload = () => resolve(window.feather);
|
||||
s.onerror = () => reject(new Error('Failed to load feather-icons'));
|
||||
document.head.appendChild(s);
|
||||
});
|
||||
return window.__featherLoading;
|
||||
}
|
||||
window.ensureFeather = ensureFeather;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
// ensure feather icons are available and replace icons in document
|
||||
try { await ensureFeather(); if (window.feather && feather.replace) try { feather.replace(); } catch(e) {} } catch (e) {}
|
||||
|
||||
// Load HTML includes (components header/footer) and fix relative paths when necessary
|
||||
async function loadIncludes() {
|
||||
const includeSelector = '[data-include]';
|
||||
const nodes = Array.from(document.querySelectorAll(includeSelector));
|
||||
if (!nodes.length) return;
|
||||
await Promise.all(nodes.map(async el => {
|
||||
const url = el.getAttribute('data-include');
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
const text = await res.text();
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = text;
|
||||
const fragment = template.content;
|
||||
// adjust relative paths for assets and page links when included from /pages/
|
||||
fragment.querySelectorAll('[href], [src]').forEach(node => {
|
||||
['href','src'].forEach(attr => {
|
||||
if (!node.hasAttribute(attr)) return;
|
||||
const original = node.getAttribute(attr);
|
||||
|
||||
// leave absolute URLs and anchors untouched
|
||||
if (/^(https?:|\/|#)/.test(original)) return;
|
||||
|
||||
// compute useful bases
|
||||
const includeUrl = new URL(url, document.baseURI);
|
||||
const includeDir = includeUrl.pathname.substring(0, includeUrl.pathname.lastIndexOf('/') + 1);
|
||||
const docUrl = new URL(document.location.href);
|
||||
const docDir = docUrl.pathname.substring(0, docUrl.pathname.lastIndexOf('/') + 1);
|
||||
|
||||
// find common prefix between include location and current document to infer site root
|
||||
const includeParts = includeDir.split('/');
|
||||
const docParts = docDir.split('/');
|
||||
let i = 0;
|
||||
while (i < includeParts.length && i < docParts.length && includeParts[i] === docParts[i]) i++;
|
||||
const baseRoot = includeParts.slice(0, i).join('/') || '/';
|
||||
|
||||
let newVal;
|
||||
if (original.startsWith('./') || original.startsWith('../')) {
|
||||
// explicit relative paths should resolve relative to the include file
|
||||
const resolved = new URL(original, includeUrl);
|
||||
newVal = resolved.pathname + resolved.search + resolved.hash;
|
||||
} else {
|
||||
// treat plain paths (e.g. "assets/..." or "pages/...") as site-root relative
|
||||
newVal = (baseRoot.endsWith('/') ? baseRoot : baseRoot + '/') + original;
|
||||
}
|
||||
|
||||
node.setAttribute(attr, newVal);
|
||||
});
|
||||
});
|
||||
el.replaceWith(fragment);
|
||||
} catch (err) {
|
||||
console.error('Failed to load include', url, err);
|
||||
}
|
||||
}));
|
||||
if (typeof ensureFeather === 'function') {
|
||||
ensureFeather().then(() => { try { if (window.feather && feather.replace) feather.replace(); } catch (e) {} }).catch(()=>{});
|
||||
} else if (window.feather && feather.replace) {
|
||||
try { feather.replace(); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
// wait for includes to be loaded so subsequent initialization can bind to elements inside them
|
||||
await loadIncludes();
|
||||
|
||||
const html = document.documentElement;
|
||||
|
||||
function getPreferredTheme() {
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme) return savedTheme;
|
||||
return window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
|
||||
}
|
||||
|
||||
// Apply preferred theme
|
||||
try {
|
||||
html.setAttribute('data-theme', getPreferredTheme());
|
||||
} catch (e) {}
|
||||
|
||||
// Theme toggle (robust)
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
if (themeToggle) {
|
||||
// sync aria state
|
||||
themeToggle.setAttribute('aria-pressed', html.getAttribute('data-theme') === 'dark' ? 'false' : 'true');
|
||||
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const currentTheme = html.getAttribute('data-theme');
|
||||
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||
html.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
themeToggle.setAttribute('aria-pressed', newTheme === 'dark' ? 'false' : 'true');
|
||||
});
|
||||
}
|
||||
|
||||
// Navbar scroll effect
|
||||
const navbar = document.getElementById('navbar');
|
||||
function updateNavbarOnScroll() {
|
||||
if (!navbar) return;
|
||||
navbar.classList.toggle('scrolled', window.scrollY > 50);
|
||||
}
|
||||
window.addEventListener('scroll', updateNavbarOnScroll);
|
||||
window.addEventListener('load', updateNavbarOnScroll);
|
||||
|
||||
// Mobile menu
|
||||
const mobileToggle = document.getElementById('mobile-toggle');
|
||||
const navLinks = document.getElementById('nav-links');
|
||||
|
||||
// mobile menu initialization (debug logs removed)
|
||||
|
||||
// create a toggle function that is safe even if elements are added later
|
||||
const toggleMenu = () => {
|
||||
const mt = document.getElementById('mobile-toggle');
|
||||
const nl = document.getElementById('nav-links');
|
||||
// console.log('[DEBUG] toggleMenu called', { mt: !!mt, nl: !!nl, mtClass: mt ? mt.className : null, nlClass: nl ? nl.className : null });
|
||||
if (!mt || !nl) {
|
||||
// elements missing: abort toggle
|
||||
// console.log('[DEBUG] toggleMenu aborted: missing elements', { mt, nl });
|
||||
return;
|
||||
}
|
||||
mt.classList.toggle('active');
|
||||
nl.classList.toggle('active');
|
||||
// console.log('[DEBUG] toggleMenu toggled', { mtClass: mt.className, nlClass: nl.className });
|
||||
const expanded = nl.classList.contains('active') ? 'true' : 'false';
|
||||
mt.setAttribute('aria-expanded', expanded);
|
||||
};
|
||||
|
||||
// |||||||||||||| ça fait buguer le menu mobile ||||||||||||||
|
||||
// direct binding if elements exist
|
||||
// if (mobileToggle && navLinks) {
|
||||
// if (!mobileToggle.hasAttribute('tabindex')) mobileToggle.setAttribute('tabindex', '0');
|
||||
// mobileToggle.setAttribute('aria-expanded', navLinks.classList.contains('active') ? 'true' : 'false');
|
||||
|
||||
// mobileToggle.addEventListener('click', (e) => {
|
||||
// console.log('[DEBUG] mobileToggle click handler fired', e.target, e);
|
||||
// e.preventDefault();
|
||||
// toggleMenu();
|
||||
// });
|
||||
|
||||
// mobileToggle.addEventListener('keydown', (e) => {
|
||||
// if (e.key === 'Enter' || e.key === ' ') {
|
||||
// console.log('[DEBUG] mobileToggle keydown:', e.key);
|
||||
// e.preventDefault();
|
||||
// toggleMenu();
|
||||
// }
|
||||
// });
|
||||
|
||||
// navLinks.querySelectorAll('a').forEach(link => {
|
||||
// link.addEventListener('click', () => {
|
||||
// console.log('[DEBUG] nav link clicked in mobile menu', link.getAttribute('href'));
|
||||
// // collapse on link click
|
||||
// const mt = document.getElementById('mobile-toggle');
|
||||
// const nl = document.getElementById('nav-links');
|
||||
// if (mt && nl) {
|
||||
// mt.classList.remove('active');
|
||||
// nl.classList.remove('active');
|
||||
// mt.setAttribute('aria-expanded', 'false');
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
// Global delegation: catch clicks anywhere on page for '#mobile-toggle' (works even if element is replaced)
|
||||
document.addEventListener('click', (e) => {
|
||||
const mt = e.target.closest ? e.target.closest('#mobile-toggle') : null;
|
||||
if (mt) {
|
||||
// console.log('[DEBUG] delegated click caught for #mobile-toggle', e.target);
|
||||
e.preventDefault();
|
||||
toggleMenu();
|
||||
}
|
||||
});
|
||||
|
||||
// expose helper for console debugging
|
||||
window.toggleMobileMenu = toggleMenu;
|
||||
|
||||
// Smooth scroll for anchor links
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
const href = this.getAttribute('href');
|
||||
if (!href || href === '#') return;
|
||||
const target = document.querySelector(href);
|
||||
if (target) {
|
||||
e.preventDefault();
|
||||
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Highlight active nav link based on current URL
|
||||
function normalizePath(path) {
|
||||
if (!path) return '/';
|
||||
// treat both '/' and '/index.html' as root
|
||||
if (path.endsWith('index.html')) {
|
||||
const p = path.slice(0, -'index.html'.length);
|
||||
return p === '' ? '/' : p;
|
||||
}
|
||||
return path.endsWith('/') ? path : path;
|
||||
}
|
||||
|
||||
function setActiveNavLink() {
|
||||
const links = document.querySelectorAll('#nav-links a[href]');
|
||||
if (!links.length) return;
|
||||
const currentPath = normalizePath(window.location.pathname);
|
||||
const currentHash = window.location.hash || '';
|
||||
|
||||
let bestMatch = null;
|
||||
let bestScore = -1;
|
||||
|
||||
links.forEach(link => {
|
||||
const href = link.getAttribute('href');
|
||||
let linkUrl;
|
||||
try {
|
||||
linkUrl = new URL(href, document.location.href);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
const linkPath = normalizePath(linkUrl.pathname);
|
||||
const linkHash = linkUrl.hash || '';
|
||||
|
||||
let score = 0;
|
||||
if (linkPath === currentPath) score += 2;
|
||||
if (linkHash && linkHash === currentHash) score += 4;
|
||||
// Prefer exact hash matches, then exact path matches
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestMatch = link;
|
||||
}
|
||||
});
|
||||
|
||||
// Fallback: if on root (/) and there is an index link, pick it
|
||||
if (!bestMatch) {
|
||||
links.forEach(link => {
|
||||
if (!bestMatch && /index\.html$|\/$/.test(link.getAttribute('href') || '')) {
|
||||
bestMatch = link;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
links.forEach(l => { l.classList.remove('active'); l.removeAttribute('aria-current'); });
|
||||
if (bestMatch) { bestMatch.classList.add('active'); bestMatch.setAttribute('aria-current', 'page'); }
|
||||
}
|
||||
|
||||
// initialize and listen for navigation/hash changes
|
||||
setActiveNavLink();
|
||||
window.addEventListener('hashchange', setActiveNavLink);
|
||||
window.addEventListener('popstate', setActiveNavLink);
|
||||
|
||||
// Home page: observe sections so #apropos and #contact become active when visible,
|
||||
// and revert to "Accueil" when neither section is in view.
|
||||
let homeSectionObserver = null;
|
||||
let homeVisibility = {};
|
||||
|
||||
function initHomeSectionObserver() {
|
||||
// clean existing observer
|
||||
if (homeSectionObserver) {
|
||||
homeSectionObserver.disconnect();
|
||||
homeSectionObserver = null;
|
||||
homeVisibility = {};
|
||||
}
|
||||
|
||||
// Instead of requiring a strict '/' path, detect whether the current document
|
||||
// actually contains any sections referenced by nav links (e.g. #apropos, #contact).
|
||||
const links = Array.from(document.querySelectorAll('#nav-links a[href]'));
|
||||
const sectionLinks = links.filter(link => {
|
||||
try {
|
||||
const u = new URL(link.getAttribute('href'), document.location.href);
|
||||
if (!u.hash) return false;
|
||||
return !!document.querySelector(u.hash);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!sectionLinks.length) return;
|
||||
|
||||
const sections = sectionLinks.map(link => {
|
||||
const hash = new URL(link.getAttribute('href'), document.location.href).hash;
|
||||
const el = document.querySelector(hash);
|
||||
return el ? { id: el.id, el, link } : null;
|
||||
}).filter(Boolean);
|
||||
|
||||
if (!sections.length) return;
|
||||
|
||||
// setup observer
|
||||
homeSectionObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
homeVisibility[entry.target.id] = entry.intersectionRatio || 0;
|
||||
});
|
||||
|
||||
// pick the section with highest intersection ratio
|
||||
let bestId = null; let bestRatio = 0;
|
||||
Object.entries(homeVisibility).forEach(([id, ratio]) => {
|
||||
if (ratio > bestRatio) { bestRatio = ratio; bestId = id; }
|
||||
});
|
||||
|
||||
const navLinks = Array.from(document.querySelectorAll('#nav-links a[href]'));
|
||||
// if a section is sufficiently visible, activate its link
|
||||
if (bestId && bestRatio > 0.15) {
|
||||
const targetLink = navLinks.find(l => {
|
||||
try {
|
||||
return new URL(l.getAttribute('href'), document.location.href).hash === '#' + bestId;
|
||||
} catch (e) { return false; }
|
||||
});
|
||||
if (targetLink) {
|
||||
navLinks.forEach(l => { l.classList.remove('active'); l.removeAttribute('aria-current'); });
|
||||
targetLink.classList.add('active');
|
||||
targetLink.setAttribute('aria-current', 'page');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback: set Accueil active when no section is visible
|
||||
const indexLink = Array.from(navLinks).find(l => /index\.html$|\/$/.test(l.getAttribute('href') || ''));
|
||||
navLinks.forEach(l => { l.classList.remove('active'); l.removeAttribute('aria-current'); });
|
||||
if (indexLink) { indexLink.classList.add('active'); indexLink.setAttribute('aria-current', 'page'); }
|
||||
|
||||
}, { root: null, threshold: [0, 0.15, 0.3, 0.6] });
|
||||
|
||||
sections.forEach(s => {
|
||||
homeVisibility[s.id] = 0;
|
||||
homeSectionObserver.observe(s.el);
|
||||
});
|
||||
}
|
||||
|
||||
// initialize observer on load and update when navigation changes
|
||||
initHomeSectionObserver();
|
||||
window.addEventListener('resize', () => { if (homeSectionObserver) initHomeSectionObserver(); });
|
||||
// re-init observer when URL path changes (i.e., leave/enter index)
|
||||
const originalSetActive = setActiveNavLink;
|
||||
function wrappedSetActive() {
|
||||
// if leaving index, disconnect observer
|
||||
const path = normalizePath(window.location.pathname);
|
||||
if (path !== '/') {
|
||||
if (homeSectionObserver) { homeSectionObserver.disconnect(); homeSectionObserver = null; homeVisibility = {}; }
|
||||
originalSetActive();
|
||||
return;
|
||||
}
|
||||
// on index, ensure observer is active and let it control the highlight where possible
|
||||
initHomeSectionObserver();
|
||||
originalSetActive();
|
||||
}
|
||||
|
||||
// replace handlers so navigation updates use our wrapped variant
|
||||
window.removeEventListener('hashchange', setActiveNavLink);
|
||||
window.removeEventListener('popstate', setActiveNavLink);
|
||||
window.addEventListener('hashchange', wrappedSetActive);
|
||||
window.addEventListener('popstate', wrappedSetActive);
|
||||
|
||||
// Reveal on scroll
|
||||
const revealElements = document.querySelectorAll('.reveal');
|
||||
function revealOnScroll() {
|
||||
if (!revealElements.length) return;
|
||||
revealElements.forEach(el => {
|
||||
const elementTop = el.getBoundingClientRect().top;
|
||||
if (elementTop < window.innerHeight - 100) {
|
||||
el.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
window.addEventListener('scroll', revealOnScroll);
|
||||
window.addEventListener('load', revealOnScroll);
|
||||
|
||||
// Contact form (if exists)
|
||||
const contactForm = document.getElementById('contact-form');
|
||||
if (contactForm) {
|
||||
contactForm.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
alert('Merci pour votre message ! Nous vous répondrons très bientôt.');
|
||||
this.reset();
|
||||
});
|
||||
}
|
||||
});
|
||||
209
assets/js/pages/404.js
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
feather.replace();
|
||||
|
||||
// Particles
|
||||
const particlesContainer = document.getElementById('particles');
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const particle = document.createElement('div');
|
||||
particle.classList.add('particle');
|
||||
particle.style.left = Math.random() * 100 + '%';
|
||||
particle.style.animationDelay = Math.random() * 10 + 's';
|
||||
particle.style.animationDuration = (Math.random() * 5 + 8) + 's';
|
||||
particle.style.width = (Math.random() * 4 + 2) + 'px';
|
||||
particle.style.height = particle.style.width;
|
||||
particlesContainer.appendChild(particle);
|
||||
}
|
||||
|
||||
// Easter Egg: Konami Code (desktop) ou 10 taps (mobile)
|
||||
const konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a'];
|
||||
let konamiIndex = 0;
|
||||
let tapCount = 0;
|
||||
let tapTimer = null;
|
||||
const REQUIRED_TAPS = 10;
|
||||
const errorCodeEl = document.querySelector('.error-code');
|
||||
|
||||
// Desktop: Konami Code
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === konamiCode[konamiIndex]) {
|
||||
konamiIndex++;
|
||||
if (konamiIndex === konamiCode.length) {
|
||||
startPortalTransition();
|
||||
konamiIndex = 0;
|
||||
}
|
||||
} else {
|
||||
konamiIndex = 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Mobile: 10 taps
|
||||
function handleTap(e) {
|
||||
if (e.type === 'touchend') e.preventDefault();
|
||||
tapCount++;
|
||||
|
||||
errorCodeEl.style.transform = 'scale(0.95)';
|
||||
setTimeout(() => errorCodeEl.style.transform = '', 100);
|
||||
|
||||
if (tapCount >= 3 && tapCount < REQUIRED_TAPS) {
|
||||
showTapCounter(tapCount, REQUIRED_TAPS);
|
||||
}
|
||||
|
||||
if (tapTimer) clearTimeout(tapTimer);
|
||||
tapTimer = setTimeout(() => { tapCount = 0; hideTapCounter(); }, 500);
|
||||
|
||||
if (tapCount >= REQUIRED_TAPS) {
|
||||
tapCount = 0;
|
||||
hideTapCounter();
|
||||
startPortalTransition();
|
||||
}
|
||||
}
|
||||
|
||||
function showTapCounter(current, total) {
|
||||
let counter = document.getElementById('tap-counter');
|
||||
if (!counter) {
|
||||
counter = document.createElement('div');
|
||||
counter.id = 'tap-counter';
|
||||
counter.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);background:rgba(139,58,98,0.9);color:white;padding:0.5rem 1rem;border-radius:20px;font-size:0.85rem;font-weight:600;z-index:1000;';
|
||||
document.body.appendChild(counter);
|
||||
}
|
||||
counter.textContent = current + ' / ' + total + ' 🔓';
|
||||
}
|
||||
|
||||
function hideTapCounter() {
|
||||
const counter = document.getElementById('tap-counter');
|
||||
if (counter) counter.remove();
|
||||
}
|
||||
|
||||
errorCodeEl.addEventListener('click', handleTap);
|
||||
errorCodeEl.addEventListener('touchend', handleTap);
|
||||
|
||||
// Portal Transition
|
||||
function startPortalTransition() {
|
||||
const transition = document.createElement('div');
|
||||
transition.id = 'portal-transition';
|
||||
transition.innerHTML = '<div class="warp-container"><div class="warp-tunnel"></div><div class="warp-stars"></div><div class="warp-center"><div class="warp-ring"></div><div class="warp-ring"></div><div class="warp-ring"></div></div><div class="warp-flash"></div></div><div class="warp-text">ENTRÉE DANS LA MATRICE</div>';
|
||||
document.body.appendChild(transition);
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.id = 'transition-styles';
|
||||
style.textContent = '#portal-transition{position:fixed;inset:0;z-index:10000;background:#000;display:flex;align-items:center;justify-content:center;overflow:hidden}.warp-container{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;perspective:500px}.warp-tunnel{position:absolute;width:200vmax;height:200vmax;background:repeating-conic-gradient(from 0deg,transparent 0deg 10deg,rgba(139,58,98,0.1) 10deg 20deg);animation:tunnelSpin 2s linear infinite,tunnelZoom 3s ease-in forwards}@keyframes tunnelSpin{to{transform:rotate(360deg)}}@keyframes tunnelZoom{0%{transform:rotate(0)scale(1);opacity:0}20%{opacity:1}100%{transform:rotate(720deg)scale(20);opacity:0}}.warp-stars{position:absolute;inset:0;background-image:radial-gradient(2px 2px at 20px 30px,#fff,transparent),radial-gradient(2px 2px at 40px 70px,rgba(255,255,255,0.8),transparent),radial-gradient(1px 1px at 90px 40px,#fff,transparent);background-size:350px 200px;animation:starsWarp 3s ease-in forwards}@keyframes starsWarp{0%{transform:scale(1);opacity:0}30%{opacity:1}100%{transform:scale(50);opacity:0}}.warp-center{position:relative;width:150px;height:150px;animation:centerPulse 0.5s ease-in-out infinite,centerGrow 2.5s ease-in forwards}@keyframes centerPulse{0%,100%{filter:brightness(1)}50%{filter:brightness(1.5)}}@keyframes centerGrow{0%{transform:scale(0);opacity:0}20%{transform:scale(1);opacity:1}80%{transform:scale(1);opacity:1}100%{transform:scale(100);opacity:1}}.warp-ring{position:absolute;inset:0;border:4px solid #8b3a62;border-radius:50%;animation:ringPulse 1s ease-in-out infinite;box-shadow:0 0 30px #8b3a62,inset 0 0 30px #8b3a62}.warp-ring:nth-child(2){inset:20px;border-color:#5e2a8b;animation-delay:0.2s;box-shadow:0 0 30px #5e2a8b,inset 0 0 30px #5e2a8b}.warp-ring:nth-child(3){inset:40px;border-color:#d4a5c9;animation-delay:0.4s;box-shadow:0 0 30px #d4a5c9,inset 0 0 30px #d4a5c9}@keyframes ringPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.1);opacity:0.8}}.warp-flash{position:absolute;inset:0;background:#fff;opacity:0;animation:flashBang 0.5s ease-out 2.5s forwards}@keyframes flashBang{0%{opacity:0}50%{opacity:1}100%{opacity:0}}.warp-text{position:absolute;font-size:1.5rem;font-weight:700;color:#fff;letter-spacing:0.3rem;z-index:10;opacity:0;animation:textAppear 0.5s ease 0.5s forwards,textFade 0.5s ease 2s forwards}@keyframes textAppear{to{opacity:1}}@keyframes textFade{to{opacity:0;transform:scale(2)}}';
|
||||
document.head.appendChild(style);
|
||||
|
||||
setTimeout(() => {
|
||||
transition.remove();
|
||||
style.remove();
|
||||
launchGameOfLife();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Game of Life
|
||||
function launchGameOfLife() {
|
||||
const gameContainer = document.createElement('div');
|
||||
gameContainer.id = 'game-of-life';
|
||||
gameContainer.innerHTML = '<canvas id="gol-canvas"></canvas><div class="gol-ui"><div class="gol-header"><div class="gol-header-text"><h1>🧬 Dimension Secrète</h1><p>Le Jeu de la Vie de Conway</p></div><button id="gol-minimize" class="gol-minimize" title="Réduire"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="icon-min"><line x1="5" y1="12" x2="19" y2="12"/></svg><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="icon-max"><rect x="3" y="3" width="18" height="18" rx="2"/></svg></button></div><div class="gol-body"><div class="gol-description"><p><strong>Règles :</strong> Cellule vivante avec 2-3 voisins survit. Cellule morte avec 3 voisins naît.</p></div><div class="gol-controls"><button id="gol-play" class="gol-btn active" title="Play/Pause"><svg viewBox="0 0 24 24" fill="currentColor" class="icon-pause"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg><svg viewBox="0 0 24 24" fill="currentColor" class="icon-play"><polygon points="5,3 19,12 5,21"/></svg></button><button id="gol-step" class="gol-btn" title="Étape"><svg viewBox="0 0 24 24" fill="currentColor"><polygon points="5,3 15,12 5,21"/><rect x="15" y="3" width="4" height="18"/></svg></button><button id="gol-random" class="gol-btn" title="Aléatoire"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/></svg></button><button id="gol-clear" class="gol-btn" title="Effacer"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg></button><button id="gol-gliders" class="gol-btn" title="Planeurs"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13"/><polygon points="22,2 15,22 11,13 2,9"/></svg></button></div><div class="gol-zoom-row"><button id="gol-zoom-out" class="gol-btn gol-btn-sm">−</button><span id="gol-zoom-val">30px</span><button id="gol-zoom-in" class="gol-btn gol-btn-sm">+</button></div><div class="gol-speed-row"><label>Vitesse: <span id="gol-speed-val">15</span> fps</label><input type="range" id="gol-speed" min="1" max="60" value="15"></div><div class="gol-stats"><div class="gol-stat"><span id="gol-gen">0</span><label>Génération</label></div><div class="gol-stat"><span id="gol-pop">0</span><label>Population</label></div><div class="gol-stat"><span id="gol-dim">0×0</span><label>Grille</label></div></div></div><button id="gol-exit" class="gol-exit">✕ Quitter</button></div>';
|
||||
document.body.appendChild(gameContainer);
|
||||
|
||||
const gameStyles = document.createElement('style');
|
||||
gameStyles.id = 'gol-styles';
|
||||
gameStyles.textContent = '#game-of-life{position:fixed;inset:0;z-index:10000;background:#050508;animation:golIn 0.5s ease}@keyframes golIn{from{opacity:0}to{opacity:1}}#gol-canvas{position:absolute;inset:0;width:100%;height:100%;cursor:crosshair}.gol-ui{position:absolute;top:20px;left:20px;background:rgba(10,10,15,0.95);backdrop-filter:blur(10px);border:1px solid rgba(139,58,98,0.3);border-radius:16px;padding:1rem;min-width:280px;box-shadow:0 20px 60px rgba(0,0,0,0.5)}.gol-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:0.75rem}.gol-header-text h1{font-size:1.1rem;margin-bottom:0.1rem;background:linear-gradient(135deg,#d4a5c9,#8b3a62);-webkit-background-clip:text;-webkit-text-fill-color:transparent}.gol-header-text p{font-size:0.7rem;color:#6b6b7b}.gol-minimize{width:32px;height:32px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.05);border-radius:8px;color:#b8b8c8;cursor:pointer;display:flex;align-items:center;justify-content:center}.gol-minimize:hover{background:rgba(139,58,98,0.3);border-color:#8b3a62;color:#fff}.gol-minimize svg{width:16px;height:16px}.gol-minimize .icon-max{display:none}.gol-ui.minimized .gol-body,.gol-ui.minimized .gol-exit{display:none}.gol-ui.minimized .gol-minimize .icon-min{display:none}.gol-ui.minimized .gol-minimize .icon-max{display:block}.gol-ui.minimized{min-width:auto}.gol-body{display:flex;flex-direction:column;gap:0.75rem}.gol-description{background:rgba(139,58,98,0.1);border:1px solid rgba(139,58,98,0.2);border-radius:8px;padding:0.5rem}.gol-description p{font-size:0.7rem;color:#b8b8c8;margin:0}.gol-description strong{color:#d4a5c9}.gol-controls{display:flex;gap:0.4rem;flex-wrap:wrap}.gol-btn{width:40px;height:40px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.05);border-radius:8px;color:#b8b8c8;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.2s}.gol-btn:hover{background:rgba(139,58,98,0.3);border-color:#8b3a62;color:#fff;transform:translateY(-2px)}.gol-btn svg{width:18px;height:18px}.gol-btn.active{background:linear-gradient(135deg,#8b3a62,#5e2a8b);border-color:transparent;color:#fff}.gol-btn .icon-play{display:none}.gol-btn .icon-pause{display:block}.gol-btn:not(.active) .icon-play{display:block}.gol-btn:not(.active) .icon-pause{display:none}.gol-btn-sm{width:32px;height:32px;font-size:1.2rem;font-weight:bold}.gol-zoom-row,.gol-speed-row{display:flex;align-items:center;gap:0.5rem}.gol-zoom-row span{color:#d4a5c9;font-family:monospace;font-size:0.85rem;min-width:40px;text-align:center}.gol-speed-row{flex-direction:column;align-items:stretch}.gol-speed-row label{font-size:0.75rem;color:#b8b8c8}.gol-speed-row label span{color:#d4a5c9;font-family:monospace}.gol-speed-row input{width:100%;height:6px;-webkit-appearance:none;background:rgba(255,255,255,0.1);border-radius:3px;cursor:pointer}.gol-speed-row input::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;background:linear-gradient(135deg,#8b3a62,#5e2a8b);border-radius:50%;cursor:pointer}.gol-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:0.5rem}.gol-stat{text-align:center;padding:0.4rem;background:rgba(255,255,255,0.03);border-radius:6px}.gol-stat span{font-size:1rem;font-weight:700;color:#d4a5c9;font-family:monospace;display:block}.gol-stat label{font-size:0.6rem;color:#6b6b7b;text-transform:uppercase}.gol-exit{width:100%;margin-top:0.5rem;padding:0.6rem;background:transparent;border:1px solid rgba(255,255,255,0.1);border-radius:8px;color:#6b6b7b;font-size:0.8rem;cursor:pointer;transition:all 0.2s}.gol-exit:hover{background:rgba(255,50,50,0.2);border-color:rgba(255,50,50,0.5);color:#ff6b6b}@media(max-width:768px){.gol-ui{top:auto;bottom:0;left:0;right:0;border-radius:16px 16px 0 0;max-height:50vh;overflow-y:auto;min-width:auto}.gol-header-text p,.gol-description{display:none}.gol-ui.minimized{max-height:none}}@media(max-width:480px){.gol-ui{padding:0.75rem}.gol-btn{width:36px;height:36px}.gol-btn-sm{width:28px;height:28px}}';
|
||||
document.head.appendChild(gameStyles);
|
||||
|
||||
const canvas = document.getElementById('gol-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const MAX_CELLS = 150, MIN_SIZE = 4, MAX_SIZE = 30;
|
||||
let cellSize = MAX_SIZE, minCellSize = MIN_SIZE, cols, rows, grid, nextGrid;
|
||||
let isRunning = true, generation = 0, speed = 15, lastTime = 0, isDrawing = false, drawValue = 1;
|
||||
|
||||
function initCanvas() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
minCellSize = Math.max(MIN_SIZE, Math.ceil(canvas.width / MAX_CELLS), Math.ceil(canvas.height / MAX_CELLS));
|
||||
cellSize = Math.max(minCellSize, Math.min(MAX_SIZE, cellSize));
|
||||
cols = Math.ceil(canvas.width / cellSize);
|
||||
rows = Math.ceil(canvas.height / cellSize);
|
||||
grid = Array(cols).fill(null).map(() => Array(rows).fill(0));
|
||||
nextGrid = Array(cols).fill(null).map(() => Array(rows).fill(0));
|
||||
updateUI();
|
||||
}
|
||||
|
||||
function addGlider(sx, sy, dir) {
|
||||
const p = [[[0,1],[1,2],[2,0],[2,1],[2,2]],[[0,1],[1,0],[2,0],[2,1],[2,2]],[[0,0],[0,1],[0,2],[1,2],[2,1]],[[0,0],[0,1],[0,2],[1,0],[2,1]]];
|
||||
p[dir % 4].forEach(([dx, dy]) => { const x = (sx + dx) % cols, y = (sy + dy) % rows; if (x >= 0 && x < cols && y >= 0 && y < rows) grid[x][y] = 1; });
|
||||
}
|
||||
|
||||
function addGliders(n) {
|
||||
grid = Array(cols).fill(null).map(() => Array(rows).fill(0));
|
||||
for (let i = 0; i < n; i++) addGlider(Math.floor(Math.random() * (cols - 10)) + 5, Math.floor(Math.random() * (rows - 10)) + 5, Math.floor(Math.random() * 4));
|
||||
generation = 0; updateUI();
|
||||
}
|
||||
|
||||
function randomize() { for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) grid[x][y] = Math.random() > 0.7 ? 1 : 0; generation = 0; updateUI(); }
|
||||
function clear() { for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) grid[x][y] = 0; generation = 0; updateUI(); }
|
||||
|
||||
function step() {
|
||||
for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) {
|
||||
let n = 0;
|
||||
for (let i = -1; i <= 1; i++) for (let j = -1; j <= 1; j++) if (i || j) n += grid[(x + i + cols) % cols][(y + j + rows) % rows];
|
||||
nextGrid[x][y] = grid[x][y] ? (n === 2 || n === 3 ? 1 : 0) : (n === 3 ? 1 : 0);
|
||||
}
|
||||
[grid, nextGrid] = [nextGrid, grid]; generation++; updateUI();
|
||||
}
|
||||
|
||||
function draw() {
|
||||
ctx.fillStyle = '#0a0a0f'; ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.strokeStyle = 'rgba(139,58,98,0.1)'; ctx.lineWidth = 0.5;
|
||||
for (let x = 0; x <= cols * cellSize; x += cellSize) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, rows * cellSize); ctx.stroke(); }
|
||||
for (let y = 0; y <= rows * cellSize; y += cellSize) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(cols * cellSize, y); ctx.stroke(); }
|
||||
ctx.shadowColor = 'rgba(139,58,98,0.5)'; ctx.shadowBlur = 8;
|
||||
for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) if (grid[x][y]) {
|
||||
const g = ctx.createRadialGradient(x * cellSize + cellSize / 2, y * cellSize + cellSize / 2, 0, x * cellSize + cellSize / 2, y * cellSize + cellSize / 2, cellSize);
|
||||
g.addColorStop(0, '#d4a5c9'); g.addColorStop(0.5, '#8b3a62'); g.addColorStop(1, '#5e2a8b');
|
||||
ctx.fillStyle = g; ctx.fillRect(x * cellSize + 1, y * cellSize + 1, cellSize - 2, cellSize - 2);
|
||||
}
|
||||
ctx.shadowBlur = 0;
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
let pop = 0; for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) pop += grid[x][y];
|
||||
document.getElementById('gol-gen').textContent = generation;
|
||||
document.getElementById('gol-pop').textContent = pop;
|
||||
document.getElementById('gol-dim').textContent = cols + '×' + rows;
|
||||
document.getElementById('gol-zoom-val').textContent = cellSize + 'px';
|
||||
document.getElementById('gol-speed-val').textContent = speed;
|
||||
}
|
||||
|
||||
function handleZoom(d) {
|
||||
const old = cellSize; cellSize = Math.max(minCellSize, Math.min(MAX_SIZE, cellSize + d));
|
||||
if (cellSize !== old) { const og = grid, oc = cols, or = rows; initCanvas(); for (let x = 0; x < Math.min(oc, cols); x++) for (let y = 0; y < Math.min(or, rows); y++) grid[x][y] = og[x][y]; updateUI(); }
|
||||
}
|
||||
|
||||
function getCell(e) {
|
||||
const r = canvas.getBoundingClientRect(), cx = e.touches ? e.touches[0].clientX : e.clientX, cy = e.touches ? e.touches[0].clientY : e.clientY;
|
||||
return { x: Math.max(0, Math.min(cols - 1, Math.floor((cx - r.left) / cellSize))), y: Math.max(0, Math.min(rows - 1, Math.floor((cy - r.top) / cellSize))) };
|
||||
}
|
||||
|
||||
function gameLoop(t) { if (isRunning && t - lastTime > 1000 / speed) { step(); lastTime = t; } draw(); requestAnimationFrame(gameLoop); }
|
||||
|
||||
canvas.addEventListener('mousedown', e => { isDrawing = true; const c = getCell(e); drawValue = grid[c.x][c.y] ? 0 : 1; grid[c.x][c.y] = drawValue; });
|
||||
canvas.addEventListener('mousemove', e => { if (isDrawing) { const c = getCell(e); grid[c.x][c.y] = drawValue; } });
|
||||
canvas.addEventListener('mouseup', () => isDrawing = false);
|
||||
canvas.addEventListener('mouseleave', () => isDrawing = false);
|
||||
canvas.addEventListener('touchstart', e => { e.preventDefault(); isDrawing = true; const c = getCell(e); drawValue = grid[c.x][c.y] ? 0 : 1; grid[c.x][c.y] = drawValue; }, { passive: false });
|
||||
canvas.addEventListener('touchmove', e => { e.preventDefault(); if (isDrawing) { const c = getCell(e); grid[c.x][c.y] = drawValue; } }, { passive: false });
|
||||
canvas.addEventListener('touchend', () => isDrawing = false);
|
||||
canvas.addEventListener('wheel', e => { e.preventDefault(); handleZoom(e.deltaY > 0 ? -1 : 1); });
|
||||
|
||||
document.getElementById('gol-play').addEventListener('click', function() { isRunning = !isRunning; this.classList.toggle('active', isRunning); });
|
||||
document.getElementById('gol-step').addEventListener('click', () => { if (!isRunning) step(); });
|
||||
document.getElementById('gol-random').addEventListener('click', randomize);
|
||||
document.getElementById('gol-clear').addEventListener('click', clear);
|
||||
document.getElementById('gol-gliders').addEventListener('click', () => addGliders(3));
|
||||
document.getElementById('gol-zoom-in').addEventListener('click', () => handleZoom(2));
|
||||
document.getElementById('gol-zoom-out').addEventListener('click', () => handleZoom(-2));
|
||||
document.getElementById('gol-speed').addEventListener('input', function() { speed = parseInt(this.value); updateUI(); });
|
||||
document.getElementById('gol-minimize').addEventListener('click', () => document.querySelector('.gol-ui').classList.toggle('minimized'));
|
||||
document.getElementById('gol-exit').addEventListener('click', () => { document.getElementById('game-of-life').remove(); document.getElementById('gol-styles').remove(); });
|
||||
window.addEventListener('resize', () => { const og = grid, oc = cols, or = rows; initCanvas(); for (let x = 0; x < Math.min(oc, cols); x++) for (let y = 0; y < Math.min(or, rows); y++) grid[x][y] = og[x][y]; updateUI(); });
|
||||
|
||||
initCanvas();
|
||||
addGliders(3);
|
||||
requestAnimationFrame(gameLoop);
|
||||
}
|
||||
31
assets/js/pages/legal.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// assets/js/pages/legal.js - minimal fallback for legal pages
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// replace feather icons if available (use centralized loader if present)
|
||||
if (typeof window.ensureFeather === 'function') {
|
||||
window.ensureFeather().then(() => { try { if (window.feather && feather.replace) feather.replace(); } catch (e) {} }).catch(()=>{});
|
||||
} else if (window.feather && feather.replace) {
|
||||
try { feather.replace(); } catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
// theme fallback (will be overwritten by assets/js/main.js if present)
|
||||
const html = document.documentElement;
|
||||
if (!html.getAttribute('data-theme')) html.setAttribute('data-theme', localStorage.getItem('theme') || 'dark');
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
if (themeToggle) themeToggle.addEventListener('click', () => {
|
||||
const newTheme = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
||||
html.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
});
|
||||
|
||||
// navbar scrolled
|
||||
const navbar = document.getElementById('navbar');
|
||||
if (navbar) window.addEventListener('scroll', () => navbar.classList.toggle('scrolled', window.scrollY > 50));
|
||||
|
||||
// mobile toggle (minimal)
|
||||
const mobileToggle = document.getElementById('mobile-toggle');
|
||||
const navLinks = document.getElementById('nav-links');
|
||||
if (mobileToggle && navLinks) mobileToggle.addEventListener('click', () => {
|
||||
mobileToggle.classList.toggle('active');
|
||||
navLinks.classList.toggle('active');
|
||||
});
|
||||
});
|
||||
228
assets/js/pages/realisations.js
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
// Page script for /pages/realisations.html
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const dataUrl = '../assets/data/projects.json';
|
||||
let allProjects = [];
|
||||
|
||||
try {
|
||||
const res = await fetch(dataUrl);
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
allProjects = await res.json();
|
||||
} catch (err) {
|
||||
console.error('Failed to load projects data:', err);
|
||||
return;
|
||||
}
|
||||
|
||||
const ITEMS_PER_PAGE = 9;
|
||||
let currentPage = 1;
|
||||
let currentFilter = 'all';
|
||||
|
||||
const portfolioGrid = document.getElementById('portfolio-grid');
|
||||
const paginationContainer = document.getElementById('pagination');
|
||||
const filterTabs = document.querySelectorAll('.filter-tab');
|
||||
|
||||
const modalOverlay = document.getElementById('project-modal-overlay');
|
||||
const modalClose = document.getElementById('project-modal-close');
|
||||
const gallerySlides = document.getElementById('gallery-slides');
|
||||
const galleryPrev = document.getElementById('gallery-prev');
|
||||
const galleryNext = document.getElementById('gallery-next');
|
||||
|
||||
const modalTitle = document.getElementById('modal-title');
|
||||
const modalCategory = document.getElementById('modal-category');
|
||||
const modalDesc = document.getElementById('modal-desc');
|
||||
const modalMeta = document.getElementById('modal-meta');
|
||||
const modalFeatures = document.getElementById('modal-features');
|
||||
const modalTech = document.getElementById('modal-tech');
|
||||
const modalStats = document.getElementById('modal-stats');
|
||||
|
||||
function getFilteredProjects() {
|
||||
if (currentFilter === 'all') return [...allProjects];
|
||||
return allProjects.filter(p => p.category === currentFilter);
|
||||
}
|
||||
|
||||
function getTotalPages(filtered) {
|
||||
return Math.ceil(filtered.length / ITEMS_PER_PAGE) || 1;
|
||||
}
|
||||
|
||||
function getProjectsForPage(filtered, page) {
|
||||
const start = (page - 1) * ITEMS_PER_PAGE;
|
||||
return filtered.slice(start, start + ITEMS_PER_PAGE);
|
||||
}
|
||||
|
||||
function getCategoryLabel(category) {
|
||||
const labels = { 'bot': 'Bot Discord', 'map': 'Fortnite Map', 'graphisme': 'Graphisme' };
|
||||
return labels[category] || category;
|
||||
}
|
||||
|
||||
function renderProjects() {
|
||||
const filtered = getFilteredProjects();
|
||||
const projects = getProjectsForPage(filtered, currentPage);
|
||||
|
||||
portfolioGrid.innerHTML = projects.map(project => `
|
||||
<div class="portfolio-item reveal" data-project-id="${project.id}">
|
||||
<div class="portfolio-bg" style="background: ${project.gradient};"></div>
|
||||
<div class="portfolio-content">
|
||||
<span class="portfolio-tag">${getCategoryLabel(project.category)}</span>
|
||||
<h4>${project.title}</h4>
|
||||
<p>${project.desc.substring(0, 80)}...</p>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
// activate reveals & icons
|
||||
setTimeout(() => {
|
||||
document.querySelectorAll('.portfolio-item.reveal').forEach(el => el.classList.add('active'));
|
||||
}, 80);
|
||||
|
||||
// ensure icons are replaced for newly injected content
|
||||
if (window.feather && feather.replace) {
|
||||
try { feather.replace(); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function renderPagination() {
|
||||
const filtered = getFilteredProjects();
|
||||
const totalPages = getTotalPages(filtered);
|
||||
|
||||
if (totalPages <= 1) {
|
||||
paginationContainer.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = `<button class="pagination-btn pagination-arrow" data-page="${Math.max(1, currentPage - 1)}" ${currentPage === 1 ? 'disabled' : ''}><i data-feather="chevron-left"></i></button>`;
|
||||
|
||||
const maxVisible = 5;
|
||||
let startPage = Math.max(1, currentPage - Math.floor(maxVisible / 2));
|
||||
let endPage = Math.min(totalPages, startPage + maxVisible - 1);
|
||||
if (endPage - startPage < maxVisible - 1) startPage = Math.max(1, endPage - maxVisible + 1);
|
||||
|
||||
if (startPage > 1) {
|
||||
html += `<button class="pagination-btn" data-page="1">1</button>`;
|
||||
if (startPage > 2) html += `<span class="pagination-ellipsis">...</span>`;
|
||||
}
|
||||
|
||||
for (let i = startPage; i <= endPage; i++) {
|
||||
html += `<button class="pagination-btn ${i === currentPage ? 'active' : ''}" data-page="${i}">${i}</button>`;
|
||||
}
|
||||
|
||||
if (endPage < totalPages) {
|
||||
if (endPage < totalPages - 1) html += `<span class="pagination-ellipsis">...</span>`;
|
||||
html += `<button class="pagination-btn" data-page="${totalPages}">${totalPages}</button>`;
|
||||
}
|
||||
|
||||
html += `<button class="pagination-btn pagination-arrow" data-page="${Math.min(totalPages, currentPage + 1)}" ${currentPage === totalPages ? 'disabled' : ''}><i data-feather="chevron-right"></i></button>`;
|
||||
|
||||
const startItem = (currentPage - 1) * ITEMS_PER_PAGE + 1;
|
||||
const endItem = Math.min(currentPage * ITEMS_PER_PAGE, filtered.length);
|
||||
html += `<div class="pagination-info">Affichage ${startItem}-${endItem} sur ${filtered.length} projets</div>`;
|
||||
|
||||
paginationContainer.innerHTML = html;
|
||||
|
||||
if (window.feather && feather.replace) {
|
||||
try { feather.replace(); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function goToPage(page) {
|
||||
const filtered = getFilteredProjects();
|
||||
const totalPages = getTotalPages(filtered);
|
||||
if (page < 1 || page > totalPages) return;
|
||||
currentPage = page;
|
||||
renderProjects();
|
||||
renderPagination();
|
||||
portfolioGrid.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
function openProjectModal(projectId) {
|
||||
const project = allProjects.find(p => p.id === Number(projectId));
|
||||
if (!project) return;
|
||||
|
||||
modalCategory.textContent = getCategoryLabel(project.category);
|
||||
modalTitle.textContent = project.title;
|
||||
modalDesc.textContent = project.desc;
|
||||
|
||||
modalMeta.innerHTML = `<span><i data-feather="calendar"></i> ${project.year}</span> <span><i data-feather="clock"></i> ${project.duration}</span>`;
|
||||
|
||||
modalFeatures.innerHTML = project.features.map(f => `<div class="project-feature-item">${f}</div>`).join('');
|
||||
modalTech.innerHTML = project.tech.map(t => `<div class="project-tech-item">${t}</div>`).join('');
|
||||
modalStats.innerHTML = project.stats.map(s => `
|
||||
<div class="project-stat-card">
|
||||
<div class="project-stat-card-value">${s.value}</div>
|
||||
<div class="project-stat-card-label">${s.label}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
// gallery slides (use gradient as placeholder slides like original)
|
||||
gallerySlides.innerHTML = `
|
||||
<div class="project-gallery-slide" style="background: ${project.gradient};"></div>
|
||||
<div class="project-gallery-slide" style="background: ${project.gradient}; filter: hue-rotate(30deg);"></div>
|
||||
<div class="project-gallery-slide" style="background: ${project.gradient}; filter: hue-rotate(-30deg);"></div>
|
||||
`;
|
||||
|
||||
// reset gallery state
|
||||
galleryIndex = 0;
|
||||
updateGallery();
|
||||
|
||||
if (modalOverlay) modalOverlay.classList.add('active');
|
||||
|
||||
if (window.feather && feather.replace) {
|
||||
try { feather.replace(); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function closeProjectModal() {
|
||||
if (modalOverlay) modalOverlay.classList.remove('active');
|
||||
}
|
||||
|
||||
// Gallery helpers
|
||||
let galleryIndex = 0;
|
||||
function updateGallery() {
|
||||
const slides = gallerySlides ? Array.from(gallerySlides.children) : [];
|
||||
slides.forEach((s, i) => {
|
||||
s.style.transform = `translateX(${(i - galleryIndex) * 100}%)`;
|
||||
s.classList.toggle('active', i === galleryIndex);
|
||||
});
|
||||
}
|
||||
|
||||
function prevSlide() { galleryIndex = Math.max(0, galleryIndex - 1); updateGallery(); }
|
||||
function nextSlide() { const slides = gallerySlides ? gallerySlides.children.length : 0; galleryIndex = Math.min(slides - 1, galleryIndex + 1); updateGallery(); }
|
||||
|
||||
// Event bindings
|
||||
filterTabs.forEach(tab => tab.addEventListener('click', (e) => {
|
||||
filterTabs.forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
currentFilter = tab.dataset.filter || 'all';
|
||||
currentPage = 1;
|
||||
renderProjects();
|
||||
renderPagination();
|
||||
}));
|
||||
|
||||
paginationContainer.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('button[data-page]');
|
||||
if (!btn) return;
|
||||
const page = Number(btn.getAttribute('data-page'));
|
||||
goToPage(page);
|
||||
});
|
||||
|
||||
portfolioGrid.addEventListener('click', (e) => {
|
||||
const item = e.target.closest('.portfolio-item');
|
||||
if (!item) return;
|
||||
const id = item.getAttribute('data-project-id');
|
||||
openProjectModal(id);
|
||||
});
|
||||
|
||||
if (modalClose) modalClose.addEventListener('click', closeProjectModal);
|
||||
if (modalOverlay) modalOverlay.addEventListener('click', (e) => { if (e.target === modalOverlay) closeProjectModal(); });
|
||||
window.addEventListener('keydown', (e) => { if (e.key === 'Escape' && modalOverlay.classList.contains('active')) closeProjectModal(); });
|
||||
|
||||
if (galleryPrev) galleryPrev.addEventListener('click', prevSlide);
|
||||
if (galleryNext) galleryNext.addEventListener('click', nextSlide);
|
||||
|
||||
// Expose for compatibility
|
||||
window.openProjectModal = openProjectModal;
|
||||
window.goToPage = goToPage;
|
||||
|
||||
// Initial render
|
||||
renderProjects();
|
||||
renderPagination();
|
||||
});
|
||||
57
assets/js/pages/services.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Services page scripts (moved from inline in pages/services.html)
|
||||
// Depends on ../main.js which initializes feather and other globals
|
||||
|
||||
(function() {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Timeline Animation
|
||||
const timeline = document.getElementById('process-timeline');
|
||||
const steps = document.querySelectorAll('.process-step');
|
||||
|
||||
function animateTimeline() {
|
||||
if (!timeline) return;
|
||||
const timelineTop = timeline.getBoundingClientRect().top;
|
||||
|
||||
if (timelineTop < window.innerHeight - 200) {
|
||||
timeline.classList.add('animated');
|
||||
|
||||
// Animate steps sequentially
|
||||
steps.forEach((step, index) => {
|
||||
setTimeout(() => {
|
||||
step.classList.add('active');
|
||||
}, index * 400);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', animateTimeline);
|
||||
window.addEventListener('load', animateTimeline);
|
||||
|
||||
// Service Tabs
|
||||
const tabBtns = document.querySelectorAll('.service-tab-btn');
|
||||
const tabContents = document.querySelectorAll('.service-tab-content');
|
||||
|
||||
if (tabBtns.length && tabContents.length) {
|
||||
tabBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const tabId = btn.dataset.tab;
|
||||
|
||||
// Update buttons
|
||||
tabBtns.forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
|
||||
// Update content
|
||||
tabContents.forEach(content => {
|
||||
content.classList.remove('active');
|
||||
if (content.id === 'tab-' + tabId) {
|
||||
content.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Re-init feather icons for new content (safe if feather is loaded)
|
||||
if (window.feather) window.feather.replace();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
})();
|
||||
8
components/favicons.html
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<!-- components/favicons.html: shared favicon + PWA metadata -->
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/testarea/omegakube/v1bis/assets/images/favicon/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/testarea/omegakube/v1bis/assets/images/favicon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/testarea/omegakube/v1bis/assets/images/favicon/favicon-16x16.png">
|
||||
<link rel="manifest" href="/testarea/omegakube/v1bis/assets/images/favicon/site.webmanifest">
|
||||
<link rel="shortcut icon" href="/testarea/omegakube/v1bis/assets/images/favicon/favicon.ico">
|
||||
<meta name="msapplication-TileColor" content="#0a0a0f">
|
||||
<meta name="theme-color" content="#0a0a0f">
|
||||
39
components/footer.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!-- components/footer.html - shared footer -->
|
||||
<footer>
|
||||
<div class="footer-content">
|
||||
<a href="index.html" class="logo">
|
||||
<div class="logo-icon">
|
||||
<img src="assets/images/logo.png" alt="OmégaKube Logo">
|
||||
</div>
|
||||
<div class="logo-text">
|
||||
<span class="logo-full">
|
||||
<span class="omega">OMEGA </span>
|
||||
<span class="kube">KUBE</span>
|
||||
</span>
|
||||
<span class="logo-short">
|
||||
<span class="omega-symbol">Ω</span>
|
||||
<span class="kube-short">Kube</span>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="footer-links">
|
||||
<a href="index.html">Accueil</a>
|
||||
<a href="#apropos">À propos</a>
|
||||
<a href="pages/services.html">Services</a>
|
||||
<a href="pages/realisations.html">Réalisations</a>
|
||||
<a href="#contact">Contact</a>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<a href="pages/mentions-legales.html">Mentions légales</a>
|
||||
<a href="pages/cgv.html">CGV</a>
|
||||
</div>
|
||||
<div class="footer-social">
|
||||
<a href="#" aria-label="Discord"><i data-feather="message-circle"></i></a>
|
||||
<a href="#" aria-label="Twitter"><i data-feather="twitter"></i></a>
|
||||
<a href="#" aria-label="Instagram"><i data-feather="instagram"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
© 2026 OmégaKube. Tous droits réservés.
|
||||
</div>
|
||||
</footer>
|
||||
39
components/header.html
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!-- components/header.html - shared navigation -->
|
||||
<nav id="navbar">
|
||||
<div class="nav-container">
|
||||
<a href="index.html" class="logo">
|
||||
<div class="logo-icon">
|
||||
<img src="assets/images/logo.png" alt="OmégaKube Logo">
|
||||
</div>
|
||||
<div class="logo-text">
|
||||
<span class="logo-full">
|
||||
<span class="omega">OMEGA </span>
|
||||
<span class="kube">KUBE</span>
|
||||
</span>
|
||||
<span class="logo-short">
|
||||
<span class="omega-symbol">Ω</span>
|
||||
<span class="kube-short">Kube</span>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="nav-right">
|
||||
<ul class="nav-links" id="nav-links">
|
||||
<li><a href="index.html">Accueil</a></li>
|
||||
<li><a href="index.html#apropos">À propos</a></li>
|
||||
<li><a href="pages/services.html">Services</a></li>
|
||||
<li><a href="pages/realisations.html">Réalisations</a></li>
|
||||
<li><a href="index.html#contact">Contact</a></li>
|
||||
</ul>
|
||||
<button class="theme-toggle" id="theme-toggle" aria-label="Changer de thème">
|
||||
<i data-feather="moon" class="icon-moon"></i>
|
||||
<i data-feather="sun" class="icon-sun"></i>
|
||||
<div class="theme-toggle-thumb"></div>
|
||||
</button>
|
||||
<div class="mobile-toggle" id="mobile-toggle" tabindex="0" aria-expanded="false">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
289
index.html
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>OmégaKube — L'univers du Role Play réinventé</title>
|
||||
<template data-include="/testarea/omegakube/v1bis/components/favicons.html"></template>
|
||||
<link rel="stylesheet" href="assets/css/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Geometric Background -->
|
||||
<div class="geo-bg"></div>
|
||||
<div class="grid-pattern"></div>
|
||||
|
||||
<!-- Floating Shapes -->
|
||||
<div class="geo-shapes">
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
<div class="shape shape-diamond"></div>
|
||||
<div class="shape shape-rect"></div>
|
||||
<div class="shape shape-square"></div>
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-dots">
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
</div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
</div>
|
||||
|
||||
<div data-include="components/header.html"></div>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="hero" id="accueil">
|
||||
<div class="hero-content">
|
||||
<div class="hero-badge">
|
||||
<span>Créateurs d'univers RP</span>
|
||||
</div>
|
||||
<h1>
|
||||
L'univers du<br>
|
||||
<span class="highlight">Role Play</span><br>
|
||||
réinventé
|
||||
</h1>
|
||||
<p>Bots Discord personnalisés, maps Fortnite immersives — des expériences sur mesure pour vos communautés gaming.</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="pages/services.html" class="btn btn-primary">
|
||||
<i data-feather="zap"></i>
|
||||
Découvrir nos services
|
||||
</a>
|
||||
<a href="#contact" class="btn btn-secondary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Nous contacter
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- About Section -->
|
||||
<section class="about" id="apropos">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">À propos</p>
|
||||
<h2 class="section-title">Qui sommes-nous ?</h2>
|
||||
<p class="section-desc">Une équipe passionnée dédiée à la création d'expériences RP uniques</p>
|
||||
</div>
|
||||
<div class="about-grid">
|
||||
<div class="about-content reveal">
|
||||
<h3>Notre Mission</h3>
|
||||
<p>OmégaKube est né de la passion du Role Play et de l'envie de créer des outils innovants pour les communautés gaming. Nous développons des solutions sur mesure qui transforment l'expérience de jeu.</p>
|
||||
<p>Notre expertise s'étend des bots Discord complexes aux environnements Fortnite immersifs, en passant par la création graphique. Chaque projet est une nouvelle aventure créative.</p>
|
||||
<div class="about-stats">
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">50+</div>
|
||||
<div class="stat-label">Projets réalisés</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">10K+</div>
|
||||
<div class="stat-label">Joueurs actifs</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-number">3</div>
|
||||
<div class="stat-label">Ans d'expérience</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="about-visual reveal reveal-delay-2">
|
||||
<div class="about-card">
|
||||
<h4>Notre Objectif</h4>
|
||||
<p>Créer des outils et environnements RP simples d'utilisation, immersifs et parfaitement adaptés à tous types de serveurs et projets. Chaque communauté mérite une expérience unique qui reflète son identité.</p>
|
||||
<div class="deco-triangle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Services Preview Section -->
|
||||
<section class="services" id="services">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Services</p>
|
||||
<h2 class="section-title">Ce que nous créons</h2>
|
||||
<p class="section-desc">Des solutions complètes pour vos projets Role Play</p>
|
||||
</div>
|
||||
<div class="services-grid">
|
||||
<div class="service-card reveal">
|
||||
<div class="service-icon">
|
||||
<i data-feather="code"></i>
|
||||
</div>
|
||||
<h3>Bots Discord RP</h3>
|
||||
<p>Des bots entièrement personnalisés pour animer et gérer vos serveurs RP.</p>
|
||||
<ul class="service-features">
|
||||
<li>Systèmes d'économie avancés</li>
|
||||
<li>Gestion des stats et inventaires</li>
|
||||
<li>Commandes RP personnalisées</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="service-card reveal reveal-delay-1">
|
||||
<div class="service-icon">
|
||||
<i data-feather="map"></i>
|
||||
</div>
|
||||
<h3>Maps Fortnite RP</h3>
|
||||
<p>Des environnements uniques conçus pour des sessions RP mémorables.</p>
|
||||
<ul class="service-features">
|
||||
<li>Design d'environnement immersif</li>
|
||||
<li>Scénarios narratifs intégrés</li>
|
||||
<li>Optimisation performance</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="service-card reveal reveal-delay-2">
|
||||
<div class="service-icon">
|
||||
<i data-feather="image"></i>
|
||||
</div>
|
||||
<h3>Créations Graphiques</h3>
|
||||
<p>Identité visuelle et assets graphiques pour vos projets.</p>
|
||||
<ul class="service-features">
|
||||
<li>Logos et branding</li>
|
||||
<li>Bannières et visuels</li>
|
||||
<li>Assets personnalisés</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: center; margin-top: 3rem;" class="reveal">
|
||||
<a href="pages/services.html" class="btn btn-secondary">
|
||||
<i data-feather="arrow-right"></i>
|
||||
Voir tous nos services
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Team Section with Carousel -->
|
||||
<section class="team" id="equipe">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Équipe</p>
|
||||
<h2 class="section-title">Les créateurs</h2>
|
||||
<p class="section-desc">Cliquez sur un membre pour en savoir plus</p>
|
||||
</div>
|
||||
<div class="team-carousel-container reveal">
|
||||
<div class="team-carousel" id="team-carousel">
|
||||
<!-- Team cards are rendered dynamically from assets/data/team.json by assets/js/home.js -->
|
||||
</div>
|
||||
<div class="carousel-controls">
|
||||
<button class="carousel-btn" id="carousel-prev">
|
||||
<i data-feather="chevron-left"></i>
|
||||
</button>
|
||||
<div class="carousel-dots" id="carousel-dots"></div>
|
||||
<button class="carousel-btn" id="carousel-next">
|
||||
<i data-feather="chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Team Member Modal -->
|
||||
<div class="team-modal-overlay" id="team-modal-overlay">
|
||||
<div class="team-modal">
|
||||
<div class="team-modal-header">
|
||||
<button class="team-modal-close" id="team-modal-close">
|
||||
<i data-feather="x"></i>
|
||||
</button>
|
||||
<div class="team-modal-avatar">
|
||||
<div class="team-modal-avatar-inner" id="modal-avatar">A</div>
|
||||
</div>
|
||||
<h3 class="team-modal-name" id="modal-name">Alexandre</h3>
|
||||
<p class="team-modal-role" id="modal-role">Développeur Principal</p>
|
||||
</div>
|
||||
<div class="team-modal-content">
|
||||
<p class="team-modal-bio" id="modal-bio">Bio du membre...</p>
|
||||
<div class="team-modal-stats" id="modal-stats"></div>
|
||||
<div class="team-modal-skills" id="modal-skills"></div>
|
||||
<div class="team-modal-social" id="modal-social"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Preview Section -->
|
||||
<section class="portfolio" id="realisations">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Portfolio</p>
|
||||
<h2 class="section-title">Nos réalisations</h2>
|
||||
<p class="section-desc">Découvrez quelques-uns de nos projets récents</p>
|
||||
</div>
|
||||
<div class="portfolio-grid">
|
||||
<div class="portfolio-item reveal">
|
||||
<div class="portfolio-bg"></div>
|
||||
<div class="portfolio-content">
|
||||
<span class="portfolio-tag">Bot Discord</span>
|
||||
<h4>Medieval RP Bot</h4>
|
||||
<p>Système complet pour serveur fantasy</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="portfolio-item reveal reveal-delay-1">
|
||||
<div class="portfolio-bg" style="background: linear-gradient(135deg, #5E2040, #8b3a62);"></div>
|
||||
<div class="portfolio-content">
|
||||
<span class="portfolio-tag">Fortnite Map</span>
|
||||
<h4>Cyberpunk City</h4>
|
||||
<p>Environnement urbain futuriste</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="portfolio-item reveal reveal-delay-2">
|
||||
<div class="portfolio-bg" style="background: linear-gradient(135deg, #3a1f5e, #8b3a62);"></div>
|
||||
<div class="portfolio-content">
|
||||
<span class="portfolio-tag">Bot Discord</span>
|
||||
<h4>Space Station RP</h4>
|
||||
<p>Bot Sci-Fi avec économie spatiale</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: center; margin-top: 3rem;" class="reveal">
|
||||
<a href="pages/realisations.html" class="btn btn-secondary">
|
||||
<i data-feather="arrow-right"></i>
|
||||
Voir toutes nos réalisations
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contact Section -->
|
||||
<section class="contact" id="contact">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Contact</p>
|
||||
<h2 class="section-title">Parlons de votre projet</h2>
|
||||
<p class="section-desc">Un projet RP en tête ? Contactez-nous !</p>
|
||||
</div>
|
||||
<div class="contact-wrapper">
|
||||
<div class="contact-info reveal">
|
||||
<h3>Discutons ensemble</h3>
|
||||
<p>Vous avez un serveur à développer, une map à créer ou besoin d'un bot personnalisé ? Notre équipe est prête à donner vie à vos idées.</p>
|
||||
<div class="contact-links">
|
||||
<a href="mailto:contact@omegakube.com" class="contact-link">
|
||||
<div class="contact-link-icon">
|
||||
<i data-feather="mail"></i>
|
||||
</div>
|
||||
<span>contact@omegakube.com</span>
|
||||
</a>
|
||||
<a href="#" class="contact-link">
|
||||
<div class="contact-link-icon">
|
||||
<i data-feather="message-circle"></i>
|
||||
</div>
|
||||
<span>Discord : OmégaKube</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<form class="contact-form reveal reveal-delay-1" id="contact-form">
|
||||
<div class="form-group">
|
||||
<label for="name">Nom</label>
|
||||
<input type="text" id="name" name="name" placeholder="Votre nom" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" name="email" placeholder="votre@email.com" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="message">Message</label>
|
||||
<textarea id="message" name="message" placeholder="Décrivez votre projet..." required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary form-submit">
|
||||
<i data-feather="send"></i>
|
||||
Envoyer le message
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div data-include="components/footer.html"></div>
|
||||
|
||||
<script src="assets/js/main.js"></script>
|
||||
<script src="assets/js/home.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
61
pages/404.html
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>404 — Page non trouvée | OmégaKube</title>
|
||||
<template data-include="/testarea/omegakube/v1bis/components/favicons.html"></template>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
<link rel="stylesheet" href="/testarea/omegakube/v1bis/assets/css/404.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="bg-grid"></div>
|
||||
<div class="bg-glow bg-glow-1"></div>
|
||||
<div class="bg-glow bg-glow-2"></div>
|
||||
<div class="particles" id="particles"></div>
|
||||
|
||||
<div class="portal portal-left">
|
||||
<div class="portal-ring"></div>
|
||||
<div class="portal-ring"></div>
|
||||
<div class="portal-ring"></div>
|
||||
</div>
|
||||
<div class="portal portal-right">
|
||||
<div class="portal-ring"></div>
|
||||
<div class="portal-ring"></div>
|
||||
<div class="portal-ring"></div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="error-icon">
|
||||
<i data-feather="alert-triangle"></i>
|
||||
</div>
|
||||
<div class="error-code">404</div>
|
||||
<h1 class="error-title">Dimension introuvable</h1>
|
||||
<p class="error-message">
|
||||
Oups ! Il semblerait que vous ayez traversé un <span>portail défectueux</span>.
|
||||
Cette page n'existe pas dans notre univers... ou peut-être a-t-elle été téléportée ailleurs ?
|
||||
</p>
|
||||
<div class="buttons">
|
||||
<a href="/testarea/omegakube/v1bis/index.html" class="btn btn-primary">
|
||||
<i data-feather="home"></i>
|
||||
Retour à l'accueil
|
||||
</a>
|
||||
<a href="javascript:history.back()" class="btn btn-secondary">
|
||||
<i data-feather="arrow-left"></i>
|
||||
Page précédente
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<span class="logo-mini">ΩK</span>
|
||||
<span>•</span>
|
||||
<a href="/testarea/omegakube/v1bis/index.html">OmégaKube</a>
|
||||
</div>
|
||||
|
||||
<script src="/testarea/omegakube/v1bis/assets/js/pages/404.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
256
pages/cgv.html
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Conditions Générales de Vente — OmégaKube</title>
|
||||
<template data-include="/testarea/omegakube/v1bis/components/favicons.html"></template>
|
||||
<link rel="stylesheet" href="../assets/css/main.css">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Geometric Background -->
|
||||
<div class="geo-bg"></div>
|
||||
<div class="grid-pattern"></div>
|
||||
|
||||
<!-- Floating Shapes -->
|
||||
<div class="geo-shapes">
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
<div class="shape shape-diamond"></div>
|
||||
<div class="shape shape-rect"></div>
|
||||
<div class="shape shape-square"></div>
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-dots">
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
</div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
</div>
|
||||
|
||||
<!-- Header -->
|
||||
<div data-include="../components/header.html"></div>
|
||||
|
||||
<section class="page-hero" style="min-height: 40vh;">
|
||||
<div class="hero-content">
|
||||
<h1>Conditions Générales <span class="highlight">de Vente</span></h1>
|
||||
<p>Conditions applicables aux prestations de l'association OmégaKube</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="legal-content">
|
||||
<div class="legal-container">
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="book-open"></i> Article 1 - Préambule</h2>
|
||||
<div class="legal-card">
|
||||
<p>Les présentes Conditions Générales de Vente (CGV) régissent les relations contractuelles entre :</p>
|
||||
<p><strong>L'association OmégaKube</strong>, association loi 1901, dont le siège social est situé à [Adresse], ci-après dénommée "l'Association" ou "OmégaKube"</p>
|
||||
<p>Et</p>
|
||||
<p>Toute personne physique ou morale souhaitant bénéficier des prestations proposées par l'Association, ci-après dénommée "le Client".</p>
|
||||
<p>Toute commande implique l'acceptation sans réserve des présentes CGV.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="package"></i> Article 2 - Services proposés</h2>
|
||||
<div class="legal-card">
|
||||
<p>L'association OmégaKube propose les prestations suivantes :</p>
|
||||
<ul>
|
||||
<li><strong>Développement de bots Discord RP</strong> : création de bots personnalisés pour serveurs de Role Play</li>
|
||||
<li><strong>Création de maps Fortnite RP</strong> : conception d'environnements pour le mode créatif Fortnite</li>
|
||||
<li><strong>Créations graphiques</strong> : logos, bannières, visuels pour serveurs et communautés</li>
|
||||
<li><strong>Consulting</strong> : accompagnement et conseils pour projets RP</li>
|
||||
<li><strong>Packs complets</strong> : offres groupées incluant plusieurs services</li>
|
||||
</ul>
|
||||
<p>Les caractéristiques détaillées de chaque service sont présentées sur la page Services du site.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="credit-card"></i> Article 3 - Tarifs et paiement</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>3.1 Tarifs</strong></p>
|
||||
<p>Les tarifs des prestations sont communiqués sur devis, établi gratuitement après étude du projet. En tant qu'association loi 1901, OmégaKube n'est pas assujettie à la TVA.</p>
|
||||
|
||||
<p><strong>3.2 Modalités de paiement</strong></p>
|
||||
<p>Le paiement s'effectue selon les modalités suivantes :</p>
|
||||
<ul>
|
||||
<li>Acompte de 30% à la commande</li>
|
||||
<li>Solde de 70% à la livraison du projet</li>
|
||||
</ul>
|
||||
<p>Moyens de paiement acceptés : virement bancaire, PayPal.</p>
|
||||
|
||||
<p><strong>3.3 Retard de paiement</strong></p>
|
||||
<p>Tout retard de paiement entraînera la suspension des travaux en cours jusqu'à régularisation.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="check-circle"></i> Article 4 - Commande et validation</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>4.1 Demande de devis</strong></p>
|
||||
<p>Le Client formule sa demande via le formulaire de contact ou par Discord. Un devis détaillé lui est adressé dans les meilleurs délais.</p>
|
||||
|
||||
<p><strong>4.2 Validation de la commande</strong></p>
|
||||
<p>La commande est considérée comme validée après :</p>
|
||||
<ul>
|
||||
<li>Acceptation écrite du devis par le Client</li>
|
||||
<li>Réception de l'acompte</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>4.3 Cahier des charges</strong></p>
|
||||
<p>Un cahier des charges détaillant les spécifications du projet sera établi et validé par les deux parties avant le début des travaux.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="clock"></i> Article 5 - Délais de réalisation</h2>
|
||||
<div class="legal-card">
|
||||
<p>Les délais de réalisation sont communiqués à titre indicatif dans le devis. Ils courent à compter de la validation de la commande et de la réception de tous les éléments nécessaires.</p>
|
||||
<p>Des ajustements de délai peuvent être nécessaires en cas de :</p>
|
||||
<ul>
|
||||
<li>Modifications demandées par le Client en cours de projet</li>
|
||||
<li>Retard dans la fourniture des éléments par le Client</li>
|
||||
<li>Circonstances exceptionnelles (force majeure)</li>
|
||||
</ul>
|
||||
<p>Le Client sera informé de tout changement de délai.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="edit-3"></i> Article 6 - Modifications et révisions</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>6.1 Révisions incluses</strong></p>
|
||||
<p>Chaque prestation inclut un nombre de révisions défini dans le devis (généralement 2 à 3 révisions).</p>
|
||||
|
||||
<p><strong>6.2 Modifications supplémentaires</strong></p>
|
||||
<p>Au-delà des révisions incluses, toute modification fera l'objet d'un devis complémentaire.</p>
|
||||
|
||||
<p><strong>6.3 Modifications majeures</strong></p>
|
||||
<p>Les demandes de modifications substantielles du cahier des charges initial peuvent entraîner une réévaluation du devis et des délais.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="download"></i> Article 7 - Livraison et réception</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>7.1 Livraison</strong></p>
|
||||
<p>Les livrables sont transmis par voie électronique (Discord, email, lien de téléchargement).</p>
|
||||
|
||||
<p><strong>7.2 Réception</strong></p>
|
||||
<p>Le Client dispose d'un délai de 7 jours après livraison pour émettre des réserves. Passé ce délai, la prestation est réputée acceptée.</p>
|
||||
|
||||
<p><strong>7.3 Transfert de propriété</strong></p>
|
||||
<p>Le transfert de propriété des livrables au Client n'intervient qu'après paiement intégral du prix.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="shield"></i> Article 8 - Propriété intellectuelle</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>8.1 Cession des droits</strong></p>
|
||||
<p>Après paiement intégral, le Client acquiert les droits d'utilisation des créations pour l'usage défini dans le devis.</p>
|
||||
|
||||
<p><strong>8.2 Crédit et portfolio</strong></p>
|
||||
<p>L'association OmégaKube se réserve le droit d'utiliser les créations réalisées à des fins de promotion (portfolio, réseaux sociaux, autres), sauf demande expresse de confidentialité du Client.</p>
|
||||
|
||||
<p><strong>8.3 Éléments tiers</strong></p>
|
||||
<p>Le Client garantit disposer des droits nécessaires sur les éléments qu'il fournit (logos, images, textes).</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="x-circle"></i> Article 9 - Annulation et résiliation</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>9.1 Annulation par le Client</strong></p>
|
||||
<p>En cas d'annulation par le Client :</p>
|
||||
<ul>
|
||||
<li>Avant début des travaux : l'acompte reste acquis à l'Association</li>
|
||||
<li>En cours de réalisation : facturation du travail réalisé, avec un minimum correspondant à l'acompte</li>
|
||||
</ul>
|
||||
|
||||
<p><strong>9.2 Résiliation par l'Association</strong></p>
|
||||
<p>L'Association se réserve le droit de résilier la commande en cas de non-respect des obligations par le Client (non-paiement, comportement inapproprié). Les sommes versées resteront acquises.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="alert-triangle"></i> Article 10 - Responsabilité</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>10.1 Obligation de moyens</strong></p>
|
||||
<p>
|
||||
L'Association s'engage à mettre en œuvre tous les moyens dont elle dispose pour la bonne exécution de ses prestations.
|
||||
</p>
|
||||
|
||||
<p><strong>10.2 Limitation de responsabilité</strong></p>
|
||||
<p>La responsabilité de l'Association ne saurait être engagée en cas de :</p>
|
||||
<ul>
|
||||
<li>Mauvaise utilisation des livrables par le Client</li>
|
||||
<li>Dommages indirects (perte de données, manque à gagner)</li>
|
||||
<li>Force majeure</li>
|
||||
<li>Modifications apportées par le Client ou un tiers aux livrables</li>
|
||||
</ul>
|
||||
<p>
|
||||
En tout état de cause, la responsabilité de l'Association est limitée au montant effectivement perçu au titre de la prestation concernée.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="lock"></i> Article 11 - Confidentialité</h2>
|
||||
<div class="legal-card">
|
||||
<p>Les parties s'engagent à garder confidentielles les informations échangées dans le cadre de leur collaboration.</p>
|
||||
<p>Cette obligation de confidentialité ne s'applique pas aux informations :</p>
|
||||
<ul>
|
||||
<li>Déjà connues du public</li>
|
||||
<li>Obtenues légitimement par des tiers</li>
|
||||
<li>Dont la divulgation est exigée par la loi</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="file-text"></i> Article 12 - Droit applicable et litiges</h2>
|
||||
<div class="legal-card">
|
||||
<p>Les présentes CGV sont soumises au droit français.</p>
|
||||
<p>En cas de litige, les parties s'engagent à rechercher une solution amiable. À défaut d'accord, le litige sera porté devant les tribunaux compétents.</p>
|
||||
<p><strong>Date de dernière mise à jour :</strong> Février 2026</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- Footer -->
|
||||
<div data-include="../components/footer.html"></div>
|
||||
<!-- JS -->
|
||||
<script src="../assets/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
feather.replace();
|
||||
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const html = document.documentElement;
|
||||
html.setAttribute('data-theme', localStorage.getItem('theme') || 'dark');
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const newTheme = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
||||
html.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
});
|
||||
|
||||
const navbar = document.getElementById('navbar');
|
||||
window.addEventListener('scroll', () => navbar.classList.toggle('scrolled', window.scrollY > 50));
|
||||
|
||||
const mobileToggle = document.getElementById('mobile-toggle');
|
||||
const navLinks = document.getElementById('nav-links');
|
||||
mobileToggle.addEventListener('click', () => {
|
||||
mobileToggle.classList.toggle('active');
|
||||
navLinks.classList.toggle('active');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
163
pages/mentions-legales.html
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mentions Légales — OmégaKube</title>
|
||||
<template data-include="/testarea/omegakube/v1bis/components/favicons.html"></template>
|
||||
<link rel="stylesheet" href="../assets/css/main.css">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Geometric Background -->
|
||||
<div class="geo-bg"></div>
|
||||
<div class="grid-pattern"></div>
|
||||
|
||||
<!-- Floating Shapes -->
|
||||
<div class="geo-shapes">
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
<div class="shape shape-diamond"></div>
|
||||
<div class="shape shape-rect"></div>
|
||||
<div class="shape shape-square"></div>
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-dots">
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
</div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
</div>
|
||||
|
||||
<!-- Header -->
|
||||
<div data-include="../components/header.html"></div>
|
||||
|
||||
<section class="page-hero" style="min-height: 40vh;">
|
||||
<div class="hero-content">
|
||||
<h1>Mentions <span class="highlight">Légales</span></h1>
|
||||
<p>Informations légales relatives à l'association OmégaKube</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="legal-content">
|
||||
<div class="legal-container">
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="info"></i> Éditeur du site</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>Association OmégaKube</strong></p>
|
||||
<p>Association loi 1901</p>
|
||||
<p>Siège social : [Adresse du siège social]</p>
|
||||
<p>Numéro RNA : W[XXX] (en cours d'immatriculation)</p>
|
||||
<p>Email : contact@omegakube.fr</p>
|
||||
<p>Discord : OmégaKube#0001</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="user"></i> Directeur de la publication</h2>
|
||||
<div class="legal-card">
|
||||
<p>Le directeur de la publication est le Président de l'association OmégaKube.</p>
|
||||
<p>Contact : contact@omegakube.fr</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="server"></i> Hébergement</h2>
|
||||
<div class="legal-card">
|
||||
<p><strong>[Nom de l'hébergeur]</strong></p>
|
||||
<p>Adresse : [Adresse de l'hébergeur]</p>
|
||||
<p>Téléphone : [Numéro de téléphone]</p>
|
||||
<p>Site web : [URL de l'hébergeur]</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="shield"></i> Propriété intellectuelle</h2>
|
||||
<div class="legal-card">
|
||||
<p>L'ensemble du contenu de ce site (textes, images, vidéos, logos, icônes, sons, logiciels, etc.) est la propriété exclusive de l'association OmégaKube ou de ses partenaires et est protégé par les lois françaises et internationales relatives à la propriété intellectuelle.</p>
|
||||
<p>Toute reproduction, représentation, modification, publication, adaptation de tout ou partie des éléments du site, quel que soit le moyen ou le procédé utilisé, est interdite, sauf autorisation écrite préalable de l'association OmégaKube.</p>
|
||||
<p>Toute exploitation non autorisée du site ou de son contenu sera considérée comme constitutive d'une contrefaçon et poursuivie conformément aux dispositions des articles L.335-2 et suivants du Code de Propriété Intellectuelle.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="database"></i> Protection des données personnelles</h2>
|
||||
<div class="legal-card">
|
||||
<p>Conformément au Règlement Général sur la Protection des Données (RGPD) et à la loi Informatique et Libertés du 6 janvier 1978 modifiée, vous disposez des droits suivants concernant vos données personnelles :</p>
|
||||
<ul>
|
||||
<li>Droit d'accès</li>
|
||||
<li>Droit de rectification</li>
|
||||
<li>Droit à l'effacement</li>
|
||||
<li>Droit à la limitation du traitement</li>
|
||||
<li>Droit à la portabilité</li>
|
||||
<li>Droit d'opposition</li>
|
||||
</ul>
|
||||
<p>Pour exercer ces droits, vous pouvez nous contacter à l'adresse : contact@omegakube.fr</p>
|
||||
<p>Les informations collectées via le formulaire de contact sont utilisées uniquement pour répondre à vos demandes et ne sont jamais cédées à des tiers.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="link"></i> Liens hypertextes</h2>
|
||||
<div class="legal-card">
|
||||
<p>Le site OmégaKube peut contenir des liens hypertextes vers d'autres sites. L'association OmégaKube n'exerce aucun contrôle sur ces sites et décline toute responsabilité quant à leur contenu.</p>
|
||||
<p>La création de liens hypertextes vers le site omegakube.fr est soumise à l'accord préalable de l'association.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="alert-circle"></i> Limitation de responsabilité</h2>
|
||||
<div class="legal-card">
|
||||
<p>L'association OmégaKube s'efforce d'assurer au mieux l'exactitude et la mise à jour des informations diffusées sur ce site. Toutefois, elle ne peut garantir l'exactitude, la précision ou l'exhaustivité des informations mises à disposition.</p>
|
||||
<p>En conséquence, l'association OmégaKube décline toute responsabilité :</p>
|
||||
<ul>
|
||||
<li>Pour toute imprécision, inexactitude ou omission portant sur des informations disponibles sur le site</li>
|
||||
<li>Pour tous dommages résultant d'une intrusion frauduleuse d'un tiers</li>
|
||||
<li>Pour tous dommages, directs ou indirects, quelles qu'en soient les causes, origines, natures ou conséquences</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-section">
|
||||
<h2><i data-feather="file-text"></i> Droit applicable</h2>
|
||||
<div class="legal-card">
|
||||
<p>Les présentes mentions légales sont régies par le droit français. En cas de litige, les tribunaux français seront seuls compétents.</p>
|
||||
<p>Date de dernière mise à jour : Février 2026</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- Footer -->
|
||||
<div data-include="../components/footer.html"></div>
|
||||
<!-- JS -->
|
||||
<script src="../assets/js/main.js"></script>
|
||||
|
||||
<script>
|
||||
feather.replace();
|
||||
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const html = document.documentElement;
|
||||
html.setAttribute('data-theme', localStorage.getItem('theme') || 'dark');
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const newTheme = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
||||
html.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
});
|
||||
|
||||
const navbar = document.getElementById('navbar');
|
||||
window.addEventListener('scroll', () => navbar.classList.toggle('scrolled', window.scrollY > 50));
|
||||
|
||||
const mobileToggle = document.getElementById('mobile-toggle');
|
||||
const navLinks = document.getElementById('nav-links');
|
||||
mobileToggle.addEventListener('click', () => {
|
||||
mobileToggle.classList.toggle('active');
|
||||
navLinks.classList.toggle('active');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
334
pages/realisations.html
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nos Réalisations — OmégaKube</title>
|
||||
<template data-include="/testarea/omegakube/v1bis/components/favicons.html"></template>
|
||||
<link rel="stylesheet" href="../assets/css/main.css">
|
||||
<style>
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.filter-tab {
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 4px;
|
||||
color: var(--text-secondary);
|
||||
font-family: 'OmegaSmall', sans-serif;
|
||||
font-size: 0.95rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.filter-tab:hover,
|
||||
.filter-tab.active {
|
||||
background: var(--accent-primary);
|
||||
border-color: var(--accent-primary);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Geometric Background -->
|
||||
<div class="geo-bg"></div>
|
||||
<div class="grid-pattern"></div>
|
||||
|
||||
<!-- Floating Shapes -->
|
||||
<div class="geo-shapes">
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
<div class="shape shape-diamond"></div>
|
||||
<div class="shape shape-rect"></div>
|
||||
<div class="shape shape-square"></div>
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-dots">
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
</div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
</div>
|
||||
|
||||
<div data-include="../components/header.html"></div>
|
||||
|
||||
<!-- Page Hero -->
|
||||
<section class="page-hero">
|
||||
<div class="hero-content">
|
||||
<div class="hero-badge">
|
||||
<span>Notre portfolio</span>
|
||||
</div>
|
||||
<h1>Nos <span class="highlight">Réalisations</span></h1>
|
||||
<p>Découvrez les projets que nous avons concrétisés pour nos clients et partenaires.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Projets Phares - Bento Grid -->
|
||||
<section style="padding-top: 2rem;">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">En vedette</p>
|
||||
<h2 class="section-title">Projets phares</h2>
|
||||
<p class="section-desc">Nos réalisations les plus marquantes</p>
|
||||
</div>
|
||||
|
||||
<div class="bento-grid" style="padding: 0 2rem;">
|
||||
|
||||
<!-- Projet Phare 1 - Medieval RP Bot -->
|
||||
<div class="bento-project reveal">
|
||||
<div class="bento-image" style="background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));">
|
||||
<div class="bento-image-content">
|
||||
<span class="portfolio-tag">Bot Discord</span>
|
||||
<h3>Medieval RP Bot</h3>
|
||||
<p>Un système RP médiéval complet pour serveur fantasy</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bento-stats">
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="users"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">5000+</div>
|
||||
<div class="bento-stat-label">Joueurs actifs</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="clock"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">3 mois</div>
|
||||
<div class="bento-stat-label">Développement</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="terminal"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">150+</div>
|
||||
<div class="bento-stat-label">Commandes</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="database"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">99.9%</div>
|
||||
<div class="bento-stat-label">Uptime</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bento-info">
|
||||
<h4>Description</h4>
|
||||
<p>Développé pour l'un des plus grands serveurs Discord francophones, ce bot gère l'intégralité de l'expérience RP : économie, métiers, combat tour par tour, gestion de royaumes et alliances, quêtes automatisées et bien plus encore.</p>
|
||||
<div class="bento-features">
|
||||
<span class="bento-feature">Économie</span>
|
||||
<span class="bento-feature">Combat</span>
|
||||
<span class="bento-feature">Métiers</span>
|
||||
<span class="bento-feature">Royaumes</span>
|
||||
<span class="bento-feature">Quêtes</span>
|
||||
<span class="bento-feature">Events</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bento-divider"></div>
|
||||
|
||||
<!-- Projet Phare 2 - Cyberpunk City (Reverse) -->
|
||||
<div class="bento-project reverse reveal">
|
||||
<div class="bento-image" style="background: linear-gradient(135deg, #5E2040, #1a3a5e);">
|
||||
<div class="bento-image-content">
|
||||
<span class="portfolio-tag">Fortnite Map</span>
|
||||
<h3>Cyberpunk City</h3>
|
||||
<p>Une ville futuriste immersive pour le RP urbain</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bento-stats">
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="play"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">50K+</div>
|
||||
<div class="bento-stat-label">Parties jouées</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="home"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">100+</div>
|
||||
<div class="bento-stat-label">Bâtiments</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="map-pin"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">5</div>
|
||||
<div class="bento-stat-label">Quartiers</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="users"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">50</div>
|
||||
<div class="bento-stat-label">Joueurs max</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bento-info">
|
||||
<h4>Description</h4>
|
||||
<p>Néons, gratte-ciels, quartiers distincts et ambiance blade runner. Cette map a été optimisée pour accueillir jusqu'à 50 joueurs simultanément avec un système jour/nuit dynamique et des zones interactives scriptées.</p>
|
||||
<div class="bento-features">
|
||||
<span class="bento-feature">Néons</span>
|
||||
<span class="bento-feature">Jour/Nuit</span>
|
||||
<span class="bento-feature">Scripts</span>
|
||||
<span class="bento-feature">Optimisé</span>
|
||||
<span class="bento-feature">Immersif</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bento-divider"></div>
|
||||
|
||||
<!-- Projet Phare 3 - Nova RP -->
|
||||
<div class="bento-project reveal">
|
||||
<div class="bento-image" style="background: linear-gradient(135deg, #2d1b5e, #5E2040);">
|
||||
<div class="bento-image-content">
|
||||
<span class="portfolio-tag">Pack Complet</span>
|
||||
<h3>Nova RP - Lancement</h3>
|
||||
<p>Accompagnement complet pour un lancement réussi</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bento-stats">
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="users"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">8000+</div>
|
||||
<div class="bento-stat-label">Membres</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="trending-up"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">0→8K</div>
|
||||
<div class="bento-stat-label">En 3 mois</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="package"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">4</div>
|
||||
<div class="bento-stat-label">Services inclus</div>
|
||||
</div>
|
||||
<div class="bento-stat">
|
||||
<div class="bento-stat-icon">
|
||||
<i data-feather="award"></i>
|
||||
</div>
|
||||
<div class="bento-stat-value">Top 10</div>
|
||||
<div class="bento-stat-label">Serveur FR</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bento-info">
|
||||
<h4>Description</h4>
|
||||
<p>Un accompagnement clé en main : bot Discord personnalisé, identité visuelle complète, map Fortnite exclusive et stratégie de lancement. En 3 mois, le serveur est passé de 0 à 8000 membres actifs.</p>
|
||||
<div class="bento-features">
|
||||
<span class="bento-feature">Bot RP</span>
|
||||
<span class="bento-feature">Map Fortnite</span>
|
||||
<span class="bento-feature">Branding</span>
|
||||
<span class="bento-feature">Stratégie</span>
|
||||
<span class="bento-feature">Support</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tous nos projets (injected via JS) -->
|
||||
<section style="padding-top: 6rem;">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Portfolio</p>
|
||||
<h2 class="section-title">Tous nos projets</h2>
|
||||
<p class="section-desc">Cliquez sur un projet pour voir les détails</p>
|
||||
</div>
|
||||
|
||||
<!-- Filter Tabs -->
|
||||
<div style="max-width: 1200px; margin: 0 auto 2rem; text-align: center; padding: 0 2rem;">
|
||||
<div class="filter-tabs reveal">
|
||||
<button class="filter-tab active" data-filter="all">Tous</button>
|
||||
<button class="filter-tab" data-filter="bot">Bots Discord</button>
|
||||
<button class="filter-tab" data-filter="map">Maps Fortnite</button>
|
||||
<button class="filter-tab" data-filter="graphisme">Graphisme</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Portfolio Grid with Pagination -->
|
||||
<div class="portfolio-grid" style="max-width: 1200px; margin: 0 auto;" id="portfolio-grid">
|
||||
<!-- Les projets seront injectés ici par JavaScript -->
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="pagination" id="pagination" style="max-width: 1200px; margin: 4rem auto 0;">
|
||||
<!-- Généré par JavaScript -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Project Modal (structure only — content populated by JS) -->
|
||||
<div class="project-modal-overlay" id="project-modal-overlay">
|
||||
<div class="project-modal">
|
||||
<button class="project-modal-close" id="project-modal-close">
|
||||
<i data-feather="x"></i>
|
||||
</button>
|
||||
|
||||
<div class="project-gallery" id="project-gallery">
|
||||
<div class="project-gallery-slides" id="gallery-slides"></div>
|
||||
<button class="gallery-nav prev" id="gallery-prev"><i data-feather="chevron-left"></i></button>
|
||||
<button class="gallery-nav next" id="gallery-next"><i data-feather="chevron-right"></i></button>
|
||||
<div class="gallery-dots" id="gallery-dots"></div>
|
||||
</div>
|
||||
|
||||
<div class="project-modal-content">
|
||||
<div class="project-modal-header">
|
||||
<div>
|
||||
<span class="portfolio-tag" id="modal-category">Bot Discord</span>
|
||||
<h2 id="modal-title">Nom du projet</h2>
|
||||
</div>
|
||||
<div class="project-modal-meta" id="modal-meta"></div>
|
||||
</div>
|
||||
|
||||
<p class="project-modal-desc" id="modal-desc"></p>
|
||||
|
||||
<div class="project-modal-tabs">
|
||||
<button class="project-modal-tab active" data-tab="features">Fonctionnalités</button>
|
||||
<button class="project-modal-tab" data-tab="tech">Technologies</button>
|
||||
<button class="project-modal-tab" data-tab="stats">Statistiques</button>
|
||||
</div>
|
||||
|
||||
<div class="project-modal-tab-content active" id="tab-features"><div class="project-features-grid" id="modal-features"></div></div>
|
||||
<div class="project-modal-tab-content" id="tab-tech"><div class="project-tech-grid" id="modal-tech"></div></div>
|
||||
<div class="project-modal-tab-content" id="tab-stats"><div class="project-stats-grid" id="modal-stats"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="contact" style="padding-top: 4rem;">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Votre projet</p>
|
||||
<h2 class="section-title">Prêt à créer ensemble ?</h2>
|
||||
<p class="section-desc">Votre projet pourrait être le prochain dans notre portfolio</p>
|
||||
</div>
|
||||
<div style="text-align: center;" class="reveal">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Démarrer un projet
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div data-include="../components/footer.html"></div>
|
||||
|
||||
<script src="../assets/js/main.js"></script>
|
||||
<script src="../assets/js/pages/realisations.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
741
pages/services.html
Normal file
|
|
@ -0,0 +1,741 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nos Services — OmégaKube</title>
|
||||
<template data-include="/testarea/omegakube/v1bis/components/favicons.html"></template>
|
||||
<link rel="stylesheet" href="../assets/css/main.css">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Geometric Background -->
|
||||
<div class="geo-bg"></div>
|
||||
<div class="grid-pattern"></div>
|
||||
|
||||
<!-- Floating Shapes -->
|
||||
<div class="geo-shapes">
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
<div class="shape shape-diamond"></div>
|
||||
<div class="shape shape-rect"></div>
|
||||
<div class="shape shape-square"></div>
|
||||
<div class="shape shape-triangle"></div>
|
||||
<div class="shape shape-dots">
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
<span></span><span></span><span></span><span></span>
|
||||
</div>
|
||||
<div class="shape shape-square-outline"></div>
|
||||
<div class="shape shape-triangle-outline"></div>
|
||||
</div>
|
||||
|
||||
<div data-include="../components/header.html"></div>
|
||||
|
||||
<!-- Page Hero -->
|
||||
<section class="page-hero">
|
||||
<div class="hero-content">
|
||||
<div class="hero-badge">
|
||||
<span>Ce que nous proposons</span>
|
||||
</div>
|
||||
<h1>Nos <span class="highlight">Services</span></h1>
|
||||
<p>Des solutions complètes et sur mesure pour donner vie à vos projets Role Play les plus ambitieux.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Process Timeline -->
|
||||
<section class="process-section">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Notre processus</p>
|
||||
<h2 class="section-title">Comment ça marche ?</h2>
|
||||
<p class="section-desc">Un accompagnement clair et structuré, de l'idée à la livraison</p>
|
||||
</div>
|
||||
|
||||
<div class="process-timeline reveal" id="process-timeline">
|
||||
<div class="process-step active" data-step="1">
|
||||
<div class="process-step-number">
|
||||
<i data-feather="message-circle" class="process-step-icon"></i>
|
||||
</div>
|
||||
<div class="process-step-content">
|
||||
<h4 class="process-step-title">Contact</h4>
|
||||
<p class="process-step-desc">Discutons de votre projet et de vos besoins</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="process-step" data-step="2">
|
||||
<div class="process-step-number">
|
||||
<i data-feather="file-text" class="process-step-icon"></i>
|
||||
</div>
|
||||
<div class="process-step-content">
|
||||
<h4 class="process-step-title">Devis</h4>
|
||||
<p class="process-step-desc">Proposition détaillée et validation ensemble</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="process-step" data-step="3">
|
||||
<div class="process-step-number">
|
||||
<i data-feather="code" class="process-step-icon"></i>
|
||||
</div>
|
||||
<div class="process-step-content">
|
||||
<h4 class="process-step-title">Création</h4>
|
||||
<p class="process-step-desc">Développement avec suivi régulier</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="process-step" data-step="4">
|
||||
<div class="process-step-number">
|
||||
<i data-feather="check-circle" class="process-step-icon"></i>
|
||||
</div>
|
||||
<div class="process-step-content">
|
||||
<h4 class="process-step-title">Livraison</h4>
|
||||
<p class="process-step-desc">Tests, ajustements et support inclus</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Service Tabs -->
|
||||
<section class="service-tabs-section">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Nos expertises</p>
|
||||
<h2 class="section-title">Choisissez votre service</h2>
|
||||
<p class="section-desc">Cliquez sur un service pour découvrir tous les détails</p>
|
||||
</div>
|
||||
|
||||
<div class="service-tabs-container">
|
||||
<!-- Tabs Navigation -->
|
||||
<div class="service-tabs-nav reveal">
|
||||
<button class="service-tab-btn active" data-tab="bots">
|
||||
<i data-feather="code"></i>
|
||||
<span>Bots Discord</span>
|
||||
</button>
|
||||
<button class="service-tab-btn" data-tab="maps">
|
||||
<i data-feather="map"></i>
|
||||
<span>Maps Fortnite</span>
|
||||
<span class="service-stamp service-stamp-new">New</span>
|
||||
</button>
|
||||
<button class="service-tab-btn" data-tab="graphisme">
|
||||
<i data-feather="image"></i>
|
||||
<span>Graphisme</span>
|
||||
</button>
|
||||
<button class="service-tab-btn" data-tab="consulting">
|
||||
<i data-feather="users"></i>
|
||||
<span>Consulting</span>
|
||||
<span class="service-stamp service-stamp-free">Gratuit</span>
|
||||
</button>
|
||||
<button class="service-tab-btn" data-tab="pack">
|
||||
<i data-feather="package"></i>
|
||||
<span>Pack Complet</span>
|
||||
<span class="service-stamp service-stamp-popular">Populaire</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tab Contents -->
|
||||
<!-- BOTS DISCORD -->
|
||||
<div class="service-tab-content active" id="tab-bots">
|
||||
<div class="service-tab-grid">
|
||||
<div class="service-visual">
|
||||
<div class="service-visual-particles">
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
</div>
|
||||
<div class="service-visual-icon">
|
||||
<div class="icon-main">
|
||||
<i data-feather="code"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-tab-details">
|
||||
<div class="service-tab-header">
|
||||
<h2>Bots Discord RP</h2>
|
||||
<p>Des bots entièrement personnalisés pour animer et gérer vos serveurs Role Play. Nous développons des systèmes complets adaptés à votre univers et à vos mécaniques de jeu.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-highlights">
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">2-4</div>
|
||||
<div class="service-highlight-label">Semaines de dev</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">1 mois</div>
|
||||
<div class="service-highlight-label">Support inclus</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">100%</div>
|
||||
<div class="service-highlight-label">Personnalisable</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-features">
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon">
|
||||
<i data-feather="dollar-sign"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Économie virtuelle</h4>
|
||||
<p>Monnaie, banque, transactions</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon">
|
||||
<i data-feather="briefcase"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Système de métiers</h4>
|
||||
<p>Jobs, skills, progression</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon">
|
||||
<i data-feather="shield"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Combat & Stats</h4>
|
||||
<p>PvP, PvE, attributs</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon">
|
||||
<i data-feather="box"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Inventaire avancé</h4>
|
||||
<p>Items, crafting, échanges</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon">
|
||||
<i data-feather="flag"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Factions & Guildes</h4>
|
||||
<p>Clans, territoires, guerres</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon">
|
||||
<i data-feather="settings"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Panel Admin</h4>
|
||||
<p>Interface web de gestion</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-cta">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Demander un devis
|
||||
</a>
|
||||
<a href="realisations.html" class="btn btn-secondary">
|
||||
<i data-feather="eye"></i>
|
||||
Voir nos réalisations
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MAPS FORTNITE -->
|
||||
<div class="service-tab-content" id="tab-maps">
|
||||
<div class="service-tab-grid">
|
||||
<div class="service-visual" style="--accent-primary: #1a5e8b; --accent-secondary: #3a8bb5;">
|
||||
<span class="service-stamp service-visual-stamp service-stamp-new">✦ New</span>
|
||||
<div class="service-visual-particles">
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
</div>
|
||||
<div class="service-visual-icon">
|
||||
<div class="icon-main" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="map"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-tab-details">
|
||||
<div class="service-tab-header">
|
||||
<h2>Maps Fortnite RP</h2>
|
||||
<p>Des environnements immersifs créés sur mesure pour vos sessions Role Play. De la ville moderne au village médiéval, nous donnons vie à tous les univers.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-highlights">
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">3-6</div>
|
||||
<div class="service-highlight-label">Semaines de création</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">50+</div>
|
||||
<div class="service-highlight-label">Joueurs supportés</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">UEFN</div>
|
||||
<div class="service-highlight-label">Compatible</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-features">
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="home"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Bâtiments détaillés</h4>
|
||||
<p>Intérieurs accessibles et déco</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="sun"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Cycle jour/nuit</h4>
|
||||
<p>Ambiance dynamique</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="zap"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Zones interactives</h4>
|
||||
<p>Scripts et triggers</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="cpu"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Optimisation</h4>
|
||||
<p>Performance garantie</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="map-pin"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Points d'intérêt</h4>
|
||||
<p>Lieux uniques et mémorables</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #1a5e8b, #3a8bb5);">
|
||||
<i data-feather="edit-3"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Modifications</h4>
|
||||
<p>Ajustements post-livraison</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-cta">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Demander un devis
|
||||
</a>
|
||||
<a href="realisations.html" class="btn btn-secondary">
|
||||
<i data-feather="eye"></i>
|
||||
Voir nos maps
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GRAPHISME -->
|
||||
<div class="service-tab-content" id="tab-graphisme">
|
||||
<div class="service-tab-grid">
|
||||
<div class="service-visual">
|
||||
<div class="service-visual-particles">
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
</div>
|
||||
<div class="service-visual-icon">
|
||||
<div class="icon-main" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="image"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-tab-details">
|
||||
<div class="service-tab-header">
|
||||
<h2>Créations Graphiques</h2>
|
||||
<p>Une identité visuelle forte et cohérente pour vos projets. Du logo aux bannières, nous créons des visuels qui marquent les esprits et attirent votre communauté.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-highlights">
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">1-2</div>
|
||||
<div class="service-highlight-label">Semaines</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">∞</div>
|
||||
<div class="service-highlight-label">Révisions</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">HD</div>
|
||||
<div class="service-highlight-label">Qualité</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-features">
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="hexagon"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Logo & Branding</h4>
|
||||
<p>Identité visuelle complète</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="layout"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Bannières Discord</h4>
|
||||
<p>Server banner, splash, icône</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="smile"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Emojis custom</h4>
|
||||
<p>Pack emojis personnalisés</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="grid"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Icônes & Assets</h4>
|
||||
<p>Items, skills, badges</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="play-circle"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Animations</h4>
|
||||
<p>GIFs et motion design</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b5e3a, #b58a5a);">
|
||||
<i data-feather="book-open"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Guide de style</h4>
|
||||
<p>Charte graphique fournie</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-cta">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Demander un devis
|
||||
</a>
|
||||
<a href="realisations.html" class="btn btn-secondary">
|
||||
<i data-feather="eye"></i>
|
||||
Voir nos créations
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CONSULTING -->
|
||||
<div class="service-tab-content" id="tab-consulting">
|
||||
<div class="service-tab-grid">
|
||||
<div class="service-visual">
|
||||
<span class="service-stamp service-visual-stamp service-stamp-free service-stamp-animated">✓ Gratuit</span>
|
||||
<div class="service-visual-particles">
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
</div>
|
||||
<div class="service-visual-icon">
|
||||
<div class="icon-main" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="users"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-tab-details">
|
||||
<div class="service-tab-header">
|
||||
<h2>Consulting & Accompagnement <span class="service-stamp service-stamp-inline service-stamp-free">Gratuit</span></h2>
|
||||
<p>Bénéficiez de notre expérience pour structurer, lancer et développer votre projet RP. Conseils stratégiques et accompagnement personnalisé.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-highlights">
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">50+</div>
|
||||
<div class="service-highlight-label">Projets accompagnés</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">3 ans</div>
|
||||
<div class="service-highlight-label">D'expérience</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">24/7</div>
|
||||
<div class="service-highlight-label">Support Discord</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-features">
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="search"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Audit serveur</h4>
|
||||
<p>Analyse de l'existant</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="trending-up"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Stratégie croissance</h4>
|
||||
<p>Plan de développement</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="user-check"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Formation staff</h4>
|
||||
<p>Équipe modération</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="heart"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Expérience joueur</h4>
|
||||
<p>Optimisation UX</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="calendar"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Planning events</h4>
|
||||
<p>Calendrier d'animations</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #3a8b5e, #5ab57a);">
|
||||
<i data-feather="dollar-sign"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Monétisation</h4>
|
||||
<p>Conseils revenus</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-cta">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Prendre rendez-vous
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PACK COMPLET -->
|
||||
<div class="service-tab-content" id="tab-pack">
|
||||
<div class="service-tab-grid">
|
||||
<div class="service-visual">
|
||||
<span class="service-stamp service-visual-stamp service-stamp-popular service-stamp-animated">★ Populaire</span>
|
||||
<div class="service-visual-particles">
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
<div class="particle"></div>
|
||||
</div>
|
||||
<div class="service-visual-icon">
|
||||
<div class="icon-main" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="package"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-tab-details">
|
||||
<div class="service-tab-header">
|
||||
<h2>Pack Serveur Complet <span class="service-stamp service-stamp-inline service-stamp-promo">-20%</span></h2>
|
||||
<p>La solution tout-en-un pour lancer votre projet RP. Bot personnalisé, map Fortnite, identité visuelle et accompagnement : tout est inclus pour un lancement réussi.</p>
|
||||
</div>
|
||||
|
||||
<div class="service-highlights">
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">-20%</div>
|
||||
<div class="service-highlight-label">VS services séparés</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">3 mois</div>
|
||||
<div class="service-highlight-label">Support inclus</div>
|
||||
</div>
|
||||
<div class="service-highlight">
|
||||
<div class="service-highlight-value">Clé en main</div>
|
||||
<div class="service-highlight-label">Prêt à lancer</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-features">
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="code"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Bot Discord RP</h4>
|
||||
<p>Système complet personnalisé</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="map"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Map Fortnite</h4>
|
||||
<p>Environnement sur mesure</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="image"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Pack graphique</h4>
|
||||
<p>Logo, bannières, emojis</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="server"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Config Discord</h4>
|
||||
<p>Serveur prêt à l'emploi</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="book"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Documentation</h4>
|
||||
<p>Guides et tutoriels</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-feature-item">
|
||||
<div class="service-feature-icon" style="background: linear-gradient(135deg, #8b3a8b, #b55ab5);">
|
||||
<i data-feather="headphones"></i>
|
||||
</div>
|
||||
<div class="service-feature-text">
|
||||
<h4>Support 3 mois</h4>
|
||||
<p>Accompagnement lancement</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-tab-cta">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Demander un devis pack
|
||||
</a>
|
||||
<a href="realisations.html" class="btn btn-secondary">
|
||||
<i data-feather="eye"></i>
|
||||
Voir nos packs livrés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Why Choose Us -->
|
||||
<section style="padding: 6rem 2rem; background: linear-gradient(180deg, transparent 0%, var(--bg-secondary) 50%, transparent 100%);">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Nos atouts</p>
|
||||
<h2 class="section-title">Pourquoi nous choisir ?</h2>
|
||||
<p class="section-desc">Ce qui fait la différence OmégaKube</p>
|
||||
</div>
|
||||
|
||||
<div class="why-us-grid reveal">
|
||||
<div class="why-us-card">
|
||||
<div class="why-us-icon">
|
||||
<i data-feather="star"></i>
|
||||
</div>
|
||||
<h3>Expertise RP</h3>
|
||||
<p>3 ans d'expérience dans l'écosystème Role Play. Nous connaissons vos besoins car nous sommes aussi des joueurs.</p>
|
||||
</div>
|
||||
<div class="why-us-card">
|
||||
<div class="why-us-icon">
|
||||
<i data-feather="refresh-cw"></i>
|
||||
</div>
|
||||
<h3>Suivi continu</h3>
|
||||
<p>Communication régulière pendant le développement. Vous suivez l'avancement et validez chaque étape.</p>
|
||||
</div>
|
||||
<div class="why-us-card">
|
||||
<div class="why-us-icon">
|
||||
<i data-feather="life-buoy"></i>
|
||||
</div>
|
||||
<h3>Support inclus</h3>
|
||||
<p>Maintenance et assistance après livraison. Nous restons disponibles pour les ajustements et questions.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<section class="contact" style="padding-top: 4rem;">
|
||||
<div class="section-header reveal">
|
||||
<p class="section-tag">Prêt à commencer ?</p>
|
||||
<h2 class="section-title">Discutons de votre projet</h2>
|
||||
<p class="section-desc">Contactez-nous pour un devis gratuit et personnalisé</p>
|
||||
</div>
|
||||
<div style="text-align: center;" class="reveal">
|
||||
<a href="index.html#contact" class="btn btn-primary">
|
||||
<i data-feather="message-circle"></i>
|
||||
Nous contacter
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Footer -->
|
||||
<div data-include="../components/footer.html"></div>
|
||||
|
||||
<script src="../assets/js/main.js"></script>
|
||||
<script src="../assets/js/pages/services.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||