Major UI update
Some checks failed
Build / build-check (pull_request) Failing after 1m33s

This commit is contained in:
Sacha VAUDEY 2025-09-13 22:55:24 +02:00
parent d36f6f48e8
commit 30fd66f2c9
96 changed files with 12918 additions and 931 deletions

View File

@ -10,6 +10,11 @@
"static/chunks/webpack.js",
"static/chunks/main-app.js",
"static/chunks/app/page.js"
],
"/_not-found/page": [
"static/chunks/webpack.js",
"static/chunks/main-app.js",
"static/chunks/app/_not-found/page.js"
]
}
}

View File

@ -2,7 +2,9 @@
"polyfillFiles": [
"static/chunks/polyfills.js"
],
"devFiles": [],
"devFiles": [
"static/chunks/react-refresh.js"
],
"ampDevFiles": [],
"lowPriorityFiles": [
"static/development/_buildManifest.js",
@ -14,7 +16,16 @@
],
"rootMainFilesTree": {},
"pages": {
"/_app": []
"/_app": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_app.js"
],
"/_error": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_error.js"
]
},
"ampFirstPages": []
}

View File

@ -1 +1 @@
{"encryption.key":"bVK0K0gnCM2bs6Da9nFoUA8a2zIlQZHDxVww33b2AKc=","encryption.expire_at":1759003679699}
{"encryption.key":"rIRQqKrzkq/nscX7E9tJwSHGEP7hQQrrFXjGQ825mYs=","encryption.expire_at":1759006065637}

View File

@ -0,0 +1,31 @@
{
"polyfillFiles": [
"static/chunks/polyfills.js"
],
"devFiles": [
"static/chunks/fallback/react-refresh.js"
],
"ampDevFiles": [
"static/chunks/fallback/webpack.js",
"static/chunks/fallback/amp.js"
],
"lowPriorityFiles": [],
"rootMainFiles": [
"static/chunks/fallback/webpack.js",
"static/chunks/fallback/main-app.js"
],
"rootMainFilesTree": {},
"pages": {
"/_app": [
"static/chunks/fallback/webpack.js",
"static/chunks/fallback/main.js",
"static/chunks/fallback/pages/_app.js"
],
"/_error": [
"static/chunks/fallback/webpack.js",
"static/chunks/fallback/main.js",
"static/chunks/fallback/pages/_error.js"
]
},
"ampFirstPages": []
}

View File

