diff --git a/README.md b/README.md
index a908d42..694c8a0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,66 @@
-# website-front
-test
+# Website Front pour Banquise
+
+Ce projet est une application web React développée avec Vite, TypeScript et TailwindCSS.
+
+## Architecture du Projet
+
+```
+website-front/
+├── banquise-website/ # Application React principale
+│ ├── public/ # Fichiers statiques
+│ ├── src/ # Code source
+│ │ ├── assets/ # Images et ressources
+│ │ ├── App.tsx # Composant principal
+│ │ └── main.tsx # Point d'entrée de l'application
+│ ├── index.html # Template HTML principal
+│ ├── package.json # Configuration des dépendances
+│ ├── tsconfig.json # Configuration TypeScript
+│ ├── vite.config.ts # Configuration Vite
+│ └── tailwind.config.js # Configuration TailwindCSS
+└── shell.nix # Configuration pour environnement Nix
+```
+
+## Technologies Utilisées
+
+- **React 18** - Bibliothèque d'interface utilisateur
+- **TypeScript** - Langage de programmation typé
+- **Vite** - Outil de build et serveur de développement
+- **TailwindCSS** - Framework CSS utilitaire
+- **React Router** - Navigation entre les pages
+- **Zustand** - Gestion d'état
+- **React Query** - Gestion des requêtes API
+- **Framer Motion** - Animations
+
+## Pré-requis
+
+- Node.js (v16.0.0 ou supérieur)
+- npm ou yarn
+
+## Installation
+
+```bash
+# Se déplacer dans le dossier du projet
+cd banquise-website
+
+# Installer les dépendances
+npm install
+# ou avec yarn
+yarn
+```
+
+## Scripts Disponibles
+
+- `npm run dev` - Lance le serveur de développement
+- `npm run build` - Compile le projet pour la production
+- `npm run preview` - Prévisualise la version de production localement
+- `npm run lint` - Vérifie la qualité du code avec ESLint
+
+## Déploiement
+
+### Compilation pour la Production
+
+```bash
+npm run build
+```
+
+Cette commande générera un dossier `dist` dans le répertoire `banquise-website/` contenant tous les fichiers optimisés pour la production.
\ No newline at end of file
diff --git a/banquise-website/.gitignore b/banquise-website/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/banquise-website/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/banquise-website/README.md b/banquise-website/README.md
new file mode 100644
index 0000000..da98444
--- /dev/null
+++ b/banquise-website/README.md
@@ -0,0 +1,54 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default tseslint.config({
+ extends: [
+ // Remove ...tseslint.configs.recommended and replace with this
+ ...tseslint.configs.recommendedTypeChecked,
+ // Alternatively, use this for stricter rules
+ ...tseslint.configs.strictTypeChecked,
+ // Optionally, add this for stylistic rules
+ ...tseslint.configs.stylisticTypeChecked,
+ ],
+ languageOptions: {
+ // other options...
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+})
+```
+
+You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
+
+```js
+// eslint.config.js
+import reactX from 'eslint-plugin-react-x'
+import reactDom from 'eslint-plugin-react-dom'
+
+export default tseslint.config({
+ plugins: {
+ // Add the react-x and react-dom plugins
+ 'react-x': reactX,
+ 'react-dom': reactDom,
+ },
+ rules: {
+ // other rules...
+ // Enable its recommended typescript rules
+ ...reactX.configs['recommended-typescript'].rules,
+ ...reactDom.configs.recommended.rules,
+ },
+})
+```
diff --git a/banquise-website/eslint.config.js b/banquise-website/eslint.config.js
new file mode 100644
index 0000000..092408a
--- /dev/null
+++ b/banquise-website/eslint.config.js
@@ -0,0 +1,28 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+
+export default tseslint.config(
+ { ignores: ['dist'] },
+ {
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
+ files: ['**/*.{ts,tsx}'],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ plugins: {
+ 'react-hooks': reactHooks,
+ 'react-refresh': reactRefresh,
+ },
+ rules: {
+ ...reactHooks.configs.recommended.rules,
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+ },
+)
diff --git a/banquise-website/index.html b/banquise-website/index.html
new file mode 100644
index 0000000..ee5ab91
--- /dev/null
+++ b/banquise-website/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+ La Banquise - Services d'hébergement
+
+
+
+
+
+
+
+
+
+
diff --git a/banquise-website/package.json b/banquise-website/package.json
new file mode 100644
index 0000000..5bbfe07
--- /dev/null
+++ b/banquise-website/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "banquise-website",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "axios": "^1.6.5",
+ "clsx": "^2.1.0",
+ "framer-motion": "^10.18.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-icons": "^4.12.0",
+ "react-router-dom": "^6.22.0",
+ "@tanstack/react-query": "^5.17.9",
+ "tailwind-merge": "^2.2.0",
+ "zustand": "^4.4.7"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.25.0",
+ "@tailwindcss/forms": "^0.5.7",
+ "@tailwindcss/typography": "^0.5.10",
+ "@types/react": "^18.2.58",
+ "@types/react-dom": "^18.2.19",
+ "@vitejs/plugin-react": "^4.4.1",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^9.25.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.19",
+ "eslint-plugin-tailwindcss": "^3.14.0",
+ "globals": "^16.0.0",
+ "postcss": "^8.4.33",
+ "typescript": "~5.8.3",
+ "typescript-eslint": "^8.30.1",
+ "vite": "^6.3.5",
+ "vite-plugin-compression": "^0.5.1",
+ "tailwindcss": "^3.4.1"
+ }
+}
diff --git a/banquise-website/postcss.config.js b/banquise-website/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/banquise-website/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/banquise-website/public/vite.svg b/banquise-website/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/banquise-website/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/banquise-website/src/App.css b/banquise-website/src/App.css
new file mode 100644
index 0000000..b82c161
--- /dev/null
+++ b/banquise-website/src/App.css
@@ -0,0 +1,1124 @@
+#root {
+ max-width: 100%;
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ width: 100%;
+}
+
+.app-container {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ width: 100%;
+}
+
+/* Navigation */
+.navbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.8rem 2rem;
+ background-color: rgba(31, 93, 137, 0.95); /* #1F5D89 avec transparence */
+ color: white;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ width: 100%;
+ box-sizing: border-box;
+ z-index: 10;
+ backdrop-filter: blur(8px);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ position: sticky;
+ top: 0;
+}
+
+.navbar-left {
+ display: flex;
+ align-items: center;
+}
+
+.site-logo {
+ height: 2.2rem;
+ width: auto;
+ margin-right: 1rem;
+ filter: drop-shadow(0 0 5px rgba(168, 218, 255, 0.4));
+}
+
+.site-name {
+ font-size: 1.6rem;
+ font-weight: 700;
+ margin: 0;
+ color: #ffffff;
+ letter-spacing: 0.5px;
+ font-family: var(--font-heading);
+}
+
+.navbar-right {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.discord-button {
+ display: flex;
+ align-items: center;
+ background-color: #40B4FF;
+ color: white;
+ border: none;
+ padding: 0.6rem 1.2rem;
+ border-radius: 6px;
+ cursor: pointer;
+ text-decoration: none;
+ font-weight: 600;
+ letter-spacing: 0.3px;
+ box-shadow: 0 2px 8px rgba(64, 180, 255, 0.4);
+ transition: all 0.2s ease;
+}
+
+.discord-button:hover {
+ background-color: #2ba3f7;
+ color: #ffffff;
+ text-shadow: 0 0 1px rgba(255, 255, 255, 0.5);
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px rgba(64, 180, 255, 0.6);
+}
+
+.discord-button:focus-visible {
+ outline: 3px solid #ffffff;
+ outline-offset: 2px;
+ background-color: #2ba3f7;
+}
+
+.login-button {
+ display: flex;
+ align-items: center;
+ background-color: rgba(105, 183, 226, 0.9); /* #69B7E2 */
+ color: white;
+ border: none;
+ padding: 0.6rem 1.2rem;
+ border-radius: 6px;
+ cursor: pointer;
+ text-decoration: none;
+ font-weight: 600;
+ letter-spacing: 0.3px;
+ box-shadow: 0 2px 8px rgba(105, 183, 226, 0.3);
+ transition: all 0.2s ease;
+}
+
+.login-button:hover {
+ background-color: #69B7E2;
+ color: #ffffff;
+ text-shadow: 0 0 1px rgba(255, 255, 255, 0.5);
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px rgba(105, 183, 226, 0.5);
+}
+
+.login-button:focus-visible {
+ outline: 3px solid #ffffff;
+ outline-offset: 2px;
+ background-color: #69B7E2;
+}
+
+.login-icon {
+ margin-right: 0.5rem;
+}
+
+.content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+.ocean {
+ position: relative;
+ flex: 1;
+ background: linear-gradient(180deg, #40B4FF 0%, #69B7E2 50%, #1F5D89 100%);
+ width: 100%;
+ min-height: calc(100vh - 72px);
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ overflow-x: hidden;
+}
+
+.page-section {
+ width: 100%;
+ max-width: 1200px;
+ margin: 1rem auto;
+ padding: 2rem 2rem;
+ position: relative;
+ z-index: 3;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ box-sizing: border-box;
+}
+
+.hero-section {
+ min-height: calc(70vh - 72px);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ padding-top: 2rem;
+ padding-bottom: 3rem;
+ margin-top: 0;
+}
+
+.hero-title {
+ color: #F6F6F6;
+ font-size: 3.5rem;
+ margin-bottom: 1.5rem;
+ font-weight: 800;
+ text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
+ line-height: 1.1;
+ max-width: 800px;
+}
+
+.hero-subtitle {
+ color: #F6F6F6;
+ font-size: 1.5rem;
+ margin-bottom: 2.5rem;
+ max-width: 700px;
+ font-weight: 400;
+ opacity: 0.9;
+ text-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
+}
+
+.cta-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #F6F6F6;
+ color: #1F5D89;
+ border: none;
+ padding: 1rem 2.5rem;
+ border-radius: 30px;
+ font-size: 1.1rem;
+ font-weight: 600;
+ text-decoration: none;
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
+ transition: all 0.3s ease;
+ min-width: 200px;
+}
+
+.cta-button:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
+ background-color: #ffffff;
+}
+
+.cta-icon {
+ margin-left: 0.75rem;
+ transition: transform 0.2s ease;
+}
+
+.cta-button:hover .cta-icon {
+ transform: translateX(3px);
+}
+
+.section-divider {
+ width: 80px;
+ height: 4px;
+ background: linear-gradient(90deg, #A5F0FF, #40B4FF);
+ margin: 0 auto 2rem;
+ border-radius: 2px;
+}
+
+.section-title {
+ color: #F6F6F6;
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ font-size: 2.5rem;
+ margin-bottom: 1rem;
+ text-align: center;
+ font-family: var(--font-heading);
+ font-weight: 700;
+ letter-spacing: -0.01em;
+}
+
+.section-subtitle {
+ color: #F6F6F6;
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+ font-size: 1.25rem;
+ opacity: 0.9;
+ margin-bottom: 3.5rem;
+ max-width: 800px;
+ text-align: center;
+}
+
+.services-section {
+ position: relative;
+ z-index: 2;
+ padding-top: 2rem;
+ padding-bottom: 4rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+.icebergs-container {
+ position: relative;
+ width: 100%;
+ max-width: 1000px;
+ height: auto;
+ min-height: 350px;
+ z-index: 2;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin: 2rem auto;
+ padding: 0;
+ gap: 5%;
+}
+
+.iceberg {
+ cursor: pointer;
+ text-decoration: none;
+ width: 250px;
+ height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: transform 0.3s ease;
+ z-index: 3;
+ margin: 0;
+}
+
+.iceberg:hover {
+ transform: translateY(-10px) !important;
+}
+
+.float-1, .float-2, .float-3 {
+ animation: none;
+}
+
+.iceberg img {
+ width: 100%;
+ height: auto;
+ max-width: 250px;
+ max-height: 200px;
+ object-fit: contain;
+ filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.3));
+}
+
+.service-name {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: #1F5D89;
+ font-weight: 700;
+ font-size: 1.4rem;
+ background-color: rgba(255, 255, 255, 0.92);
+ padding: 12px 20px;
+ border-radius: 10px;
+ text-align: center;
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15), 0 0 0 2px rgba(165, 240, 255, 0.5); /* #A5F0FF */
+ z-index: 4;
+ font-family: var(--font-heading);
+ letter-spacing: -0.01em;
+ border: 1px solid rgba(165, 240, 255, 0.8);
+ backdrop-filter: blur(4px);
+ transition: all 0.3s ease;
+ min-width: 160px;
+ max-width: 90%;
+ width: auto;
+}
+
+.iceberg:hover .service-name {
+ background-color: rgba(255, 255, 255, 0.97);
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(165, 240, 255, 0.7);
+ transform: translate(-50%, -55%);
+ color: #40B4FF;
+}
+
+.float-1 {
+ animation: float1 5s ease-in-out infinite;
+}
+
+.float-2 {
+ animation: float2 6s ease-in-out infinite;
+}
+
+.float-3 {
+ animation: float3 7s ease-in-out infinite;
+}
+
+@keyframes float1 {
+ 0%, 100% { transform: translateY(0); }
+ 50% { transform: translateY(-15px); }
+}
+
+@keyframes float2 {
+ 0%, 100% { transform: translateY(0); }
+ 50% { transform: translateY(-20px); }
+}
+
+@keyframes float3 {
+ 0%, 100% { transform: translateY(0); }
+ 50% { transform: translateY(-10px); }
+}
+
+.about-section {
+ position: relative;
+ background-color: rgba(31, 93, 137, 0.15);
+ backdrop-filter: blur(10px);
+ margin: 1rem 0;
+ padding: 3rem 2rem;
+ z-index: 2;
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.about-container {
+ max-width: 1000px;
+ margin: 0 auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+}
+
+/* Modern FAQ Accordion Styles */
+.accordion-group {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ margin-top: 1.5rem;
+}
+
+.accordion-item {
+ background: rgba(31, 93, 137, 0.1);
+ border-radius: 12px;
+ overflow: hidden;
+ border: 1px solid rgba(165, 240, 255, 0.2);
+ transition: all 0.3s ease;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
+}
+
+.accordion-item:hover {
+ background: rgba(31, 93, 137, 0.2);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
+}
+
+.accordion-header {
+ padding: 1.2rem 1.5rem;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-weight: 600;
+ color: #F6F6F6;
+ background: rgba(31, 93, 137, 0.2);
+ transition: all 0.2s ease;
+ font-size: 1.1rem;
+ user-select: none;
+}
+
+.accordion-header:hover {
+ background: rgba(64, 180, 255, 0.2);
+}
+
+.accordion-toggle-icon {
+ font-size: 1.2rem;
+ transition: transform 0.3s ease;
+ color: #A5F0FF;
+}
+
+.accordion-item.active .accordion-toggle-icon {
+ transform: rotate(180deg);
+}
+
+.accordion-content {
+ max-height: 0;
+ overflow: hidden;
+ transition: max-height 0.5s cubic-bezier(0, 1, 0, 1), padding 0.3s ease;
+ background: rgba(31, 93, 137, 0.05);
+ line-height: 1.6;
+ font-size: 1rem;
+ color: rgba(246, 246, 246, 0.9);
+}
+
+.accordion-item.active .accordion-content {
+ max-height: 1000px;
+ transition: max-height 1s ease-in-out, padding 0.3s ease;
+ padding: 1.5rem;
+}
+
+.accordion-content p {
+ margin-top: 0;
+}
+
+.accordion-content p:last-child {
+ margin-bottom: 0;
+}
+
+.accordion-content ul {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ padding-left: 1.5rem;
+}
+
+.accordion-content li {
+ margin-bottom: 0.5rem;
+}
+
+.about-image-container {
+ max-width: 180px;
+ margin: 0 auto 2rem;
+ position: relative;
+ z-index: 2;
+}
+
+.about-logo {
+ width: 100%;
+ height: auto;
+ border-radius: 50%;
+ padding: 1rem;
+ background: rgba(255, 255, 255, 0.05);
+ border: 2px solid rgba(165, 240, 255, 0.3);
+ box-shadow: 0 10px 25px rgba(31, 93, 137, 0.3);
+ animation: gentle-float 6s ease-in-out infinite;
+}
+
+@keyframes gentle-float {
+ 0%, 100% {
+ transform: translateY(0);
+ }
+ 50% {
+ transform: translateY(-10px);
+ }
+}
+
+.about-intro {
+ text-align: center;
+ max-width: 800px;
+ margin: 0 auto 2rem;
+ color: #F6F6F6;
+ font-size: 1.1rem;
+ line-height: 1.6;
+}
+
+.accordion-cta {
+ display: inline-flex;
+ align-items: center;
+ background-color: #40B4FF;
+ color: white;
+ border: none;
+ padding: 0.7rem 1.2rem;
+ border-radius: 6px;
+ margin-top: 0.5rem;
+ text-decoration: none;
+ font-weight: 600;
+ transition: all 0.2s ease;
+}
+
+.accordion-cta:hover {
+ background-color: #2ba3f7;
+ transform: translateY(-2px);
+}
+
+.accordion-cta-icon {
+ margin-left: 0.5rem;
+ font-size: 0.9rem;
+}
+
+/* Media queries for responsive design */
+@media (max-width: 768px) {
+ .about-section {
+ padding: 2rem 1.2rem;
+ }
+
+ .about-image-container {
+ max-width: 140px;
+ margin-bottom: 1.5rem;
+ }
+
+ .accordion-header {
+ padding: 1rem 1.2rem;
+ font-size: 1rem;
+ }
+
+ .accordion-item.active .accordion-content {
+ padding: 1.2rem;
+ }
+
+ .accordion-toggle-icon {
+ font-size: 1.1rem;
+ }
+}
+
+/* ...existing code... */
+
+.about-text {
+ flex: 1;
+ min-width: 300px;
+ max-width: 600px;
+ color: white;
+ text-align: left;
+}
+
+.about-text h3 {
+ font-size: 2rem;
+ margin-bottom: 1.5rem;
+ color: white;
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
+}
+
+.about-text p {
+ margin-bottom: 1.25rem;
+ line-height: 1.7;
+ font-size: 1.1rem;
+}
+
+.about-image {
+ flex: 1;
+ min-width: 300px;
+ max-width: 500px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.about-image img {
+ width: 100%;
+ height: auto;
+ border-radius: 12px;
+ box-shadow: 0 15px 30px rgba(0, 0, 0, 0.25);
+ transform: perspective(1000px) rotateY(-5deg);
+ transition: transform 0.5s ease;
+}
+
+.about-image img:hover {
+ transform: perspective(1000px) rotateY(0);
+}
+
+/* Statistiques */
+.stats-section {
+ background: linear-gradient(180deg, rgba(64, 180, 255, 0.2) 0%, rgba(31, 93, 137, 0) 100%);
+ padding: 4rem 2rem;
+ position: relative;
+ z-index: 2;
+}
+
+.stats-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 2rem;
+}
+
+.stat-card {
+ background: rgba(31, 93, 137, 0.1);
+ border-radius: 12px;
+ padding: 2rem;
+ text-align: center;
+ transition: transform 0.3s ease;
+}
+
+.stat-card:hover {
+ transform: translateY(-5px);
+}
+
+.stat-icon {
+ font-size: 2.5rem;
+ margin-bottom: 1rem;
+ color: #40B4FF;
+}
+
+.stat-title {
+ font-size: 1.2rem;
+ margin-bottom: 0.5rem;
+ color: #F6F6F6;
+}
+
+.stat-value {
+ font-size: 2rem;
+ font-weight: 700;
+ color: #A5F0FF;
+}
+
+/* Fonctionnalités */
+.features-section {
+ background: linear-gradient(180deg, rgba(64, 180, 255, 0.2) 0%, rgba(31, 93, 137, 0) 100%);
+ padding: 4rem 2rem;
+ position: relative;
+ z-index: 2;
+}
+
+.feature-card {
+ background: rgba(31, 93, 137, 0.1);
+ border-radius: 12px;
+ padding: 2rem;
+ transition: transform 0.3s ease;
+}
+
+.feature-card:hover {
+ background: rgba(64, 180, 255, 0.15);
+}
+
+.feature-icon {
+ font-size: 2rem;
+ margin-bottom: 1rem;
+ color: #A5F0FF;
+ background: rgba(31, 93, 137, 0.3);
+ padding: 1rem;
+ border-radius: 50%;
+}
+
+.feature-title {
+ font-size: 1.2rem;
+ margin-bottom: 0.5rem;
+ color: #F6F6F6;
+}
+
+.feature-description {
+ color: #F6F6F6;
+ line-height: 1.6;
+}
+
+/* FAQ */
+.faq-section {
+ background: rgba(31, 93, 137, 0.05);
+ padding: 4rem 2rem;
+ position: relative;
+ z-index: 2;
+}
+
+.faq-item {
+ background: rgba(31, 93, 137, 0.08);
+ border-radius: 8px;
+ margin-bottom: 1.5rem;
+ padding: 1.5rem;
+ transition: background 0.3s ease;
+}
+
+.faq-item:hover {
+ background: rgba(31, 93, 137, 0.12);
+}
+
+.faq-question {
+ font-size: 1.1rem;
+ margin-bottom: 0.5rem;
+ color: #F6F6F6;
+}
+
+.faq-answer {
+ color: #F6F6F6;
+ line-height: 1.6;
+}
+
+/* Pied de page */
+.footer {
+ background-color: #1F5D89;
+ color: white;
+ padding: 4rem 2rem 2rem;
+ position: relative;
+ z-index: 3;
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.footer-content {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.footer-column {
+ flex: 1;
+ min-width: 250px;
+ margin-bottom: 2rem;
+ text-align: left;
+ padding: 0 1.5rem;
+}
+
+.footer-column h4 {
+ font-size: 1.2rem;
+ margin-bottom: 1.5rem;
+ color: #A5F0FF;
+ position: relative;
+ padding-bottom: 0.75rem;
+}
+
+.footer-column h4:after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 40px;
+ height: 2px;
+ background-color: #A5F0FF;
+}
+
+.footer-column ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.footer-column ul li {
+ margin-bottom: 0.8rem;
+}
+
+.footer-column a {
+ color: rgba(246, 246, 246, 0.8); /* #F6F6F6 */
+ text-decoration: none;
+ transition: all 0.2s;
+ display: inline-block;
+}
+
+.footer-column a:hover {
+ color: #F6F6F6;
+ transform: translateX(3px);
+}
+
+.footer-bottom {
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ padding-top: 1.5rem;
+ margin-top: 2rem;
+ text-align: center;
+ font-size: 0.9rem;
+ color: rgba(255, 255, 255, 0.7);
+ max-width: 1200px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.popup-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.7);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 100;
+ padding: 1rem;
+ backdrop-filter: blur(3px);
+ animation: fadeIn 0.2s ease-out;
+}
+
+.popup-content {
+ background: linear-gradient(135deg, #F6F6F6 0%, #E8F7FF 100%);
+ color: #1F5D89;
+ border-radius: 12px;
+ padding: 2rem;
+ max-width: 500px;
+ width: 100%;
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
+ position: relative;
+ overflow: hidden;
+ animation: slideUp 0.3s ease-out;
+}
+
+.popup-close {
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ background: none;
+ border: none;
+ font-size: 1.5rem;
+ cursor: pointer;
+ color: #1F5D89;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ transition: background-color 0.2s;
+ padding: 0;
+}
+
+.popup-close:hover {
+ background-color: rgba(64, 180, 255, 0.1); /* #40B4FF */
+}
+
+.popup-title {
+ font-family: var(--font-heading);
+ font-size: 1.8rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+ color: #1F5D89;
+ line-height: 1.2;
+}
+
+.popup-description {
+ font-size: 1.1rem;
+ line-height: 1.5;
+ margin-bottom: 1.5rem;
+ color: #1F5D89;
+}
+
+.popup-button {
+ display: inline-flex;
+ align-items: center;
+ background-color: #40B4FF;
+ color: white;
+ border: none;
+ padding: 0.8rem 1.5rem;
+ border-radius: 6px;
+ cursor: pointer;
+ text-decoration: none;
+ font-weight: 600;
+ letter-spacing: 0.3px;
+ box-shadow: 0 2px 8px rgba(64, 180, 255, 0.3);
+ transition: all 0.2s ease;
+}
+
+.popup-button:hover {
+ background-color: #2ba3f7;
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px rgba(64, 180, 255, 0.4);
+}
+
+.popup-button:focus-visible {
+ outline: 3px solid #69B7E2;
+ outline-offset: 2px;
+}
+
+.popup-button-icon {
+ margin-right: 0.5rem;
+ font-size: 1.1em;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes slideUp {
+ from {
+ transform: translateY(30px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+.bubbles {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: none;
+}
+
+.bubble {
+ position: absolute;
+ bottom: -20px;
+ width: 40px;
+ height: 40px;
+ background: rgba(165, 240, 255, 0.2); /* #A5F0FF */
+ border-radius: 50%;
+ opacity: 0.8;
+ animation: rise 10s infinite ease-in;
+}
+
+.bubble:nth-child(1) {
+ width: 25px;
+ height: 25px;
+ left: 10%;
+ animation-duration: 8s;
+}
+
+.bubble:nth-child(2) {
+ width: 30px;
+ height: 30px;
+ left: 20%;
+ animation-duration: 9s;
+ animation-delay: 1s;
+}
+
+.bubble:nth-child(3) {
+ width: 35px;
+ height: 35px;
+ left: 35%;
+ animation-duration: 10s;
+ animation-delay: 2s;
+}
+
+.bubble:nth-child(4) {
+ width: 28px;
+ height: 28px;
+ left: 50%;
+ animation-duration: 7s;
+ animation-delay: 0s;
+}
+
+.bubble:nth-child(5) {
+ width: 22px;
+ height: 22px;
+ left: 65%;
+ animation-duration: 12s;
+ animation-delay: 3s;
+}
+
+.bubble:nth-child(6) {
+ width: 32px;
+ height: 32px;
+ left: 80%;
+ animation-duration: 9s;
+ animation-delay: 1.5s;
+}
+
+.bubble:nth-child(7) {
+ width: 20px;
+ height: 20px;
+ left: 90%;
+ animation-duration: 8s;
+ animation-delay: 2.5s;
+}
+
+@keyframes rise {
+ 0% {
+ bottom: -100px;
+ transform: translateX(0);
+ opacity: 0.8;
+ }
+ 50% {
+ transform: translateX(40px);
+ opacity: 0.4;
+ }
+ 100% {
+ bottom: 1080px;
+ transform: translateX(-40px);
+ opacity: 0;
+ }
+}
+
+.navbar-mobile-toggle {
+ display: none;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ padding: 5px;
+ z-index: 20;
+ width: 40px;
+ height: 40px;
+ position: relative;
+}
+
+.navbar-mobile-toggle span {
+ display: block;
+ width: 25px;
+ height: 3px;
+ background-color: white;
+ margin: 5px auto;
+ transition: all 0.3s ease;
+}
+
+.navbar-right {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+@media (max-width: 768px) {
+ .navbar {
+ padding: 0.6rem 1rem;
+ }
+
+ .navbar-mobile-toggle {
+ display: block;
+ }
+
+ .navbar-right {
+ position: fixed;
+ top: 0;
+ right: -100%;
+ flex-direction: column;
+ background-color: rgba(12, 59, 93, 0.98);
+ height: 100vh;
+ width: 70%;
+ max-width: 300px;
+ padding-top: 70px;
+ transition: all 0.3s ease;
+ z-index: 15;
+ gap: 20px;
+ backdrop-filter: blur(10px);
+ box-shadow: -5px 0 15px rgba(0, 0, 0, 0.2);
+ visibility: hidden; /* Add this */
+ opacity: 0; /* Add this */
+ }
+
+ .navbar-right.mobile-active {
+ right: 0;
+ visibility: visible; /* Add this */
+ opacity: 1; /* Add this */
+ }
+
+ .navbar-mobile-toggle.active span:nth-child(1) {
+ transform: translateY(8px) rotate(45deg);
+ }
+
+ .navbar-mobile-toggle.active span:nth-child(2) {
+ opacity: 0;
+ transform: scale(0);
+ }
+
+ .navbar-mobile-toggle.active span:nth-child(3) {
+ transform: translateY(-8px) rotate(-45deg);
+ }
+
+ /* Iceberg consistency fixes */
+ .iceberg {
+ width: 220px;
+ height: 180px;
+ margin: 0 auto;
+ }
+
+ .iceberg img {
+ width: 100%;
+ max-width: 220px;
+ max-height: 180px;
+ object-fit: contain;
+ }
+
+ .service-name {
+ font-size: 1.2rem;
+ padding: 10px 16px;
+ width: auto;
+ min-width: 160px;
+ max-width: 90%;
+ }
+}
+
+/* Desktop consistency for icebergs */
+.iceberg {
+ position: relative;
+ width: 250px;
+ height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.iceberg img {
+ width: 100%;
+ height: auto;
+ max-width: 250px;
+ max-height: 200px;
+ object-fit: contain;
+}
diff --git a/banquise-website/src/App.tsx b/banquise-website/src/App.tsx
new file mode 100644
index 0000000..a67b62c
--- /dev/null
+++ b/banquise-website/src/App.tsx
@@ -0,0 +1,525 @@
+import { FiUser, FiDatabase, FiShield, FiChevronDown } from 'react-icons/fi'
+import { FaDiscord, FaArrowRight, FaEnvelope, FaGithub, FaNetworkWired, FaServer, FaLaptopCode, FaCloudUploadAlt, FaExternalLinkAlt } from 'react-icons/fa'
+import { FiX, FiExternalLink } from 'react-icons/fi'
+import './App.css'
+import icebergImage from './assets/iceberg.png'
+import logoImage from './assets/banquise.png'
+import { useEffect, useState, useMemo, useCallback, useRef } from 'react'
+
+import aboutImage from './assets/banquise.png'
+
+function App() {
+ const [selectedService, setSelectedService] = useState(null);
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
+ const mobileMenuRef = useRef(null);
+
+ const services = useMemo(() => [
+ {
+ name: "Notre Wiki",
+ url: "https://wiki.la-banquise.fr/en/home",
+ description: "Notre Wiki est une base de connaissances collaborative où vous trouverez toute la documentation relative à nos projets et services. Apprenez, contribuez et partagez vos connaissances avec la communauté La Banquise."
+ },
+ {
+ name: "Gitea",
+ url: "https://git.la-banquise.fr/",
+ description: "Gitea est notre plateforme de gestion de code source, similaire à GitHub mais hébergée par nos soins. Créez des dépôts, collaborez sur des projets et participez au développement d'applications open-source dans un environnement sécurisé."
+ },
+ {
+ name: "Panel de jeux",
+ url: "https://panel.la-banquise.fr/auth/login",
+ description: "Interface de connection à notre panel Pterodactyl, qui vous permet de gérer vos serveurs de jeux. Créez, gérez et configurez vos serveurs de jeux préférés en toute simplicité."
+ },
+ ], []);
+
+ const [icebergs, setIcebergs] = useState>([])
+
+ const [reducedMotion, setReducedMotion] = useState(false);
+
+ useEffect(() => {
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
+ setReducedMotion(prefersReducedMotion);
+
+ const startTime = performance.now();
+ let count = 0;
+ while (performance.now() - startTime < 5) {
+ count++;
+ }
+
+ if (count < 1000) {
+ setReducedMotion(true);
+ }
+ }, []);
+
+ const positionIcebergs = useCallback(() => {
+ const newIcebergs = [];
+
+ const positions = [
+ { x: 25, y: 35, scale: 0.95, rotation: 0 },
+ { x: 50, y: 25, scale: 1.1, rotation: 0 },
+ { x: 75, y: 35, scale: 0.95, rotation: 0 },
+ ];
+
+ const floatClasses = ['float-1', 'float-2', 'float-3', 'float-4', 'float-5'];
+
+ for (let i = 0; i < services.length; i++) {
+ const position = positions[i % positions.length];
+
+ newIcebergs.push({
+ id: i,
+ x: position.x,
+ y: position.y,
+ scale: position.scale,
+ rotation: position.rotation,
+ service: services[i],
+ floatClass: reducedMotion ? '' : floatClasses[i % floatClasses.length]
+ });
+ }
+
+ return newIcebergs;
+ }, [services, reducedMotion]);
+
+ useEffect(() => {
+ setIcebergs(positionIcebergs());
+ }, [positionIcebergs]);
+
+ const renderBubbles = useMemo(() => {
+ if (reducedMotion) return null;
+
+ return (
+
+ );
+ }, [reducedMotion]);
+
+ const handleIcebergClick = (event: React.MouseEvent, serviceId: number) => {
+ event.preventDefault();
+ setSelectedService(serviceId);
+ };
+
+ const handleClosePopup = () => {
+ setSelectedService(null);
+ };
+
+ useEffect(() => {
+ const handleOutsideClick = (event: MouseEvent) => {
+ if (mobileMenuRef.current && !mobileMenuRef.current.contains(event.target as Node)) {
+ setMobileMenuOpen(false);
+ }
+ };
+
+ if (mobileMenuOpen) {
+ document.addEventListener('mousedown', handleOutsideClick);
+ }
+
+ return () => {
+ document.removeEventListener('mousedown', handleOutsideClick);
+ };
+ }, [mobileMenuOpen]);
+
+ useEffect(() => {
+ if (mobileMenuOpen) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = 'auto';
+ }
+
+ return () => {
+ document.body.style.overflow = 'auto';
+ };
+ }, [mobileMenuOpen]);
+
+ const [activeAccordion, setActiveAccordion] = useState(null);
+
+ // FAQ items for the about section
+ const faqItems = useMemo(() => [
+ {
+ question: "Qui sommes-nous ?",
+ answer: (
+ <>
+ La Banquise est une initiative d'étudiants de l'EPITA Lyon dont l'objectif est de rendre plus accessible l'hébergement de services informatiques. Fondée en 2023, notre association à but non lucratif vise à permettre à ceux qui le souhaitent de se former sur des technologies d'hébergement et de réseau.
+ Notre équipe est composée d'étudiants passionnés par l'informatique, le réseau et le partage de connaissances. Nous mettons notre expertise au service des étudiants et des associations de l'EPITA.
+ >
+ )
+ },
+ {
+ question: "Comment candidater pour rejoindre La Banquise ?",
+ answer: (
+ <>
+ Pour rejoindre notre équipe, rien de plus simple :
+
+ Rejoignez notre serveur Discord
+ Présentez-vous et expliquez votre motivation dans un ticket
+ Précisez vos compétences ou les domaines qui vous intéressent
+ Un membre de notre équipe vous contactera pour un échange
+
+ Nous recherchons des personnes motivées, peu importe votre niveau technique actuel !
+
+ Rejoindre le Discord
+
+ >
+ )
+ },
+ {
+ question: "Quels sont nos objectifs ?",
+ answer: (
+ <>
+ Nos principaux objectifs sont :
+
+ Former les étudiants aux technologies d'hébergement et de réseau
+ Fournir des services informatiques de qualité aux étudiants et associations de l'EPITA
+ Promouvoir le partage de connaissances et l'entraide
+ Créer un environnement d'apprentissage pratique par l'expérience
+ Maintenir une infrastructure robuste et sécurisée
+
+ >
+ )
+ },
+ {
+ question: "Comment utiliser nos services ?",
+ answer: (
+ <>
+ Pour accéder à nos services :
+
+ Créez un compte sur notre plateforme d'authentification
+ Connectez-vous au service souhaité avec vos identifiants
+ Consultez notre Wiki pour obtenir de l'aide sur l'utilisation de chaque service
+
+ Si vous rencontrez des difficultés, n'hésitez pas à demander de l'aide sur notre Discord.
+
+ Créer un compte
+
+ >
+ )
+ },
+ {
+ question: "Comment contribuer au projet ?",
+ answer: (
+ <>
+ Il existe plusieurs façons de contribuer au projet La Banquise :
+
+ Rejoindre l'équipe en tant que membre actif
+ Contribuer au code source de nos projets via Gitea
+ Rédiger ou améliorer la documentation sur notre Wiki
+ Proposer de nouvelles idées de services ou d'améliorations
+ Aider d'autres utilisateurs sur notre Discord
+
+ Toutes les contributions sont les bienvenues, même les plus modestes !
+ >
+ )
+ },
+ ], []);
+
+ const toggleAccordion = (index: number) => {
+ setActiveAccordion(activeAccordion === index ? null : index);
+ };
+
+ return (
+
+
Passer au contenu principal
+
+
+
+
+
+ {renderBubbles}
+
+
+
+
+
+
+
+ Association La Banquise
+
+ Association d'hébergement et lab réseau pour tous les étudiants et associations de l'EPITA
+
+
+
+
+
+
+ Notre infrastructure
+
+ Des services robustes et sécurisés pour répondre à vos besoins
+
+
+
+
+
+
+
+
Serveurs performants
+
+ Infrastructure optimisée pour assurer des performances élevées et une disponibilité maximale de vos applications
+
+
+
+
+
+
+
+
Stockage sécurisé
+
+ Solutions de stockage distribuées avec redondance pour garantir l'intégrité et la durabilité de vos données
+
+
+
+
+
+
+
+
Réseau optimisé
+
+ Architecture réseau à haute disponibilité avec une faible latence pour vos applications critiques
+
+
+
+
+
+
+
+
Sécurité renforcée
+
+ Protection contre les menaces avec systèmes de sécurité modernes et mises à jour régulières
+
+
+
+
+
+
+
+ Nos services
+
+ Explorez notre écosystème de services conçus pour répondre à vos besoins.
+
+
+
+
+
+
+
+ À propos de nous
+
+ Découvrez notre mission et posez-nous vos questions
+
+
+
+
+
+
+
+
+ La Banquise est une association étudiante dédiée à l'hébergement de services et à la formation sur les technologies réseau, au service de la communauté EPITA.
+
+
+
+ {faqItems.map((item, index) => (
+
+
toggleAccordion(index)}
+ role="button"
+ aria-expanded={activeAccordion === index}
+ aria-controls={`accordion-content-${index}`}
+ tabIndex={0}
+ onKeyPress={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ toggleAccordion(index);
+ }
+ }}
+ >
+ {item.question}
+
+
+
+ {item.answer}
+
+
+ ))}
+
+
+
+
+ {selectedService !== null && (
+
+ )}
+
+
+
const banquise = new ServerInfra();
+
banquise.deploy('wiki');
+
banquise.deploy('gitea');
+
banquise.optimize();
+
banquise.monitor();
+
+
+
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/banquise-website/src/assets/banquise.png b/banquise-website/src/assets/banquise.png
new file mode 100644
index 0000000..39c3011
Binary files /dev/null and b/banquise-website/src/assets/banquise.png differ
diff --git a/banquise-website/src/assets/iceberg.png b/banquise-website/src/assets/iceberg.png
new file mode 100644
index 0000000..3b97360
Binary files /dev/null and b/banquise-website/src/assets/iceberg.png differ
diff --git a/banquise-website/src/assets/react.svg b/banquise-website/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/banquise-website/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/banquise-website/src/index.css b/banquise-website/src/index.css
new file mode 100644
index 0000000..29d7987
--- /dev/null
+++ b/banquise-website/src/index.css
@@ -0,0 +1,103 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+/* Système typographique moderne */
+:root {
+ --font-heading: 'Space Grotesk', sans-serif;
+ --font-body: 'Inter', system-ui, sans-serif;
+
+ font-family: var(--font-body);
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+/* Hiérarchie typographique */
+h1, h2, h3, h4, h5, h6, .site-name, .welcome-title {
+ font-family: var(--font-heading);
+ font-weight: 600;
+ line-height: 1.2;
+ letter-spacing: -0.025em;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+ font-weight: 700;
+}
+
+h2 {
+ font-size: 2.4em;
+ font-weight: 600;
+}
+
+h3 {
+ font-size: 1.8em;
+ font-weight: 600;
+}
+
+p, span, div, a, button, input {
+ font-family: var(--font-body);
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ padding: 0;
+ display: flex;
+ min-width: 320px;
+ min-height: 100vh;
+ width: 100%;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: var(--font-body);
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+
+button:hover {
+ border-color: #646cff;
+}
+
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/banquise-website/src/main.tsx b/banquise-website/src/main.tsx
new file mode 100644
index 0000000..bef5202
--- /dev/null
+++ b/banquise-website/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.tsx'
+
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/banquise-website/src/vite-env.d.ts b/banquise-website/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/banquise-website/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/banquise-website/tailwind.config.js b/banquise-website/tailwind.config.js
new file mode 100644
index 0000000..0bdb22b
--- /dev/null
+++ b/banquise-website/tailwind.config.js
@@ -0,0 +1,21 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ "./index.html",
+ "./src/**/*.{js,ts,jsx,tsx}",
+ ],
+ theme: {
+ extend: {
+ colors: {
+ // Vous pouvez personnaliser vos couleurs ici
+ },
+ fontFamily: {
+ // Personnalisation des polices
+ }
+ },
+ },
+ plugins: [
+ require('@tailwindcss/forms'),
+ require('@tailwindcss/typography'),
+ ],
+}
diff --git a/banquise-website/tsconfig.app.json b/banquise-website/tsconfig.app.json
new file mode 100644
index 0000000..c9ccbd4
--- /dev/null
+++ b/banquise-website/tsconfig.app.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/banquise-website/tsconfig.json b/banquise-website/tsconfig.json
new file mode 100644
index 0000000..1ffef60
--- /dev/null
+++ b/banquise-website/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/banquise-website/tsconfig.node.json b/banquise-website/tsconfig.node.json
new file mode 100644
index 0000000..9728af2
--- /dev/null
+++ b/banquise-website/tsconfig.node.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/banquise-website/vite.config.ts b/banquise-website/vite.config.ts
new file mode 100644
index 0000000..350511a
--- /dev/null
+++ b/banquise-website/vite.config.ts
@@ -0,0 +1,27 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+import viteCompression from 'vite-plugin-compression'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [
+ react(),
+ viteCompression({
+ verbose: false,
+ algorithm: 'gzip',
+ ext: '.gz',
+ }),
+ ],
+ build: {
+ minify: 'esbuild',
+ cssMinify: true,
+ rollupOptions: {
+ output: {
+ manualChunks: {
+ react: ['react', 'react-dom'],
+ router: ['react-router-dom'],
+ },
+ },
+ },
+ },
+})
diff --git a/la-banquise/assets/iceberg.svg b/la-banquise/assets/iceberg.svg
deleted file mode 100644
index f8a610e..0000000
--- a/la-banquise/assets/iceberg.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/la-banquise/index.html b/la-banquise/index.html
deleted file mode 100644
index 9ce3aed..0000000
--- a/la-banquise/index.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
- La Banquise
-
-
-
-
- La Banquise
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/la-banquise/script.js b/la-banquise/script.js
deleted file mode 100644
index 5bb84d8..0000000
--- a/la-banquise/script.js
+++ /dev/null
@@ -1,22 +0,0 @@
-const tile = document.querySelectorAll(".grid-container > *")[0];
-const parent = tile.parentNode;
-tile.remove();
-
-const tiles = [
- { name: "Notre wiki", href: "https://wiki.la-banquise.fr" },
- { name: "Notre git", href: "https://git.la-banquise.fr" },
- { name: "Panel jeux", href: "https://panel.la-banquise.fr" },
- { name: "Discord", href: "https://discord.gg/QQWwzX5ptY" },
- { name: "Login", href: "https://auth.la-banquise.fr" },
- { name: "Change password", href: "https://ssp.la-banquise.fr" },
-]
-
-tiles.forEach((info) => {
- const newTile = tile.cloneNode(true);
- newTile.querySelectorAll(".item-name").forEach((el) => {
- el.innerText = info.name;
- });
- newTile.href = info.href;
- parent.appendChild(newTile);
-});
-
diff --git a/la-banquise/style.css b/la-banquise/style.css
deleted file mode 100644
index 2feae16..0000000
--- a/la-banquise/style.css
+++ /dev/null
@@ -1,136 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=League+Spartan:wght@100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap');
-
-* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- font-family: Roboto, sans-serif;
-}
-
-body {
- margin: 0;
- padding: 30px;
- min-height: 100vh;
- background: linear-gradient(45deg, #001e6c, #5dadc2, #001e6c);
- background-size: 400% 400%;
- animation: gradient 100s ease infinite;
-}
-
-@keyframes gradient {
- 0% {
- background-position: 0% 50%;
- }
-
- 50% {
- background-position: 100% 50%;
- }
-
- 100% {
- background-position: 0% 50%;
- }
-}
-
-h1.title {
- display: flex;
- justify-content: center;
-}
-
-.hidden {
- visibility: hidden;
-}
-
-/* Style de la vague en bas de page */
-.wave {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- overflow: hidden;
- line-height: 0;
-}
-
-.wave svg {
- position: relative;
- display: block;
- width: calc(100% + 1.3px);
- height: 150px;
-}
-
-.wave .shape-fill {
- fill: rgba(255, 255, 255, 0.2);
-}
-
-.title {
- font-size: 2.5rem;
- margin-bottom: 2rem;
-}
-
-/* En-tête du site */
-header {
- text-align: center;
- color: #fff;
- padding: 1rem;
-}
-
-/* Container en flexbox pour agencer les éléments dans une "grid" */
-.grid-container {
- flex: 1;
- display: flex;
- flex-wrap: wrap;
- justify-content: center;
- align-items: stretch;
- gap: 20px;
- padding: 1rem;
-}
-
-/* Chaque élément de la grid */
-.grid-item {
- background: rgba(255, 255, 255, 0);
- padding: 2px;
- border-radius: 8px;
- color: #fff;
- text-align: center;
- /* Permet de s'étendre sur au moins 300px et de grandir si besoin */
- flex: 0 1 calc(10% - 40px);
- /* 3 items par ligne avec 20px de gap */
- max-width: calc(10% - 40px);
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0);
- transition: transform 0.3s;
-}
-
-.grid-item:hover {
- transform: scale(1.05);
- background: rgba(255, 255, 255, 0.1);
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
-}
-
-.grid-item img,
-.grid-item object {
- max-width: 100%;
- height: auto;
- display: block;
- margin: 0 auto 10px;
- /* Pour donner une vue isométrique */
- transform: rotateX(0deg) rotateZ(0deg);
- transform-origin: center;
-}
-
-.grid-item p {
- font-size: 1.5rem;
- margin-top: 0rem;
- font-weight: bold;
-}
-
-@media (max-width: 900px) {
- .grid-item {
- flex: 0 1 calc(25% - 40px);
- max-width: calc(25% - 40px);
- }
-}
-
-@media (max-width: 600px) {
- .grid-item {
- flex: 0 1 calc(50% - 40px);
- max-width: calc(50% - 40px);
- }
-}
\ No newline at end of file