Improve onboarding section across home and about
All checks were successful
Deploy Sokko G / deploy (push) Successful in 8s
|
|
@ -81,10 +81,12 @@ export function validateSiteContent(site) {
|
|||
"home.stats.toolboxPlural",
|
||||
"home.stats.toolSingular",
|
||||
"home.stats.toolPlural",
|
||||
"home.orientation.ariaLabel",
|
||||
"home.startMap.eyebrow",
|
||||
"home.startMap.title",
|
||||
"home.startMap.description",
|
||||
"home.onboarding.eyebrow",
|
||||
"home.onboarding.title",
|
||||
"home.onboarding.description",
|
||||
"home.onboarding.stepsTitle",
|
||||
"home.onboarding.sliderLabel",
|
||||
"home.onboarding.slideButtonLabel",
|
||||
"home.origin.eyebrow",
|
||||
"home.origin.title",
|
||||
"home.origin.visualAlt",
|
||||
|
|
@ -531,27 +533,39 @@ export function validateSiteContent(site) {
|
|||
assertNonEmptyString({ tool }, "tool.description");
|
||||
});
|
||||
|
||||
const orientationCards = valueAt(site, "home.orientation.cards");
|
||||
assert.ok(Array.isArray(orientationCards), "home.orientation.cards must be an array");
|
||||
assert.ok(orientationCards.length >= 2, "home.orientation.cards must contain at least 2 items");
|
||||
orientationCards.forEach((card, index) => {
|
||||
assert.equal(typeof card, "object", `home.orientation.cards[${index}] must be an object`);
|
||||
const onboardingCards = valueAt(site, "home.onboarding.cards");
|
||||
assert.ok(Array.isArray(onboardingCards), "home.onboarding.cards must be an array");
|
||||
assert.ok(onboardingCards.length >= 2, "home.onboarding.cards must contain at least 2 items");
|
||||
onboardingCards.forEach((card, index) => {
|
||||
assert.equal(typeof card, "object", `home.onboarding.cards[${index}] must be an object`);
|
||||
assertNonEmptyString({ card }, "card.icon");
|
||||
assertNonEmptyString({ card }, "card.image");
|
||||
assertNonEmptyString({ card }, "card.title");
|
||||
assertNonEmptyString({ card }, "card.text");
|
||||
assertNonEmptyString({ card }, "card.action");
|
||||
assertNonEmptyString({ card }, "card.href");
|
||||
});
|
||||
|
||||
const startMapSteps = valueAt(site, "home.startMap.steps");
|
||||
assert.ok(Array.isArray(startMapSteps), "home.startMap.steps must be an array");
|
||||
assert.ok(startMapSteps.length >= 1, "home.startMap.steps must contain at least 1 item");
|
||||
startMapSteps.forEach((step, index) => {
|
||||
assert.equal(typeof step, "object", `home.startMap.steps[${index}] must be an object`);
|
||||
const onboardingSteps = valueAt(site, "home.onboarding.steps");
|
||||
assert.ok(Array.isArray(onboardingSteps), "home.onboarding.steps must be an array");
|
||||
assert.ok(onboardingSteps.length >= 1, "home.onboarding.steps must contain at least 1 item");
|
||||
onboardingSteps.forEach((step, index) => {
|
||||
assert.equal(typeof step, "object", `home.onboarding.steps[${index}] must be an object`);
|
||||
assertNonEmptyString({ step }, "step.title");
|
||||
assertNonEmptyString({ step }, "step.text");
|
||||
});
|
||||
|
||||
const onboardingSlides = valueAt(site, "home.onboarding.slides");
|
||||
assert.ok(Array.isArray(onboardingSlides), "home.onboarding.slides must be an array");
|
||||
assert.equal(onboardingSlides.length, 4, "home.onboarding.slides must contain 4 items");
|
||||
onboardingSlides.forEach((slide, index) => {
|
||||
assert.equal(typeof slide, "object", `home.onboarding.slides[${index}] must be an object`);
|
||||
assertNonEmptyString({ slide }, "slide.src");
|
||||
assertNonEmptyString({ slide }, "slide.alt");
|
||||
assertNonEmptyString({ slide }, "slide.title");
|
||||
assertNonEmptyString({ slide }, "slide.text");
|
||||
});
|
||||
|
||||
const lines = valueAt(site, "home.origin.lines");
|
||||
assert.ok(Array.isArray(lines), "home.origin.lines must be an array");
|
||||
assert.ok(lines.length >= 2, "home.origin.lines must contain at least 2 items");
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ test("vite entrypoint and app shell are wired", async () => {
|
|||
const imageViewer = await readFile("website/src/components/ImageViewer.jsx", "utf8");
|
||||
const richText = await readFile("website/src/components/RichText.jsx", "utf8");
|
||||
const homePage = await readFile("website/src/pages/HomePage.jsx", "utf8");
|
||||
const homeOnboarding = await readFile("website/src/pages/HomeOnboardingSection.jsx", "utf8");
|
||||
const aboutPage = await readFile("website/src/pages/AboutPage.jsx", "utf8");
|
||||
const libraryPage = await readFile("website/src/pages/LibraryPage.jsx", "utf8");
|
||||
const hashRouter = await readFile("website/src/router/hashRouter.js", "utf8");
|
||||
|
|
@ -60,8 +61,15 @@ test("vite entrypoint and app shell are wired", async () => {
|
|||
assert.match(richText, /value\.split\("\\n"\)/);
|
||||
assert.match(richText, /<br key=/);
|
||||
assert.match(homePage, /export function HomePage/);
|
||||
assert.match(homePage, /HomeOnboardingSection/);
|
||||
assert.match(homePage, /import\.meta\.env\.DEV \|\| toolboxes\.length === 0/);
|
||||
assert.match(homePage, /dragon\.png/);
|
||||
assert.match(homeOnboarding, /export function HomeOnboardingSection/);
|
||||
assert.match(homeOnboarding, /prefers-reduced-motion: reduce/);
|
||||
assert.match(homeOnboarding, /home-onboarding-dots/);
|
||||
assert.match(aboutPage, /export function AboutPage/);
|
||||
assert.match(aboutPage, /HomeOnboardingSection/);
|
||||
assert.match(aboutPage, /siteContent\.home\.onboarding/);
|
||||
assert.match(aboutPage, /module-icon-\$\{tool\.icon \|\| "notepad"\}/);
|
||||
assert.match(libraryPage, /export function LibraryPage/);
|
||||
assert.match(libraryPage, /LIBRARY_TOOLBOX_ID/);
|
||||
|
|
@ -125,6 +133,12 @@ test("legacy icons and primary images are available", async () => {
|
|||
await readFile("website/public/static/icons/zoom.svg", "utf8");
|
||||
await readFile("website/public/favicon.ico");
|
||||
await readFile("website/public/static/img/dragon.png");
|
||||
await readFile("website/public/static/img/dragon-gameguide.png");
|
||||
await readFile("website/public/static/img/dragon-toolbox.png");
|
||||
await readFile("website/public/static/img/onboarding/toolbox-overview.png");
|
||||
await readFile("website/public/static/img/onboarding/toolbox-tools.png");
|
||||
await readFile("website/public/static/img/onboarding/toolbox-save.png");
|
||||
await readFile("website/public/static/img/onboarding/toolbox-game-link.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/toolbox.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/sword.png");
|
||||
await readFile("website/public/static/img/toolbox-icons/puzzle.png");
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ test("style entrypoint and theme layers are wired", async () => {
|
|||
assert.match(styleHome, /font-style: italic/);
|
||||
assert.match(styleHome, /\.about-page/);
|
||||
assert.match(styleHome, /\.nebula-panel/);
|
||||
assert.match(styleHome, /\.home-onboarding-layout/);
|
||||
assert.match(styleHome, /\.home-onboarding-slider figcaption/);
|
||||
assert.match(styleHome, /\.home-onboarding-dots/);
|
||||
assert.match(styleHome, /\.about-story-section/);
|
||||
assert.match(styleHome, /\.about-tools-list/);
|
||||
assert.match(styleHome, /\.about-tool-item \.module-icon/);
|
||||
|
|
|
|||
|
|
@ -1182,29 +1182,13 @@
|
|||
"toolSingular": "outil disponible",
|
||||
"toolPlural": "outils disponibles"
|
||||
},
|
||||
"orientation": {
|
||||
"ariaLabel": "Accès rapides de la page d'accueil",
|
||||
"cards": [
|
||||
{
|
||||
"icon": "toolbox",
|
||||
"title": "Toolboxes",
|
||||
"text": "Votre espace personnel : notes, listes, images, liens et outils pratiques enregistrés dans ce navigateur.",
|
||||
"action": "Gérer mes toolboxes",
|
||||
"href": "#/toolboxes"
|
||||
},
|
||||
{
|
||||
"icon": "controller",
|
||||
"title": "Jeux",
|
||||
"text": "Les pages de référence disponibles. Vous pouvez ensuite y associer votre toolbox pour garder vos infos à côté.",
|
||||
"action": "Voir les jeux",
|
||||
"href": "#/games"
|
||||
}
|
||||
]
|
||||
},
|
||||
"startMap": {
|
||||
"eyebrow": "Première toolbox",
|
||||
"title": "Comment démarrer ?",
|
||||
"description": "Vous n'avez pas encore de toolbox dans ce navigateur. Créez votre premier espace en quelques étapes, ou récupérez une sauvegarde si quelqu'un vous en a partagé une.",
|
||||
"onboarding": {
|
||||
"eyebrow": "Prise en main",
|
||||
"title": "Prise en main",
|
||||
"description": "Une toolbox est votre espace personnel pour garder vos notes, listes, images, liens et outils utiles dans ce navigateur.",
|
||||
"stepsTitle": "Créer votre première toolbox",
|
||||
"sliderLabel": "Aperçu de la prise en main",
|
||||
"slideButtonLabel": "Afficher l'aperçu",
|
||||
"steps": [
|
||||
{
|
||||
"title": "Créez une toolbox",
|
||||
|
|
@ -1222,6 +1206,50 @@
|
|||
"title": "Exportez pour sauvegarder",
|
||||
"text": "Les données restent dans ce navigateur. Exportez vos toolboxes avant un nettoyage, un changement de machine ou une réinstallation."
|
||||
}
|
||||
],
|
||||
"slides": [
|
||||
{
|
||||
"src": "/static/img/onboarding/toolbox-overview.png",
|
||||
"alt": "Aperçu d'une toolbox Sokko G",
|
||||
"title": "Un espace unique",
|
||||
"text": "Regroupez les informations utiles à votre session dans une interface locale."
|
||||
},
|
||||
{
|
||||
"src": "/static/img/onboarding/toolbox-tools.png",
|
||||
"alt": "Aperçu des outils disponibles dans une toolbox",
|
||||
"title": "Des outils à choisir",
|
||||
"text": "Ajoutez seulement les outils dont vous avez besoin pour votre jeu ou votre objectif."
|
||||
},
|
||||
{
|
||||
"src": "/static/img/onboarding/toolbox-save.png",
|
||||
"alt": "Aperçu d'une sauvegarde de toolbox",
|
||||
"title": "Des sauvegardes simples",
|
||||
"text": "Exportez vos toolboxes pour les conserver ou les partager."
|
||||
},
|
||||
{
|
||||
"src": "/static/img/onboarding/toolbox-game-link.png",
|
||||
"alt": "Aperçu d'une toolbox associée à une page jeu",
|
||||
"title": "Jeu et notes côte à côte",
|
||||
"text": "Associez une toolbox à une page jeu pour garder vos repères personnels à proximité."
|
||||
}
|
||||
],
|
||||
"cards": [
|
||||
{
|
||||
"icon": "toolbox",
|
||||
"image": "/static/img/dragon-toolbox.png",
|
||||
"title": "Toolboxes",
|
||||
"text": "Votre espace personnel : notes, listes, images, liens et outils pratiques enregistrés dans ce navigateur.",
|
||||
"action": "Gérer mes toolboxes",
|
||||
"href": "#/toolboxes"
|
||||
},
|
||||
{
|
||||
"icon": "controller",
|
||||
"image": "/static/img/dragon-gameguide.png",
|
||||
"title": "Guides de jeux",
|
||||
"text": "Les pages de référence disponibles. Vous pouvez ensuite y associer votre toolbox pour garder vos infos à côté.",
|
||||
"action": "Voir les jeux",
|
||||
"href": "#/games"
|
||||
}
|
||||
]
|
||||
},
|
||||
"origin": {
|
||||
|
|
|
|||
BIN
website/public/static/img/dragon-gameguide.png
Normal file
|
After Width: | Height: | Size: 403 KiB |
BIN
website/public/static/img/dragon-toolbox.png
Normal file
|
After Width: | Height: | Size: 374 KiB |
|
Before Width: | Height: | Size: 469 KiB After Width: | Height: | Size: 636 KiB |
BIN
website/public/static/img/onboarding/toolbox-game-link.png
Normal file
|
After Width: | Height: | Size: 552 KiB |
BIN
website/public/static/img/onboarding/toolbox-overview.png
Normal file
|
After Width: | Height: | Size: 312 KiB |
BIN
website/public/static/img/onboarding/toolbox-save.png
Normal file
|
After Width: | Height: | Size: 462 KiB |
BIN
website/public/static/img/onboarding/toolbox-tools.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
|
|
@ -461,8 +461,7 @@ export function TableModule({ toolboxId, moduleId, context, editing }) {
|
|||
const bounds = getSelectionBounds(selection);
|
||||
copiedSelectionRef.current = getCellBlock(data.cells, bounds);
|
||||
const text = getTsv(bounds);
|
||||
if (!await context.copyText(text)) return;
|
||||
context.notify?.(textContent.copiedTitle || "Tableau copié");
|
||||
await context.copyText(text);
|
||||
}
|
||||
|
||||
function pasteBlock(block, rowIndex, columnIndex) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Icon } from "../components/Icon.jsx";
|
||||
import { RichText } from "../components/RichText.jsx";
|
||||
import { HomeOnboardingSection } from "./HomeOnboardingSection.jsx";
|
||||
|
||||
export function AboutPage({ siteContent }) {
|
||||
const content = siteContent.about;
|
||||
|
|
@ -60,6 +61,7 @@ export function AboutPage({ siteContent }) {
|
|||
))}
|
||||
</div>
|
||||
</section>
|
||||
<HomeOnboardingSection content={siteContent.home.onboarding} className="about-onboarding-section" />
|
||||
<section className="about-tools-section nebula-panel">
|
||||
<div className="page-heading">
|
||||
<div>
|
||||
|
|
|
|||
100
website/src/pages/HomeOnboardingSection.jsx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Rôle : affiche la section de prise en main de la home avec étapes, slider et accès rapides.
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
|
||||
const SLIDE_INTERVAL_MS = 4500;
|
||||
|
||||
function prefersReducedMotion() {
|
||||
return typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
||||
}
|
||||
|
||||
export function HomeOnboardingSection({ content, className = "" }) {
|
||||
const slides = useMemo(() => content?.slides || [], [content]);
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
const [isPaused, setIsPaused] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (slides.length <= 1 || isPaused || prefersReducedMotion()) return undefined;
|
||||
const intervalId = window.setInterval(() => {
|
||||
setActiveSlide((current) => (current + 1) % slides.length);
|
||||
}, SLIDE_INTERVAL_MS);
|
||||
return () => window.clearInterval(intervalId);
|
||||
}, [isPaused, slides.length]);
|
||||
|
||||
if (!content) return null;
|
||||
|
||||
const currentSlide = slides[activeSlide] || slides[0];
|
||||
|
||||
return (
|
||||
<section className={["home-onboarding nebula-panel", className].filter(Boolean).join(" ")} aria-labelledby="home-onboarding-title">
|
||||
<div className="home-section-heading home-onboarding-heading">
|
||||
<p className="eyebrow">{content.eyebrow}</p>
|
||||
<h2 id="home-onboarding-title">{content.title}</h2>
|
||||
<p>{content.description}</p>
|
||||
</div>
|
||||
<div className="home-onboarding-layout">
|
||||
<div className="home-onboarding-steps">
|
||||
<h3>{content.stepsTitle}</h3>
|
||||
<ol>
|
||||
{content.steps.map((step, index) => (
|
||||
<li key={step.title}>
|
||||
<span>{index + 1}</span>
|
||||
<div>
|
||||
<strong>{step.title}</strong>
|
||||
<p>{step.text}</p>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
<div
|
||||
className="home-onboarding-slider"
|
||||
onMouseEnter={() => setIsPaused(true)}
|
||||
onMouseLeave={() => setIsPaused(false)}
|
||||
onFocus={() => setIsPaused(true)}
|
||||
onBlur={() => setIsPaused(false)}
|
||||
>
|
||||
{currentSlide && (
|
||||
<figure>
|
||||
<img src={currentSlide.src} alt={currentSlide.alt} />
|
||||
<figcaption>
|
||||
<strong>{currentSlide.title}</strong>
|
||||
<span>{currentSlide.text}</span>
|
||||
</figcaption>
|
||||
</figure>
|
||||
)}
|
||||
{slides.length > 1 && (
|
||||
<div className="home-onboarding-dots" aria-label={content.sliderLabel}>
|
||||
{slides.map((slide, index) => (
|
||||
<button
|
||||
className={index === activeSlide ? "active" : ""}
|
||||
key={slide.src}
|
||||
type="button"
|
||||
onClick={() => setActiveSlide(index)}
|
||||
aria-label={`${content.slideButtonLabel} ${index + 1}`}
|
||||
aria-pressed={index === activeSlide}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="home-onboarding-cards">
|
||||
{content.cards.map((card) => (
|
||||
<a className="home-onboarding-card" href={card.href} key={card.href}>
|
||||
<span className="home-onboarding-card-visual">
|
||||
<img src={card.image} alt="" aria-hidden="true" />
|
||||
</span>
|
||||
<span className="home-onboarding-card-body">
|
||||
<span className="home-onboarding-card-title">
|
||||
<span className={`module-icon-svg module-icon-${card.icon}`} aria-hidden="true" />
|
||||
<strong>{card.title}</strong>
|
||||
</span>
|
||||
<span className="home-onboarding-card-text">{card.text}</span>
|
||||
<em>{card.action}</em>
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -2,11 +2,12 @@
|
|||
import React from "react";
|
||||
import { TOOLBOX_MODULES } from "../features/toolboxes/modules/index.jsx";
|
||||
import { RichText } from "../components/RichText.jsx";
|
||||
import { HomeOnboardingSection } from "./HomeOnboardingSection.jsx";
|
||||
|
||||
export function HomePage({ siteContent, toolboxes }) {
|
||||
const content = siteContent.home;
|
||||
const toolCount = Object.keys(TOOLBOX_MODULES).length;
|
||||
const showStartMap = import.meta.env.DEV || toolboxes.length === 0;
|
||||
const showOnboarding = import.meta.env.DEV || toolboxes.length === 0;
|
||||
return (
|
||||
<>
|
||||
<section className="hero">
|
||||
|
|
@ -24,40 +25,7 @@ export function HomePage({ siteContent, toolboxes }) {
|
|||
<article><strong>{toolCount}</strong><span>{toolCount > 1 ? content.stats.toolPlural : content.stats.toolSingular}</span></article>
|
||||
</div>
|
||||
</section>
|
||||
<section className="home-orientation nebula-panel" aria-label={content.orientation.ariaLabel}>
|
||||
{showStartMap && (
|
||||
<div className="home-start-map" aria-labelledby="home-start-map-title">
|
||||
<div className="home-section-heading">
|
||||
<p className="eyebrow">{content.startMap.eyebrow}</p>
|
||||
<h2 id="home-start-map-title">{content.startMap.title}</h2>
|
||||
<p>{content.startMap.description}</p>
|
||||
</div>
|
||||
<ol className="home-start-steps">
|
||||
{content.startMap.steps.map((step, index) => (
|
||||
<li key={step.title}>
|
||||
<span>{index + 1}</span>
|
||||
<div>
|
||||
<strong>{step.title}</strong>
|
||||
<p>{step.text}</p>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
)}
|
||||
<div className={showStartMap ? "home-orientation-main has-start-map" : "home-orientation-main"}>
|
||||
<div className="home-orientation-grid">
|
||||
{content.orientation.cards.map((card) => (
|
||||
<a className="home-orientation-card" href={card.href} key={card.href}>
|
||||
<span className={`module-icon-svg module-icon-${card.icon}`} aria-hidden="true" />
|
||||
<strong>{card.title}</strong>
|
||||
<span>{card.text}</span>
|
||||
<em>{card.action}</em>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{showOnboarding && <HomeOnboardingSection content={content.onboarding} />}
|
||||
<section className="origin-section nebula-panel" aria-labelledby="origin-title">
|
||||
<div className="origin-copy">
|
||||
<p className="eyebrow">{content.origin.eyebrow}</p>
|
||||
|
|
|
|||
|
|
@ -199,112 +199,38 @@ span {
|
|||
max-width: 980px;
|
||||
}
|
||||
|
||||
.home-orientation {
|
||||
.home-onboarding {
|
||||
display: grid;
|
||||
gap: var(--space-5);
|
||||
gap: var(--space-6);
|
||||
margin-top: var(--space-6);
|
||||
padding: var(--space-5);
|
||||
padding: var(--space-6);
|
||||
}
|
||||
|
||||
.home-orientation-main {
|
||||
.home-onboarding-heading {
|
||||
max-width: 980px;
|
||||
}
|
||||
|
||||
.home-onboarding-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(280px, 0.85fr) minmax(360px, 1.15fr);
|
||||
align-items: stretch;
|
||||
gap: var(--space-5);
|
||||
}
|
||||
|
||||
.home-orientation-main.has-start-map {
|
||||
padding-top: var(--space-5);
|
||||
border-top: 1px solid rgba(150, 165, 205, 0.12);
|
||||
}
|
||||
|
||||
.home-orientation-grid {
|
||||
.home-onboarding-steps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(280px, 440px));
|
||||
align-content: start;
|
||||
gap: var(--space-4);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.home-orientation-card {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
justify-items: center;
|
||||
gap: var(--space-3);
|
||||
overflow: hidden;
|
||||
min-height: 220px;
|
||||
padding: var(--space-4);
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-md);
|
||||
background:
|
||||
linear-gradient(rgba(10, 13, 27, 0.92), rgba(10, 13, 27, 0.92)) padding-box,
|
||||
radial-gradient(circle at 100% 0%, rgba(246, 196, 83, 0.2), transparent 28%) border-box,
|
||||
linear-gradient(135deg, rgba(246, 196, 83, 0.44), rgba(139, 92, 246, 0.22) 66%, rgba(34, 211, 238, 0.16)) border-box;
|
||||
box-shadow: var(--shadow-sm);
|
||||
text-decoration: none;
|
||||
transition:
|
||||
border-color var(--duration-fast) var(--ease-standard),
|
||||
background var(--duration-fast) var(--ease-standard),
|
||||
box-shadow var(--duration-fast) var(--ease-standard);
|
||||
}
|
||||
|
||||
.home-orientation-card > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.home-orientation-card .module-icon-svg {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: var(--color-accent-gold);
|
||||
}
|
||||
|
||||
.home-orientation-card strong {
|
||||
text-align: center;
|
||||
.home-onboarding-steps h3 {
|
||||
margin: 0;
|
||||
color: var(--color-text-primary);
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
|
||||
.home-orientation-card span:not(.module-icon-svg) {
|
||||
max-width: 620px;
|
||||
text-align: center;
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.home-orientation-card em {
|
||||
display: inline-flex;
|
||||
min-height: 38px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
margin-top: auto;
|
||||
padding: 0 var(--space-3);
|
||||
border: 1px solid rgba(246, 196, 83, 0.28);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(246, 196, 83, 0.08);
|
||||
color: var(--color-accent-gold);
|
||||
font-style: normal;
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.home-orientation-card:hover,
|
||||
.home-orientation-card:focus-visible {
|
||||
transform: none;
|
||||
border-color: transparent;
|
||||
background:
|
||||
linear-gradient(rgba(18, 23, 44, 0.96), rgba(18, 23, 44, 0.96)) padding-box,
|
||||
radial-gradient(circle at 100% 0%, rgba(246, 196, 83, 0.26), transparent 28%) border-box,
|
||||
linear-gradient(135deg, rgba(246, 196, 83, 0.58), rgba(196, 181, 253, 0.34) 62%, rgba(34, 211, 238, 0.2)) border-box;
|
||||
box-shadow:
|
||||
var(--shadow-sm),
|
||||
0 0 18px rgba(139, 92, 246, 0.16);
|
||||
}
|
||||
|
||||
.home-start-map {
|
||||
display: grid;
|
||||
gap: var(--space-5);
|
||||
}
|
||||
|
||||
.home-start-steps {
|
||||
.home-onboarding-steps ol {
|
||||
display: grid;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
|
|
@ -312,7 +238,7 @@ span {
|
|||
list-style: none;
|
||||
}
|
||||
|
||||
.home-start-steps li {
|
||||
.home-onboarding-steps li {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
gap: var(--space-3);
|
||||
|
|
@ -320,16 +246,16 @@ span {
|
|||
border-top: 1px solid rgba(150, 165, 205, 0.1);
|
||||
}
|
||||
|
||||
.home-start-steps li:first-child {
|
||||
.home-onboarding-steps li:first-child {
|
||||
padding-top: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.home-start-steps li:last-child {
|
||||
.home-onboarding-steps li:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.home-start-steps li > span {
|
||||
.home-onboarding-steps li > span {
|
||||
display: grid;
|
||||
width: 28px;
|
||||
min-width: 28px;
|
||||
|
|
@ -343,41 +269,241 @@ span {
|
|||
font-weight: 900;
|
||||
}
|
||||
|
||||
.home-start-steps div {
|
||||
.home-onboarding-steps div {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.home-start-steps strong,
|
||||
.home-start-steps p {
|
||||
.home-onboarding-steps strong,
|
||||
.home-onboarding-steps p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.home-start-steps strong {
|
||||
.home-onboarding-steps strong {
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.home-start-steps p {
|
||||
.home-onboarding-steps p {
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.home-onboarding-slider {
|
||||
position: relative;
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(150, 165, 205, 0.14);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(5, 7, 17, 0.38);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.home-onboarding-slider figure {
|
||||
position: relative;
|
||||
display: grid;
|
||||
min-height: 340px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.home-onboarding-slider img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 340px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.home-onboarding-slider figcaption {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: grid;
|
||||
min-height: 4.8em;
|
||||
align-content: center;
|
||||
gap: 2px;
|
||||
padding: var(--space-3) var(--space-4);
|
||||
background: rgba(0, 0, 0, 0.56);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.home-onboarding-slider figcaption strong,
|
||||
.home-onboarding-slider figcaption span {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.home-onboarding-slider figcaption strong {
|
||||
color: var(--color-text-primary);
|
||||
font-size: var(--font-size-md);
|
||||
}
|
||||
|
||||
.home-onboarding-slider figcaption span {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.home-onboarding-dots {
|
||||
position: absolute;
|
||||
right: var(--space-3);
|
||||
bottom: calc(4.8em + var(--space-3));
|
||||
display: flex;
|
||||
gap: 7px;
|
||||
}
|
||||
|
||||
.home-onboarding-dots button {
|
||||
width: 10px;
|
||||
min-width: 10px;
|
||||
height: 10px;
|
||||
min-height: 10px;
|
||||
padding: 0;
|
||||
border-color: rgba(246, 196, 83, 0.36);
|
||||
border-radius: var(--radius-pill);
|
||||
background: rgba(5, 7, 17, 0.68);
|
||||
}
|
||||
|
||||
.home-onboarding-dots button.active,
|
||||
.home-onboarding-dots button:hover,
|
||||
.home-onboarding-dots button:focus-visible {
|
||||
background: var(--color-accent-gold);
|
||||
box-shadow: 0 0 10px rgba(246, 196, 83, 0.26);
|
||||
}
|
||||
|
||||
.home-onboarding-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(260px, 320px));
|
||||
gap: var(--space-4);
|
||||
justify-content: center;
|
||||
padding-top: var(--space-6);
|
||||
border-top: 1px solid rgba(150, 165, 205, 0.12);
|
||||
}
|
||||
|
||||
.home-onboarding-card {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
align-content: start;
|
||||
padding: 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-md);
|
||||
background:
|
||||
linear-gradient(rgba(16, 20, 38, 0.88), rgba(16, 20, 38, 0.88)) padding-box,
|
||||
radial-gradient(circle at 100% 0%, rgba(34, 211, 238, 0.42), transparent 28%) border-box,
|
||||
linear-gradient(135deg, rgba(246, 196, 83, 0.62) 0%, rgba(246, 196, 83, 0.42) 72%, rgba(34, 211, 238, 0.24) 100%) border-box;
|
||||
box-shadow: var(--shadow-sm);
|
||||
text-decoration: none;
|
||||
transition:
|
||||
border-color var(--duration-fast) var(--ease-standard),
|
||||
background var(--duration-fast) var(--ease-standard),
|
||||
box-shadow var(--duration-fast) var(--ease-standard);
|
||||
}
|
||||
|
||||
@supports (corner-shape: scoop) {
|
||||
.home-onboarding-card {
|
||||
corner-shape: scoop;
|
||||
}
|
||||
}
|
||||
|
||||
.home-onboarding-card-visual {
|
||||
position: relative;
|
||||
display: grid;
|
||||
aspect-ratio: 3 / 2;
|
||||
min-height: 0;
|
||||
place-items: center;
|
||||
overflow: hidden;
|
||||
border-bottom: 1px solid rgba(246, 196, 83, 0.42);
|
||||
background:
|
||||
radial-gradient(circle at 50% 15%, rgba(246, 196, 83, 0.12), transparent 34%),
|
||||
rgba(5, 7, 17, 0.28);
|
||||
}
|
||||
|
||||
.home-onboarding-card-visual img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
filter: drop-shadow(0 14px 22px rgba(0, 0, 0, 0.3));
|
||||
}
|
||||
|
||||
.home-onboarding-card-body {
|
||||
display: grid;
|
||||
gap: var(--space-3);
|
||||
justify-items: center;
|
||||
padding: var(--space-4);
|
||||
}
|
||||
|
||||
.home-onboarding-card-title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 9px;
|
||||
min-width: 0;
|
||||
color: var(--color-text-primary);
|
||||
}
|
||||
|
||||
.home-onboarding-card-title .module-icon-svg {
|
||||
width: 20px;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
background: var(--color-accent-gold);
|
||||
}
|
||||
|
||||
.home-onboarding-card strong {
|
||||
color: var(--color-text-primary);
|
||||
font-size: var(--font-size-lg);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.home-onboarding-card-text {
|
||||
max-width: 30ch;
|
||||
text-align: center;
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.home-onboarding-card em {
|
||||
display: inline-flex;
|
||||
min-height: 38px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
padding: 0 var(--space-3);
|
||||
border: 1px solid rgba(246, 196, 83, 0.28);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(246, 196, 83, 0.08);
|
||||
color: var(--color-accent-gold);
|
||||
font-style: normal;
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.home-onboarding-card:hover,
|
||||
.home-onboarding-card:focus-visible {
|
||||
transform: none;
|
||||
border-color: transparent;
|
||||
background:
|
||||
linear-gradient(rgba(18, 23, 44, 0.96), rgba(18, 23, 44, 0.96)) padding-box,
|
||||
radial-gradient(circle at 100% 0%, rgba(246, 196, 83, 0.26), transparent 28%) border-box,
|
||||
linear-gradient(135deg, rgba(246, 196, 83, 0.58), rgba(196, 181, 253, 0.34) 62%, rgba(34, 211, 238, 0.2)) border-box;
|
||||
box-shadow:
|
||||
var(--shadow-sm),
|
||||
0 0 18px rgba(139, 92, 246, 0.16);
|
||||
}
|
||||
|
||||
.home-visual {
|
||||
display: grid;
|
||||
align-self: center;
|
||||
justify-self: stretch;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 320px;
|
||||
justify-self: center;
|
||||
width: min(100%, 640px);
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.home-visual img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: auto;
|
||||
max-height: 520px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-lg);
|
||||
filter: drop-shadow(0 22px 36px rgba(0, 0, 0, 0.34));
|
||||
}
|
||||
|
|
@ -1019,7 +1145,7 @@ span {
|
|||
|
||||
.origin-section {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.1fr) minmax(300px, 0.65fr);
|
||||
grid-template-columns: minmax(0, 1fr) minmax(360px, 0.78fr);
|
||||
gap: var(--space-6);
|
||||
margin-top: var(--space-6);
|
||||
padding: var(--space-6);
|
||||
|
|
@ -1081,6 +1207,10 @@ span {
|
|||
gap: var(--space-6);
|
||||
}
|
||||
|
||||
.about-onboarding-section {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.about-story-section {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(210px, 260px) minmax(0, 1fr);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@
|
|||
.game-hero,
|
||||
.page-hero,
|
||||
.origin-section,
|
||||
.home-orientation-grid,
|
||||
.home-onboarding-layout,
|
||||
.home-onboarding-cards,
|
||||
.about-story-section,
|
||||
.about-contribute-section,
|
||||
.about-tools-list,
|
||||
|
|
@ -121,13 +122,7 @@
|
|||
}
|
||||
|
||||
.home-visual {
|
||||
justify-self: center;
|
||||
width: min(320px, 100%);
|
||||
min-height: 240px;
|
||||
}
|
||||
|
||||
.home-visual img {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.origin-section {
|
||||
|
|
|
|||