@ -4,8 +4,8 @@
"dynamicRoutes": {},
"notFoundRoutes": [],
"preview": {
"previewModeId": "15e3d8b0600a40f1c95cc8490237aa1d",
"previewModeSigningKey": "ec8401872d1c2c363465fbb59f2b46091853c1bb7af8c29aab0456a3bda01bab",
"previewModeEncryptionKey": "95bb5b17a07536103860cba80fca3930023dc8a5cc46bdfedf2061149543cc8e"
"previewModeId": "b0b3c48d7c3608f61dfb7d547d9d8bbc",
"previewModeSigningKey": "8f8d1c4621f9a66e558f1b6882a875d2e56781a1648bf0f33250413923f72738",
"previewModeEncryptionKey": "ced38bf88e161ebc4fc20b682c3ecfd387210d8316506f87c51079ffb7288614"
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,4 @@
{
"/_not-found/page": "app/_not-found/page.js",
"/page": "app/page.js"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,9 @@ globalThis.__BUILD_MANIFEST = {
"polyfillFiles": [
"static/chunks/polyfills.js"
],
"devFiles": [],
"devFiles": [
"static/chunks/react-refresh.js"
],
"ampDevFiles": [],
"lowPriorityFiles": [],
"rootMainFiles": [
@ -11,7 +13,16 @@ globalThis.__BUILD_MANIFEST = {
],
"rootMainFilesTree": {},
"pages": {
"/_app": []
"/_app": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_app.js"
],
"/_error": [
"static/chunks/webpack.js",
"static/chunks/main.js",
"static/chunks/pages/_error.js"
]
},
"ampFirstPages": []
};

View File

@ -1 +1,5 @@
{}
{
"/_app": "pages/_app.js",
"/_error": "pages/_error.js",
"/_document": "pages/_document.js"
}

View File

@ -0,0 +1,46 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(() => {
var exports = {};
exports.id = "pages/_app";
exports.ids = ["pages/_app"];
exports.modules = {
/***/ "react":
/*!************************!*\
!*** external "react" ***!
\************************/
/***/ ((module) => {
module.exports = require("react");
/***/ }),
/***/ "react/jsx-runtime":
/*!************************************!*\
!*** external "react/jsx-runtime" ***!
\************************************/
/***/ ((module) => {
module.exports = require("react/jsx-runtime");
/***/ })
};
;
// load runtime
var __webpack_require__ = require("../webpack-runtime.js");
__webpack_require__.C(exports);
var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
var __webpack_exports__ = __webpack_require__.X(0, ["vendor-chunks/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1","vendor-chunks/@swc+helpers@0.5.15"], () => (__webpack_exec__("(pages-dir-node)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_app.js")));
module.exports = __webpack_exports__;
})();

View File

@ -0,0 +1,66 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(() => {
var exports = {};
exports.id = "pages/_document";
exports.ids = ["pages/_document"];
exports.modules = {
/***/ "next/dist/compiled/next-server/pages.runtime.dev.js":
/*!**********************************************************************!*\
!*** external "next/dist/compiled/next-server/pages.runtime.dev.js" ***!
\**********************************************************************/
/***/ ((module) => {
module.exports = require("next/dist/compiled/next-server/pages.runtime.dev.js");
/***/ }),
/***/ "path":
/*!***********************!*\
!*** external "path" ***!
\***********************/
/***/ ((module) => {
module.exports = require("path");
/***/ }),
/***/ "react":
/*!************************!*\
!*** external "react" ***!
\************************/
/***/ ((module) => {
module.exports = require("react");
/***/ }),
/***/ "react/jsx-runtime":
/*!************************************!*\
!*** external "react/jsx-runtime" ***!
\************************************/
/***/ ((module) => {
module.exports = require("react/jsx-runtime");
/***/ })
};
;
// load runtime
var __webpack_require__ = require("../webpack-runtime.js");
__webpack_require__.C(exports);
var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
var __webpack_exports__ = __webpack_require__.X(0, ["vendor-chunks/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1","vendor-chunks/@swc+helpers@0.5.15"], () => (__webpack_exec__("(pages-dir-node)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_document.js")));
module.exports = __webpack_exports__;
})();

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
{
"node": {},
"edge": {},
"encryptionKey": "bVK0K0gnCM2bs6Da9nFoUA8a2zIlQZHDxVww33b2AKc="
"encryptionKey": "rIRQqKrzkq/nscX7E9tJwSHGEP7hQQrrFXjGQ825mYs="
}

View File

@ -11,6 +11,26 @@ exports.id = "vendor-chunks/@swc+helpers@0.5.15";
exports.ids = ["vendor-chunks/@swc+helpers@0.5.15"];
exports.modules = {
/***/ "(pages-dir-node)/./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_default.cjs":
/*!***********************************************************************************************************!*\
!*** ./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_default.cjs ***!
\***********************************************************************************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("\n\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : { default: obj };\n}\nexports._ = _interop_require_default;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1ub2RlKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9Ac3djK2hlbHBlcnNAMC41LjE1L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdC5janMiLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWI7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQSxTQUFTIiwic291cmNlcyI6WyIvaG9tZS9zYWhhbW9uZS9Eb2N1bWVudHMvTGEgQmFucXVpc2Uvd2Vic2l0ZS1mcm9udC9iYW5xdWlzZS13ZWJzaXRlL25vZGVfbW9kdWxlcy8ucG5wbS9Ac3djK2hlbHBlcnNAMC41LjE1L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdC5janMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdChvYmopIHtcbiAgICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTtcbn1cbmV4cG9ydHMuXyA9IF9pbnRlcm9wX3JlcXVpcmVfZGVmYXVsdDtcbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOlswXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(pages-dir-node)/./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_default.cjs\n");
/***/ }),
/***/ "(pages-dir-node)/./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs":
/*!************************************************************************************************************!*\
!*** ./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs ***!
\************************************************************************************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("\n\nfunction _getRequireWildcardCache(nodeInterop) {\n if (typeof WeakMap !== \"function\") return null;\n\n var cacheBabelInterop = new WeakMap();\n var cacheNodeInterop = new WeakMap();\n\n return (_getRequireWildcardCache = function(nodeInterop) {\n return nodeInterop ? cacheNodeInterop : cacheBabelInterop;\n })(nodeInterop);\n}\nfunction _interop_require_wildcard(obj, nodeInterop) {\n if (!nodeInterop && obj && obj.__esModule) return obj;\n if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") return { default: obj };\n\n var cache = _getRequireWildcardCache(nodeInterop);\n\n if (cache && cache.has(obj)) return cache.get(obj);\n\n var newObj = { __proto__: null };\n var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;\n\n for (var key in obj) {\n if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) {\n var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;\n if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);\n else newObj[key] = obj[key];\n }\n }\n\n newObj.default = obj;\n\n if (cache) cache.set(obj, newObj);\n\n return newObj;\n}\nexports._ = _interop_require_wildcard;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1ub2RlKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9Ac3djK2hlbHBlcnNAMC41LjE1L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQuY2pzIiwibWFwcGluZ3MiOiJBQUFhOztBQUViO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLHVGQUF1Rjs7QUFFdkY7O0FBRUE7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxTQUFTIiwic291cmNlcyI6WyIvaG9tZS9zYWhhbW9uZS9Eb2N1bWVudHMvTGEgQmFucXVpc2Uvd2Vic2l0ZS1mcm9udC9iYW5xdWlzZS13ZWJzaXRlL25vZGVfbW9kdWxlcy8ucG5wbS9Ac3djK2hlbHBlcnNAMC41LjE1L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvY2pzL19pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQuY2pzIl0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xuXG5mdW5jdGlvbiBfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUobm9kZUludGVyb3ApIHtcbiAgICBpZiAodHlwZW9mIFdlYWtNYXAgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgY2FjaGVCYWJlbEludGVyb3AgPSBuZXcgV2Vha01hcCgpO1xuICAgIHZhciBjYWNoZU5vZGVJbnRlcm9wID0gbmV3IFdlYWtNYXAoKTtcblxuICAgIHJldHVybiAoX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlID0gZnVuY3Rpb24obm9kZUludGVyb3ApIHtcbiAgICAgICAgcmV0dXJuIG5vZGVJbnRlcm9wID8gY2FjaGVOb2RlSW50ZXJvcCA6IGNhY2hlQmFiZWxJbnRlcm9wO1xuICAgIH0pKG5vZGVJbnRlcm9wKTtcbn1cbmZ1bmN0aW9uIF9pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQob2JqLCBub2RlSW50ZXJvcCkge1xuICAgIGlmICghbm9kZUludGVyb3AgJiYgb2JqICYmIG9iai5fX2VzTW9kdWxlKSByZXR1cm4gb2JqO1xuICAgIGlmIChvYmogPT09IG51bGwgfHwgdHlwZW9mIG9iaiAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2Ygb2JqICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiB7IGRlZmF1bHQ6IG9iaiB9O1xuXG4gICAgdmFyIGNhY2hlID0gX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlKG5vZGVJbnRlcm9wKTtcblxuICAgIGlmIChjYWNoZSAmJiBjYWNoZS5oYXMob2JqKSkgcmV0dXJuIGNhY2hlLmdldChvYmopO1xuXG4gICAgdmFyIG5ld09iaiA9IHsgX19wcm90b19fOiBudWxsIH07XG4gICAgdmFyIGhhc1Byb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO1xuXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICBpZiAoa2V5ICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICAgICAgICB2YXIgZGVzYyA9IGhhc1Byb3BlcnR5RGVzY3JpcHRvciA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqLCBrZXkpIDogbnVsbDtcbiAgICAgICAgICAgIGlmIChkZXNjICYmIChkZXNjLmdldCB8fCBkZXNjLnNldCkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuZXdPYmosIGtleSwgZGVzYyk7XG4gICAgICAgICAgICBlbHNlIG5ld09ialtrZXldID0gb2JqW2tleV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZXdPYmouZGVmYXVsdCA9IG9iajtcblxuICAgIGlmIChjYWNoZSkgY2FjaGUuc2V0KG9iaiwgbmV3T2JqKTtcblxuICAgIHJldHVybiBuZXdPYmo7XG59XG5leHBvcnRzLl8gPSBfaW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkO1xuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6WzBdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(pages-dir-node)/./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs\n");
/***/ }),
/***/ "(ssr)/./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/esm/_class_private_field_loose_base.js":
/*!*****************************************************************************************************************!*\
!*** ./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/esm/_class_private_field_loose_base.js ***!
@ -49,6 +69,26 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ _: () => (/* binding */ _interop_require_wildcard)\n/* harmony export */ });\nfunction _getRequireWildcardCache(nodeInterop) {\n if (typeof WeakMap !== \"function\") return null;\n\n var cacheBabelInterop = new WeakMap();\n var cacheNodeInterop = new WeakMap();\n\n return (_getRequireWildcardCache = function(nodeInterop) {\n return nodeInterop ? cacheNodeInterop : cacheBabelInterop;\n })(nodeInterop);\n}\nfunction _interop_require_wildcard(obj, nodeInterop) {\n if (!nodeInterop && obj && obj.__esModule) return obj;\n if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") return { default: obj };\n\n var cache = _getRequireWildcardCache(nodeInterop);\n\n if (cache && cache.has(obj)) return cache.get(obj);\n\n var newObj = { __proto__: null };\n var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;\n\n for (var key in obj) {\n if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) {\n var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;\n if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);\n else newObj[key] = obj[key];\n }\n }\n\n newObj.default = obj;\n\n if (cache) cache.set(obj, newObj);\n\n return newObj;\n}\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHNzcikvLi9ub2RlX21vZHVsZXMvLnBucG0vQHN3YytoZWxwZXJzQDAuNS4xNS9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2VzbS9faW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkLmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSx1RkFBdUY7O0FBRXZGOztBQUVBOztBQUVBLG1CQUFtQjtBQUNuQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQzBDIiwic291cmNlcyI6WyIvaG9tZS9zYWhhbW9uZS9Eb2N1bWVudHMvTGEgQmFucXVpc2Uvd2Vic2l0ZS1mcm9udC9iYW5xdWlzZS13ZWJzaXRlL25vZGVfbW9kdWxlcy8ucG5wbS9Ac3djK2hlbHBlcnNAMC41LjE1L25vZGVfbW9kdWxlcy9Ac3djL2hlbHBlcnMvZXNtL19pbnRlcm9wX3JlcXVpcmVfd2lsZGNhcmQuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlKG5vZGVJbnRlcm9wKSB7XG4gICAgaWYgKHR5cGVvZiBXZWFrTWFwICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBudWxsO1xuXG4gICAgdmFyIGNhY2hlQmFiZWxJbnRlcm9wID0gbmV3IFdlYWtNYXAoKTtcbiAgICB2YXIgY2FjaGVOb2RlSW50ZXJvcCA9IG5ldyBXZWFrTWFwKCk7XG5cbiAgICByZXR1cm4gKF9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSA9IGZ1bmN0aW9uKG5vZGVJbnRlcm9wKSB7XG4gICAgICAgIHJldHVybiBub2RlSW50ZXJvcCA/IGNhY2hlTm9kZUludGVyb3AgOiBjYWNoZUJhYmVsSW50ZXJvcDtcbiAgICB9KShub2RlSW50ZXJvcCk7XG59XG5mdW5jdGlvbiBfaW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkKG9iaiwgbm9kZUludGVyb3ApIHtcbiAgICBpZiAoIW5vZGVJbnRlcm9wICYmIG9iaiAmJiBvYmouX19lc01vZHVsZSkgcmV0dXJuIG9iajtcbiAgICBpZiAob2JqID09PSBudWxsIHx8IHR5cGVvZiBvYmogIT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG9iaiAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4geyBkZWZhdWx0OiBvYmogfTtcblxuICAgIHZhciBjYWNoZSA9IF9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZShub2RlSW50ZXJvcCk7XG5cbiAgICBpZiAoY2FjaGUgJiYgY2FjaGUuaGFzKG9iaikpIHJldHVybiBjYWNoZS5nZXQob2JqKTtcblxuICAgIHZhciBuZXdPYmogPSB7IF9fcHJvdG9fXzogbnVsbCB9O1xuICAgIHZhciBoYXNQcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkgJiYgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcblxuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgaWYgKGtleSAhPT0gXCJkZWZhdWx0XCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgICAgICAgdmFyIGRlc2MgPSBoYXNQcm9wZXJ0eURlc2NyaXB0b3IgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iaiwga2V5KSA6IG51bGw7XG4gICAgICAgICAgICBpZiAoZGVzYyAmJiAoZGVzYy5nZXQgfHwgZGVzYy5zZXQpKSBPYmplY3QuZGVmaW5lUHJvcGVydHkobmV3T2JqLCBrZXksIGRlc2MpO1xuICAgICAgICAgICAgZWxzZSBuZXdPYmpba2V5XSA9IG9ialtrZXldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV3T2JqLmRlZmF1bHQgPSBvYmo7XG5cbiAgICBpZiAoY2FjaGUpIGNhY2hlLnNldChvYmosIG5ld09iaik7XG5cbiAgICByZXR1cm4gbmV3T2JqO1xufVxuZXhwb3J0IHsgX2ludGVyb3BfcmVxdWlyZV93aWxkY2FyZCBhcyBfIH07XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(ssr)/./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/esm/_interop_require_wildcard.js\n");
/***/ }),
/***/ "./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_default.cjs":
/*!***********************************************************************************************************!*\
!*** ./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_default.cjs ***!
\***********************************************************************************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("\n\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : { default: obj };\n}\nexports._ = _interop_require_default;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvLnBucG0vQHN3YytoZWxwZXJzQDAuNS4xNS9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2Nqcy9faW50ZXJvcF9yZXF1aXJlX2RlZmF1bHQuY2pzIiwibWFwcGluZ3MiOiJBQUFhOztBQUViO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ0EsU0FBUyIsInNvdXJjZXMiOlsiL2hvbWUvc2FoYW1vbmUvRG9jdW1lbnRzL0xhIEJhbnF1aXNlL3dlYnNpdGUtZnJvbnQvYmFucXVpc2Utd2Vic2l0ZS9ub2RlX21vZHVsZXMvLnBucG0vQHN3YytoZWxwZXJzQDAuNS4xNS9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2Nqcy9faW50ZXJvcF9yZXF1aXJlX2RlZmF1bHQuY2pzIl0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xuXG5mdW5jdGlvbiBfaW50ZXJvcF9yZXF1aXJlX2RlZmF1bHQob2JqKSB7XG4gICAgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07XG59XG5leHBvcnRzLl8gPSBfaW50ZXJvcF9yZXF1aXJlX2RlZmF1bHQ7XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_default.cjs\n");
/***/ }),
/***/ "./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs":
/*!************************************************************************************************************!*\
!*** ./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs ***!
\************************************************************************************************************/
/***/ ((__unused_webpack_module, exports) => {
eval("\n\nfunction _getRequireWildcardCache(nodeInterop) {\n if (typeof WeakMap !== \"function\") return null;\n\n var cacheBabelInterop = new WeakMap();\n var cacheNodeInterop = new WeakMap();\n\n return (_getRequireWildcardCache = function(nodeInterop) {\n return nodeInterop ? cacheNodeInterop : cacheBabelInterop;\n })(nodeInterop);\n}\nfunction _interop_require_wildcard(obj, nodeInterop) {\n if (!nodeInterop && obj && obj.__esModule) return obj;\n if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") return { default: obj };\n\n var cache = _getRequireWildcardCache(nodeInterop);\n\n if (cache && cache.has(obj)) return cache.get(obj);\n\n var newObj = { __proto__: null };\n var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;\n\n for (var key in obj) {\n if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) {\n var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;\n if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);\n else newObj[key] = obj[key];\n }\n }\n\n newObj.default = obj;\n\n if (cache) cache.set(obj, newObj);\n\n return newObj;\n}\nexports._ = _interop_require_wildcard;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvLnBucG0vQHN3YytoZWxwZXJzQDAuNS4xNS9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2Nqcy9faW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkLmNqcyIsIm1hcHBpbmdzIjoiQUFBYTs7QUFFYjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSx1RkFBdUY7O0FBRXZGOztBQUVBOztBQUVBLG1CQUFtQjtBQUNuQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyIsInNvdXJjZXMiOlsiL2hvbWUvc2FoYW1vbmUvRG9jdW1lbnRzL0xhIEJhbnF1aXNlL3dlYnNpdGUtZnJvbnQvYmFucXVpc2Utd2Vic2l0ZS9ub2RlX21vZHVsZXMvLnBucG0vQHN3YytoZWxwZXJzQDAuNS4xNS9ub2RlX21vZHVsZXMvQHN3Yy9oZWxwZXJzL2Nqcy9faW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkLmNqcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcblxuZnVuY3Rpb24gX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlKG5vZGVJbnRlcm9wKSB7XG4gICAgaWYgKHR5cGVvZiBXZWFrTWFwICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBudWxsO1xuXG4gICAgdmFyIGNhY2hlQmFiZWxJbnRlcm9wID0gbmV3IFdlYWtNYXAoKTtcbiAgICB2YXIgY2FjaGVOb2RlSW50ZXJvcCA9IG5ldyBXZWFrTWFwKCk7XG5cbiAgICByZXR1cm4gKF9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSA9IGZ1bmN0aW9uKG5vZGVJbnRlcm9wKSB7XG4gICAgICAgIHJldHVybiBub2RlSW50ZXJvcCA/IGNhY2hlTm9kZUludGVyb3AgOiBjYWNoZUJhYmVsSW50ZXJvcDtcbiAgICB9KShub2RlSW50ZXJvcCk7XG59XG5mdW5jdGlvbiBfaW50ZXJvcF9yZXF1aXJlX3dpbGRjYXJkKG9iaiwgbm9kZUludGVyb3ApIHtcbiAgICBpZiAoIW5vZGVJbnRlcm9wICYmIG9iaiAmJiBvYmouX19lc01vZHVsZSkgcmV0dXJuIG9iajtcbiAgICBpZiAob2JqID09PSBudWxsIHx8IHR5cGVvZiBvYmogIT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG9iaiAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4geyBkZWZhdWx0OiBvYmogfTtcblxuICAgIHZhciBjYWNoZSA9IF9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZShub2RlSW50ZXJvcCk7XG5cbiAgICBpZiAoY2FjaGUgJiYgY2FjaGUuaGFzKG9iaikpIHJldHVybiBjYWNoZS5nZXQob2JqKTtcblxuICAgIHZhciBuZXdPYmogPSB7IF9fcHJvdG9fXzogbnVsbCB9O1xuICAgIHZhciBoYXNQcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkgJiYgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcblxuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgaWYgKGtleSAhPT0gXCJkZWZhdWx0XCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgICAgICAgdmFyIGRlc2MgPSBoYXNQcm9wZXJ0eURlc2NyaXB0b3IgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iaiwga2V5KSA6IG51bGw7XG4gICAgICAgICAgICBpZiAoZGVzYyAmJiAoZGVzYy5nZXQgfHwgZGVzYy5zZXQpKSBPYmplY3QuZGVmaW5lUHJvcGVydHkobmV3T2JqLCBrZXksIGRlc2MpO1xuICAgICAgICAgICAgZWxzZSBuZXdPYmpba2V5XSA9IG9ialtrZXldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV3T2JqLmRlZmF1bHQgPSBvYmo7XG5cbiAgICBpZiAoY2FjaGUpIGNhY2hlLnNldChvYmosIG5ld09iaik7XG5cbiAgICByZXR1cm4gbmV3T2JqO1xufVxuZXhwb3J0cy5fID0gX2ludGVyb3BfcmVxdWlyZV93aWxkY2FyZDtcbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOlswXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/.pnpm/@swc+helpers@0.5.15/node_modules/@swc/helpers/cjs/_interop_require_wildcard.cjs\n");
/***/ })
};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["/_error"],{
/***/ "(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2Fhome%2Fsahamone%2FDocuments%2FLa%20Banquise%2Fwebsite-front%2Fbanquise-website%2Fnode_modules%2F.pnpm%2Fnext%4015.5.3_react-dom%4019.1.1_react%4019.1.1__react%4019.1.1%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!":
/*!**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2Fhome%2Fsahamone%2FDocuments%2FLa%20Banquise%2Fwebsite-front%2Fbanquise-website%2Fnode_modules%2F.pnpm%2Fnext%4015.5.3_react-dom%4019.1.1_react%4019.1.1__react%4019.1.1%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error! ***!
\**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_error\",\n function () {\n return __webpack_require__(/*! ./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_error.js */ \"(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_error.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_error\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9uZXh0QDE1LjUuM19yZWFjdC1kb21AMTkuMS4xX3JlYWN0QDE5LjEuMV9fcmVhY3RAMTkuMS4xL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPSUyRmhvbWUlMkZzYWhhbW9uZSUyRkRvY3VtZW50cyUyRkxhJTIwQmFucXVpc2UlMkZ3ZWJzaXRlLWZyb250JTJGYmFucXVpc2Utd2Vic2l0ZSUyRm5vZGVfbW9kdWxlcyUyRi5wbnBtJTJGbmV4dCU0MDE1LjUuM19yZWFjdC1kb20lNDAxOS4xLjFfcmVhY3QlNDAxOS4xLjFfX3JlYWN0JTQwMTkuMS4xJTJGbm9kZV9tb2R1bGVzJTJGbmV4dCUyRmRpc3QlMkZwYWdlcyUyRl9lcnJvci5qcyZwYWdlPSUyRl9lcnJvciEiLCJtYXBwaW5ncyI6IjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQU8sQ0FBQyxvUUFBcUg7QUFDNUk7QUFDQTtBQUNBLE9BQU8sSUFBVTtBQUNqQixNQUFNLFVBQVU7QUFDaEI7QUFDQSxPQUFPO0FBQ1A7QUFDQSIsInNvdXJjZXMiOlsiIl0sInNvdXJjZXNDb250ZW50IjpbIlxuICAgICh3aW5kb3cuX19ORVhUX1AgPSB3aW5kb3cuX19ORVhUX1AgfHwgW10pLnB1c2goW1xuICAgICAgXCIvX2Vycm9yXCIsXG4gICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiByZXF1aXJlKFwiLi9ub2RlX21vZHVsZXMvLnBucG0vbmV4dEAxNS41LjNfcmVhY3QtZG9tQDE5LjEuMV9yZWFjdEAxOS4xLjFfX3JlYWN0QDE5LjEuMS9ub2RlX21vZHVsZXMvbmV4dC9kaXN0L3BhZ2VzL19lcnJvci5qc1wiKTtcbiAgICAgIH1cbiAgICBdKTtcbiAgICBpZihtb2R1bGUuaG90KSB7XG4gICAgICBtb2R1bGUuaG90LmRpc3Bvc2UoZnVuY3Rpb24gKCkge1xuICAgICAgICB3aW5kb3cuX19ORVhUX1AucHVzaChbXCIvX2Vycm9yXCJdKVxuICAgICAgfSk7XG4gICAgfVxuICAiXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2Fhome%2Fsahamone%2FDocuments%2FLa%20Banquise%2Fwebsite-front%2Fbanquise-website%2Fnode_modules%2F.pnpm%2Fnext%4015.5.3_react-dom%4019.1.1_react%4019.1.1__react%4019.1.1%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=%2Fhome%2Fsahamone%2FDocuments%2FLa%20Banquise%2Fwebsite-front%2Fbanquise-website%2Fnode_modules%2F.pnpm%2Fnext%4015.5.3_react-dom%4019.1.1_react%4019.1.1__react%4019.1.1%2Fnode_modules%2Fnext%2Fdist%2Fpages%2F_error.js&page=%2F_error!")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"f73b100390b1\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9ob21lL3NhaGFtb25lL0RvY3VtZW50cy9MYSBCYW5xdWlzZS93ZWJzaXRlLWZyb250L2JhbnF1aXNlLXdlYnNpdGUvYXBwL2dsb2JhbHMuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IFwiZjczYjEwMDM5MGIxXCJcbmlmIChtb2R1bGUuaG90KSB7IG1vZHVsZS5ob3QuYWNjZXB0KCkgfVxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"cf1cf2b3bb4f\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9ob21lL3NhaGFtb25lL0RvY3VtZW50cy9MYSBCYW5xdWlzZS93ZWJzaXRlLWZyb250L2JhbnF1aXNlLXdlYnNpdGUvYXBwL2dsb2JhbHMuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IFwiY2YxY2YyYjNiYjRmXCJcbmlmIChtb2R1bGUuaG90KSB7IG1vZHVsZS5ob3QuYWNjZXB0KCkgfVxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ }),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["pages/_app"],{
/***/ "(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app!":
/*!***********************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app! ***!
\***********************************************************************************************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_app\",\n function () {\n return __webpack_require__(/*! next/dist/pages/_app */ \"(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_app.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_app\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9uZXh0QDE1LjUuM19yZWFjdC1kb21AMTkuMS4xX3JlYWN0QDE5LjEuMV9fcmVhY3RAMTkuMS4xL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPW5leHQlMkZkaXN0JTJGcGFnZXMlMkZfYXBwJnBhZ2U9JTJGX2FwcCEiLCJtYXBwaW5ncyI6IjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQU8sQ0FBQyxtS0FBc0I7QUFDN0M7QUFDQTtBQUNBLE9BQU8sSUFBVTtBQUNqQixNQUFNLFVBQVU7QUFDaEI7QUFDQSxPQUFPO0FBQ1A7QUFDQSIsInNvdXJjZXMiOlsiIl0sInNvdXJjZXNDb250ZW50IjpbIlxuICAgICh3aW5kb3cuX19ORVhUX1AgPSB3aW5kb3cuX19ORVhUX1AgfHwgW10pLnB1c2goW1xuICAgICAgXCIvX2FwcFwiLFxuICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVxdWlyZShcIm5leHQvZGlzdC9wYWdlcy9fYXBwXCIpO1xuICAgICAgfVxuICAgIF0pO1xuICAgIGlmKG1vZHVsZS5ob3QpIHtcbiAgICAgIG1vZHVsZS5ob3QuZGlzcG9zZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHdpbmRvdy5fX05FWFRfUC5wdXNoKFtcIi9fYXBwXCJdKVxuICAgICAgfSk7XG4gICAgfVxuICAiXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app!"), __webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/client/router.js")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

