Transforme l'accueil et sépare l'application

This commit is contained in:
2026-04-12 12:51:57 +02:00
parent ae56850e5c
commit 776e9ccf2f
8 changed files with 519 additions and 213 deletions

View File

@@ -30,9 +30,11 @@ L'application est ensuite disponible sur `http://localhost:8080`.
## Fichiers clés
- `index.html` : page de configuration et reprise de match
- `index.html` : page d'accueil du site
- `application.html` : page de configuration et reprise de match
- `chrono.html` : page dédiée à la phase chrono
- `cube.html` : page dédiée à la phase cube
- `reglement.html` : page éditoriale qui présente le règlement officiel
- `styles.css` : design mobile/tablette
- `app.js` : logique de match et arbitrage
- `docker-compose.yml` + `Dockerfile` : exécution locale

15
app.js
View File

@@ -1,4 +1,5 @@
const PAGE = document.body.dataset.page;
const SETUP_PAGE = "application.html";
const STORAGE_KEY = "chesscubing-arena-state-v2";
const WINDOW_NAME_KEY = "chesscubing-arena-state-v2:";
@@ -178,7 +179,7 @@ function initSetupPage() {
function initChronoPage() {
if (!match) {
replaceTo("index.html");
replaceTo(SETUP_PAGE);
return;
}
@@ -314,7 +315,7 @@ function initChronoPage() {
refs.arbiterResetButton?.addEventListener("click", () => {
clearMatch();
replaceTo("index.html");
replaceTo(SETUP_PAGE);
});
function handleChronoTap(color) {
@@ -344,7 +345,7 @@ function initChronoPage() {
syncRunningState(match);
if (match.result) {
navigateTo("index.html");
navigateTo(SETUP_PAGE);
return;
}
@@ -500,7 +501,7 @@ function initChronoPage() {
function initCubePage() {
if (!match) {
replaceTo("index.html");
replaceTo(SETUP_PAGE);
return;
}
@@ -564,7 +565,7 @@ function initCubePage() {
refs.primaryButton?.addEventListener("click", () => {
if (match.result) {
navigateTo("index.html");
navigateTo(SETUP_PAGE);
return;
}
@@ -596,7 +597,7 @@ function initCubePage() {
refs.resetButton?.addEventListener("click", () => {
clearMatch();
replaceTo("index.html");
replaceTo(SETUP_PAGE);
});
function handleCubeTap(color) {
@@ -1384,7 +1385,7 @@ function resultText(storedMatch) {
function routeForMatch(storedMatch) {
if (!storedMatch) {
return "index.html";
return SETUP_PAGE;
}
return storedMatch.phase === "cube" && !storedMatch.result ? "cube.html" : "chrono.html";

259
application.html Normal file
View File

@@ -0,0 +1,259 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="Application officielle de match pour ChessCubing Arena sur téléphone et tablette."
/>
<title>ChessCubing Arena | Application</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body data-page="setup">
<div class="ambient ambient-left"></div>
<div class="ambient ambient-right"></div>
<div class="setup-shell">
<header class="hero hero-setup">
<div class="hero-copy">
<p class="eyebrow">Application officielle de match</p>
<h1>ChessCubing Arena</h1>
<p class="lead">
Une version mobile et tablette organisée par phases : configuration,
page chrono ultra lisible, puis page cube dédiée qui s'ouvre
automatiquement à la fin de la phase chess.
</p>
<div class="hero-pills">
<span>Pages séparées</span>
<span>Face-à-face téléphone</span>
<span>Twice + Time</span>
<span>Arbitrage tactile</span>
</div>
<div class="hero-actions">
<a class="button ghost" href="index.html">Accueil du site</a>
<a class="button secondary" href="reglement.html">Consulter le règlement</a>
</div>
</div>
<aside class="hero-preview">
<div class="preview-card">
<p class="micro-label">Flux de match</p>
<ol class="phase-list">
<li>Configurer la rencontre</li>
<li>Passer à la page chrono</li>
<li>Basculer automatiquement sur la page cube</li>
<li>Revenir sur la page chrono pour le block suivant</li>
</ol>
</div>
<div class="preview-banner">
<span class="mini-chip">Téléphone</span>
<strong>Un joueur en haut, un joueur en bas</strong>
<p>
La zone du haut s'inverse automatiquement pour que les deux
joueurs se fassent face autour de l'appareil.
</p>
</div>
</aside>
</header>
<main class="setup-grid">
<section class="panel">
<div class="section-heading">
<div>
<p class="eyebrow">Nouvelle rencontre</p>
<h2>Configuration</h2>
</div>
<p class="section-copy">
Les réglages ci-dessous préparent les pages chrono et cube.
</p>
</div>
<form id="setupForm" class="setup-form">
<label class="field span-2">
<span>Nom de la rencontre</span>
<input
name="matchLabel"
type="text"
maxlength="80"
placeholder="Open ChessCubing de Paris"
/>
</label>
<fieldset class="field span-2">
<legend>Mode officiel</legend>
<div class="option-grid mode-grid">
<label class="option-card">
<input type="radio" name="mode" value="twice" checked />
<strong>ChessCubing Twice</strong>
<span>
Le gagnant du cube ouvre le block suivant et peut obtenir un
double coup V2.
</span>
</label>
<label class="option-card">
<input type="radio" name="mode" value="time" />
<strong>ChessCubing Time</strong>
<span>
Même structure de blocks, avec chronos cumulés et alternance
bloc - / bloc +.
</span>
</label>
</div>
</fieldset>
<fieldset class="field span-2">
<legend>Cadence du block</legend>
<div class="option-grid preset-grid">
<label class="option-card">
<input type="radio" name="preset" value="fast" checked />
<strong>FAST</strong>
<span>6 coups par joueur</span>
</label>
<label class="option-card">
<input type="radio" name="preset" value="freeze" />
<strong>FREEZE</strong>
<span>8 coups par joueur</span>
</label>
<label class="option-card">
<input type="radio" name="preset" value="masters" />
<strong>MASTERS</strong>
<span>10 coups par joueur</span>
</label>
</div>
</fieldset>
<fieldset class="field span-2">
<legend>Temps personnalisés</legend>
<div class="timing-grid">
<label class="field">
<span>Temps block (secondes)</span>
<input
name="blockSeconds"
type="number"
min="30"
max="1800"
step="5"
value="180"
/>
</label>
<label class="field">
<span>Temps coup (secondes)</span>
<input
name="moveSeconds"
type="number"
min="5"
max="300"
step="1"
value="20"
/>
</label>
</div>
</fieldset>
<label class="field">
<span>Joueur blanc</span>
<input name="whiteName" type="text" maxlength="40" placeholder="Blanc" value="Blanc" />
</label>
<label class="field">
<span>Joueur noir</span>
<input name="blackName" type="text" maxlength="40" placeholder="Noir" value="Noir" />
</label>
<label class="field">
<span>Arbitre</span>
<input
name="arbiterName"
type="text"
maxlength="40"
placeholder="Arbitre principal"
/>
</label>
<label class="field">
<span>Club / événement</span>
<input
name="eventName"
type="text"
maxlength="60"
placeholder="Club, tournoi, démonstration"
/>
</label>
<label class="field span-2">
<span>Notes</span>
<textarea
name="notes"
rows="3"
placeholder="Tirage au sort effectué, 8 cubes vérifiés, variante prête..."
></textarea>
</label>
<div id="setupSummary" class="setup-summary span-2"></div>
<div class="setup-actions span-2">
<button class="button primary" type="submit">
Ouvrir la page chrono
</button>
<button class="button secondary" id="loadDemoButton" type="button">
Charger une démo
</button>
<a class="button ghost" href="reglement.html">Consulter le règlement</a>
</div>
</form>
</section>
<aside class="panel side-panel">
<div class="section-heading">
<div>
<p class="eyebrow">Match en mémoire</p>
<h2>Reprise rapide</h2>
</div>
</div>
<div id="resumeCard" class="resume-card empty">
<p>Aucun match en cours pour l'instant.</p>
</div>
<div class="rules-stack">
<article class="rule-card">
<span class="micro-label">Page chrono</span>
<strong>Gros boutons uniquement</strong>
<p>
Chaque joueur dispose d'une grande zone tactile pour signaler la
fin de son coup, puis l'app ouvre automatiquement la phase cube
quand le block chess est terminé.
</p>
</article>
<article class="rule-card">
<span class="micro-label">Page cube</span>
<strong>Une page dédiée</strong>
<p>
Les deux joueurs lancent et arrêtent leur propre chrono cube sur
un écran séparé, toujours en face-à-face sur mobile.
</p>
</article>
<article class="rule-card">
<span class="micro-label">Sources</span>
<strong>Règlements intégrés</strong>
<p>
<a href="reglement.html">Page règlement du site</a>
<br />
<a href="ChessCubing_Twice_Reglement_Officiel_V2-1.pdf" target="_blank"
>Règlement ChessCubing Twice</a
>
<br />
<a href="ChessCubing_Time_Reglement_Officiel_V1-1.pdf" target="_blank"
>Règlement ChessCubing Time</a
>
</p>
</article>
</div>
</aside>
</main>
</div>
<script type="module" src="app.js"></script>
</body>
</html>

View File

@@ -13,7 +13,7 @@
<body data-page="chrono" class="phase-body">
<main class="phase-shell">
<header class="phase-header">
<a class="brand-link" href="index.html">Configuration</a>
<a class="brand-link" href="application.html">Application</a>
<div class="phase-title">
<p class="eyebrow">Phase chrono</p>
<h1 id="chronoTitle">Block 1</h1>

View File

@@ -13,7 +13,7 @@
<body data-page="cube" class="phase-body">
<main class="phase-shell cube-shell">
<header class="phase-header">
<a class="brand-link" href="index.html">Configuration</a>
<a class="brand-link" href="application.html">Application</a>
<div class="phase-title">
<p class="eyebrow">Phase cube</p>
<h1 id="cubeTitle">Cube n°1</h1>

View File

@@ -5,251 +5,244 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="Configuration de match pour ChessCubing Arena sur téléphone et tablette."
content="Découvrez ChessCubing, l'association et le jeu qui réunit échecs et Rubik's Cube dans un format simple, vivant et spectaculaire."
/>
<title>ChessCubing Arena | Configuration</title>
<title>ChessCubing Arena | Accueil</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body data-page="setup">
<body class="home-body">
<div class="ambient ambient-left"></div>
<div class="ambient ambient-right"></div>
<div class="setup-shell">
<header class="hero hero-setup">
<div class="rules-shell">
<header class="hero hero-home">
<div class="hero-copy">
<p class="eyebrow">Application officielle de match</p>
<h1>ChessCubing Arena</h1>
<p class="eyebrow">Association ChessCubing</p>
<h1>Les échecs rencontrent le Rubik's Cube</h1>
<p class="lead">
Une version mobile et tablette organisée par phases : configuration,
page chrono ultra lisible, puis page cube dédiée qui s'ouvre
automatiquement à la fin de la phase chess.
ChessCubing propose un jeu hybride simple à comprendre, intense à
vivre et très plaisant à regarder. On joue un block d'échecs, on
passe par une phase cube obligatoire, puis la partie repart avec un
nouveau rythme.
</p>
<div class="hero-pills">
<span>Pages séparées</span>
<span>Face-à-face téléphone</span>
<span>Twice + Time</span>
<span>Arbitrage tactile</span>
<span>Accessible en club</span>
<span>Spectaculaire en démonstration</span>
<span>Stratégie + vitesse</span>
<span>Application officielle</span>
</div>
<div class="hero-actions">
<a class="button primary" href="application.html">Ouvrir l'application</a>
<a class="button secondary" href="reglement.html">Lire le règlement</a>
</div>
</div>
<aside class="hero-preview">
<div class="preview-card">
<p class="micro-label">Flux de match</p>
<p class="micro-label">Le principe</p>
<ol class="phase-list">
<li>Configurer la rencontre</li>
<li>Passer à la page chrono</li>
<li>Basculer automatiquement sur la page cube</li>
<li>Revenir sur la page chrono pour le block suivant</li>
<li>Deux joueurs disputent un block d'échecs court et nerveux.</li>
<li>Une phase cube coupe le rythme et relance la tension.</li>
<li>Le résultat du cube influence immédiatement la suite du match.</li>
</ol>
</div>
<div class="preview-banner">
<span class="mini-chip">Téléphone</span>
<strong>Un joueur en haut, un joueur en bas</strong>
<span class="mini-chip">Découverte rapide</span>
<strong>On comprend en quelques minutes</strong>
<p>
La zone du haut s'inverse automatiquement pour que les deux
joueurs se fassent face autour de l'appareil.
Le format donne envie de jouer même quand on découvre seulement
l'un des deux univers. On peut venir pour les échecs, pour le
cube, ou simplement pour l'énergie du duel.
</p>
</div>
</aside>
</header>
<main class="setup-grid">
<section class="panel">
<main class="rules-grid">
<section class="panel panel-wide">
<div class="section-heading">
<div>
<p class="eyebrow">Nouvelle rencontre</p>
<h2>Configuration</h2>
<p class="eyebrow">L'association</p>
<h2>Une passerelle entre deux passions</h2>
</div>
<p class="section-copy">
Les réglages ci-dessous préparent les pages chrono et cube.
L'association ChessCubing veut créer des moments de rencontre, de
découverte et de jeu partagé autour d'un format hybride.
</p>
</div>
<form id="setupForm" class="setup-form">
<label class="field span-2">
<span>Nom de la rencontre</span>
<input
name="matchLabel"
type="text"
maxlength="80"
placeholder="Open ChessCubing de Paris"
/>
</label>
<fieldset class="field span-2">
<legend>Mode officiel</legend>
<div class="option-grid mode-grid">
<label class="option-card">
<input type="radio" name="mode" value="twice" checked />
<strong>ChessCubing Twice</strong>
<span>
Le gagnant du cube ouvre le block suivant et peut obtenir un
double coup V2.
</span>
</label>
<label class="option-card">
<input type="radio" name="mode" value="time" />
<strong>ChessCubing Time</strong>
<span>
Même structure de blocks, avec chronos cumulés et alternance
bloc - / bloc +.
</span>
</label>
</div>
</fieldset>
<fieldset class="field span-2">
<legend>Cadence du block</legend>
<div class="option-grid preset-grid">
<label class="option-card">
<input type="radio" name="preset" value="fast" checked />
<strong>FAST</strong>
<span>6 coups par joueur</span>
</label>
<label class="option-card">
<input type="radio" name="preset" value="freeze" />
<strong>FREEZE</strong>
<span>8 coups par joueur</span>
</label>
<label class="option-card">
<input type="radio" name="preset" value="masters" />
<strong>MASTERS</strong>
<span>10 coups par joueur</span>
</label>
</div>
</fieldset>
<fieldset class="field span-2">
<legend>Temps personnalisés</legend>
<div class="timing-grid">
<label class="field">
<span>Temps block (secondes)</span>
<input
name="blockSeconds"
type="number"
min="30"
max="1800"
step="5"
value="180"
/>
</label>
<label class="field">
<span>Temps coup (secondes)</span>
<input
name="moveSeconds"
type="number"
min="5"
max="300"
step="1"
value="20"
/>
</label>
</div>
</fieldset>
<label class="field">
<span>Joueur blanc</span>
<input name="whiteName" type="text" maxlength="40" placeholder="Blanc" value="Blanc" />
</label>
<label class="field">
<span>Joueur noir</span>
<input name="blackName" type="text" maxlength="40" placeholder="Noir" value="Noir" />
</label>
<label class="field">
<span>Arbitre</span>
<input
name="arbiterName"
type="text"
maxlength="40"
placeholder="Arbitre principal"
/>
</label>
<label class="field">
<span>Club / événement</span>
<input
name="eventName"
type="text"
maxlength="60"
placeholder="Club, tournoi, démonstration"
/>
</label>
<label class="field span-2">
<span>Notes</span>
<textarea
name="notes"
rows="3"
placeholder="Tirage au sort effectué, 8 cubes vérifiés, variante prête..."
></textarea>
</label>
<div id="setupSummary" class="setup-summary span-2"></div>
<div class="setup-actions span-2">
<button class="button primary" type="submit">
Ouvrir la page chrono
</button>
<button class="button secondary" id="loadDemoButton" type="button">
Charger une démo
</button>
<a class="button ghost" href="reglement.html">Consulter le règlement</a>
</div>
</form>
<div class="home-story-grid">
<article class="stage-card">
<span class="micro-label">Partager</span>
<strong>Faire découvrir un format original</strong>
<p>
L'idée est simple : réunir des profils différents autour d'un
jeu lisible, vivant et immédiatement intriguant.
</p>
</article>
<article class="stage-card">
<span class="micro-label">Rassembler</span>
<strong>Créer un terrain commun</strong>
<p>
Joueurs d'échecs, cubers, curieux, familles ou clubs peuvent se
retrouver dans une expérience facile à lancer et à commenter.
</p>
</article>
<article class="stage-card">
<span class="micro-label">Animer</span>
<strong>Donner envie de revenir jouer</strong>
<p>
Le mélange de réflexion, de vitesse et de rebondissements donne
au format un côté spectaculaire qui marche très bien en
initiation comme en événement.
</p>
</article>
</div>
</section>
<aside class="panel side-panel">
<section class="panel panel-half">
<div class="section-heading">
<div>
<p class="eyebrow">Match en mémoire</p>
<h2>Reprise rapide</h2>
<p class="eyebrow">Le jeu en simple</p>
<h2>Comment se passe une partie</h2>
</div>
</div>
<div id="resumeCard" class="resume-card empty">
<p>Aucun match en cours pour l'instant.</p>
<div class="home-mini-grid">
<article class="mini-panel">
<span class="micro-label">1</span>
<strong>On joue un block d'échecs</strong>
<p>
La partie avance par séquences courtes, ce qui garde un très bon
rythme et rend l'action facile à suivre.
</p>
</article>
<article class="mini-panel">
<span class="micro-label">2</span>
<strong>On résout un cube</strong>
<p>
Les deux joueurs enchaînent avec une phase cube obligatoire qui
sert de relance, de pression et de bascule.
</p>
</article>
<article class="mini-panel">
<span class="micro-label">3</span>
<strong>Le match repart</strong>
<p>
Selon le mode choisi, la phase cube donne l'initiative ou agit
sur les chronos. Le duel ne retombe jamais.
</p>
</article>
</div>
</section>
<section class="panel panel-half">
<div class="section-heading">
<div>
<p class="eyebrow">Pourquoi ça plaît</p>
<h2>Un format qui donne envie d'essayer</h2>
</div>
</div>
<div class="rules-stack">
<article class="rule-card">
<span class="micro-label">Page chrono</span>
<strong>Gros boutons uniquement</strong>
<p>
Chaque joueur dispose d'une grande zone tactile pour signaler la
fin de son coup, puis l'app ouvre automatiquement la phase cube
quand le block chess est terminé.
</p>
<div class="home-mini-grid two-columns">
<article class="mini-panel">
<strong>Très lisible</strong>
<p>On comprend vite quand la pression monte et pourquoi le cube change tout.</p>
</article>
<article class="rule-card">
<span class="micro-label">Page cube</span>
<strong>Une page dédiée</strong>
<p>
Les deux joueurs lancent et arrêtent leur propre chrono cube sur
un écran séparé, toujours en face-à-face sur mobile.
</p>
<article class="mini-panel">
<strong>Toujours relancé</strong>
<p>Chaque phase cube remet du suspense dans la partie et ouvre de nouvelles options.</p>
</article>
<article class="rule-card">
<span class="micro-label">Sources</span>
<strong>Règlements intégrés</strong>
<p>
<a href="reglement.html">Page règlement du site</a>
<br />
<a href="ChessCubing_Twice_Reglement_Officiel_V2-1.pdf" target="_blank"
>Règlement ChessCubing Twice</a
>
<br />
<a href="ChessCubing_Time_Reglement_Officiel_V1-1.pdf" target="_blank"
>Règlement ChessCubing Time</a
>
</p>
<article class="mini-panel">
<strong>Convivial</strong>
<p>Le format marche bien en initiation, en animation de club ou en démonstration publique.</p>
</article>
<article class="mini-panel">
<strong>Mémorable</strong>
<p>On ressort d'une partie avec des coups, des temps et des retournements dont on se souvient.</p>
</article>
</div>
</aside>
</section>
<section class="panel panel-wide">
<div class="section-heading">
<div>
<p class="eyebrow">Deux formats</p>
<h2>Deux manières de vivre le duel</h2>
</div>
<p class="section-copy">
Le règlement officiel propose deux lectures du même concept, l'une
plus orientée initiative, l'autre plus orientée gestion du temps.
</p>
</div>
<div class="rules-compare">
<article class="format-card twice-card">
<div class="format-head">
<span class="mini-chip">ChessCubing Twice</span>
<h3>Le cube donne l'élan</h3>
<p>
Le joueur le plus rapide sur la phase cube prend le départ du
block suivant et peut même obtenir un double coup dans
certaines situations.
</p>
</div>
<div class="format-badges">
<span>Mode nerveux</span>
<span>Initiative forte</span>
<span>Effet immédiat</span>
</div>
</article>
<article class="format-card time-card">
<div class="format-head">
<span class="mini-chip">ChessCubing Time</span>
<h3>Le cube agit sur les chronos</h3>
<p>
Ici, on garde le trait mais la performance sur le cube retire
ou ajoute du temps selon l'alternance des blocs.
</p>
</div>
<div class="format-badges">
<span>Gestion de temps</span>
<span>Blocs - et +</span>
<span>Suspense permanent</span>
</div>
</article>
</div>
</section>
<section class="panel panel-wide cta-panel">
<div class="section-heading">
<div>
<p class="eyebrow">Envie de tester</p>
<h2>Choisis ton entrée</h2>
</div>
<p class="section-copy">
Tu peux découvrir le jeu tranquillement avec la page règlement ou
aller directement vers l'application officielle de match.
</p>
</div>
<div class="source-grid">
<a class="source-card" href="application.html">
<span class="micro-label">Application</span>
<strong>Ouvrir la partie arbitrage</strong>
<p>Configurer une rencontre, lancer le chrono et enchaîner avec la phase cube.</p>
</a>
<a class="source-card" href="reglement.html">
<span class="micro-label">Règlement</span>
<strong>Comprendre les formats officiels</strong>
<p>Retrouver une présentation claire du Twice, du Time et des règles de match.</p>
</a>
<a class="source-card" href="ChessCubing_Twice_Reglement_Officiel_V2-1.pdf" target="_blank">
<span class="micro-label">PDF officiel</span>
<strong>Lire le texte source</strong>
<p>Consulter directement le document officiel si tu veux tous les détails.</p>
</a>
</div>
</section>
</main>
</div>
<script type="module" src="app.js"></script>
</body>
</html>

View File

@@ -32,8 +32,8 @@
<span>Fin uniquement par mat ou abandon</span>
</div>
<div class="hero-actions">
<a class="button primary" href="index.html">Retour à l'application</a>
<a class="button secondary" href="#formats">Comparer les formats</a>
<a class="button primary" href="application.html">Ouvrir l'application</a>
<a class="button secondary" href="index.html">Retour à l'accueil</a>
</div>
</div>
@@ -339,7 +339,7 @@
<strong>ChessCubing Time V1</strong>
<p>Version entrée en vigueur le 4 février 2026.</p>
</a>
<a class="source-card" href="index.html">
<a class="source-card" href="application.html">
<span class="micro-label">Application</span>
<strong>Retour à ChessCubing Arena</strong>
<p>Revenir à la configuration du match et à l'arbitrage mobile.</p>

View File

@@ -792,6 +792,15 @@ textarea:focus {
0 0 30px rgba(30, 214, 255, 0.08);
}
.hero-home h1 {
margin: 0;
font-size: clamp(2.9rem, 6.4vw, 5.2rem);
line-height: 0.93;
text-shadow:
0 0 12px rgba(30, 214, 255, 0.18),
0 0 32px rgba(24, 217, 127, 0.08);
}
.hero-actions {
display: flex;
flex-wrap: wrap;
@@ -870,6 +879,12 @@ textarea:focus {
gap: 0.9rem;
}
.home-story-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.9rem;
}
.stage-card {
display: grid;
gap: 0.45rem;
@@ -898,6 +913,39 @@ textarea:focus {
opacity: 0.7;
}
.mini-panel {
position: relative;
display: grid;
gap: 0.45rem;
padding: 1rem;
border-radius: 22px;
border: 1px solid var(--panel-border-soft);
background:
linear-gradient(160deg, rgba(10, 31, 47, 0.96), rgba(3, 13, 21, 0.96));
box-shadow:
inset 0 0 0 1px rgba(30, 214, 255, 0.03),
0 0 22px rgba(30, 214, 255, 0.04);
}
.mini-panel p {
margin-bottom: 0;
color: var(--muted);
}
.home-mini-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.9rem;
}
.home-mini-grid.two-columns {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.cta-panel {
border-color: rgba(125, 247, 189, 0.24);
}
.twice-card {
border-color: rgba(117, 242, 255, 0.24);
}
@@ -1035,8 +1083,11 @@ textarea:focus {
.faceoff-board,
.rules-compare,
.rules-stage-grid,
.home-story-grid,
.split-callouts,
.source-grid {
.source-grid,
.home-mini-grid,
.home-mini-grid.two-columns {
grid-template-columns: 1fr;
}