diff --git a/Frontend/package-lock.json b/Frontend/package-lock.json
index 1e96e5a..eaddc74 100755
--- a/Frontend/package-lock.json
+++ b/Frontend/package-lock.json
@@ -14,7 +14,6 @@
"react-helmet": "^6.1.0",
"react-lottie-player": "^1.5.5",
"react-router-dom": "^6.19.0",
- "sass": "^1.69.5",
"tailwindcss": "^4.2.2",
"zustand": "^5.0.12"
},
@@ -1033,9 +1032,11 @@
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
+ "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"detect-libc": "^2.0.3",
"is-glob": "^4.0.3",
@@ -1072,11 +1073,13 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1092,11 +1095,13 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1112,11 +1117,13 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1132,11 +1139,13 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1152,11 +1161,13 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1172,11 +1183,13 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1192,11 +1205,13 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1212,11 +1227,13 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1232,11 +1249,13 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1252,11 +1271,13 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1272,11 +1293,13 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1292,11 +1315,13 @@
"cpu": [
"ia32"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -1312,11 +1337,13 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">= 10.0.0"
},
@@ -2579,6 +2606,8 @@
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"readdirp": "^4.0.1"
},
@@ -3600,7 +3629,9 @@
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
"integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/import-fresh": {
"version": "3.3.0",
@@ -3757,7 +3788,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "devOptional": true,
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3793,7 +3824,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -4442,8 +4473,10 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
"license": "MIT",
- "optional": true
+ "optional": true,
+ "peer": true
},
"node_modules/node-releases": {
"version": "2.0.13",
@@ -4685,7 +4718,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -4885,6 +4918,8 @@
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">= 14.18.0"
},
@@ -5114,6 +5149,8 @@
"resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz",
"integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==",
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.1.5",
diff --git a/Frontend/package.json b/Frontend/package.json
index 36ad1c2..b1eddf8 100755
--- a/Frontend/package.json
+++ b/Frontend/package.json
@@ -17,7 +17,6 @@
"react-helmet": "^6.1.0",
"react-lottie-player": "^1.5.5",
"react-router-dom": "^6.19.0",
- "sass": "^1.69.5",
"tailwindcss": "^4.2.2",
"zustand": "^5.0.12"
},
diff --git a/Frontend/src/App.jsx b/Frontend/src/App.jsx
index 72d0f30..b9ed1bd 100755
--- a/Frontend/src/App.jsx
+++ b/Frontend/src/App.jsx
@@ -6,10 +6,6 @@ import Footer from "./components/footer";
import { GameTick } from "./components/GameTick";
import { GameSync } from "./components/GameSync";
-import "./scss/root.scss";
-import "./scss/zones.scss";
-import "./scss/components/footer.scss";
-
import navData from "./data/NavBarData.json";
function App() {
diff --git a/Frontend/src/components/EvolutionTree.tsx b/Frontend/src/components/EvolutionTree.tsx
index 1a913b1..8d2a99d 100644
--- a/Frontend/src/components/EvolutionTree.tsx
+++ b/Frontend/src/components/EvolutionTree.tsx
@@ -29,7 +29,7 @@ function NodeRow({
return (
-
+
{node.name}
{EFFECT_LABELS[node.effect](node.value)}
@@ -39,8 +39,7 @@ function NodeRow({
@@ -58,7 +57,7 @@ export function EvolutionTree() {
return (
-
+
Évolution
{state.ancestralDna} ADN
diff --git a/Frontend/src/components/GeneratorShop.tsx b/Frontend/src/components/GeneratorShop.tsx
index ed4301a..70bfa74 100644
--- a/Frontend/src/components/GeneratorShop.tsx
+++ b/Frontend/src/components/GeneratorShop.tsx
@@ -12,7 +12,7 @@ export function GeneratorShop() {
return (
-
+
Générateurs
{formatNumber(productionPerSecond)}/s
@@ -26,8 +26,8 @@ export function GeneratorShop() {
key={gen.id}
className={`gp-row ${canAfford ? "gp-row--active" : "gp-row--locked"}`}
>
-
-
+
+
{gen.name}
{gen.owned > 0 && (
x{gen.owned}
diff --git a/Frontend/src/components/MilestoneBar.tsx b/Frontend/src/components/MilestoneBar.tsx
index a689256..ef7ca62 100644
--- a/Frontend/src/components/MilestoneBar.tsx
+++ b/Frontend/src/components/MilestoneBar.tsx
@@ -13,8 +13,8 @@ export function MilestoneBar() {
const remaining = Math.max(PRESTIGE_THRESHOLD - resources, 0);
return (
-
-
+
+
Prochaine Génération
{formatNumber(resources)} / {formatNumber(PRESTIGE_THRESHOLD)}
@@ -22,14 +22,11 @@ export function MilestoneBar() {
-
+
{remaining > 0
? `${formatNumber(remaining)} restants`
: "Nouvelle Génération disponible !"}
diff --git a/Frontend/src/components/PrestigePanel.tsx b/Frontend/src/components/PrestigePanel.tsx
index 9948d3e..8a0c2ea 100644
--- a/Frontend/src/components/PrestigePanel.tsx
+++ b/Frontend/src/components/PrestigePanel.tsx
@@ -26,7 +26,7 @@ export function PrestigePanel() {
Prestige
{canPrestige ? (
-
+
+{dnaPreview} ADN · +0.1x mult
diff --git a/Frontend/src/components/burger.jsx b/Frontend/src/components/burger.jsx
index e0d7fab..4ce832d 100755
--- a/Frontend/src/components/burger.jsx
+++ b/Frontend/src/components/burger.jsx
@@ -1,8 +1,5 @@
import { NavLink as Link } from "react-router-dom";
import PropTypes from "prop-types";
-import "../scss/components/navbar.scss";
-
-import "../scss/root.scss";
import PrimaryButton from "./buttons/PrimaryButton";
export default function Burger({ navData }) {
diff --git a/Frontend/src/components/buttons/PrimaryButton.jsx b/Frontend/src/components/buttons/PrimaryButton.jsx
index f1a415b..506fea3 100755
--- a/Frontend/src/components/buttons/PrimaryButton.jsx
+++ b/Frontend/src/components/buttons/PrimaryButton.jsx
@@ -1,5 +1,4 @@
import PropTypes from "prop-types";
-import "../../scss/components/buttons.scss";
import { Link } from "react-router-dom";
export default function PrimaryButton({ btnText, btnLink }) {
diff --git a/Frontend/src/components/buttons/SecondaryButton.jsx b/Frontend/src/components/buttons/SecondaryButton.jsx
index 1a36e0b..34e96a5 100755
--- a/Frontend/src/components/buttons/SecondaryButton.jsx
+++ b/Frontend/src/components/buttons/SecondaryButton.jsx
@@ -1,4 +1,3 @@
-import "../../scss/components/buttons.scss";
import PropTypes from "prop-types";
import { Link } from "react-router";
diff --git a/Frontend/src/components/footer.jsx b/Frontend/src/components/footer.jsx
index 6586220..8e6b055 100755
--- a/Frontend/src/components/footer.jsx
+++ b/Frontend/src/components/footer.jsx
@@ -1,4 +1,3 @@
-import "../scss/components/footer.scss";
import { NavLink as Link } from "react-router-dom";
export default function Footer() {
diff --git a/Frontend/src/components/navbar.jsx b/Frontend/src/components/navbar.jsx
index 3895b26..591551e 100755
--- a/Frontend/src/components/navbar.jsx
+++ b/Frontend/src/components/navbar.jsx
@@ -1,9 +1,6 @@
import { NavLink as Link } from "react-router-dom";
import PropTypes from "prop-types";
-import "../scss/components/navbar.scss";
-import "../scss/root.scss";
-
import PrimaryButton from "./buttons/PrimaryButton";
import Burger from "./burger";
import { useAuth } from "../context/AuthContext";
diff --git a/Frontend/src/index.css b/Frontend/src/index.css
index 2c653ff..e77c071 100755
--- a/Frontend/src/index.css
+++ b/Frontend/src/index.css
@@ -1,12 +1,979 @@
-@import "tailwindcss";
-
-:root {
- margin: 0;
- padding: 0;
-
-}
-::-webkit-scrollbar {
- width: 1px;
- display: none;
-
-}
\ No newline at end of file
+@import "tailwindcss";
+
+/* ── Tailwind v4 theme — tokens du jeu ── */
+@theme {
+ /* Base colors */
+ --color-blue-light: #dcecf3;
+ --color-purple-light: #e4e3f3;
+ --color-red-light: #c33636;
+ --color-light: #eaeaea;
+ --color-grey: #202020;
+ --color-grey-hover: #606060;
+
+ /* Game panel tokens */
+ --color-gp-bg: rgba(17, 17, 17, 0.75);
+ --color-gp-bg-hover: rgba(17, 17, 17, 0.85);
+ --color-gp-border: rgba(255, 255, 255, 0.08);
+ --color-gp-text: rgba(255, 255, 255, 0.9);
+ --color-gp-text-muted: rgba(255, 255, 255, 0.5);
+ --color-gp-accent-green: #34d399;
+ --color-gp-accent-purple: #a78bfa;
+ --color-gp-accent-amber: #fbbf24;
+ --color-gp-accent-green-bg: rgba(16, 185, 129, 0.12);
+ --color-gp-accent-purple-bg: rgba(139, 92, 246, 0.12);
+ --color-gp-accent-amber-bg: rgba(251, 191, 36, 0.12);
+ --color-gp-btn: #059669;
+ --color-gp-btn-hover: #10b981;
+ --color-gp-btn-disabled: rgba(255, 255, 255, 0.08);
+ --color-gp-btn-text-disabled: rgba(255, 255, 255, 0.3);
+
+ /* Spacing / sizing tokens */
+ --radius-gp: 0.75rem;
+ --spacing-gp: 0.75rem;
+ --spacing-gp-gap: 0.5rem;
+
+ /* Font sizes */
+ --font-size-gp-title: 0.8rem;
+ --font-size-gp-text: 0.75rem;
+ --font-size-gp-sm: 0.65rem;
+
+ /* Animation */
+ --animate-gp-pulse: gp-pulse 2s ease-in-out infinite;
+}
+
+@keyframes gp-pulse {
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.4); }
+ 50% { box-shadow: 0 0 0 6px rgba(124, 58, 237, 0); }
+}
+
+/* ── Global reset & base ── */
+@layer base {
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ user-select: none;
+ }
+
+ :root {
+ --font: "Hanken Grotesk", sans-serif;
+ --bg-color: var(--color-blue-light);
+ }
+
+ a {
+ text-decoration: none;
+ }
+
+ main {
+ min-height: 92vh;
+ margin-top: 80px;
+ padding: 0 0 2rem;
+ background-color: var(--bg-color);
+ }
+
+ ::-webkit-scrollbar {
+ width: 1px;
+ display: none;
+ }
+}
+
+/* ── Zone system (biomes) ── */
+@layer components {
+ .zone {
+ width: 100%;
+ min-height: 92vh;
+ position: relative;
+ display: flex;
+ align-items: flex-end;
+ justify-content: center;
+ background-size: cover;
+ background-repeat: no-repeat;
+ transition: background-image 0.5s ease;
+ }
+
+ [data-zone="swamp"] {
+ background-image: url("/webp/bg-cover.webp");
+ background-position: center 70%;
+ }
+
+ [data-zone="landing"] {
+ background: var(--bg-color);
+ align-items: center;
+ }
+
+ [data-zone="page"] {
+ background: var(--bg-color);
+ align-items: flex-start;
+ min-height: auto;
+ }
+
+ /* ── Game panels design system ── */
+
+ .gp {
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-gp-gap);
+ padding: var(--spacing-gp);
+ background: var(--color-gp-bg);
+ backdrop-filter: blur(8px);
+ border: 1px solid var(--color-gp-border);
+ border-radius: var(--radius-gp);
+ }
+
+ .gp-title {
+ font-family: var(--font);
+ font-size: var(--font-size-gp-title);
+ font-weight: 700;
+ color: var(--color-gp-text);
+ letter-spacing: 0.02em;
+ text-transform: uppercase;
+ }
+
+ .gp-label {
+ font-family: var(--font);
+ font-size: var(--font-size-gp-sm);
+ font-weight: 500;
+ color: var(--color-gp-text-muted);
+ }
+
+ .gp-value {
+ font-family: var(--font);
+ font-size: var(--font-size-gp-text);
+ font-weight: 600;
+ color: var(--color-gp-text);
+ }
+
+ .gp-accent-green { color: var(--color-gp-accent-green); }
+ .gp-accent-purple { color: var(--color-gp-accent-purple); }
+ .gp-accent-amber { color: var(--color-gp-accent-amber); }
+
+ /* Row item (générateur, noeud évolution) */
+ .gp-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.4rem;
+ padding: 0.4rem 0.5rem;
+ border-radius: calc(var(--radius-gp) - 0.15rem);
+ border: 1px solid transparent;
+ transition: background 0.15s ease, border-color 0.15s ease;
+ }
+
+ .gp-row--active {
+ border-color: rgba(16, 185, 129, 0.3);
+ background: var(--color-gp-accent-green-bg);
+ }
+ .gp-row--active:hover {
+ background: rgba(16, 185, 129, 0.18);
+ }
+
+ .gp-row--locked {
+ border-color: var(--color-gp-border);
+ background: rgba(255, 255, 255, 0.02);
+ opacity: 0.5;
+ }
+
+ .gp-row--evolution {
+ border-color: rgba(251, 191, 36, 0.3);
+ background: var(--color-gp-accent-amber-bg);
+ }
+
+ .gp-row--unlocked {
+ border-color: rgba(16, 185, 129, 0.3);
+ background: var(--color-gp-accent-green-bg);
+ }
+
+ /* Bouton achat */
+ .gp-btn {
+ font-family: var(--font);
+ font-size: var(--font-size-gp-sm);
+ font-weight: 600;
+ padding: 0.3rem 0.6rem;
+ border-radius: 0.4rem;
+ border: none;
+ cursor: pointer;
+ transition: background 0.15s ease;
+ white-space: nowrap;
+ }
+
+ .gp-btn--buy {
+ background: var(--color-gp-btn);
+ color: white;
+ }
+ .gp-btn--buy:hover {
+ background: var(--color-gp-btn-hover);
+ }
+
+ .gp-btn--disabled {
+ background: var(--color-gp-btn-disabled);
+ color: var(--color-gp-btn-text-disabled);
+ cursor: not-allowed;
+ }
+
+ .gp-btn--prestige {
+ background: #7c3aed;
+ color: white;
+ padding: 0.4rem 0.8rem;
+ font-size: var(--font-size-gp-text);
+ animation: var(--animate-gp-pulse);
+ }
+ .gp-btn--prestige:hover {
+ background: #8b5cf6;
+ }
+
+ /* Header cockpit (stats résumé) */
+ .gp-cockpit-header {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: 0.2rem;
+ padding: 0.5rem;
+ }
+
+ .gp-stat {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.05rem;
+ }
+
+ /* Progress bar */
+ .gp-progress {
+ height: 0.35rem;
+ background: rgba(255, 255, 255, 0.08);
+ border-radius: 1rem;
+ overflow: hidden;
+ }
+
+ .gp-progress-fill {
+ height: 100%;
+ border-radius: 1rem;
+ transition: width 0.5s ease;
+ }
+
+ /* Section separator */
+ .gp-sep {
+ height: 1px;
+ background: var(--color-gp-border);
+ margin: 0.15rem 0;
+ }
+
+ /* Zone titles in sidebar */
+ .gp-zone-label {
+ font-family: var(--font);
+ font-size: var(--font-size-gp-sm);
+ font-weight: 600;
+ color: var(--color-gp-text-muted);
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+ padding-left: 0.2rem;
+ }
+
+ /* ── Home / Game view ── */
+
+ .click-zone {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 1rem;
+ padding-bottom: 2vh;
+ cursor: pointer;
+ flex: 1;
+ }
+ @media (min-width: 768px) {
+ .click-zone {
+ padding-right: 22rem;
+ }
+ }
+
+ .tadpole-sprite {
+ width: 280px;
+ height: 280px;
+ background: url("/svg/tadpole.svg") no-repeat center / contain;
+ transition: transform 0.1s ease;
+ }
+ @media (min-width: 768px) {
+ .tadpole-sprite {
+ width: 320px;
+ height: 320px;
+ }
+ }
+ .click-zone:active .tadpole-sprite {
+ transform: scale(0.95) rotate(2deg);
+ }
+
+ .click-zone-counter {
+ font-family: var(--font);
+ font-size: 2rem;
+ font-weight: 800;
+ color: white;
+ text-shadow: 0 0 12px rgba(52, 211, 153, 0.5), 0 2px 6px rgba(0, 0, 0, 0.7);
+ pointer-events: none;
+ user-select: none;
+ letter-spacing: 0.02em;
+ }
+ @media (min-width: 768px) {
+ .click-zone-counter {
+ font-size: 2.5rem;
+ }
+ }
+
+ .achieve-badge {
+ display: block;
+ text-align: center;
+ padding: 0.4rem;
+ border-radius: var(--radius-gp);
+ background: var(--color-gp-accent-green-bg);
+ border: 1px solid rgba(16, 185, 129, 0.2);
+ font-family: var(--font);
+ font-size: var(--font-size-gp-sm);
+ font-weight: 600;
+ color: var(--color-gp-accent-green);
+ text-decoration: none;
+ transition: all 0.15s ease;
+ }
+ .achieve-badge:hover {
+ background: rgba(16, 185, 129, 0.2);
+ }
+
+ .click-particle {
+ position: fixed;
+ pointer-events: none;
+ font-family: var(--font);
+ font-size: 1.6rem;
+ font-weight: 800;
+ color: #34d399;
+ text-shadow: 0 0 8px rgba(52, 211, 153, 0.6), 0 2px 4px rgba(0, 0, 0, 0.7);
+ z-index: 100;
+ animation: float-up 1.2s ease-out forwards;
+ }
+
+ .game-sidebar {
+ position: fixed;
+ right: 0.75rem;
+ top: 5.5rem;
+ bottom: 0.75rem;
+ width: 20rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+ overflow-y: auto;
+ z-index: 10;
+ padding-right: 0.25rem;
+ }
+ @media (max-width: 767px) {
+ .game-sidebar {
+ right: 0;
+ left: 0;
+ top: auto;
+ bottom: 0;
+ width: 100%;
+ max-height: 45vh;
+ padding: 0.75rem;
+ background: rgba(0, 0, 0, 0.85);
+ backdrop-filter: blur(8px);
+ border-top-left-radius: 1rem;
+ border-top-right-radius: 1rem;
+ }
+ }
+}
+
+@keyframes float-up {
+ 0% {
+ opacity: 1;
+ transform: translateY(0) scale(1.2);
+ }
+ 60% {
+ opacity: 0.9;
+ }
+ 100% {
+ opacity: 0;
+ transform: translateY(-80px) scale(1.5);
+ }
+}
+
+/* ── Navbar ── */
+@layer components {
+ .header-main {
+ display: flex;
+ justify-content: space-between;
+ position: absolute;
+ width: 100%;
+ height: 80px;
+ padding: 0 2rem;
+ top: 0;
+ background-color: var(--bg-color);
+ background-blend-mode: darken;
+ background-size: cover;
+ z-index: 99;
+ box-sizing: border-box;
+ }
+ @media (max-width: 999px) {
+ .header-main {
+ padding: 0 0.4rem;
+ }
+ }
+
+ .logo {
+ width: 5rem;
+ content: url(/svg/tadpole.svg);
+ transition: 0.2s;
+ }
+ .logo:hover {
+ transform: scale(0.9);
+ }
+
+ .navbar {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 1rem;
+ box-sizing: border-box;
+ cursor: pointer;
+ }
+
+ .nav-list {
+ display: flex;
+ justify-content: space-between;
+ gap: 1.6rem;
+ align-items: center;
+ list-style-type: none;
+ }
+ @media (max-width: 999px) {
+ .nav-list {
+ display: none;
+ }
+ }
+
+ .nav-list li {
+ list-style: none;
+ font-family: var(--font);
+ font-weight: 300;
+ font-size: 1rem;
+ color: white;
+ float: left;
+ width: fit-content;
+ }
+
+ .mainLink {
+ text-decoration: none;
+ color: var(--color-grey);
+ font-weight: 500;
+ padding: 30px 0;
+ }
+ .mainLink:hover {
+ color: var(--color-red-light);
+ }
+
+ .dropLink {
+ text-decoration: none;
+ color: white;
+ font-weight: 400;
+ }
+ .dropLink:hover {
+ color: var(--color-red-light);
+ }
+
+ .dropdown-content {
+ display: none;
+ position: absolute;
+ background: var(--color-grey);
+ transform: translateY(30px);
+ min-width: 160px;
+ box-shadow: 0 8px 16px rgba(10, 10, 10, 0.2);
+ z-index: 1;
+ }
+ .dropdown-content a {
+ color: white;
+ padding: 12px 16px;
+ text-decoration: none;
+ display: block;
+ text-align: left;
+ }
+ .dropdown-content a:hover {
+ background-color: var(--color-grey-hover);
+ }
+ .dropdown:hover .dropdown-content {
+ display: block;
+ }
+
+ .auth-nav {
+ display: flex;
+ align-items: center;
+ gap: 0.6rem;
+ font-family: var(--font);
+ }
+ .auth-nickname {
+ font-size: 0.9rem;
+ font-weight: 500;
+ color: var(--color-grey);
+ }
+ .auth-btn {
+ padding: 0.3rem 0.8rem;
+ border: 1px solid var(--color-grey);
+ border-radius: 0.4rem;
+ background: none;
+ font-family: var(--font);
+ font-size: 0.8rem;
+ color: var(--color-grey);
+ cursor: pointer;
+ transition: all 0.15s ease;
+ }
+ .auth-btn:hover {
+ background: var(--color-grey);
+ color: white;
+ }
+
+ /* ── Burger menu (mobile) ── */
+ @media (min-width: 1000px) {
+ .menuToggle {
+ display: none;
+ }
+ }
+}
+
+@media (max-width: 999px) {
+ .menuToggle {
+ float: left;
+ position: relative;
+ box-sizing: border-box;
+ top: 2px;
+ left: -10px;
+ z-index: 99;
+ user-select: none;
+ }
+ .menuToggle a {
+ text-decoration: none;
+ color: var(--color-grey);
+ transition: color 0.3s ease;
+ }
+ .menuToggle a:hover {
+ color: var(--color-red-light);
+ }
+ .menuToggle input {
+ display: block;
+ width: 40px;
+ height: 32px;
+ position: absolute;
+ top: -7px;
+ left: -5px;
+ cursor: pointer;
+ opacity: 0;
+ z-index: 2;
+ }
+ .menuToggle span {
+ display: block;
+ width: 33px;
+ height: 4px;
+ margin-bottom: 5px;
+ position: relative;
+ background: var(--color-grey);
+ border-radius: 3px;
+ z-index: 1;
+ transform-origin: 4px 0;
+ transition: transform 0.2s cubic-bezier(0.77, 0.2, 0.05, 1),
+ background 0.2s cubic-bezier(0.77, 0.2, 0.05, 1), opacity 0.55s ease;
+ }
+ .menuToggle span:first-child {
+ transform-origin: 0% 0%;
+ }
+ .menuToggle span:nth-last-child(2) {
+ transform-origin: 0% 100%;
+ }
+ .menuToggle input:checked ~ span {
+ opacity: 1;
+ transform: rotate(45deg) translate(-2px, -1px);
+ background: white;
+ }
+ .menuToggle input:checked ~ span:nth-last-child(3) {
+ opacity: 0;
+ transform: rotate(0deg) scale(0.2, 0.2);
+ }
+ .menuToggle input:checked ~ span:nth-last-child(2) {
+ transform: rotate(-45deg) translate(0, -1px);
+ }
+ .menu {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ width: 280px;
+ height: 110vh;
+ margin: -100px 0 0 -231px;
+ padding: 1.2rem;
+ padding-top: 100px;
+ background: var(--color-grey);
+ list-style-type: none;
+ transform-origin: 0% 0%;
+ overflow: hidden;
+ visibility: hidden;
+ opacity: 0;
+ transition: opacity 0.2s ease, visibility 0.2s ease;
+ }
+ .menu li {
+ padding: 10px 0;
+ font-size: 1.2rem;
+ font-family: var(--font);
+ font-weight: 500;
+ color: white;
+ }
+ .menuToggle input:checked ~ ul {
+ visibility: visible;
+ opacity: 1;
+ }
+ .sousmenu {
+ display: flex;
+ flex-direction: column;
+ margin-left: 1.2rem;
+ color: white;
+ font-size: 1.2rem;
+ font-family: var(--font);
+ font-weight: 500;
+ padding-bottom: 1rem;
+ }
+}
+
+/* ── Buttons ── */
+@layer components {
+ .primary-button {
+ display: flex;
+ padding: 0.6rem 1rem;
+ height: fit-content;
+ background-color: var(--color-red-light);
+ border-radius: 0.6rem;
+ justify-content: center;
+ text-decoration: none;
+ font-family: var(--font);
+ color: white !important;
+ text-align: center;
+ font-size: 1rem;
+ font-weight: 400;
+ transition: transform 0.1s ease-in-out;
+ border: none;
+ }
+ .primary-button:hover {
+ transform: scale(0.95);
+ }
+
+ .secondary-button {
+ display: flex;
+ padding: 1rem;
+ background-color: white;
+ border-radius: 0.6rem;
+ justify-content: center;
+ width: fit-content;
+ height: fit-content;
+ text-decoration: none;
+ font-family: var(--font);
+ color: var(--color-grey) !important;
+ text-align: center;
+ font-size: 1rem;
+ transition: transform 0.1s ease-in-out;
+ border: none;
+ }
+ .secondary-button:hover {
+ transform: scale(0.95);
+ background-color: var(--color-grey-hover);
+ }
+}
+
+/* ── Footer ── */
+@layer components {
+ .footer {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ align-items: center;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ background-color: var(--bg-color);
+ border-top: solid 1px var(--color-grey);
+ padding: 2rem 0;
+ gap: 2rem;
+ }
+ .footer-container {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ width: 90%;
+ gap: 2rem;
+ }
+ .footer-logo {
+ background-image: url(/svg/tadpole.svg);
+ background-size: contain;
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 250px;
+ height: 100px;
+ transition: all 0.15s ease-in-out;
+ }
+ .footer-logo:hover {
+ transform: scale(0.9);
+ }
+ .footer .section {
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ gap: 1.4rem;
+ }
+ .section-title {
+ font-family: var(--font);
+ font-size: 1.2rem;
+ color: var(--color-grey);
+ text-decoration-line: underline;
+ text-underline-offset: 0.5rem;
+ }
+ .section-text {
+ max-width: 26ch;
+ font-family: var(--font);
+ font-size: 1rem;
+ color: var(--color-grey);
+ }
+ .section-list {
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ gap: 1rem;
+ list-style: none;
+ }
+ .section-list .section-item,
+ .section-list a {
+ width: fit-content;
+ font-family: var(--font);
+ font-size: 1rem;
+ color: var(--color-grey);
+ transition: all 0.15s ease-in-out;
+ }
+ .section-list .section-item:hover,
+ .section-list a:hover {
+ transform: scale(0.9);
+ }
+ .spacing {
+ min-width: 150px;
+ width: 10%;
+ }
+ .footer-github {
+ font-family: var(--font);
+ font-size: 0.9rem;
+ font-weight: 500;
+ color: var(--color-grey);
+ text-decoration: none;
+ transition: all 0.15s ease-in-out;
+ }
+ .footer-github:hover {
+ transform: scale(0.95);
+ }
+ .copyright {
+ font-family: var(--font);
+ font-size: 0.8rem;
+ font-weight: 300;
+ color: var(--color-grey);
+ text-align: center;
+ }
+
+ /* ── Pages layout (error, legal, settings, login) ── */
+
+ .container {
+ display: flex;
+ flex-direction: column;
+ max-width: 132ch;
+ width: 80%;
+ gap: 3rem;
+ margin: 150px auto 50px;
+ }
+ .container h1 {
+ font-family: var(--font);
+ color: var(--color-grey);
+ font-size: 1.8rem;
+ text-align: center;
+ width: fit-content;
+ }
+ .container h2 {
+ font-family: var(--font);
+ font-size: 2rem;
+ font-weight: 600;
+ color: var(--color-grey);
+ }
+ .container .subtitle {
+ font-family: var(--font);
+ color: var(--color-grey);
+ font-size: 1.2rem;
+ font-weight: 600;
+ text-align: left;
+ margin-bottom: 0.8rem;
+ }
+ .container .content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.6rem;
+ }
+ .container .paragraphe {
+ font-family: var(--font);
+ color: var(--color-grey);
+ font-size: 1rem;
+ font-weight: 400;
+ margin-bottom: 0.5rem;
+ list-style: inside;
+ }
+ .container .info {
+ font-family: var(--font);
+ color: var(--color-grey);
+ font-size: 1rem;
+ font-weight: 400;
+ }
+
+ section {
+ display: flex;
+ flex-direction: column;
+ height: 90vh;
+ justify-content: center;
+ width: 100%;
+ }
+ .containererror {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2rem;
+ }
+ .containererror h1 {
+ font-family: var(--font);
+ color: var(--color-grey);
+ font-size: 2rem;
+ text-align: center;
+ width: fit-content;
+ }
+ .message {
+ font-family: var(--font);
+ color: var(--color-grey);
+ font-size: 1rem;
+ font-weight: 300;
+ text-align: center;
+ }
+ .btn-return {
+ display: flex;
+ justify-content: center;
+ width: fit-content;
+ margin: auto;
+ padding: 0.5rem 1rem;
+ background-color: var(--color-grey);
+ border: none;
+ border-radius: 0.6rem;
+ font-family: var(--font);
+ color: white;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ }
+ .btn-return:hover {
+ transform: scale(0.9);
+ }
+
+ /* ── Achievements ── */
+
+ .fullachieve {
+ display: flex;
+ flex-direction: column;
+ padding-top: 6rem;
+ padding-bottom: 3rem;
+ background-color: var(--color-blue-light);
+ width: 100%;
+ max-width: 1280px;
+ margin: 0 auto;
+ min-height: 80vh;
+ }
+ .fullachieve h1 {
+ text-align: center;
+ font-family: var(--font);
+ font-size: 2.5rem;
+ color: var(--color-grey);
+ margin-bottom: 0.5rem;
+ }
+ .achieve-counter {
+ text-align: center;
+ font-family: var(--font);
+ font-size: 1.1rem;
+ color: var(--color-grey);
+ opacity: 0.7;
+ margin-bottom: 2rem;
+ }
+ .achievementscontainer {
+ margin: auto;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ padding: 0 2rem;
+ }
+ .achievementscardcontainer {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ min-height: 200px;
+ gap: 1rem;
+ width: 100%;
+ }
+ .achieve-card {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ padding: 1rem 1.2rem;
+ border-radius: 0.75rem;
+ width: 100%;
+ max-width: 380px;
+ transition: transform 0.15s ease;
+ }
+ .achieve-card:hover {
+ transform: translateY(-2px);
+ }
+ .achieve-unlocked {
+ background: rgba(16, 185, 129, 0.12);
+ border: 1px solid rgba(16, 185, 129, 0.3);
+ }
+ .achieve-locked {
+ background: rgba(107, 114, 128, 0.08);
+ border: 1px solid rgba(107, 114, 128, 0.15);
+ opacity: 0.5;
+ }
+ .achieve-icon {
+ font-size: 2rem;
+ flex-shrink: 0;
+ width: 3rem;
+ text-align: center;
+ }
+ .achieve-info {
+ display: flex;
+ flex-direction: column;
+ gap: 0.2rem;
+ }
+ .achieve-name {
+ font-family: var(--font);
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--color-grey);
+ }
+ .achieve-desc {
+ font-family: var(--font);
+ font-size: 0.85rem;
+ color: var(--color-grey);
+ opacity: 0.7;
+ }
+
+ /* ── Legal / Cookie pages ── */
+
+ .mentionslegales {
+ width: 100%;
+ margin: 0 auto;
+ max-width: 1280px;
+ font-family: var(--font);
+ display: flex;
+ flex-direction: column;
+ gap: 3rem;
+ padding: 15rem 1rem 4rem;
+ }
+ .mentionslegales h2 {
+ font-family: var(--font);
+ font-size: 2rem;
+ font-weight: 600;
+ color: var(--color-grey);
+ }
+}
diff --git a/Frontend/src/main.jsx b/Frontend/src/main.jsx
index 0a0123d..6e3bf40 100755
--- a/Frontend/src/main.jsx
+++ b/Frontend/src/main.jsx
@@ -1,5 +1,6 @@
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
+import "./index.css";
import App from "./App";
import Landing from "./pages/Landing";
import Home from "./pages/Home";
diff --git a/Frontend/src/pages/404.jsx b/Frontend/src/pages/404.jsx
index ff71cbe..c021e1d 100755
--- a/Frontend/src/pages/404.jsx
+++ b/Frontend/src/pages/404.jsx
@@ -1,5 +1,4 @@
import { Link } from "react-router-dom";
-import "../scss/pages.scss";
import Lottie from "react-lottie-player";
import animation404 from "../data/404-animation.json";
diff --git a/Frontend/src/pages/Achievements.jsx b/Frontend/src/pages/Achievements.jsx
index 8168641..b7acbfb 100755
--- a/Frontend/src/pages/Achievements.jsx
+++ b/Frontend/src/pages/Achievements.jsx
@@ -1,6 +1,5 @@
import { useGameStore } from "../store/useGameStore";
import { ACHIEVEMENTS } from "../data/achievements";
-import "../scss/achievements.scss";
function Achievements() {
const state = useGameStore((s) => s.state);
diff --git a/Frontend/src/pages/AuthCallback.jsx b/Frontend/src/pages/AuthCallback.jsx
index fb84ddc..aaf77e6 100644
--- a/Frontend/src/pages/AuthCallback.jsx
+++ b/Frontend/src/pages/AuthCallback.jsx
@@ -3,7 +3,6 @@ import { useNavigate, Link } from "react-router-dom";
import { exchangeCode, loadVerifier, clearVerifier } from "../lib/oauth";
import { apiFetch } from "../lib/api";
import { useAuth } from "../context/AuthContext";
-import "../scss/pages.scss";
export default function AuthCallback() {
const navigate = useNavigate();
diff --git a/Frontend/src/pages/Cookie.jsx b/Frontend/src/pages/Cookie.jsx
index 4e1b317..204966e 100755
--- a/Frontend/src/pages/Cookie.jsx
+++ b/Frontend/src/pages/Cookie.jsx
@@ -1,4 +1,3 @@
-import "../scss/Cookie.scss";
function Cookie() {
return (
diff --git a/Frontend/src/pages/Home.jsx b/Frontend/src/pages/Home.jsx
index edef6f7..14cae96 100755
--- a/Frontend/src/pages/Home.jsx
+++ b/Frontend/src/pages/Home.jsx
@@ -11,8 +11,6 @@ import { EvolutionTree } from "../components/EvolutionTree";
import { MilestoneBar } from "../components/MilestoneBar";
import { CockpitHeader } from "../components/CockpitHeader";
import { ACHIEVEMENTS } from "../data/achievements";
-import "../scss/home.scss";
-import "../scss/components/game-panels.scss";
export default function Home() {
const [toggleRain] = useOutletContext();
@@ -113,7 +111,7 @@ export default function Home() {
if (!ready) {
return (
-
+
Chargement de ta progression...
diff --git a/Frontend/src/pages/Legal.jsx b/Frontend/src/pages/Legal.jsx
index 51569c6..0de07c8 100755
--- a/Frontend/src/pages/Legal.jsx
+++ b/Frontend/src/pages/Legal.jsx
@@ -1,4 +1,3 @@
-import "../scss/Legal.scss";
function Legal() {
return (
diff --git a/Frontend/src/pages/Login.jsx b/Frontend/src/pages/Login.jsx
index 2220e9b..0b24e9a 100644
--- a/Frontend/src/pages/Login.jsx
+++ b/Frontend/src/pages/Login.jsx
@@ -2,7 +2,6 @@ import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
import { buildAuthUrl, saveVerifier } from "../lib/oauth";
-import "../scss/pages.scss";
const PROVIDERS = [
{ id: "discord", label: "Discord", emoji: "🎮" },
@@ -31,7 +30,7 @@ export default function Login() {
Connexion
Connecte-toi pour sauvegarder ta progression.
-
+
{PROVIDERS.map((p) => (