View File

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["pages/_error"],{
/***/ "(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error!":
/*!***************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error! ***!
\***************************************************************************************************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_error\",\n function () {\n return __webpack_require__(/*! next/dist/pages/_error */ \"(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_error.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_error\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9uZXh0QDE1LjUuM19yZWFjdC1kb21AMTkuMS4xX3JlYWN0QDE5LjEuMV9fcmVhY3RAMTkuMS4xL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPW5leHQlMkZkaXN0JTJGcGFnZXMlMkZfZXJyb3ImcGFnZT0lMkZfZXJyb3IhIiwibWFwcGluZ3MiOiI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG1CQUFPLENBQUMsdUtBQXdCO0FBQy9DO0FBQ0E7QUFDQSxPQUFPLElBQVU7QUFDakIsTUFBTSxVQUFVO0FBQ2hCO0FBQ0EsT0FBTztBQUNQO0FBQ0EiLCJzb3VyY2VzIjpbIiJdLCJzb3VyY2VzQ29udGVudCI6WyJcbiAgICAod2luZG93Ll9fTkVYVF9QID0gd2luZG93Ll9fTkVYVF9QIHx8IFtdKS5wdXNoKFtcbiAgICAgIFwiL19lcnJvclwiLFxuICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVxdWlyZShcIm5leHQvZGlzdC9wYWdlcy9fZXJyb3JcIik7XG4gICAgICB9XG4gICAgXSk7XG4gICAgaWYobW9kdWxlLmhvdCkge1xuICAgICAgbW9kdWxlLmhvdC5kaXNwb3NlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgd2luZG93Ll9fTkVYVF9QLnB1c2goW1wiL19lcnJvclwiXSlcbiAgICAgIH0pO1xuICAgIH1cbiAgIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["pages/_app","main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error!")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["pages/_app"],{
/***/ "(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app!":
/*!***********************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app! ***!
\***********************************************************************************************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_app\",\n function () {\n return __webpack_require__(/*! next/dist/pages/_app */ \"(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_app.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_app\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9uZXh0QDE1LjUuM19yZWFjdC1kb21AMTkuMS4xX3JlYWN0QDE5LjEuMV9fcmVhY3RAMTkuMS4xL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPW5leHQlMkZkaXN0JTJGcGFnZXMlMkZfYXBwJnBhZ2U9JTJGX2FwcCEiLCJtYXBwaW5ncyI6IjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQU8sQ0FBQyxtS0FBc0I7QUFDN0M7QUFDQTtBQUNBLE9BQU8sSUFBVTtBQUNqQixNQUFNLFVBQVU7QUFDaEI7QUFDQSxPQUFPO0FBQ1A7QUFDQSIsInNvdXJjZXMiOlsiIl0sInNvdXJjZXNDb250ZW50IjpbIlxuICAgICh3aW5kb3cuX19ORVhUX1AgPSB3aW5kb3cuX19ORVhUX1AgfHwgW10pLnB1c2goW1xuICAgICAgXCIvX2FwcFwiLFxuICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVxdWlyZShcIm5leHQvZGlzdC9wYWdlcy9fYXBwXCIpO1xuICAgICAgfVxuICAgIF0pO1xuICAgIGlmKG1vZHVsZS5ob3QpIHtcbiAgICAgIG1vZHVsZS5ob3QuZGlzcG9zZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHdpbmRvdy5fX05FWFRfUC5wdXNoKFtcIi9fYXBwXCJdKVxuICAgICAgfSk7XG4gICAgfVxuICAiXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_app&page=%2F_app!"), __webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/client/router.js")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

View File

@ -0,0 +1,28 @@
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([["pages/_error"],{
/***/ "(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error!":
/*!***************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error! ***!
\***************************************************************************************************************************************************************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
eval(__webpack_require__.ts("\n (window.__NEXT_P = window.__NEXT_P || []).push([\n \"/_error\",\n function () {\n return __webpack_require__(/*! next/dist/pages/_error */ \"(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/pages/_error.js\");\n }\n ]);\n if(true) {\n module.hot.dispose(function () {\n window.__NEXT_P.push([\"/_error\"])\n });\n }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHBhZ2VzLWRpci1icm93c2VyKS8uL25vZGVfbW9kdWxlcy8ucG5wbS9uZXh0QDE1LjUuM19yZWFjdC1kb21AMTkuMS4xX3JlYWN0QDE5LjEuMV9fcmVhY3RAMTkuMS4xL25vZGVfbW9kdWxlcy9uZXh0L2Rpc3QvYnVpbGQvd2VicGFjay9sb2FkZXJzL25leHQtY2xpZW50LXBhZ2VzLWxvYWRlci5qcz9hYnNvbHV0ZVBhZ2VQYXRoPW5leHQlMkZkaXN0JTJGcGFnZXMlMkZfZXJyb3ImcGFnZT0lMkZfZXJyb3IhIiwibWFwcGluZ3MiOiI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG1CQUFPLENBQUMsdUtBQXdCO0FBQy9DO0FBQ0E7QUFDQSxPQUFPLElBQVU7QUFDakIsTUFBTSxVQUFVO0FBQ2hCO0FBQ0EsT0FBTztBQUNQO0FBQ0EiLCJzb3VyY2VzIjpbIiJdLCJzb3VyY2VzQ29udGVudCI6WyJcbiAgICAod2luZG93Ll9fTkVYVF9QID0gd2luZG93Ll9fTkVYVF9QIHx8IFtdKS5wdXNoKFtcbiAgICAgIFwiL19lcnJvclwiLFxuICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcmVxdWlyZShcIm5leHQvZGlzdC9wYWdlcy9fZXJyb3JcIik7XG4gICAgICB9XG4gICAgXSk7XG4gICAgaWYobW9kdWxlLmhvdCkge1xuICAgICAgbW9kdWxlLmhvdC5kaXNwb3NlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgd2luZG93Ll9fTkVYVF9QLnB1c2goW1wiL19lcnJvclwiXSlcbiAgICAgIH0pO1xuICAgIH1cbiAgIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error!\n"));
/***/ })
},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, ["pages/_app","main"], () => (__webpack_exec__("(pages-dir-browser)/./node_modules/.pnpm/next@15.5.3_react-dom@19.1.1_react@19.1.1__react@19.1.1/node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=next%2Fdist%2Fpages%2F_error&page=%2F_error!")));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
/******/ }
]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
self.__BUILD_MANIFEST = (function(a){return {__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:a,__routerFilterDynamic:a,sortedPages:["\u002F_app"]}}(void 0));self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()
self.__BUILD_MANIFEST = (function(a){return {__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:a,__routerFilterDynamic:a,"/_error":["static\u002Fchunks\u002Fpages\u002F_error.js"],sortedPages:["\u002F_app","\u002F_error"]}}(void 0));self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB()

