feat: migrate SCSS → Tailwind CSS + remove sass dependency

12 SCSS files (1167 lines) replaced by centralized index.css with
Tailwind v4 @theme tokens, @layer components, and utility classes.
Game panel design system (gp-*) preserved as CSS components.
Inline styles in Settings/Login/MilestoneBar converted to Tailwind utilities.
sass removed from dependencies. Build clean, 53 tests pass.
This commit is contained in:
2026-03-28 11:19:45 +01:00
parent 8cc9fdaa62
commit b58d39e707
34 changed files with 1055 additions and 1259 deletions

View File

@@ -14,7 +14,6 @@
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-lottie-player": "^1.5.5", "react-lottie-player": "^1.5.5",
"react-router-dom": "^6.19.0", "react-router-dom": "^6.19.0",
"sass": "^1.69.5",
"tailwindcss": "^4.2.2", "tailwindcss": "^4.2.2",
"zustand": "^5.0.12" "zustand": "^5.0.12"
}, },
@@ -1033,9 +1032,11 @@
"version": "2.5.6", "version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
"dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true,
"dependencies": { "dependencies": {
"detect-libc": "^2.0.3", "detect-libc": "^2.0.3",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -1072,11 +1073,13 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"android" "android"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1092,11 +1095,13 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1112,11 +1117,13 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1132,11 +1139,13 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"freebsd" "freebsd"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1152,11 +1161,13 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1172,11 +1183,13 @@
"cpu": [ "cpu": [
"arm" "arm"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1192,11 +1205,13 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1212,11 +1227,13 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1232,11 +1249,13 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1252,11 +1271,13 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1272,11 +1293,13 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1292,11 +1315,13 @@
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -1312,11 +1337,13 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
], ],
"peer": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
}, },
@@ -2579,6 +2606,8 @@
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"readdirp": "^4.0.1" "readdirp": "^4.0.1"
}, },
@@ -3600,7 +3629,9 @@
"version": "5.1.5", "version": "5.1.5",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
"integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
"license": "MIT" "license": "MIT",
"optional": true,
"peer": true
}, },
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
@@ -3757,7 +3788,7 @@
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"devOptional": true, "dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -3793,7 +3824,7 @@
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"devOptional": true, "dev": true,
"dependencies": { "dependencies": {
"is-extglob": "^2.1.1" "is-extglob": "^2.1.1"
}, },
@@ -4442,8 +4473,10 @@
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true "optional": true,
"peer": true
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.13", "version": "2.0.13",
@@ -4685,7 +4718,7 @@
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"devOptional": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -4885,6 +4918,8 @@
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">= 14.18.0" "node": ">= 14.18.0"
}, },
@@ -5114,6 +5149,8 @@
"resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz",
"integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==", "integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==",
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"chokidar": "^4.0.0", "chokidar": "^4.0.0",
"immutable": "^5.1.5", "immutable": "^5.1.5",

View File

@@ -17,7 +17,6 @@
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-lottie-player": "^1.5.5", "react-lottie-player": "^1.5.5",
"react-router-dom": "^6.19.0", "react-router-dom": "^6.19.0",
"sass": "^1.69.5",
"tailwindcss": "^4.2.2", "tailwindcss": "^4.2.2",
"zustand": "^5.0.12" "zustand": "^5.0.12"
}, },

View File

