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) => ( ) : (