View File

@ -0,0 +1 @@
{"c":["app/layout","app/page","webpack"],"r":[],"m":[]}

View File

@ -0,0 +1 @@
{"c":["webpack"],"r":[],"m":[]}

View File

@ -0,0 +1 @@
{"c":["app/layout","app/page","webpack"],"r":[],"m":[]}

View File

@ -0,0 +1 @@
{"c":["app/layout","app/page","webpack"],"r":[],"m":[]}

View File

@ -0,0 +1,22 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
self["webpackHotUpdate_N_E"]("app/layout",{
/***/ "(app-pages-browser)/./app/globals.css":
/*!*************************!*\
!*** ./app/globals.css ***!
\*************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"cf1cf2b3bb4f\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9ob21lL3NhaGFtb25lL0RvY3VtZW50cy9MYSBCYW5xdWlzZS93ZWJzaXRlLWZyb250L2JhbnF1aXNlLXdlYnNpdGUvYXBwL2dsb2JhbHMuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IFwiY2YxY2YyYjNiYjRmXCJcbmlmIChtb2R1bGUuaG90KSB7IG1vZHVsZS5ob3QuYWNjZXB0KCkgfVxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ })
});

View File

@ -0,0 +1,22 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
self["webpackHotUpdate_N_E"]("app/layout",{
/***/ "(app-pages-browser)/./app/globals.css":
/*!*************************!*\
!*** ./app/globals.css ***!
\*************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"2d23e44fab4b\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9ob21lL3NhaGFtb25lL0RvY3VtZW50cy9MYSBCYW5xdWlzZS93ZWJzaXRlLWZyb250L2JhbnF1aXNlLXdlYnNpdGUvYXBwL2dsb2JhbHMuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IFwiMmQyM2U0NGZhYjRiXCJcbmlmIChtb2R1bGUuaG90KSB7IG1vZHVsZS5ob3QuYWNjZXB0KCkgfVxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ })
});

View File

@ -0,0 +1,22 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
self["webpackHotUpdate_N_E"]("app/layout",{
/***/ "(app-pages-browser)/./app/globals.css":
/*!*************************!*\
!*** ./app/globals.css ***!
\*************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"b110782f546e\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9ob21lL3NhaGFtb25lL0RvY3VtZW50cy9MYSBCYW5xdWlzZS93ZWJzaXRlLWZyb250L2JhbnF1aXNlLXdlYnNpdGUvYXBwL2dsb2JhbHMuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IFwiYjExMDc4MmY1NDZlXCJcbmlmIChtb2R1bGUuaG90KSB7IG1vZHVsZS5ob3QuYWNjZXB0KCkgfVxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ })
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("39ecaccf2924ffcc")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCIzOWVjYWNjZjI5MjRmZmNjXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View File

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("6d8ac73f0166cb2e")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCI2ZDhhYzczZjAxNjZjYjJlXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View File

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("8718965bffdc3be0")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCI4NzE4OTY1YmZmZGMzYmUwXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View File

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("115bc1bc45888edc")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCIxMTViYzFiYzQ1ODg4ZWRjXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,7 @@
import React from 'react';
import { componentStyles, mergeClasses } from '@/lib/styles/designSystem';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'discord' | 'auth' | 'secondary';
variant?: 'primary' | 'discord' | 'auth' | 'secondary' | 'ghost' | 'outline';
size?: 'sm' | 'md' | 'lg';
fullWidth?: boolean;
leftIcon?: React.ReactNode;
@ -12,16 +11,18 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
}
const sizeClasses = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 lg:px-6 py-2.5 lg:py-3 text-sm lg:text-base',
lg: 'px-6 py-3 text-base lg:text-lg',
sm: 'px-4 py-2 text-sm',
md: 'px-6 py-3 text-base',
lg: 'px-8 py-4 text-lg',
};
const variantClasses = {
primary: 'bg-gradient-to-r from-banquise-blue to-banquise-blue-light hover:shadow-banquise-blue/25',
discord: 'bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500 hover:shadow-indigo-500/25',
auth: 'bg-gradient-to-r from-banquise-blue-light to-banquise-blue hover:shadow-banquise-blue-light/25',
secondary: 'bg-white/10 hover:bg-white/20 border border-white/20',
primary: 'bg-gradient-to-r from-blue-600 to-blue-500 text-white shadow-lg hover:shadow-xl hover:from-blue-700 hover:to-blue-600 border-2 border-blue-600/20',
discord: 'bg-gradient-to-r from-indigo-600 to-purple-600 text-white shadow-lg hover:shadow-xl hover:from-indigo-700 hover:to-purple-700 border-2 border-indigo-600/20',
auth: 'bg-gradient-to-r from-blue-500 to-blue-400 text-white shadow-lg hover:shadow-xl hover:from-blue-600 hover:to-blue-500 border-2 border-blue-500/20',
secondary: 'bg-white text-blue-700 border-2 border-blue-600 shadow-md hover:shadow-lg hover:bg-blue-50',
outline: 'bg-transparent text-gray-700 border-2 border-gray-300 hover:bg-gray-50 hover:border-gray-400',
ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',
};
export const Button: React.FC<ButtonProps> = ({
@ -36,14 +37,15 @@ export const Button: React.FC<ButtonProps> = ({
disabled,
...props
}) => {
const baseClasses = mergeClasses(
componentStyles.button.base,
const baseClasses = [
'inline-flex items-center justify-center font-semibold rounded-xl transition-all duration-300 transform',
'hover:scale-105 active:scale-95 focus:outline-none focus:ring-4 focus:ring-blue-300',
sizeClasses[size],
variantClasses[variant],
fullWidth ? 'w-full' : '',
(disabled || loading) ? 'opacity-50 cursor-not-allowed' : '',
(disabled || loading) ? 'opacity-50 cursor-not-allowed transform-none' : '',
className
);
].filter(Boolean).join(' ');
return (
<button
@ -52,7 +54,7 @@ export const Button: React.FC<ButtonProps> = ({
{...props}
>
{loading && (
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<svg className="animate-spin -ml-1 mr-3 h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>

View File

@ -1,6 +1,5 @@
import React from 'react';
import Image from 'next/image'
import { componentStyles, mergeClasses } from '@/lib/styles/designSystem';
import type { Service } from '@/types/service';
interface ServiceCardProps {
@ -14,70 +13,50 @@ export const ServiceCard: React.FC<ServiceCardProps> = ({
onServiceClick,
className = '',
}) => {
const cardClasses = mergeClasses(
'group relative p-6 sm:p-8 transition-all duration-300 cursor-pointer',
componentStyles.card.base,
componentStyles.card.gradient,
'hover:-translate-y-4 hover:shadow-2xl hover:border-banquise-blue-200/50 hover:from-banquise-blue-800/15 hover:to-banquise-blue-800/8 active:scale-95',
className
);
const handleClick = () => {
onServiceClick(service);
};
return (
<div
className={cardClasses}
className={`group relative p-8 bg-white rounded-2xl shadow-lg hover:shadow-2xl border border-gray-200 hover:border-blue-300 transition-all duration-300 cursor-pointer transform hover:-translate-y-4 hover:scale-105 active:scale-95 ${className}`}
onClick={handleClick}
style={{
background: 'linear-gradient(to bottom right, rgba(31, 80, 120, 0.1), rgba(31, 80, 120, 0.05))',
backdropFilter: 'blur(16px)',
borderRadius: '1rem',
border: '1px solid rgba(160, 236, 249, 0.3)',
transition: 'all 0.3s ease'
}}
>
{/* Icon */}
<div
className="mb-6 sm:mb-8 w-20 h-20 sm:w-24 sm:h-24 rounded-2xl flex items-center justify-center text-3xl sm:text-4xl shadow-lg group-hover:scale-110 transition-transform duration-300 mx-auto"
style={{
background: 'linear-gradient(to bottom right, var(--banquise-blue-600), var(--banquise-blue-400))'
}}
>
<Image
src={service.image as any}
alt={service.icon}
className="h-10 sm:h-12 lg:h-14 w-auto relative z-10 transition-transform duration-300 group-hover:scale-130 m-10"
width={56}
height={56}
/>
{/* Indicateur de survol */}
<div className="absolute inset-0 bg-gradient-to-br from-blue-50/50 to-indigo-50/50 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
{/* Contenu de la carte */}
<div className="relative z-10">
{/* Icône du service */}
<div className="mb-8 w-24 h-24 rounded-2xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center shadow-xl group-hover:shadow-2xl group-hover:scale-110 transition-all duration-300 mx-auto">
<Image
src={service.image as any}
alt={service.icon}
className="h-12 w-12 transition-transform duration-300 group-hover:scale-110"
width={48}
height={48}
/>
</div>
{/* Nom du service */}
<h3 className="text-xl md:text-2xl font-bold mb-4 text-gray-900 text-center group-hover:text-blue-700 transition-colors duration-300">
{service.name}
</h3>
{/* Description courte */}
<p className="text-gray-600 leading-relaxed text-center group-hover:text-gray-700 transition-colors duration-300">
{service.description.split('.')[0]}.
</p>
{/* Flèche indicatrice au hover */}
<div className="mt-6 flex justify-center opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0">
<div className="w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center shadow-lg">
<svg className="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</div>
{/* Service name */}
<h3
className="text-xl sm:text-2xl font-bold mb-4 sm:mb-6 font-heading text-center group-hover:text-banquise-blue-200 transition-colors duration-300"
style={{ color: 'var(--banquise-blue-900)' }}
>
{service.name}
</h3>
{/* Short description */}
<p
className="leading-relaxed text-center text-sm sm:text-base"
style={{ color: 'var(--banquise-slate-700)' }}
>
{service.description.split('.')[0]}.
</p>
{/* Hover effect */}
<div
className="absolute inset-0 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none"
style={{
background: 'linear-gradient(to bottom right, rgba(160, 236, 249, 0.1), rgba(52, 166, 252, 0.05))'
}}
></div>
</div>
);
};

View File