@@ -6,10 +6,6 @@ import Footer from "./components/footer";
import { GameTick } from "./components/GameTick"; import { GameTick } from "./components/GameTick";
import { GameSync } from "./components/GameSync"; import { GameSync } from "./components/GameSync";
import "./scss/root.scss";
import "./scss/zones.scss";
import "./scss/components/footer.scss";
import navData from "./data/NavBarData.json"; import navData from "./data/NavBarData.json";
function App() { function App() {

View File

@@ -29,7 +29,7 @@ function NodeRow({
return ( return (
<div className={rowClass}> <div className={rowClass}>
<div style={{ display: "flex", flexDirection: "column", minWidth: 0 }}> <div className="flex flex-col min-w-0">
<span className="gp-value">{node.name}</span> <span className="gp-value">{node.name}</span>
<span className="gp-label">{EFFECT_LABELS[node.effect](node.value)}</span> <span className="gp-label">{EFFECT_LABELS[node.effect](node.value)}</span>
</div> </div>
@@ -39,8 +39,7 @@ function NodeRow({
<button <button
disabled={!canBuy} disabled={!canBuy}
onClick={onBuy} onClick={onBuy}
className={`gp-btn ${canBuy ? "gp-btn--buy" : "gp-btn--disabled"}`} className={`gp-btn ${canBuy ? "gp-btn--buy bg-amber-600!" : "gp-btn--disabled"}`}
style={canBuy ? { background: "#d97706" } : {}}
> >
{node.cost} ADN {node.cost} ADN
</button> </button>
@@ -58,7 +57,7 @@ export function EvolutionTree() {
return ( return (
<div className="gp"> <div className="gp">
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}> <div className="flex justify-between items-center">
<span className="gp-title">Évolution</span> <span className="gp-title">Évolution</span>
<span className="gp-value gp-accent-amber">{state.ancestralDna} ADN</span> <span className="gp-value gp-accent-amber">{state.ancestralDna} ADN</span>
</div> </div>

View File

@@ -12,7 +12,7 @@ export function GeneratorShop() {
return ( return (
<div className="gp"> <div className="gp">
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}> <div className="flex justify-between items-center">
<span className="gp-title" title="Achète des générateurs pour produire des têtards automatiquement">Générateurs</span> <span className="gp-title" title="Achète des générateurs pour produire des têtards automatiquement">Générateurs</span>
<span className="gp-value gp-accent-green" title="Production totale par seconde">{formatNumber(productionPerSecond)}/s</span> <span className="gp-value gp-accent-green" title="Production totale par seconde">{formatNumber(productionPerSecond)}/s</span>
</div> </div>
@@ -26,8 +26,8 @@ export function GeneratorShop() {
key={gen.id} key={gen.id}
className={`gp-row ${canAfford ? "gp-row--active" : "gp-row--locked"}`} className={`gp-row ${canAfford ? "gp-row--active" : "gp-row--locked"}`}
> >
<div style={{ display: "flex", flexDirection: "column", minWidth: 0 }}> <div className="flex flex-col min-w-0">
<div style={{ display: "flex", alignItems: "center", gap: "0.3rem" }}> <div className="flex items-center gap-1">
<span className="gp-value">{gen.name}</span> <span className="gp-value">{gen.name}</span>
{gen.owned > 0 && ( {gen.owned > 0 && (
<span className="gp-label gp-accent-green">x{gen.owned}</span> <span className="gp-label gp-accent-green">x{gen.owned}</span>

View File

@@ -13,8 +13,8 @@ export function MilestoneBar() {
const remaining = Math.max(PRESTIGE_THRESHOLD - resources, 0); const remaining = Math.max(PRESTIGE_THRESHOLD - resources, 0);
return ( return (
<div className="gp" style={{ gap: "0.25rem" }}> <div className="gp gap-1">
<div style={{ display: "flex", justifyContent: "space-between" }}> <div className="flex justify-between">
<span className="gp-label">Prochaine Génération</span> <span className="gp-label">Prochaine Génération</span>
<span className="gp-label"> <span className="gp-label">
{formatNumber(resources)} / {formatNumber(PRESTIGE_THRESHOLD)} {formatNumber(resources)} / {formatNumber(PRESTIGE_THRESHOLD)}
@@ -22,14 +22,11 @@ export function MilestoneBar() {
</div> </div>
<div className="gp-progress"> <div className="gp-progress">
<div <div
className="gp-progress-fill" className="gp-progress-fill bg-gradient-to-r from-violet-600 to-violet-400"
style={{ style={{ width: `${progressPercent}%` }}
width: `${progressPercent}%`,
background: "linear-gradient(90deg, #7c3aed, #a78bfa)",
}}
/> />
</div> </div>
<span className="gp-label" style={{ textAlign: "right" }}> <span className="gp-label text-right">
{remaining > 0 {remaining > 0
? `${formatNumber(remaining)} restants` ? `${formatNumber(remaining)} restants`
: "Nouvelle Génération disponible !"} : "Nouvelle Génération disponible !"}

View File

@@ -26,7 +26,7 @@ export function PrestigePanel() {
<div className="gp"> <div className="gp">
<span className="gp-title" title="Recommence à zéro en échange d'un bonus permanent — tes têtards et générateurs sont réinitialisés mais tu gagnes de l'ADN et un multiplicateur">Prestige</span> <span className="gp-title" title="Recommence à zéro en échange d'un bonus permanent — tes têtards et générateurs sont réinitialisés mais tu gagnes de l'ADN et un multiplicateur">Prestige</span>
{canPrestige ? ( {canPrestige ? (
<div style={{ display: "flex", flexDirection: "column", gap: "0.4rem" }}> <div className="flex flex-col gap-1.5">
<span className="gp-value gp-accent-purple"> <span className="gp-value gp-accent-purple">
+{dnaPreview} ADN · +0.1x mult +{dnaPreview} ADN · +0.1x mult
</span> </span>

View File

@@ -1,8 +1,5 @@
import { NavLink as Link } from "react-router-dom"; import { NavLink as Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import "../scss/components/navbar.scss";
import "../scss/root.scss";
import PrimaryButton from "./buttons/PrimaryButton"; import PrimaryButton from "./buttons/PrimaryButton";
export default function Burger({ navData }) { export default function Burger({ navData }) {

View File

@@ -1,5 +1,4 @@
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import "../../scss/components/buttons.scss";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
export default function PrimaryButton({ btnText, btnLink }) { export default function PrimaryButton({ btnText, btnLink }) {

View File

@@ -1,4 +1,3 @@
import "../../scss/components/buttons.scss";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { Link } from "react-router"; import { Link } from "react-router";

View File

@@ -1,4 +1,3 @@
import "../scss/components/footer.scss";
import { NavLink as Link } from "react-router-dom"; import { NavLink as Link } from "react-router-dom";
export default function Footer() { export default function Footer() {

View File

@@ -1,9 +1,6 @@
import { NavLink as Link } from "react-router-dom"; import { NavLink as Link } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import "../scss/components/navbar.scss";
import "../scss/root.scss";
import PrimaryButton from "./buttons/PrimaryButton"; import PrimaryButton from "./buttons/PrimaryButton";
import Burger from "./burger"; import Burger from "./burger";
import { useAuth } from "../context/AuthContext"; import { useAuth } from "../context/AuthContext";

View File

@@ -1,12 +1,979 @@
@import "tailwindcss"; @import "tailwindcss";
:root { /* ── Tailwind v4 theme — tokens du jeu ── */
margin: 0; @theme {
padding: 0; /* 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 */
::-webkit-scrollbar { --color-gp-bg: rgba(17, 17, 17, 0.75);
width: 1px; --color-gp-bg-hover: rgba(17, 17, 17, 0.85);
display: none; --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);
}
} }

View File

@@ -1,5 +1,6 @@
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom"; import { createBrowserRouter, RouterProvider } from "react-router-dom";
import "./index.css";
import App from "./App"; import App from "./App";
import Landing from "./pages/Landing"; import Landing from "./pages/Landing";
import Home from "./pages/Home"; import Home from "./pages/Home";

View File

@@ -1,5 +1,4 @@
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import "../scss/pages.scss";
import Lottie from "react-lottie-player"; import Lottie from "react-lottie-player";
import animation404 from "../data/404-animation.json"; import animation404 from "../data/404-animation.json";

View File

@@ -1,6 +1,5 @@
import { useGameStore } from "../store/useGameStore"; import { useGameStore } from "../store/useGameStore";
import { ACHIEVEMENTS } from "../data/achievements"; import { ACHIEVEMENTS } from "../data/achievements";
import "../scss/achievements.scss";
function Achievements() { function Achievements() {
const state = useGameStore((s) => s.state); const state = useGameStore((s) => s.state);

View File

@@ -3,7 +3,6 @@ import { useNavigate, Link } from "react-router-dom";
import { exchangeCode, loadVerifier, clearVerifier } from "../lib/oauth"; import { exchangeCode, loadVerifier, clearVerifier } from "../lib/oauth";
import { apiFetch } from "../lib/api"; import { apiFetch } from "../lib/api";
import { useAuth } from "../context/AuthContext"; import { useAuth } from "../context/AuthContext";
import "../scss/pages.scss";
export default function AuthCallback() { export default function AuthCallback() {
const navigate = useNavigate(); const navigate = useNavigate();

View File

@@ -1,4 +1,3 @@
import "../scss/Cookie.scss";
function Cookie() { function Cookie() {
return ( return (
<div className="container"> <div className="container">

View File

@@ -11,8 +11,6 @@ import { EvolutionTree } from "../components/EvolutionTree";
import { MilestoneBar } from "../components/MilestoneBar"; import { MilestoneBar } from "../components/MilestoneBar";
import { CockpitHeader } from "../components/CockpitHeader"; import { CockpitHeader } from "../components/CockpitHeader";
import { ACHIEVEMENTS } from "../data/achievements"; import { ACHIEVEMENTS } from "../data/achievements";
import "../scss/home.scss";
import "../scss/components/game-panels.scss";
export default function Home() { export default function Home() {
const [toggleRain] = useOutletContext(); const [toggleRain] = useOutletContext();
@@ -113,7 +111,7 @@ export default function Home() {
if (!ready) { if (!ready) {
return ( return (
<section className="game-container"> <section className="game-container">
<p style={{ textAlign: "center", color: "#6b7a99", marginTop: "20vh" }}> <p className="text-center text-slate-400 mt-[20vh]">
Chargement de ta progression... Chargement de ta progression...
</p> </p>
</section> </section>

View File

@@ -1,4 +1,3 @@
import "../scss/Legal.scss";
function Legal() { function Legal() {
return ( return (
<div className="mentionslegales"> <div className="mentionslegales">

View File

@@ -2,7 +2,6 @@ import { useEffect } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext"; import { useAuth } from "../context/AuthContext";
import { buildAuthUrl, saveVerifier } from "../lib/oauth"; import { buildAuthUrl, saveVerifier } from "../lib/oauth";
import "../scss/pages.scss";
const PROVIDERS = [ const PROVIDERS = [
{ id: "discord", label: "Discord", emoji: "🎮" }, { id: "discord", label: "Discord", emoji: "🎮" },
@@ -31,7 +30,7 @@ export default function Login() {
<div className="containererror"> <div className="containererror">
<h1>Connexion</h1> <h1>Connexion</h1>
<p className="message">Connecte-toi pour sauvegarder ta progression.</p> <p className="message">Connecte-toi pour sauvegarder ta progression.</p>
<div style={{ display: "flex", flexDirection: "column", gap: 8, marginTop: 16 }}> <div className="flex flex-col gap-2 mt-4">
{PROVIDERS.map((p) => ( {PROVIDERS.map((p) => (
<button <button
key={p.id} key={p.id}

View File

@@ -1,6 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useAuth } from "../context/AuthContext"; import { useAuth } from "../context/AuthContext";
import "../scss/pages.scss";
const OAUTH_URL = import.meta.env.VITE_OAUTH_URL || ""; const OAUTH_URL = import.meta.env.VITE_OAUTH_URL || "";
const PROVIDERS = ["discord", "github", "google", "twitch"]; const PROVIDERS = ["discord", "github", "google", "twitch"];
@@ -87,7 +86,6 @@ export default function Settings() {
returnUrl: `${window.location.origin}/settings`, returnUrl: `${window.location.origin}/settings`,
}), }),
}); });
// Redirect to OAuth provider
window.location.href = data.data.authUrl; window.location.href = data.data.authUrl;
} catch (e) { } catch (e) {
setError(e.message); setError(e.message);
@@ -134,30 +132,28 @@ export default function Settings() {
return ( return (
<section> <section>
<div className="containererror" style={{ maxWidth: 500 }}> <div className="containererror max-w-[500px]">
<h1>Paramètres</h1> <h1>Paramètres</h1>
{error && ( {error && (
<p style={{ color: "#ef4444", fontSize: 13, marginBottom: 16 }}> <p className="text-red-500 text-[13px] mb-4">{error}</p>
{error}
</p>
)} )}
{/* Profile info */} {/* Profile info */}
{profile && ( {profile && (
<div style={{ marginBottom: 24, textAlign: "left" }}> <div className="mb-6 text-left">
<p style={{ fontSize: 14, color: "#9ca3af", margin: "4px 0" }}> <p className="text-sm text-gray-400 my-1">
<strong>Pseudo :</strong> {profile.nickname} <strong>Pseudo :</strong> {profile.nickname}
</p> </p>
<p style={{ fontSize: 14, color: "#9ca3af", margin: "4px 0" }}> <p className="text-sm text-gray-400 my-1">
<strong>Email :</strong> {profile.email || "—"} <strong>Email :</strong> {profile.email || "—"}
</p> </p>
</div> </div>
)} )}
{/* Linked providers */} {/* Linked providers */}
<h2 style={{ fontSize: 18, marginBottom: 12 }}>Comptes liés</h2> <h2 className="text-lg mb-3">Comptes liés</h2>
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}> <div className="flex flex-col gap-2">
{PROVIDERS.map((provider) => { {PROVIDERS.map((provider) => {
const linked = linkedNames.has(provider); const linked = linkedNames.has(provider);
const isLoading = actionLoading === provider; const isLoading = actionLoading === provider;
@@ -165,39 +161,32 @@ export default function Settings() {
return ( return (
<div <div
key={provider} key={provider}
style={{ className={`flex items-center justify-between px-3 py-2 rounded-lg border ${
display: "flex", linked
alignItems: "center", ? "bg-[#1a2a1a] border-[#2a4a2a]"
justifyContent: "space-between", : "bg-[#1a1a2a] border-[#2a2a4a]"
padding: "8px 12px", }`}
background: linked ? "#1a2a1a" : "#1a1a2a",
borderRadius: 8,
border: `1px solid ${linked ? "#2a4a2a" : "#2a2a4a"}`,
}}
> >
<span style={{ fontSize: 14 }}> <span className="text-sm">
{EMOJIS[provider]} {provider.charAt(0).toUpperCase() + provider.slice(1)} {EMOJIS[provider]} {provider.charAt(0).toUpperCase() + provider.slice(1)}
{linked && ( {linked && (
<span style={{ color: "#4ade80", fontSize: 12, marginLeft: 8 }}> <span className="text-green-400 text-xs ml-2"> lié</span>
lié
</span>
)} )}
</span> </span>
{linked ? ( {linked ? (
<button <button
className="btn-return" className="btn-return text-xs! py-1! px-2.5!"
style={{ fontSize: 12, padding: "4px 10px", opacity: canUnlink ? 1 : 0.4 }}
disabled={!canUnlink || isLoading} disabled={!canUnlink || isLoading}
onClick={() => handleUnlink(provider)} onClick={() => handleUnlink(provider)}
type="button" type="button"
style={{ opacity: canUnlink ? 1 : 0.4 }}
> >
{isLoading ? "..." : "Délier"} {isLoading ? "..." : "Délier"}
</button> </button>
) : ( ) : (
<button <button
className="btn-return" className="btn-return text-xs! py-1! px-2.5!"
style={{ fontSize: 12, padding: "4px 10px" }}
disabled={isLoading} disabled={isLoading}
onClick={() => handleLink(provider)} onClick={() => handleLink(provider)}
type="button" type="button"
@@ -212,8 +201,7 @@ export default function Settings() {
{/* Logout */} {/* Logout */}
<button <button
className="btn-return" className="btn-return mt-6 w-full!"
style={{ marginTop: 24, width: "100%" }}
onClick={logout} onClick={logout}
type="button" type="button"
> >

View File

@@ -1,3 +0,0 @@
a {
text-decoration: none;
}

View File

@@ -1,19 +0,0 @@
.container {
width: 100%;
margin: 0 auto;
max-width: 1280px;
font-family: var(--font);
display: flex;
flex-direction: column;
gap: 3rem;
padding: 15rem 1rem 4rem;
}
h2 {
font-family: var(--font);
font-size: 2rem;
font-weight: 600;
color: var(--color-grey);
}

View File

@@ -1,19 +0,0 @@
.mentionslegales {
width: 100%;
margin: 0 auto;
max-width: 1280px;
font-family: var(--font);
display: flex;
flex-direction: column;
gap: 3rem;
padding: 15rem 1rem 4rem;
}
h2 {
font-family: var(--font);
font-size: 2rem;
font-weight: 600;
color: var(--color-grey);
}

View File

@@ -1,98 +0,0 @@
.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;
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;
&: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;
}

View File

@@ -1,46 +0,0 @@
.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: var(--color-white) !important;
text-align: center;
font-size: 1rem;
font-weight: 400;
transition: transform 0.1s ease-in-out;
border: none;
&:hover {
transform: scale(0.95);
background-color: var(--color-red-light);
}
}
.secondary-button {
display: flex;
padding: 1rem 1rem;
background-color: var(--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;
&:hover {
transform: scale(0.95);
background-color: var(--color-grey-hover);
}
}

View File

@@ -1,105 +0,0 @@
.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;
&:hover {
transform: scale(0.9);
}
}
.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-item,
a {
width: fit-content;
font-family: var(--font);
font-size: 1rem;
color: var(--color-grey);
transition: all 0.15s ease-in-out;
&: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;
&:hover {
transform: scale(0.95);
}
}
.copyright {
font-family: var(--font);
font-size: 0.8rem;
font-weight: 300;
color: var(--color-grey);
text-align: center;
}
}

View File

@@ -1,170 +0,0 @@
// game-panels.scss — Système de style partagé pour tous les panels du cockpit
// Modifier les tokens dans root.scss, pas ici.
// --- Panel de base ---
.gp {
display: flex;
flex-direction: column;
gap: var(--gp-gap);
padding: var(--gp-padding);
background: var(--gp-bg);
backdrop-filter: blur(8px);
border: 1px solid var(--gp-border);
border-radius: var(--gp-radius);
}
.gp-title {
font-family: var(--font);
font-size: var(--gp-title);
font-weight: 700;
color: var(--gp-text-color);
letter-spacing: 0.02em;
text-transform: uppercase;
}
.gp-label {
font-family: var(--font);
font-size: var(--gp-text-sm);
font-weight: 500;
color: var(--gp-text-muted);
}
.gp-value {
font-family: var(--font);
font-size: var(--gp-text);
font-weight: 600;
color: var(--gp-text-color);
}
.gp-accent-green { color: var(--gp-accent-green); }
.gp-accent-purple { color: var(--gp-accent-purple); }
.gp-accent-amber { color: var(--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(--gp-radius) - 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(--gp-accent-green-bg);
&:hover {
background: rgba(16, 185, 129, 0.18);
}
}
.gp-row--locked {
border-color: var(--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(--gp-accent-amber-bg);
}
.gp-row--unlocked {
border-color: rgba(16, 185, 129, 0.3);
background: var(--gp-accent-green-bg);
}
// --- Bouton achat ---
.gp-btn {
font-family: var(--font);
font-size: var(--gp-text-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(--gp-btn-bg);
color: white;
&:hover {
background: var(--gp-btn-bg-hover);
}
}
.gp-btn--disabled {
background: var(--gp-btn-disabled);
color: var(--gp-btn-text-disabled);
cursor: not-allowed;
}
.gp-btn--prestige {
background: #7c3aed;
color: white;
padding: 0.4rem 0.8rem;
font-size: var(--gp-text);
animation: gp-pulse 2s ease-in-out infinite;
&:hover {
background: #8b5cf6;
}
}
@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); }
}
// --- 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(--gp-border);
margin: 0.15rem 0;
}
// --- Zone titles in sidebar ---
.gp-zone-label {
font-family: var(--font);
font-size: var(--gp-text-sm);
font-weight: 600;
color: var(--gp-text-muted);
text-transform: uppercase;
letter-spacing: 0.06em;
padding-left: 0.2rem;
}

View File

@@ -1,306 +0,0 @@
.header-main {
display: flex;
justify-content: space-between;
position: absolute;
width: 100%;
height: 80px;
padding: 0rem 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) {
padding: 0rem 0.4rem;
box-sizing: border-box;
}
}
.logo {
width: 5rem;
content: url(/svg/tadpole.svg);
transition: 0.2s;
&:hover {
width: 5rem;
transition: 0.2s;
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;
@media screen and (max-width: 999px) {
display: none;
}
li {
list-style: none;
font-family: var(--font);
font-weight: 300;
font-size: 1rem;
color: var(--color-white);
height: 100%;
.mainLink {
text-decoration: none;
color: var(--color-grey);
font-weight: 500;
padding: 30px 0;
&:hover {
color: var(--color-red-light);
font-weight: 500;
}
}
.dropLink {
text-decoration: none;
color: var(--color-white);
font-weight: 400;
&:hover {
color: var(--color-red-light);
font-weight: 400;
}
}
}
}
ul {
list-style-type: none;
@media screen and (max-width: 999px) {
color: var(--color-white) !important;
}
li {
float: left;
width: fit-content;
.dropdown-content {
display: none;
position: absolute;
background: var(--color-black);
transform: translateY(30px);
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(10, 10, 10, 0.2);
z-index: 1;
}
li.dropdown {
display: inline-block;
}
a {
color: var(--color-white);
width: fit-content;
}
a:hover,
.dropdown:hover {
color: var(--color-red-light);
font-weight: 400;
}
}
}
.dropdown-content a {
color: var(--color-black);
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
&:hover {
background-color: var(--color-black);
color: var(--color-gold);
}
}
.dropdown:hover .dropdown-content {
display: block;
}
}
@media screen and (min-width: 1000px) {
.menuToggle {
display: none;
}
}
@media screen and (max-width: 999px) {
.menuToggle {
float: left;
position: relative;
box-sizing: border-box;
top: 2px;
left: -10px;
z-index: 99;
-webkit-user-select: none;
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;
-webkit-touch-callout: none;
}
.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 0px;
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: var(--color-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 !important;
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: var(--color-white);
}
.menuToggle input:checked ~ ul {
visibility: visible;
opacity: 100;
}
.sousmenu {
display: flex;
flex-direction: column;
margin-left: 1.2rem;
color: var(--color-white);
font-size: 1.2rem;
font-family: var(--font);
font-weight: 500;
padding-bottom: 1rem;
}
.empty {
line-height: 20rem;
}
}
.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;
&:hover {
background: var(--color-grey);
color: var(--color-white);
}
}
}

View File

@@ -1,133 +0,0 @@
// home.scss — Game view styles (layout géré par zones.scss)
// --- Clicker zone ---
.click-zone {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
gap: 1rem;
padding-bottom: 2vh;
cursor: pointer;
flex: 1;
// Desktop: center
@media (min-width: 768px) {
padding-right: 22rem; // offset for sidebar
}
}
.tadpole-sprite {
width: 280px;
height: 280px;
background: url("/svg/tadpole.svg") no-repeat center / contain;
transition: transform 0.1s ease;
@media (min-width: 768px) {
width: 320px;
height: 320px;
}
.click-zone:active & {
transform: scale(0.95) rotate(2deg);
}
}
// --- Compteur ressources sous le têtard ---
.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) {
font-size: 2.5rem;
}
}
// --- Badge achievements sidebar ---
.achieve-badge {
display: block;
text-align: center;
padding: 0.4rem;
border-radius: var(--gp-radius);
background: var(--gp-accent-green-bg);
border: 1px solid rgba(16, 185, 129, 0.2);
font-family: var(--font);
font-size: var(--gp-text-sm);
font-weight: 600;
color: var(--gp-accent-green);
text-decoration: none;
transition: all 0.15s ease;
&:hover {
background: rgba(16, 185, 129, 0.2);
}
}
// --- Click feedback particle ---
.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;
}
@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);
}
}
// --- Game sidebar ---
.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;
// Mobile: bottom drawer
@media (max-width: 767px) {
position: fixed;
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;
}
}

View File

@@ -1,171 +0,0 @@
.container {
display: flex;
flex-direction: column;
max-width: 132ch;
width: 80%;
gap: 3rem;
margin: 150px auto 50px;
h1 {
font-family: var(--font);
color: var(--color-black);
font-size: 1.8rem;
text-align: center;
width: fit-content;
}
.separator {
border: solid 1px var(--color-gold-hover);
}
.massageinfo {
display: flex;
flex-direction: column;
gap: 0.4rem;
.info {
font-family: var(--font);
color: var(--color-grey);
font-size: 1rem;
font-weight: 400;
}
}
.subtitle {
font-family: var(--font);
color: var(--color-black);
font-size: 1.2rem;
font-weight: 600;
text-align: left;
margin-bottom: 0.8rem;
}
.content {
display: flex;
flex-direction: column;
gap: 0.6rem;
.subtitle {
font-family: var(--font);
color: var(--color-black);
font-size: 1.2rem;
font-weight: 600;
text-align: left;
margin-bottom: 0.5rem;
}
.paragraphe {
font-family: var(--font);
color: var(--color-grey);
font-size: 1rem;
font-weight: 400;
margin-bottom: 0.5rem;
list-style: inside;
a {
font-family: var(--font);
color: var(--color-gold-link);
font-size: 1rem;
font-weight: 600;
margin-bottom: 0.5rem;
list-style: inside;
text-decoration: none;
&:hover {
color: var(--color-gold-hover);
}
}
}
.picture-container {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 1rem;
@media (max-width: 449px) {
flex-direction: column;
}
.picture {
background-position: center;
background-size: cover;
width: 100%;
height: 300px;
}
}
}
//Massages pages
.listing-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 3rem;
.listcontent {
display: flex;
flex-direction: column;
.listdetail {
font-family: var(--font);
color: var(--color-grey);
font-size: 0.95rem;
font-weight: 400;
margin-bottom: 0.5rem;
list-style-type: none;
padding-left: 1rem;
}
}
}
}
//error pages
section {
display: flex;
flex-direction: column;
height: 90vh;
justify-content: center;
width: 100%;
.containererror {
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
h1 {
font-family: var(--font);
color: var(--color-black);
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: var(--color-white);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
&:hover {
background-color: var(--color-grey);
transform: scale(0.9);
}
}
}
}

View File

@@ -1,60 +0,0 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
:root {
--color-blue-light: #dcecf3;
--color-purple-light: #e4e3f3;
--color-red-light: #c33636;
--color-white: #ffffff;
--color-light: #eaeaea;
--color-grey: #202020;
--color-grey-hover: #606060;
--bg-color: var(--color-blue-light);
--font: "Hanken Grotesk", sans-serif;
// --- Game panel tokens ---
--gp-bg: rgba(17, 17, 17, 0.75);
--gp-bg-hover: rgba(17, 17, 17, 0.85);
--gp-border: rgba(255, 255, 255, 0.08);
--gp-radius: 0.75rem;
--gp-padding: 0.75rem;
--gp-gap: 0.5rem;
// Text
--gp-title: 0.8rem;
--gp-text: 0.75rem;
--gp-text-sm: 0.65rem;
--gp-text-color: rgba(255, 255, 255, 0.9);
--gp-text-muted: rgba(255, 255, 255, 0.5);
// Accent colors
--gp-accent-green: #34d399;
--gp-accent-purple: #a78bfa;
--gp-accent-amber: #fbbf24;
--gp-accent-green-bg: rgba(16, 185, 129, 0.12);
--gp-accent-purple-bg: rgba(139, 92, 246, 0.12);
--gp-accent-amber-bg: rgba(251, 191, 36, 0.12);
// Buttons
--gp-btn-bg: #059669;
--gp-btn-bg-hover: #10b981;
--gp-btn-disabled: rgba(255, 255, 255, 0.08);
--gp-btn-text-disabled: rgba(255, 255, 255, 0.3);
}
a {
text-decoration: none;
}
main {
min-height: 92vh;
margin-top: 80px;
padding: 0 0 2rem;
background-color: var(--bg-color);
}

View File

@@ -1,41 +0,0 @@
// zones.scss — Système de zones visuelles
// Chaque page déclare sa zone via data-zone sur le wrapper.
// Le background, les tons, l'ambiance changent — navbar/footer restent fixes.
//
// Usage : <div className="zone" data-zone="swamp"> ... </div>
// Ajouter un nouveau biome : juste un nouveau [data-zone="xxx"] ici.
.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;
}
// --- Biomes ---
[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;
}
// Futur :
// [data-zone="cave"] { background-image: url("/webp/bg-cave.webp"); }
// [data-zone="volcano"] { background-image: url("/webp/bg-volcano.webp"); }
// [data-zone="ocean"] { background-image: url("/webp/bg-ocean.webp"); }