@ -1,9 +1,13 @@
import React, { useState, useRef, useEffect } from 'react';
import Image from 'next/image';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import { useTranslation } from '@/lib/hooks/useTranslation';
import type { AutheliaUser } from '@/lib/services/auth';
// Fonction utilitaire simple pour combiner les classes
const cn = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface UserProfileProps {
user: AutheliaUser;
onLogout: () => void;
@ -56,10 +60,10 @@ export const UserProfile: React.FC<UserProfileProps> = ({
onClick={() => setIsOpen(!isOpen)}
className={cn(
'flex items-center justify-center w-8 h-8 rounded-full overflow-hidden',
'border-2 border-transparent hover:border-primary-300',
'border-2 border-transparent hover:border-blue-300',
'transition-all duration-200',
'focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2',
isOpen && 'ring-2 ring-primary-500 ring-offset-2'
'focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2',
isOpen && 'ring-2 ring-blue-500 ring-offset-2'
)}
aria-label={t.user.userMenu}
>
@ -117,7 +121,7 @@ export const UserProfile: React.FC<UserProfileProps> = ({
key={index}
className={cn(
'inline-flex px-2 py-1 text-xs font-medium rounded',
'bg-primary-100 text-primary-800'
'bg-blue-100 text-blue-800'
)}
>
{group}

View File

@ -2,86 +2,112 @@ import React from 'react';
import { URLS, SITE_CONFIG } from '@/lib/config/constants';
export const Footer: React.FC = () => (
<footer
className="text-white py-8 px-4 sm:px-6 md:px-8 relative z-10 border-t w-full box-border"
style={{
backgroundColor: 'var(--banquise-blue-800)',
borderTopColor: 'var(--banquise-blue-700)'
}}
>
<div className="max-w-6xl mx-auto">
{/* Main Footer Content */}
<div className="flex flex-col md:flex-row justify-between items-center gap-6 mb-6">
{/* Logo/Brand */}
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-gradient-to-br from-banquise-blue-400 to-banquise-blue-600 rounded-lg flex items-center justify-center">
<span className="text-white font-bold text-sm">B</span>
</div>
<span className="text-banquise-blue-200 font-semibold text-lg">
{SITE_CONFIG.name}
</span>
</div>
{/* Quick Links */}
<div className="flex flex-wrap items-center gap-6 text-sm">
<a
href={URLS.services.wiki}
className="text-banquise-blue-200 hover:text-white transition-colors duration-200"
>
Wiki
</a>
<a
href={URLS.services.gitea}
className="text-banquise-blue-200 hover:text-white transition-colors duration-200"
>
Gitea
</a>
<a
href={URLS.services.panel}
className="text-banquise-blue-200 hover:text-white transition-colors duration-200"
>
Panel
</a>
<a
href={URLS.services.opencloud}
className="text-banquise-blue-200 hover:text-white transition-colors duration-200"
>
OpenCloud
</a>
</div>
{/* Social Links */}
<div className="flex items-center gap-4">
<a
href={URLS.social.discord}
className="w-10 h-10 bg-banquise-blue-600/30 hover:bg-banquise-blue-600/50 rounded-full flex items-center justify-center transition-all duration-200 hover:scale-110"
aria-label="Discord"
>
<span className="text-banquise-blue-200 text-sm">
<svg className="w-4 h-4 lg:w-5 lg:h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
<footer className="bg-gray-900 text-white py-16 px-4 sm:px-6 lg:px-8 border-t border-gray-800">
<div className="max-w-7xl mx-auto">
{/* Contenu principal du footer */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-12 mb-12">
{/* Marque et description */}
<div className="space-y-6">
<div className="flex items-center gap-4">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center shadow-lg">
<span className="text-white font-bold text-xl">B</span>
</div>
<span className="text-white font-bold text-2xl">
{SITE_CONFIG.name}
</span>
</a>
<a
href={URLS.contact.email}
className="w-10 h-10 bg-banquise-blue-600/30 hover:bg-banquise-blue-600/50 rounded-full flex items-center justify-center transition-all duration-200 hover:scale-110"
aria-label="Email"
>
<span className="text-banquise-blue-200 text-sm">📧</span>
</a>
</div>
<p className="text-gray-300 leading-relaxed">
Une communauté passionnée qui propose des services d'hébergement et des outils collaboratifs pour les développeurs et les gamers.
</p>
{/* Réseaux sociaux */}
<div className="flex items-center gap-4">
<a
href={URLS.social.discord}
className="w-12 h-12 bg-gray-800 hover:bg-blue-600 rounded-xl flex items-center justify-center transition-all duration-300 hover:scale-110 shadow-lg hover:shadow-blue-500/25"
aria-label="Discord"
>
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
</a>
<a
href={URLS.contact.email}
className="w-12 h-12 bg-gray-800 hover:bg-blue-600 rounded-xl flex items-center justify-center transition-all duration-300 hover:scale-110 shadow-lg hover:shadow-blue-500/25"
aria-label="Email"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</a>
</div>
</div>
{/* Liens rapides services */}
<div className="space-y-6">
<h3 className="text-white font-bold text-lg mb-6">Nos Services</h3>
<div className="space-y-4">
<a
href={URLS.services.wiki}
className="block text-gray-300 hover:text-blue-400 transition-colors duration-200 hover:translate-x-2 transform"
>
📚 Wiki
</a>
<a
href={URLS.services.gitea}
className="block text-gray-300 hover:text-blue-400 transition-colors duration-200 hover:translate-x-2 transform"
>
🔧 Gitea
</a>
<a
href={URLS.services.panel}
className="block text-gray-300 hover:text-blue-400 transition-colors duration-200 hover:translate-x-2 transform"
>
🎮 Panel de Jeux
</a>
<a
href={URLS.services.opencloud}
className="block text-gray-300 hover:text-blue-400 transition-colors duration-200 hover:translate-x-2 transform"
>
OpenCloud
</a>
</div>
</div>
{/* Informations communauté */}
<div className="space-y-6">
<h3 className="text-white font-bold text-lg mb-6">Communauté</h3>
<div className="space-y-4">
<div className="bg-gradient-to-r from-blue-900/30 to-blue-800/30 rounded-xl p-6 border border-blue-800/30">
<h4 className="text-blue-400 font-semibold mb-2">Rejoindre l'asso</h4>
<p className="text-gray-300 text-sm mb-4">
Connectez-vous sur Discord et créez un ticket pour rejoindre la communauté Banquise.
</p>
<a
href={URLS.social.discord}
className="inline-flex items-center text-blue-400 hover:text-blue-300 text-sm font-semibold transition-colors duration-200"
>
<span className="mr-2">🚀</span>
Rejoindre maintenant
</a>
</div>
</div>
</div>
</div>
{/* Bottom Bar */}
<div className="flex flex-col sm:flex-row justify-between items-center gap-4 pt-6 border-t border-banquise-blue-700">
<p className="text-banquise-blue-300 text-xs text-center sm:text-left">
{/* Barre du bas */}
<div className="flex flex-col md:flex-row justify-between items-center gap-6 pt-8 border-t border-gray-800">
<p className="text-gray-400 text-sm text-center md:text-left">
© 2025 {SITE_CONFIG.name}. Hébergement communautaire pour développeurs et gamers.
</p>
<div className="flex items-center gap-4 text-xs text-banquise-blue-300">
<span>Fait avec par Banquise</span>
<div className="w-1 h-1 bg-banquise-blue-400 rounded-full"></div>
<span>EPITA 2025</span>
<div className="flex items-center gap-6 text-sm text-gray-400">
<span className="flex items-center">
Fait avec
<span className="text-red-500 mx-1"></span>
par Banquise
</span>
<div className="w-1 h-1 bg-gray-600 rounded-full"></div>
<span className="text-blue-400 font-semibold">EPITA 2025</span>
</div>
</div>
</div>

View File

@ -1,10 +1,14 @@
import React, { useEffect } from 'react';
import { Button } from '@/components/common/Button';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import { Logo } from './navbar/Logo';
import { URLS } from '@/lib/config/constants';
import type { Translation } from '@/types/i18n';
// Fonction utilitaire simple pour combiner les classes
const cn = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface MobileMenuProps {
isOpen: boolean;
onClose: () => void;
@ -44,7 +48,7 @@ const MobileNavItem: React.FC<MobileNavItemProps> = ({
'bg-white/5 hover:bg-white/10 active:bg-white/15',
'border border-white/10 hover:border-white/20',
'hover:scale-[1.02] active:scale-[0.98]',
'hover:shadow-lg hover:shadow-banquise-blue/20'
'hover:shadow-lg hover:shadow-blue-500/20'
)}
target={isExternal ? '_blank' : undefined}
rel={isExternal ? 'noopener noreferrer' : undefined}
@ -52,14 +56,14 @@ const MobileNavItem: React.FC<MobileNavItemProps> = ({
<div className="flex items-center space-x-4">
<div className={cn(
'flex items-center justify-center w-10 h-10 rounded-xl',
'bg-gradient-to-br from-banquise-blue-light/20 to-banquise-blue/20',
'border border-banquise-blue-lightest/20',
'bg-gradient-to-br from-blue-400/20 to-blue-600/20',
'border border-blue-300/20',
'group-hover:scale-110 transition-transform duration-300'
)}>
{icon}
</div>
<div className="flex-1">
<span className="block text-white font-semibold text-base group-hover:text-banquise-blue-lightest transition-colors">
<span className="block text-white font-semibold text-base group-hover:text-blue-200 transition-colors">
{title}
</span>
<p className="text-white/60 text-sm mt-0.5 group-hover:text-white/80 transition-colors">
@ -125,28 +129,27 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
isOpen ? 'visible' : 'invisible'
)}>
{/* Overlay avec effet de blur moderne */}
<div
className={cn(
'absolute inset-0 transition-all duration-300',
'bg-gradient-to-br from-black/80 via-banquise-blue-dark/60 to-black/80',
'backdrop-blur-lg',
isOpen ? 'opacity-100' : 'opacity-0'
)}
<div className={cn(
'absolute inset-0 transition-all duration-300',
'bg-gradient-to-br from-black/80 via-blue-900/60 to-black/80',
'backdrop-blur-lg',
isOpen ? 'opacity-100' : 'opacity-0'
)}
onClick={onClose}
/>
{/* Menu Panel */}
<div className={cn(
'absolute top-0 right-0 h-full w-80 max-w-[90vw]',
'bg-gradient-to-b from-banquise-blue-dark/98 via-banquise-blue-dark/95 to-banquise-blue-dark/90',
'bg-gradient-to-b from-blue-900/98 via-blue-900/95 to-blue-900/90',
'backdrop-blur-2xl shadow-2xl',
'border-l border-banquise-blue-lightest/20',
'border-l border-blue-300/20',
'transition-transform duration-300 ease-out',
isOpen ? 'translate-x-0' : 'translate-x-full'
)}>
{/* Header avec Logo */}
<div className="flex items-center justify-between p-6 pt-8 border-b border-banquise-blue-lightest/20">
<div className="flex items-center justify-between p-6 pt-8 border-b border-blue-300/20">
<Logo scrolled={false} />
<button
@ -155,7 +158,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
'bg-white/10 hover:bg-white/20 active:bg-white/25',
'border border-white/20 hover:border-white/30',
'hover:scale-105 active:scale-95',
'focus:outline-none focus:ring-2 focus:ring-banquise-blue-light/50'
'focus:outline-none focus:ring-2 focus:ring-blue-400/50'
)}
onClick={onClose}
aria-label="Fermer le menu"
@ -173,7 +176,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
<div className="space-y-3">
<MobileNavItem
icon={
<svg className="w-5 h-5 text-banquise-blue-lightest" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg className="w-5 h-5 text-blue-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
}
@ -185,7 +188,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
<MobileNavItem
icon={
<svg className="w-5 h-5 text-banquise-blue-lightest" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg className="w-5 h-5 text-blue-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
}
@ -197,7 +200,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
<MobileNavItem
icon={
<svg className="w-5 h-5 text-banquise-blue-lightest" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg className="w-5 h-5 text-blue-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
}
@ -209,7 +212,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
<MobileNavItem
icon={
<svg className="w-5 h-5 text-banquise-blue-lightest" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg className="w-5 h-5 text-blue-200" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
}
@ -221,7 +224,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
</div>
{/* Divider */}
<div className="border-t border-banquise-blue-lightest/20 my-6" />
<div className="border-t border-blue-300/20 my-6" />
{/* Social & External Links */}
<div className="space-y-3">
@ -260,7 +263,7 @@ export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, transla
</div>
{/* Effet de gradient overlay */}
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-banquise-blue-dark/10 pointer-events-none" />
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-blue-900/10 pointer-events-none" />
</div>
</div>
);

View File

@ -1,6 +1,5 @@
import React from 'react';
import { useScrollEffects } from '@/lib/hooks/useScrollEffects';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import { Logo } from './navbar/Logo';
import { NavLinks } from './navbar/NavLinks';
import { ActionButtons } from './navbar/ActionButtons';
@ -8,6 +7,11 @@ import { MobileMenuButton } from './navbar/MobileMenuButton';
import { MobileMenu } from './MobileMenu';
import type { Translation } from '@/types/i18n';
// Fonction utilitaire simple pour combiner les classes
const mergeClasses = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface ModernNavigationProps {
translations: Translation['navigation'];
languageSwitcher: React.ReactElement;
@ -47,33 +51,37 @@ export const ModernNavigation: React.FC<ModernNavigationProps> = ({
return (
<>
{/* Navigation Bar - Design fixe moderne */}
<nav
className={cn(
'fixed top-0 left-0 right-0 z-50',
'shadow-banquise-lg border-b'
)}
style={{
backgroundColor: 'var(--banquise-blue-800)',
borderBottomColor: 'var(--banquise-blue-700)'
}}
>
{/* Navigation moderne épurée */}
<nav className={mergeClasses(
// Position et z-index
'fixed top-0 left-0 right-0 z-50',
// Style de fond moderne
'bg-blue-700/95 backdrop-blur-md border-b border-blue-600/30',
// Transition fluide
'transition-all duration-200 ease-in-out',
// Effet de scroll
scrolled && 'shadow-lg'
)}>
<div className="max-w-7xl mx-auto">
<div className="flex justify-between items-center px-4 sm:px-6 lg:px-8 h-16">
{/* Logo Section */}
<Logo scrolled={false} />
<Logo scrolled={scrolled} />
{/* Navigation Links (Desktop) */}
<NavLinks
translations={translations}
scrolled={false}
className="flex-1 justify-center ml-8"
/>
{/* Navigation Links (Desktop) - Centré */}
<div className="flex-1 flex justify-center">
<NavLinks
translations={translations}
scrolled={scrolled}
/>
</div>
{/* Action Buttons (Desktop) */}
<ActionButtons
scrolled={false}
scrolled={scrolled}
languageSwitcher={languageSwitcher}
/>
@ -85,10 +93,8 @@ export const ModernNavigation: React.FC<ModernNavigationProps> = ({
</div>
</div>
{/* Effet de bordure dégradée moderne */}
<div className="absolute bottom-0 left-0 right-0">
<div className="h-px bg-gradient-to-r from-transparent via-banquise-blue-200/40 to-transparent" />
</div>
{/* Ligne de séparation moderne */}
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-blue-400/40 to-transparent" />
</nav>
{/* Spacer pour compenser la navbar fixed */}

View File

@ -1,57 +1,73 @@
import React from 'react';
import { Button } from '../../common/Button';
// UserProfile removed from navbar
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import { URLS } from '@/lib/config/constants';
// Fonction utilitaire simple pour combiner les classes
const mergeClasses = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface ActionButtonsProps {
scrolled: boolean;
scrolled?: boolean;
languageSwitcher: React.ReactElement;
className?: string;
}
export const ActionButtons: React.FC<ActionButtonsProps> = ({
scrolled,
scrolled = false,
languageSwitcher,
className
}) => {
return (
<div className={cn('hidden md:flex items-center space-x-3', className)}>
{/* Language Switcher */}
<div className={mergeClasses(
'hidden md:flex items-center space-x-3',
className
)}>
{/* Sélecteur de langue moderne */}
<div className="relative">
{languageSwitcher}
</div>
{/* Discord Button */}
<Button
variant="discord"
size="sm"
leftIcon={
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
}
{/* Bouton Discord moderne */}
<button
onClick={() => window.open(URLS.social.discord, '_blank')}
className="hidden lg:flex"
className={mergeClasses(
// Base styles
'inline-flex items-center px-4 py-2.5 text-sm font-medium',
'bg-indigo-600 text-white rounded-xl border border-indigo-500/20',
'transition-all duration-200 ease-in-out',
'hover:bg-indigo-700 hover:scale-[1.02] hover:shadow-lg hover:shadow-indigo-500/25',
'focus:outline-none focus:ring-2 focus:ring-indigo-400/50',
'active:scale-[0.98]',
// Mobile adaptation
'hidden lg:flex'
)}
aria-label="Rejoindre notre Discord"
>
Discord
</Button>
{/* Discord Icon Only (tablet) */}
<Button
variant="discord"
size="sm"
onClick={() => window.open(URLS.social.discord, '_blank')}
className="lg:hidden"
aria-label="Rejoindre Discord"
>
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<svg className="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
</Button>
{/* Previously there was an auth button and user profile here; removed per request */}
Discord
</button>
{/* Version icon seulement pour les écrans moyens */}
<button
onClick={() => window.open(URLS.social.discord, '_blank')}
className={mergeClasses(
'flex lg:hidden items-center justify-center w-10 h-10',
'bg-indigo-600 text-white rounded-xl border border-indigo-500/20',
'transition-all duration-200 ease-in-out',
'hover:bg-indigo-700 hover:scale-[1.02] hover:shadow-lg hover:shadow-indigo-500/25',
'focus:outline-none focus:ring-2 focus:ring-indigo-400/50',
'active:scale-[0.98]'
)}
aria-label="Rejoindre Discord"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
</button>
</div>
);
};

View File

@ -1,51 +1,63 @@
import React from 'react';
import Image from 'next/image';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import { SITE_CONFIG } from '@/lib/config/constants';
// Fonction utilitaire simple pour combiner les classes
const mergeClasses = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface LogoProps {
scrolled: boolean;
scrolled?: boolean;
className?: string;
}
export const Logo: React.FC<LogoProps> = ({ scrolled, className }) => {
export const Logo: React.FC<LogoProps> = ({ scrolled = false, className }) => {
return (
<div className={cn('flex items-center group cursor-pointer', className)}>
{/* Logo avec effet glow */}
<div className={mergeClasses(
'flex items-center group cursor-pointer transition-all duration-200',
className
)}>
{/* Logo moderne avec effet subtil */}
<div className="relative flex items-center">
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/30 to-banquise-blue/30 rounded-full blur-md opacity-0 group-hover:opacity-100 transition-all duration-300 scale-110"></div>
<div className={cn(
'relative flex items-center justify-center rounded-full p-2 bg-white/10 backdrop-blur-sm border border-white/20 transition-all duration-300',
'group-hover:bg-white/20 group-hover:scale-105 group-hover:border-white/30'
{/* Effet de glow moderne et subtil */}
<div className="absolute inset-0 bg-blue-400/20 rounded-2xl blur-lg opacity-0 group-hover:opacity-100 transition-all duration-300 scale-125"></div>
{/* Container du logo */}
<div className={mergeClasses(
'relative flex items-center justify-center rounded-2xl transition-all duration-200',
'bg-white/10 backdrop-blur-sm border border-white/20',
'group-hover:bg-white/15 group-hover:scale-[1.02] group-hover:border-white/30',
scrolled ? 'p-2' : 'p-2.5'
)}>
<Image
src="/assets/banquise_server.svg"
alt="Logo La Banquise"
width={scrolled ? 32 : 40}
height={scrolled ? 32 : 40}
className={cn('transition-all duration-300 group-hover:scale-110')}
style={{ filter: 'drop-shadow(0 4px 12px rgba(168, 218, 255, 0.4))' }}
alt={SITE_CONFIG.name}
width={scrolled ? 28 : 32}
height={scrolled ? 28 : 32}
className="transition-all duration-200 group-hover:scale-105"
style={{
filter: 'drop-shadow(0 2px 8px rgba(59, 130, 246, 0.3))'
}}
/>
</div>
</div>
{/* Brand text avec animation */}
{/* Texte de marque épuré */}
<div className="ml-3 hidden sm:block">
<h1 className={cn(
'font-heading font-bold text-white tracking-tight transition-all duration-300',
scrolled ? 'text-lg' : 'text-xl lg:text-2xl',
'group-hover:text-banquise-blue-lightest'
<h1 className={mergeClasses(
'font-semibold text-white tracking-tight transition-all duration-200',
scrolled ? 'text-base' : 'text-lg lg:text-xl',
'group-hover:text-blue-100'
)}>
{SITE_CONFIG.name}
</h1>
<p className={cn(
'text-banquise-blue-lightest/70 font-medium transition-all duration-300',
scrolled ? 'text-xs' : 'text-sm',
'group-hover:text-banquise-blue-lightest/90'
)}>
{SITE_CONFIG.tagline}
</p>
{!scrolled && (
<p className="text-xs text-white/70 font-medium transition-all duration-200 group-hover:text-white/90">
{SITE_CONFIG.tagline}
</p>
)}
</div>
</div>
);

View File

@ -1,5 +1,9 @@
import React from 'react';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
// Fonction utilitaire simple pour combiner les classes
const cn = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface MobileMenuButtonProps {
isOpen: boolean;
@ -19,7 +23,7 @@ export const MobileMenuButton: React.FC<MobileMenuButtonProps> = ({
'bg-white/10 hover:bg-white/20 active:bg-white/25',
'border border-white/20 hover:border-white/30',
'hover:scale-105 active:scale-95',
'focus:outline-none focus:ring-2 focus:ring-banquise-blue-light/50',
'focus:outline-none focus:ring-2 focus:ring-blue-400/50',
className
)}
onClick={onClick}
@ -43,7 +47,7 @@ export const MobileMenuButton: React.FC<MobileMenuButtonProps> = ({
</div>
{/* Subtle glow effect on hover */}
<div className="absolute inset-0 rounded-xl bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
<div className="absolute inset-0 rounded-xl bg-gradient-to-r from-blue-400/20 to-blue-600/20 opacity-0 group-hover:opacity-100 transition-opacity duration-300" />
</button>
);
};

View File

@ -1,10 +1,14 @@
import React from 'react';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import type { Translation } from '@/types/i18n';
// Fonction utilitaire simple pour combiner les classes
const mergeClasses = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface NavLinksProps {
translations: Translation['navigation'];
scrolled: boolean;
scrolled?: boolean;
className?: string;
}
@ -19,26 +23,26 @@ const NavLink: React.FC<NavLinkProps> = ({ href, children, isActive = false, onC
return (
<a
href={href}
onClick={onClick}
className={cn(
'relative px-4 py-2 text-sm font-medium transition-all duration-300 rounded-lg group',
'hover:text-white focus:outline-none focus:ring-2 focus:ring-banquise-blue-light/50',
onClick={(e) => {
e.preventDefault();
onClick?.();
}}
className={mergeClasses(
// Base styles
'relative px-4 py-2.5 text-sm font-medium transition-all duration-200 rounded-xl',
'focus:outline-none focus:ring-2 focus:ring-blue-400/50',
// États conditionnels
isActive
? 'text-white bg-white/20 shadow-lg'
: 'text-white/80 hover:bg-white/10'
? 'text-white bg-white/15 shadow-sm backdrop-blur-sm border border-white/20'
: 'text-white/80 hover:text-white hover:bg-white/10'
)}
>
<span className="relative z-10">{children}</span>
{/* Hover effect */}
<div className={cn(
'absolute inset-0 rounded-lg bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20',
'opacity-0 group-hover:opacity-100 transition-all duration-300 scale-95 group-hover:scale-100'
)} />
{/* Active indicator */}
{/* Indicateur actif moderne */}
{isActive && (
<div className="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-6 h-0.5 bg-banquise-blue-lightest rounded-full" />
<div className="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-1 h-1 bg-blue-300 rounded-full" />
)}
</a>
);
@ -47,30 +51,26 @@ const NavLink: React.FC<NavLinkProps> = ({ href, children, isActive = false, onC
export const NavLinks: React.FC<NavLinksProps> = ({ translations, className }) => {
const [activeSection, setActiveSection] = React.useState<string>('home');
// Observer pour détecter la section active
// Observer pour détecter la section active (simplifié)
React.useEffect(() => {
const handleScroll = () => {
const scrollPosition = window.scrollY;
const windowHeight = window.innerHeight;
// Si on est en haut de la page (moins de 100px du haut), on active "home"
if (scrollPosition < 100) {
// Si on est en haut de la page
if (scrollPosition < 200) {
setActiveSection('home');
return;
}
// Sinon, on utilise l'intersection observer logic
const sections = ['home', 'services', 'about'];
// Détection des sections
const sections = ['services', 'about'];
let currentSection = 'home';
sections.forEach((sectionId) => {
const element = document.getElementById(sectionId);
if (element) {
const rect = element.getBoundingClientRect();
const sectionTop = rect.top + scrollPosition;
// Si la section est visible dans le viewport
if (scrollPosition >= sectionTop - windowHeight / 3) {
if (rect.top <= 200 && rect.bottom >= 200) {
currentSection = sectionId;
}
}
@ -79,65 +79,35 @@ export const NavLinks: React.FC<NavLinksProps> = ({ translations, className }) =
setActiveSection(currentSection);
};
// Écouter le scroll
window.addEventListener('scroll', handleScroll);
// Appeler une fois au chargement
window.addEventListener('scroll', handleScroll, { passive: true });
handleScroll();
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
// Observer pour détecter la section active avec IntersectionObserver (fallback)
React.useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && window.scrollY > 100) {
setActiveSection(entry.target.id);
}
});
},
{
threshold: 0.3,
rootMargin: '-100px 0px -100px 0px'
}
);
const sections = ['home', 'services', 'about'];
sections.forEach((id) => {
const element = document.getElementById(id);
if (element) observer.observe(element);
});
return () => observer.disconnect();
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const handleNavClick = (sectionId: string) => {
if (sectionId === 'home') {
// Scroll to top for home section
window.scrollTo({
top: 0,
behavior: 'smooth'
});
window.scrollTo({ top: 0, behavior: 'smooth' });
} else if (sectionId === 'contact') {
// Open email client for contact
window.location.href = 'mailto:contact@la-banquise.fr';
} else {
// Scroll to specific section
const element = document.getElementById(sectionId);
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start'
const navHeight = 64; // Hauteur de la navbar
const elementPosition = element.offsetTop - navHeight;
window.scrollTo({
top: elementPosition,
behavior: 'smooth'
});
}
}
};
return (
<nav className={cn('hidden md:flex items-center space-x-1', className)}>
<nav className={mergeClasses(
'hidden md:flex items-center space-x-2',
className
)}>
<NavLink
href="#home"
isActive={activeSection === 'home'}

View File

@ -1,7 +1,6 @@
import React from 'react';
import { AccordionItem } from '@/components/ui/AccordionItem';
import { URLS } from '@/lib/config/constants';
import { commonStyles } from '@/lib/styles/components';
interface AboutSectionProps {
openAccordion: string | null;
@ -9,23 +8,26 @@ interface AboutSectionProps {
}
export const AboutSection: React.FC<AboutSectionProps> = ({ openAccordion, toggleAccordion }) => (
<section id="about" className="relative py-16 sm:py-20 md:py-24 px-4 sm:px-6 md:px-8 z-2 w-full box-border">
<div className="max-w-4xl mx-auto">
{/* Header */}
<div className="text-center mb-12 sm:mb-16 md:mb-20">
<h2 className={`${commonStyles.text.headingXl} mb-6 sm:mb-8 px-2`} style={{ textShadow: '0 2px 4px rgba(0, 0, 0, 0.2)' }}>
<section id="about" className="py-24 md:py-32 px-4 sm:px-6 lg:px-8 bg-white">
<div className="max-w-6xl mx-auto">
{/* Header de section moderne */}
<div className="text-center mb-20">
{/* Séparateur visuel */}
<div className="w-24 h-1.5 bg-gradient-to-r from-blue-600 to-blue-400 rounded-full mx-auto mb-8" />
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold text-gray-900 mb-6 leading-tight">
À Propos de La Banquise
</h2>
<p className={`${commonStyles.text.muted} text-lg sm:text-xl max-w-3xl mx-auto px-2`} style={{ textShadow: '0 1px 2px rgba(0, 0, 0, 0.1)' }}>
<p className="text-lg md:text-xl text-gray-700 max-w-4xl mx-auto leading-relaxed font-medium">
Une communauté passionnée qui propose des services d&apos;hébergement et des outils collaboratifs pour les développeurs et les gamers.
</p>
</div>
{/* FAQ Section */}
<div className="space-y-4 sm:space-y-6">
<h3 className={`${commonStyles.text.headingLg} mb-8 sm:mb-12 flex items-center justify-center px-2`}>
<span className="text-2xl sm:text-3xl mr-3"></span>
<span className="text-center">Questions Fréquentes</span>
{/* Section FAQ avec design moderne */}
<div className="space-y-8">
<h3 className="text-2xl md:text-3xl font-bold text-gray-800 mb-12 flex items-center justify-center">
<span className="text-3xl mr-4 bg-gradient-to-r from-blue-600 to-blue-400 bg-clip-text text-transparent"></span>
<span>Questions Fréquentes</span>
</h3>
<AccordionItem
@ -33,18 +35,18 @@ export const AboutSection: React.FC<AboutSectionProps> = ({ openAccordion, toggl
isOpen={openAccordion === "mission"}
onToggle={() => toggleAccordion("mission")}
>
<div className="space-y-4">
<p className={commonStyles.text.muted}>
Former les étudiants au déploiment et a la gestion d&apos;une infra, et de maitriser des technologies entreprise grade.
<div className="space-y-6 p-6 bg-gray-50 rounded-xl">
<p className="text-gray-700 leading-relaxed">
Former les étudiants au déploiement et à la gestion d&apos;une infrastructure, et de maîtriser des technologies entreprise grade.
Cela permet de fournir une plateforme stable et accessible pour héberger vos projets, partager vos connaissances et jouer ensemble !
</p>
<p className={commonStyles.text.muted}>
<p className="text-gray-700 leading-relaxed">
Nous croyons en la puissance de la collaboration et mettons à disposition des outils modernes pour faciliter le travail en équipe.
</p>
<div className="flex flex-wrap gap-2 mt-4">
<span className="bg-banquise-blue/20 text-banquise-blue-light px-3 py-1 rounded-full text-sm font-medium">Collaboration</span>
<span className="bg-banquise-blue/20 text-banquise-blue-light px-3 py-1 rounded-full text-sm font-medium">Innovation</span>
<span className="bg-banquise-blue/20 text-banquise-blue-light px-3 py-1 rounded-full text-sm font-medium">Accessibilité</span>
<div className="flex flex-wrap gap-3 mt-6">
<span className="bg-blue-100 text-blue-800 px-4 py-2 rounded-full text-sm font-semibold border border-blue-200">Collaboration</span>
<span className="bg-blue-100 text-blue-800 px-4 py-2 rounded-full text-sm font-semibold border border-blue-200">Innovation</span>
<span className="bg-blue-100 text-blue-800 px-4 py-2 rounded-full text-sm font-semibold border border-blue-200">Accessibilité</span>
</div>
</div>
</AccordionItem>
@ -54,66 +56,67 @@ export const AboutSection: React.FC<AboutSectionProps> = ({ openAccordion, toggl
isOpen={openAccordion === "services"}
onToggle={() => toggleAccordion("services")}
>
<div className="space-y-6">
<div className="grid gap-4">
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>📚</div>
<div className="space-y-6 p-6 bg-gray-50 rounded-xl">
<div className="grid gap-6 md:grid-cols-2">
{/* Cartes de services avec design moderne */}
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg">📚</div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">Wiki</h4>
<p className="text-banquise-gray/80 text-sm">Documentation collaborative et guides détaillés</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">Wiki</h4>
<p className="text-gray-600">Documentation collaborative et guides détaillés</p>
</div>
</div>
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>🔧</div>
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg">🔧</div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">Gitea</h4>
<p className="text-banquise-gray/80 text-sm">Gestion de versions Git auto-hébergée</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">Gitea</h4>
<p className="text-gray-600">Gestion de versions Git auto-hébergée</p>
</div>
</div>
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>🎮</div>
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg">🎮</div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">Panel de Jeux</h4>
<p className="text-banquise-gray/80 text-sm">Interface de gestion pour serveurs de jeux</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">Panel de Jeux</h4>
<p className="text-gray-600">Interface de gestion pour serveurs de jeux</p>
</div>
</div>
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>🐧</div>
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg">🐧</div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">Pelican</h4>
<p className="text-banquise-gray/80 text-sm">Générateur de sites statiques</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">Pelican</h4>
<p className="text-gray-600">Générateur de sites statiques</p>
</div>
</div>
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>🏢</div>
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg">🏢</div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">Intranet</h4>
<p className="text-banquise-gray/80 text-sm">Espace privé de l&apos;association</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">Intranet</h4>
<p className="text-gray-600">Espace privé de l&apos;association</p>
</div>
</div>
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}>📧</div>
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg">📧</div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">Webmail</h4>
<p className="text-banquise-gray/80 text-sm">Service de messagerie électronique</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">Webmail</h4>
<p className="text-gray-600">Service de messagerie électronique</p>
</div>
</div>
<div className={`flex items-start space-x-4 p-4 ${commonStyles.gradients.card} rounded-xl ${commonStyles.cards.base}`}>
<div className={`${commonStyles.icons.small} ${commonStyles.gradients.primaryBr} font-bold`}></div>
<div className="flex items-start space-x-4 p-6 bg-white rounded-xl shadow-lg border border-gray-200 hover:shadow-xl transition-all duration-300 md:col-span-2">
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center text-white text-xl font-bold shadow-lg"></div>
<div>
<h4 className="font-semibold text-banquise-gray mb-1">OpenCloud</h4>
<p className="text-banquise-gray/80 text-sm">Plateforme cloud collaborative</p>
<h4 className="font-bold text-gray-900 mb-2 text-lg">OpenCloud</h4>
<p className="text-gray-600">Plateforme cloud collaborative pour tous vos besoins</p>
</div>
</div>
</div>
<p className={`${commonStyles.text.muted} mt-4`}>
Tous nos services sont maintenus avec soin et régulièrement mis à jour pour garantir une expérience optimale.
<p className="text-gray-600 mt-6 p-4 bg-blue-50 rounded-lg border border-blue-200">
<strong className="text-blue-800">💡 Tous nos services</strong> sont maintenus avec soin et régulièrement mis à jour pour garantir une expérience optimale.
</p>
</div>
</AccordionItem>
@ -123,27 +126,36 @@ export const AboutSection: React.FC<AboutSectionProps> = ({ openAccordion, toggl
isOpen={openAccordion === "community"}
onToggle={() => toggleAccordion("community")}
>
<div className="space-y-6">
<p className={commonStyles.text.muted}>
<div className="space-y-8 p-6 bg-gray-50 rounded-xl">
<p className="text-gray-700 text-lg leading-relaxed">
Rejoignez notre serveur Discord pour rejoindre l&apos;asso, échanger avec nous, obtenir de l&apos;aide et rester informé des dernières nouveautés !
</p>
<div className={`${commonStyles.cards.base} bg-gradient-to-r from-banquise-blue-dark/20 to-banquise-blue/10 rounded-2xl p-6`}>
<h4 className="font-semibold text-banquise-gray mb-3 flex items-center">
<span className="text-xl mr-2">💬</span>
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-blue-200 rounded-2xl p-8">
<h4 className="font-bold text-gray-900 mb-6 flex items-center text-xl">
<span className="text-2xl mr-3">💬</span>
Comment rejoindre l&apos;asso ?
</h4>
<ul className="space-y-2 text-banquise-gray/80 text-sm mb-6">
<li className="flex items-center"><span className="text-banquise-blue-light mr-2"></span> Creez un ticket banquise</li>
<li className="flex items-center"><span className="text-banquise-blue-light mr-2"></span> Donnez votre login EPITA ou expliquez votre situation</li>
<li className="flex items-center"><span className="text-banquise-blue-light mr-2"></span> Un moderateur validera votre demande et vous donnera acces aux salons discord de l&apos;asso !</li>
<ul className="space-y-4 text-gray-700 mb-8">
<li className="flex items-center text-lg">
<span className="w-2 h-2 bg-blue-500 rounded-full mr-4"></span>
Créez un ticket banquise
</li>
<li className="flex items-center text-lg">
<span className="w-2 h-2 bg-blue-500 rounded-full mr-4"></span>
Donnez votre login EPITA ou expliquez votre situation
</li>
<li className="flex items-center text-lg">
<span className="w-2 h-2 bg-blue-500 rounded-full mr-4"></span>
Un modérateur validera votre demande et vous donnera accès aux salons discord de l&apos;asso !
</li>
</ul>
<a
href={URLS.social.discord}
className={`${commonStyles.buttons.primary} ${commonStyles.gradients.primary} py-3 px-6 rounded-xl`}
className="inline-flex items-center justify-center px-8 py-4 text-lg font-bold text-white bg-gradient-to-r from-blue-600 to-blue-500 rounded-xl shadow-xl hover:shadow-2xl hover:from-blue-700 hover:to-blue-600 transition-all duration-300 transform hover:scale-105 border-2 border-blue-600/20"
>
<span className="mr-3 text-lg">🚀</span>
<span className="mr-3 text-xl">🚀</span>
Rejoindre Discord
</a>
</div>

View File

@ -7,56 +7,107 @@ interface HeroSectionProps {
}
export const HeroSection: React.FC<HeroSectionProps> = ({ translations }) => (
<section id="home" className="min-h-[calc(80vh-72px)] flex flex-col justify-center items-center text-center py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8 relative z-3">
<section
id="home"
className="min-h-screen flex flex-col justify-center items-center text-center relative px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-gray-50 via-blue-50/30 to-gray-100"
>
{/* Motif de fond subtil avec grille */}
<div
className="mb-8 sm:mb-10 md:mb-12 w-32 h-32 sm:w-40 sm:h-40 md:w-48 md:h-48 rounded-full p-4 sm:p-5 md:p-6 shadow-2xl backdrop-blur-sm border relative group"
className="absolute inset-0 opacity-20"
style={{
background: 'linear-gradient(to bottom right, rgba(31, 80, 120, 0.2), rgba(52, 166, 252, 0.1))',
borderColor: 'rgba(160, 236, 249, 0.3)'
backgroundImage: 'radial-gradient(circle at 1px 1px, rgba(59,130,246,0.3) 1px, transparent 0)',
backgroundSize: '40px 40px'
}}
>
<Image
src="/assets/banquise_server.svg"
alt="Logo La Banquise"
width={192}
height={192}
className="w-full h-full object-contain relative z-10 transition-transform duration-300 group-hover:scale-110"
style={{ filter: 'drop-shadow(0 10px 25px rgba(31, 93, 137, 0.3))' }}
/>
{/* Contenu principal */}
<div className="relative z-10 max-w-5xl mx-auto">
{/* Logo principal avec effet moderne */}
<div className="mb-16 group">
<div className="relative inline-block">
{/* Effet de glow au hover */}
<div className="absolute inset-0 bg-blue-400/30 rounded-3xl blur-3xl opacity-0 group-hover:opacity-100 transition-all duration-700 scale-150" />
{/* Container du logo avec glassmorphism */}
<div className="relative bg-white/90 backdrop-blur-lg rounded-3xl p-10 border border-blue-200/50 shadow-2xl transition-all duration-500 group-hover:shadow-blue-200/50 group-hover:shadow-3xl group-hover:scale-105">
<Image
src="/assets/banquise_server.svg"
alt={translations.title}
width={140}
height={140}
className="w-28 h-28 md:w-32 md:h-32 lg:w-36 lg:h-36 transition-transform duration-500 group-hover:scale-110"
style={{
filter: 'drop-shadow(0 8px 24px rgba(59, 130, 246, 0.4))'
}}
/>
</div>
</div>
</div>
{/* Titre principal avec gradient moderne */}
<h1 className="text-4xl md:text-5xl lg:text-7xl font-bold leading-tight tracking-tight mb-8 bg-gradient-to-r from-gray-900 via-blue-700 to-gray-900 bg-clip-text text-transparent">
{translations.title}
</h1>
{/* Sous-titre avec contraste amélioré */}
<p className="text-lg md:text-xl lg:text-2xl text-gray-700 mx-auto max-w-3xl mb-14 leading-relaxed font-medium">
{translations.subtitle}
</p>
{/* Call-to-action super mis en valeur */}
<div className="flex flex-col sm:flex-row gap-6 justify-center items-center mb-20">
{/* Bouton principal très visible */}
<a
href="#services"
onClick={(e) => {
e.preventDefault();
document.getElementById('services')?.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}}
className="group relative inline-flex items-center justify-center px-12 py-5 text-lg font-bold text-white bg-gradient-to-r from-blue-600 to-blue-500 rounded-2xl shadow-2xl hover:shadow-blue-500/50 transition-all duration-300 transform hover:scale-110 hover:-translate-y-2 active:scale-95 border-2 border-blue-600/20"
>
{/* Effet de brillance au hover */}
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 rounded-2xl" />
<span className="relative z-10">{translations.cta}</span>
<svg
className="relative z-10 ml-3 w-6 h-6 transition-transform duration-300 group-hover:translate-x-2"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</a>
/>
{/* Bouton secondaire épuré */}
<a
href="#about"
onClick={(e) => {
e.preventDefault();
document.getElementById('about')?.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}}
className="inline-flex items-center justify-center px-8 py-4 text-lg font-semibold text-blue-700 bg-white border-2 border-blue-600 rounded-xl shadow-lg hover:shadow-xl hover:bg-blue-50 hover:scale-105 transition-all duration-300 active:scale-95"
>
En savoir plus
</a>
</div>
{/* Indicateur de scroll moderne */}
<div className="absolute bottom-12 left-1/2 transform -translate-x-1/2 animate-bounce">
<div className="flex flex-col items-center space-y-2">
<span className="text-sm text-gray-500 font-medium">Découvrir</span>
<div className="w-6 h-10 border-2 border-blue-400 rounded-full flex justify-center bg-white/50 backdrop-blur-sm">
<div className="w-1.5 h-3 bg-blue-500 rounded-full mt-2 animate-pulse" />
</div>
</div>
</div>
</div>
<h1
className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-6 sm:mb-7 md:mb-8 font-extrabold leading-tight max-w-4xl font-heading px-2 relative z-10"
style={{
color: 'var(--banquise-blue-900)',
textShadow: '0 2px 10px rgba(0, 0, 0, 0.3)'
}}
>
{translations.title}
</h1>
<p
className="text-lg sm:text-xl md:text-2xl mb-8 sm:mb-10 md:mb-12 max-w-3xl font-normal opacity-90 leading-relaxed px-2 relative z-10"
style={{
color: 'var(--banquise-slate-700)',
textShadow: '0 1px 4px rgba(0, 0, 0, 0.2)'
}}
>
{translations.subtitle}
</p>
<a
href="#services"
className="inline-flex items-center justify-center border-0 py-4 sm:py-5 px-8 sm:px-10 md:px-12 rounded-2xl text-base sm:text-lg font-bold no-underline shadow-xl transition-all duration-300 min-w-48 sm:min-w-56 md:min-w-64 hover:-translate-y-2 hover:shadow-2xl hover:scale-105 backdrop-blur-sm border mx-4 group relative z-10"
style={{
background: 'linear-gradient(to right, var(--banquise-slate-100), var(--banquise-white))',
color: 'var(--banquise-blue-800)',
borderColor: 'rgba(160, 236, 249, 0.2)'
}}
>
<span className="text-center" style={{ color: 'var(--banquise-blue-800)' }}>{translations.cta}</span>
<span className="ml-2 sm:ml-3 text-lg sm:text-xl transition-transform duration-300 group-hover:translate-x-1" style={{ color: 'var(--banquise-blue-800)' }}></span>
</a>
</section>
);

View File

@ -1,6 +1,5 @@
import React from 'react';
import { ServiceCard } from '@/components/common/ServiceCard';
//import { componentStyles } from '@/lib/styles/designSystem';
import type { Service } from '@/types/service';
interface ServicesSectionProps {
@ -13,42 +12,40 @@ interface ServicesSectionProps {
export const ServicesSection: React.FC<ServicesSectionProps> = ({
services,
onServiceClick
onServiceClick,
translations
}) => (
<section id="services" className="relative z-2 py-12 sm:py-16 md:py-20 w-full max-w-6xl mx-auto px-4 sm:px-6 md:px-8">
<div
className="w-20 h-1 mx-auto mb-6 sm:mb-8 rounded-full"
style={{
background: 'linear-gradient(to right, var(--banquise-blue-200), var(--banquise-blue-600))'
}}
></div>
<h2
className="text-2xl sm:text-3xl md:text-4xl mb-4 sm:mb-6 text-center font-heading font-bold tracking-tight px-2"
style={{
color: 'var(--banquise-blue-900)',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.2)'
}}
>
Nos Services
</h2>
<p
className="text-lg sm:text-xl opacity-90 mb-12 sm:mb-14 md:mb-16 max-w-4xl text-center mx-auto leading-relaxed px-2"
style={{
color: 'var(--banquise-slate-700)',
textShadow: '0 1px 3px rgba(0, 0, 0, 0.2)'
}}
>
Cliquez sur un service pour découvrir toutes ses fonctionnalités
</p>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 sm:gap-8 w-full">
{services.map((service) => (
<ServiceCard
key={service.name}
service={service}
onServiceClick={onServiceClick}
/>
))}
<section
id="services"
className="py-24 md:py-32 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-white via-blue-50/30 to-gray-50"
>
<div className="max-w-7xl mx-auto">
{/* Header de section moderne avec forte hiérarchie */}
<div className="text-center mb-20">
{/* Séparateur visuel moderne */}
<div className="w-24 h-1.5 bg-gradient-to-r from-blue-600 to-blue-400 rounded-full mx-auto mb-8" />
{/* Titre principal avec contraste fort */}
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold text-gray-900 mb-6 leading-tight">
Nos Services
</h2>
{/* Sous-titre avec bon contraste */}
<p className="text-lg md:text-xl text-gray-700 mx-auto max-w-3xl leading-relaxed font-medium">
{translations.discoverFeatures}
</p>
</div>
{/* Grille de services avec espacement généreux */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-12">
{services.map((service) => (
<ServiceCard
key={service.name}
service={service}
onServiceClick={onServiceClick}
/>
))}
</div>
</div>
</section>
);

View File

@ -1,7 +1,11 @@
import React, { useState } from 'react';
import { mergeClasses as cn } from '@/lib/styles/designSystem';
import type { Language } from '@/types/i18n';
// Fonction utilitaire simple pour combiner les classes
const cn = (...classes: (string | undefined | null | false)[]): string => {
return classes.filter(Boolean).join(' ');
};
interface ModernLanguageSwitcherProps {
currentLanguage: Language;
onLanguageChange: (language: Language) => void;
@ -31,7 +35,7 @@ export const ModernLanguageSwitcher: React.FC<ModernLanguageSwitcherProps> = ({
'flex items-center space-x-2 px-3 py-2 rounded-lg transition-all duration-200',
'bg-white/10 hover:bg-white/20 border border-white/20 hover:border-white/30',
'text-white text-sm font-medium',
'focus:outline-none focus:ring-2 focus:ring-banquise-blue-light/50',
'focus:outline-none focus:ring-2 focus:ring-blue-400/50',
'group'
)}
aria-expanded={isOpen}
@ -83,11 +87,11 @@ export const ModernLanguageSwitcher: React.FC<ModernLanguageSwitcherProps> = ({
}}
className={cn(
'w-full flex items-center space-x-3 px-4 py-2.5 text-sm transition-all duration-200',
'hover:bg-banquise-blue/10 focus:bg-banquise-blue/10',
'hover:bg-blue-600/10 focus:bg-blue-600/10',
'focus:outline-none',
isSelected
? 'text-banquise-blue-dark font-semibold bg-banquise-blue/10'
: 'text-gray-700 hover:text-banquise-blue-dark'
? 'text-blue-800 font-semibold bg-blue-600/10'
: 'text-gray-700 hover:text-blue-800'
)}
role="option"
aria-selected={isSelected}
@ -95,7 +99,7 @@ export const ModernLanguageSwitcher: React.FC<ModernLanguageSwitcherProps> = ({
<span className="text-lg">{config.flag}</span>
<span className="flex-1 text-left">{config.name}</span>
{isSelected && (
<svg className="w-4 h-4 text-banquise-blue" fill="currentColor" viewBox="0 0 20 20">
<svg className="w-4 h-4 text-blue-600" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
)}

File diff suppressed because it is too large Load Diff