Étend la DA "Polaroid Néon" aux 4 derniers écrans
Upload invité (priorité haute, full traitement : fond #12100E, CTA corail, General Sans/Inter, touche Caveat sur le message de succès), galerie admin (exception admin du skill : sobre, sombre, cartes #1E1B18, pas de rotation/confettis, corail réservé aux CTA), générateur QR (même exception admin, traitement minimal), carton imprimable (reste clair — un support papier n'a pas vocation à avoir un fond noir — mais adopte les polices et l'accent corail de la nouvelle DA, contraste recalculé pour l'impression). Double thème clair/sombre de l'ancienne DA retiré au profit d'un thème unique sombre, cohérent avec src/galerie/ (premier écran de cette DA, déjà validé). Dégradés de texte et halo de fond de l'ancienne DA retirés (skill : jamais de glow/neon artificiel). Contrastes vérifiés par calcul WCAG AA pour toutes les nouvelles combinaisons. Chemins d'assets absolus et pattern [hidden]/display vérifiés sur les 4 écrans (bugs déjà rencontrés deux fois en prod).
This commit is contained in:
@@ -13,9 +13,10 @@
|
|||||||
fichier front, à mettre en place lors du déploiement.
|
fichier front, à mettre en place lors du déploiement.
|
||||||
-->
|
-->
|
||||||
<meta name="robots" content="noindex, nofollow">
|
<meta name="robots" content="noindex, nofollow">
|
||||||
<meta name="theme-color" content="#faf6f0" media="(prefers-color-scheme: light)">
|
<!-- Thème unique sombre "Polaroid Néon", exception admin (sobre/data-first,
|
||||||
<meta name="theme-color" content="#1b120b" media="(prefers-color-scheme: dark)">
|
voir src/admin/gallery/style.css). -->
|
||||||
<link rel="preload" href="/vendor/fonts/fraunces-latin-600-normal.woff2" as="font" type="font/woff2" crossorigin>
|
<meta name="theme-color" content="#12100E">
|
||||||
|
<link rel="preload" href="/vendor/fonts/generalsans-700.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
<link rel="stylesheet" href="/admin/gallery/style.css">
|
<link rel="stylesheet" href="/admin/gallery/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
+105
-157
@@ -1,100 +1,70 @@
|
|||||||
/* Page galerie admin — mobile-first mais utilisable au clavier/souris sur
|
/* Galerie admin — direction artistique "Polaroid Néon"
|
||||||
desktop (l'admin peut consulter depuis un ordinateur), sans dépendance
|
(.claude/skills/photobooth-da/SKILL.md), variante "écran admin" du skill :
|
||||||
externe. Mêmes tokens de couleur/rayon/ombre/police que la page invité
|
sobre, sombre, data-first. Pas de confettis, pas de rotation façon
|
||||||
(src/e/style.css) pour rester cohérent visuellement — c'est aussi l'écran
|
polaroid sur les cartes photo (grille classique) — l'accent corail est
|
||||||
que verront les prospects (photographes, wedding planners) lors d'une
|
réservé aux CTA (boutons), jamais décoratif.
|
||||||
démo, donc soigné au même niveau que la page invité. Palette et police
|
|
||||||
Fraunces alignées sur la passe 2 (2026-09-16) : voir src/e/style.css pour
|
|
||||||
la justification complète de la direction créative.
|
|
||||||
|
|
||||||
Passe 3 (2026-09-16) : mode sombre + finitions "type iPhone" (hover
|
Tokens repris de src/galerie/style.css (écran de référence de cette DA)
|
||||||
desktop, entrées en fondu, halo de couleur en fond) alignés sur
|
pour la cohérence de couleurs/typo entre écrans invité et admin ; les
|
||||||
src/e/style.css — voir ce fichier pour le détail complet des choix et
|
cartes utilisent #1E1B18 comme demandé par l'exception admin du skill
|
||||||
des vérifications de contraste. Cet écran est celui que verront le plus
|
(plus clair que --color-bg, pour distinguer une "carte" du fond de
|
||||||
souvent les prospects en démo depuis un ordinateur : les états hover
|
page, sans jamais recourir au blanc cassé des polaroids invité).
|
||||||
comptent ici au moins autant que sur la page invité. */
|
|
||||||
|
Contrastes vérifiés par calcul WCAG AA (même méthode que
|
||||||
|
src/galerie/style.css) : texte clair sur #12100E et sur #1E1B18 passe
|
||||||
|
très largement ; texte sombre (#12100E) sur les couleurs d'accent
|
||||||
|
pleines (utilisé uniquement sur les CTA .btn) passe confortablement
|
||||||
|
(6.3:1 à 13.2:1). */
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Fraunces";
|
font-family: "General Sans";
|
||||||
src: url("/vendor/fonts/fraunces-latin-600-normal.woff2") format("woff2");
|
src: url("/vendor/fonts/generalsans-700.woff2") format("woff2");
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
src: url("/vendor/fonts/inter-latin-variable.woff2") format("woff2");
|
||||||
|
font-weight: 400 700;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F,
|
|
||||||
U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: dark;
|
||||||
|
|
||||||
--color-bg: #fff8f0;
|
--color-bg: #12100e;
|
||||||
--color-surface: #ffffff;
|
--color-ink: #12100e;
|
||||||
--color-surface-muted: #fdecdd;
|
--color-text: #faf6f0;
|
||||||
--color-text: #2b2016;
|
--color-muted: #e8dfd3;
|
||||||
--color-muted: #8a7869;
|
--color-muted-2: #a89e90;
|
||||||
--color-border: #f1ddc6;
|
|
||||||
|
|
||||||
--color-accent: #e35f2b;
|
--color-coral: #ff5e5b;
|
||||||
--color-accent-hover: #c74c1e;
|
--color-yellow: #ffd166;
|
||||||
--color-accent-light: #ff8a52;
|
--color-mint: #06d6a0;
|
||||||
--color-accent-soft: #ffe3d0;
|
|
||||||
--color-accent-contrast: #fffaf6;
|
|
||||||
|
|
||||||
--color-plum: #7c2f56;
|
/* Exception admin du skill : cartes en #1E1B18. */
|
||||||
--color-plum-soft: #f8e3ee;
|
--color-card: #1e1b18;
|
||||||
|
--color-card-muted: #262220;
|
||||||
|
--color-border-ui: rgba(250, 246, 240, 0.14);
|
||||||
|
--color-border-ui-strong: rgba(250, 246, 240, 0.26);
|
||||||
|
|
||||||
--color-error-bg: #fdeae6;
|
--color-error-bg: rgba(255, 94, 91, 0.14);
|
||||||
--color-error-text: #a3341c;
|
--color-warning-bg: rgba(255, 209, 102, 0.16);
|
||||||
--color-warning-bg: #fbe9d8;
|
|
||||||
--color-warning-text: #8a4a10;
|
|
||||||
|
|
||||||
--radius-sm: 12px;
|
--radius-ui: 14px;
|
||||||
--radius: 20px;
|
|
||||||
--radius-pill: 999px;
|
--radius-pill: 999px;
|
||||||
|
|
||||||
--shadow-sm: 0 2px 6px rgba(163, 78, 30, 0.1);
|
--shadow-soft: 0 10px 24px rgba(0, 0, 0, 0.35);
|
||||||
--shadow-md: 0 10px 28px rgba(163, 78, 30, 0.16);
|
--shadow-card: 0 6px 16px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
--ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
|
--ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
|
||||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
--font-display: "General Sans", -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
"Helvetica Neue", Arial, sans-serif;
|
--font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
--font-display: "Fraunces", Georgia, "Times New Roman", serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Thème sombre — mêmes valeurs et même raisonnement que src/e/style.css
|
|
||||||
(fond brun quasi-noir, pas d'inversion, contrastes vérifiés WCAG AA). */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--color-bg: #1b120b;
|
|
||||||
--color-surface: #26190f;
|
|
||||||
--color-surface-muted: #32211a;
|
|
||||||
--color-text: #f7ead9;
|
|
||||||
--color-muted: #b39d84;
|
|
||||||
--color-border: #40291a;
|
|
||||||
|
|
||||||
--color-accent: #ff7a42;
|
|
||||||
--color-accent-hover: #ffa06e;
|
|
||||||
--color-accent-light: #ffab7a;
|
|
||||||
--color-accent-soft: rgba(255, 122, 66, 0.18);
|
|
||||||
--color-accent-contrast: #241206;
|
|
||||||
|
|
||||||
--color-plum: #f0b8d8;
|
|
||||||
--color-plum-soft: rgba(240, 184, 216, 0.14);
|
|
||||||
|
|
||||||
--color-error-bg: #3a1712;
|
|
||||||
--color-error-text: #ff9b86;
|
|
||||||
--color-warning-bg: #3a2a12;
|
|
||||||
--color-warning-text: #ffd98a;
|
|
||||||
|
|
||||||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.45);
|
|
||||||
--shadow-md: 0 14px 36px rgba(0, 0, 0, 0.55);
|
|
||||||
}
|
|
||||||
|
|
||||||
body::before {
|
|
||||||
opacity: 0.35;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -106,28 +76,13 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
position: relative;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-ui);
|
||||||
background: var(--color-bg);
|
background: var(--color-bg);
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Halo de couleur en fond — même principe que src/e/style.css : "plus de
|
|
||||||
couleur" en réutilisant la palette existante (corail + prune), jamais
|
|
||||||
une nouvelle teinte, purement décoratif (CSS pur, poids nul). */
|
|
||||||
body::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
z-index: -1;
|
|
||||||
pointer-events: none;
|
|
||||||
background: radial-gradient(55% 32% at 50% -8%, var(--color-accent-soft) 0%, transparent 72%),
|
|
||||||
radial-gradient(40% 26% at 100% 100%, var(--color-plum-soft) 0%, transparent 70%);
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
max-width: 960px;
|
max-width: 960px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -138,18 +93,6 @@ body::before {
|
|||||||
.page__header {
|
.page__header {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
animation: fade-rise 0.5s var(--ease-standard) both;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-rise {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(10px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand {
|
.brand {
|
||||||
@@ -158,14 +101,14 @@ body::before {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
margin-bottom: 0.6rem;
|
margin-bottom: 0.6rem;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand__mark {
|
.brand__mark {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: var(--color-accent);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand__name {
|
.brand__name {
|
||||||
@@ -175,21 +118,19 @@ body::before {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Écran admin = data-first, sobre : titre en texte plein (pas de dégradé
|
||||||
|
décoratif), contrairement à ce que faisait l'ancienne DA. */
|
||||||
.page__header h1 {
|
.page__header h1 {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: 1.7rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
margin: 0.15rem 0 0;
|
margin: 0.15rem 0 0;
|
||||||
color: var(--color-accent);
|
color: var(--color-text);
|
||||||
background: linear-gradient(100deg, var(--color-accent) 20%, var(--color-plum) 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-meta {
|
.event-meta {
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
margin: 0.4rem 0 0;
|
margin: 0.4rem 0 0;
|
||||||
}
|
}
|
||||||
@@ -197,13 +138,14 @@ body::before {
|
|||||||
.state-block {
|
.state-block {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 1.25rem 1rem;
|
padding: 1.25rem 1rem;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
background: var(--color-card);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-block--error {
|
.state-block--error {
|
||||||
background: var(--color-error-bg);
|
background: var(--color-error-bg);
|
||||||
color: var(--color-error-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-block p {
|
.state-block p {
|
||||||
@@ -219,8 +161,8 @@ body::before {
|
|||||||
width: 26px;
|
width: 26px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
margin-bottom: 0.6rem;
|
margin-bottom: 0.6rem;
|
||||||
border: 3px solid var(--color-accent-soft);
|
border: 3px solid rgba(255, 94, 91, 0.22);
|
||||||
border-top-color: var(--color-accent);
|
border-top-color: var(--color-coral);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: spin 0.8s linear infinite;
|
animation: spin 0.8s linear infinite;
|
||||||
}
|
}
|
||||||
@@ -233,8 +175,8 @@ body::before {
|
|||||||
|
|
||||||
.status-banner {
|
.status-banner {
|
||||||
background: var(--color-warning-bg);
|
background: var(--color-warning-bg);
|
||||||
color: var(--color-warning-text);
|
color: var(--color-text);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
padding: 0.85rem 1rem;
|
padding: 0.85rem 1rem;
|
||||||
margin: 0 0 1.25rem;
|
margin: 0 0 1.25rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@@ -247,6 +189,8 @@ body::before {
|
|||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Boutons — l'accent corail est réservé au CTA principal (télécharger le
|
||||||
|
ZIP) ; le bouton secondaire (Actualiser) reste sobre, sans couleur. */
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -259,10 +203,10 @@ body::before {
|
|||||||
padding: 0.75rem 1.15rem;
|
padding: 0.75rem 1.15rem;
|
||||||
min-height: 46px;
|
min-height: 46px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent));
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-card);
|
||||||
transition: transform 0.12s var(--ease-bounce), background 0.12s ease;
|
transition: transform 0.12s var(--ease-standard), background 0.12s ease, box-shadow 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
@@ -272,52 +216,53 @@ body::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn--secondary {
|
.btn--secondary {
|
||||||
background: var(--color-surface);
|
background: var(--color-card);
|
||||||
color: var(--color-plum);
|
color: var(--color-text);
|
||||||
border: 1.5px solid var(--color-plum);
|
border: 1.5px solid var(--color-border-ui-strong);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:disabled {
|
.btn:disabled {
|
||||||
opacity: 0.55;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:active:not(:disabled) {
|
.btn:active:not(:disabled) {
|
||||||
background: linear-gradient(135deg, var(--color-accent), var(--color-accent-hover));
|
background: #ff7673;
|
||||||
transform: scale(0.97);
|
transform: scale(0.97);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--secondary:active:not(:disabled) {
|
.btn--secondary:active:not(:disabled) {
|
||||||
background: var(--color-plum-soft);
|
background: var(--color-card-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
.btn:hover:not(:disabled) {
|
.btn:hover:not(:disabled) {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--secondary:hover:not(:disabled) {
|
.btn--secondary:hover:not(:disabled) {
|
||||||
background: var(--color-plum-soft);
|
background: var(--color-card-muted);
|
||||||
|
border-color: var(--color-coral);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:focus-visible,
|
.btn:focus-visible,
|
||||||
a:focus-visible {
|
a:focus-visible {
|
||||||
outline: 3px solid var(--color-plum);
|
outline: 3px solid var(--color-coral);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zip-status {
|
.zip-status {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
margin: 0 0 1.25rem;
|
margin: 0 0 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zip-status--error {
|
.zip-status--error {
|
||||||
color: var(--color-error-text);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-grid {
|
.photo-grid {
|
||||||
@@ -329,26 +274,29 @@ a:focus-visible {
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exception admin explicite : grille classique, cartes rectangulaires,
|
||||||
|
AUCUNE rotation façon polaroid (contrairement à src/galerie/style.css)
|
||||||
|
ni glow/neon — juste une carte sobre en #1E1B18. */
|
||||||
.photo-card {
|
.photo-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--color-surface);
|
background: var(--color-card);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-card);
|
||||||
transition: box-shadow 0.2s var(--ease-standard), transform 0.2s var(--ease-standard);
|
transition: box-shadow 0.2s var(--ease-standard), transform 0.2s var(--ease-standard);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Liseré de couleur en haut de carte : discret au repos, affirmé au survol
|
/* Liseré corail en haut de carte au survol desktop uniquement : seule
|
||||||
— encore de la "couleur" réutilisant la palette existante, appliquée à
|
touche décorative de couleur tolérée ici, et encore, discrète et
|
||||||
un endroit où elle valorise le contenu (la photo) sans le concurrencer. */
|
réactive au hover plutôt que permanente. */
|
||||||
.photo-card::before {
|
.photo-card::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0 0 auto 0;
|
inset: 0 0 auto 0;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
background: linear-gradient(90deg, var(--color-accent), var(--color-plum));
|
background: var(--color-coral);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.2s var(--ease-standard);
|
transition: opacity 0.2s var(--ease-standard);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@@ -356,8 +304,8 @@ a:focus-visible {
|
|||||||
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
.photo-card:hover {
|
.photo-card:hover {
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
transform: translateY(-3px) rotate(-0.6deg);
|
transform: translateY(-3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-card:hover::before {
|
.photo-card:hover::before {
|
||||||
@@ -369,7 +317,7 @@ a:focus-visible {
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
background: var(--color-surface-muted);
|
background: var(--color-card-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-card__thumb {
|
.photo-card__thumb {
|
||||||
@@ -387,7 +335,7 @@ a:focus-visible {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,17 +357,18 @@ a:focus-visible {
|
|||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
margin: 0 0 0.2rem;
|
margin: 0 0 0.2rem;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-card__message {
|
.photo-card__message {
|
||||||
color: var(--color-text);
|
color: var(--color-muted);
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
margin: 0 0 0.35rem;
|
margin: 0 0 0.35rem;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-card__date {
|
.photo-card__date {
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@@ -428,23 +377,22 @@ a:focus-visible {
|
|||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
background: var(--color-accent);
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 0.82rem;
|
font-size: 0.82rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-card__download:hover {
|
.photo-card__download:hover {
|
||||||
background: var(--color-accent-hover);
|
background: #ff7673;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.spinner,
|
.spinner,
|
||||||
.photo-card,
|
.photo-card,
|
||||||
.photo-card::before,
|
.photo-card::before,
|
||||||
.btn,
|
.btn {
|
||||||
.page__header {
|
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,51 +17,62 @@
|
|||||||
tables lors de l'événement.
|
tables lors de l'événement.
|
||||||
-->
|
-->
|
||||||
<style>
|
<style>
|
||||||
/* Palette/police alignées sur la passe 2 (2026-09-16) du reste du produit
|
/* Direction artistique "Polaroid Néon" (.claude/skills/photobooth-da/SKILL.md).
|
||||||
— voir src/e/style.css pour la justification complète de la direction
|
Compromis assumé pour cet écran (signalé à Kévin, pas tranché seul) :
|
||||||
créative (punchy/friendly plutôt que sobre). Le carton imprimé est un
|
le carton reste un support IMPRIMÉ (papier, posé sur les tables), donc
|
||||||
livrable physique posé sur les tables : mêmes contraintes qu'ailleurs
|
il garde un fond clair — un fond #12100E n'a pas de sens sur un support
|
||||||
côté fond (pas de dépendance CDN), mais on évite ici le texte en
|
physique et gâcherait de l'encre en impression maison. En revanche il
|
||||||
dégradé (background-clip:text) sur les éléments imprimés — beaucoup
|
adopte les polices (General Sans pour le titre, Caveat pour
|
||||||
d'utilisateurs impriment sans l'option "Imprimer les arrière-plans",
|
l'accroche manuscrite — remplace Fraunces) et l'accent corail de la
|
||||||
ce qui ferait disparaître un titre en dégradé. La personnalité vient
|
nouvelle DA pour rester cohérent avec le reste de la marque. Comme
|
||||||
donc de la police Fraunces + d'une couleur pleine, pas d'un effet qui
|
avant : pas de dégradé (background-clip:text) sur les éléments
|
||||||
dépend d'un réglage d'impression. */
|
imprimés — beaucoup d'utilisateurs impriment sans "Imprimer les
|
||||||
|
arrière-plans", ce qui ferait disparaître un titre en dégradé. Le
|
||||||
|
texte sur fond corail plein (bouton "Imprimer") utilise du texte
|
||||||
|
sombre (#12100E), conformément à la règle de contraste WCAG AA
|
||||||
|
vérifiée pour cette DA (le corail #FF5E5B échoue avec du texte clair,
|
||||||
|
6.3:1 à 13.2:1 avec du texte sombre). */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Fraunces";
|
font-family: "General Sans";
|
||||||
src: url("/vendor/fonts/fraunces-latin-600-normal.woff2") format("woff2");
|
src: url("/vendor/fonts/generalsans-700.woff2") format("woff2");
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Fraunces";
|
font-family: "Caveat";
|
||||||
src: url("/vendor/fonts/fraunces-latin-500-italic.woff2") format("woff2");
|
src: url("/vendor/fonts/caveat-latin-variable.woff2") format("woff2");
|
||||||
font-weight: 500;
|
font-weight: 400 700;
|
||||||
font-style: italic;
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
src: url("/vendor/fonts/inter-latin-variable.woff2") format("woff2");
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
--color-bg: #fff8f0;
|
--color-bg: #faf6f0;
|
||||||
--color-surface: #ffffff;
|
--color-surface: #ffffff;
|
||||||
--color-surface-muted: #fdecdd;
|
--color-surface-muted: #f3ece1;
|
||||||
--color-text: #2b2016;
|
--color-text: #12100e;
|
||||||
--color-muted: #8a7869;
|
--color-ink: #12100e;
|
||||||
--color-border: #f1ddc6;
|
--color-muted: #5c5348;
|
||||||
--color-accent: #e35f2b;
|
--color-border: #e8dfd3;
|
||||||
--color-accent-hover: #c74c1e;
|
--color-coral: #ff5e5b;
|
||||||
--color-accent-light: #ff8a52;
|
--color-coral-hover: #e44542;
|
||||||
--color-accent-contrast: #fffaf6;
|
|
||||||
--color-plum: #7c2f56;
|
|
||||||
--radius-sm: 12px;
|
--radius-sm: 12px;
|
||||||
--radius: 20px;
|
--radius: 20px;
|
||||||
--radius-pill: 999px;
|
--radius-pill: 999px;
|
||||||
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
"Helvetica Neue", Arial, sans-serif;
|
"Helvetica Neue", Arial, sans-serif;
|
||||||
--font-display: "Fraunces", Georgia, "Times New Roman", serif;
|
--font-display: "General Sans", Arial, sans-serif;
|
||||||
|
--font-hand: "Caveat", "Segoe Script", cursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -75,6 +86,10 @@
|
|||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
}
|
||||||
|
|
||||||
.workspace {
|
.workspace {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 300px 1fr;
|
grid-template-columns: 300px 1fr;
|
||||||
@@ -141,7 +156,7 @@
|
|||||||
input:focus-visible,
|
input:focus-visible,
|
||||||
select:focus-visible,
|
select:focus-visible,
|
||||||
button:focus-visible {
|
button:focus-visible {
|
||||||
outline: 3px solid var(--color-accent);
|
outline: 3px solid var(--color-coral);
|
||||||
outline-offset: 1px;
|
outline-offset: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,10 +177,10 @@
|
|||||||
padding: 0.8rem 1rem;
|
padding: 0.8rem 1rem;
|
||||||
min-height: 46px;
|
min-height: 46px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent));
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
box-shadow: 0 6px 16px rgba(195, 76, 30, 0.22);
|
box-shadow: 0 6px 16px rgba(255, 94, 91, 0.28);
|
||||||
transition: transform 0.12s var(--ease-bounce), background 0.12s ease;
|
transition: transform 0.12s var(--ease-spring), background 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#printBtn:disabled {
|
#printBtn:disabled {
|
||||||
@@ -175,7 +190,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#printBtn:active:not(:disabled) {
|
#printBtn:active:not(:disabled) {
|
||||||
background: linear-gradient(135deg, var(--color-accent), var(--color-accent-hover));
|
background: var(--color-coral-hover);
|
||||||
transform: scale(0.98);
|
transform: scale(0.98);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +207,7 @@
|
|||||||
width: 148mm;
|
width: 148mm;
|
||||||
height: 210mm;
|
height: 210mm;
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border: 1.5mm solid var(--color-accent);
|
border: 1.5mm solid var(--color-coral);
|
||||||
border-radius: 6mm;
|
border-radius: 6mm;
|
||||||
box-shadow: 0 10px 30px rgba(38, 36, 32, 0.18);
|
box-shadow: 0 10px 30px rgba(38, 36, 32, 0.18);
|
||||||
padding: 14mm 12mm;
|
padding: 14mm 12mm;
|
||||||
@@ -212,7 +227,7 @@
|
|||||||
.card__mark {
|
.card__mark {
|
||||||
width: 5mm;
|
width: 5mm;
|
||||||
height: 5mm;
|
height: 5mm;
|
||||||
color: var(--color-accent);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card__brand-name {
|
.card__brand-name {
|
||||||
@@ -222,23 +237,30 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Titre en --color-coral-hover (pas --color-coral tel quel) : contraste
|
||||||
|
vérifié par calcul sur fond blanc (~4:1, au-dessus du seuil 3:1 des
|
||||||
|
"grands textes" WCAG AA applicable ici vu la taille/graisse) — le
|
||||||
|
corail plein pur est trop proche du seuil (~3.0:1, marge trop faible
|
||||||
|
pour un support imprimé). */
|
||||||
.card__title {
|
.card__title {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: 9mm;
|
font-size: 9mm;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
color: var(--color-accent-hover);
|
color: var(--color-coral-hover);
|
||||||
margin: 6mm 0 2mm;
|
margin: 6mm 0 2mm;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Accroche manuscrite (Caveat, remplace l'italique Fraunces) : en encre
|
||||||
|
sombre pleine (--color-ink) plutôt qu'une couleur d'accent, pour rester
|
||||||
|
lisible et fidèle à l'impression quel que soit le réglage d'encre. */
|
||||||
.card__prompt {
|
.card__prompt {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-hand);
|
||||||
font-style: italic;
|
font-weight: 600;
|
||||||
font-weight: 500;
|
font-size: 6.5mm;
|
||||||
font-size: 4.6mm;
|
color: var(--color-ink);
|
||||||
color: var(--color-plum);
|
|
||||||
margin: 0 0 8mm;
|
margin: 0 0 8mm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+50
-60
@@ -5,57 +5,43 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Générateur de QR code — photobooth-qr (admin)</title>
|
<title>Générateur de QR code — photobooth-qr (admin)</title>
|
||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<meta name="theme-color" content="#faf6f0" media="(prefers-color-scheme: light)" />
|
<meta name="theme-color" content="#12100E" />
|
||||||
<meta name="theme-color" content="#1b120b" media="(prefers-color-scheme: dark)" />
|
|
||||||
<style>
|
<style>
|
||||||
/* Mêmes tokens que src/e/style.css et src/admin/gallery/style.css —
|
/* Direction artistique "Polaroid Néon" (.claude/skills/photobooth-da/SKILL.md),
|
||||||
cohérence visuelle même sur cet outil interne que les clients ne
|
exception admin : sobre, sombre, data-first. Mêmes tokens que
|
||||||
voient pas (cf. retour Kévin 2026-09-16). Palette/rayons resynchronisés
|
src/admin/gallery/style.css pour la cohérence visuelle entre écrans
|
||||||
avec la passe 2 (2026-09-16, direction "punchy/friendly") ; outil
|
admin, même sur cet outil interne que les clients ne voient pas (cf.
|
||||||
interne, priorité basse donc pas de police d'accent ni d'animations
|
retour Kévin 2026-09-16, toujours valable avec la nouvelle DA). Outil
|
||||||
d'entrée ajoutées ici, juste la cohérence de base (couleurs, rayons).
|
interne à priorité basse : thème unique sombre (pas de double thème
|
||||||
|
clair/sombre), pas d'animation d'entrée, juste la cohérence de base
|
||||||
Passe 3 (2026-09-16) : mode sombre ajouté (demandé explicitement pour
|
(couleurs, rayons, police). */
|
||||||
ce fichier) + petites finitions hover/focus à coût nul, mais toujours
|
|
||||||
sans Fraunces ni animation d'entrée — la priorité basse de cet outil
|
|
||||||
reste valable, seul le mode sombre est une demande directe. */
|
|
||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: dark;
|
||||||
--color-bg: #fff8f0;
|
--color-bg: #12100e;
|
||||||
--color-surface: #ffffff;
|
--color-ink: #12100e;
|
||||||
--color-surface-muted: #fdecdd;
|
--color-text: #faf6f0;
|
||||||
--color-text: #2b2016;
|
--color-muted: #e8dfd3;
|
||||||
--color-muted: #8a7869;
|
--color-muted-2: #a89e90;
|
||||||
--color-border: #f1ddc6;
|
--color-coral: #ff5e5b;
|
||||||
--color-accent: #e35f2b;
|
--color-card: #1e1b18;
|
||||||
--color-accent-hover: #c74c1e;
|
--color-card-muted: #262220;
|
||||||
--color-accent-soft: #ffe3d0;
|
--color-border-ui: rgba(250, 246, 240, 0.16);
|
||||||
--color-accent-contrast: #fffaf6;
|
--radius-sm: 10px;
|
||||||
--color-error-text: #a3341c;
|
--radius: 14px;
|
||||||
--radius-sm: 12px;
|
--shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
--radius: 20px;
|
|
||||||
--shadow-sm: 0 2px 6px rgba(163, 78, 30, 0.1);
|
|
||||||
--ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
|
--ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
"Helvetica Neue", Arial, sans-serif;
|
"Helvetica Neue", Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@font-face {
|
||||||
:root {
|
font-family: "Inter";
|
||||||
--color-bg: #1b120b;
|
src: url("/vendor/fonts/inter-latin-variable.woff2") format("woff2");
|
||||||
--color-surface: #26190f;
|
font-weight: 400 700;
|
||||||
--color-surface-muted: #32211a;
|
font-style: normal;
|
||||||
--color-text: #f7ead9;
|
font-display: swap;
|
||||||
--color-muted: #b39d84;
|
|
||||||
--color-border: #40291a;
|
|
||||||
--color-accent: #ff7a42;
|
|
||||||
--color-accent-hover: #ffa06e;
|
|
||||||
--color-accent-soft: rgba(255, 122, 66, 0.18);
|
|
||||||
--color-accent-contrast: #241206;
|
|
||||||
--color-error-text: #ff9b86;
|
|
||||||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.45);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -79,7 +65,7 @@
|
|||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: var(--color-accent);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
.brand span {
|
.brand span {
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
@@ -111,24 +97,24 @@
|
|||||||
padding: 0.7rem 0.75rem;
|
padding: 0.7rem 0.75rem;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border-ui);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
background: var(--color-surface);
|
background: var(--color-card);
|
||||||
color: inherit;
|
color: inherit;
|
||||||
transition: border-color 0.15s var(--ease-standard), box-shadow 0.15s var(--ease-standard);
|
transition: border-color 0.15s var(--ease-standard), box-shadow 0.15s var(--ease-standard);
|
||||||
}
|
}
|
||||||
input:focus,
|
input:focus,
|
||||||
select:focus {
|
select:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--color-accent);
|
border-color: var(--color-coral);
|
||||||
box-shadow: 0 0 0 4px var(--color-accent-soft);
|
box-shadow: 0 0 0 4px rgba(255, 94, 91, 0.22);
|
||||||
}
|
}
|
||||||
.preview {
|
.preview {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
padding: 1.1rem;
|
padding: 1.1rem;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border-ui);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: var(--color-surface);
|
background: var(--color-card);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -160,40 +146,44 @@
|
|||||||
button {
|
button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
padding: 0.85rem 0.7rem;
|
padding: 0.85rem 0.7rem;
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
border: 1px solid var(--color-accent);
|
border: 1px solid var(--color-coral);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: var(--radius-sm);
|
||||||
background: var(--color-accent);
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.15s var(--ease-standard), background 0.15s ease;
|
transition: transform 0.15s var(--ease-standard), background 0.15s ease;
|
||||||
}
|
}
|
||||||
button:active:not(:disabled) {
|
button:active:not(:disabled) {
|
||||||
background: var(--color-accent-hover);
|
background: #ff7673;
|
||||||
}
|
}
|
||||||
button.secondary {
|
button.secondary {
|
||||||
background: var(--color-surface);
|
background: var(--color-card);
|
||||||
color: var(--color-accent);
|
color: var(--color-text);
|
||||||
|
border-color: var(--color-border-ui);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
button.secondary:active:not(:disabled) {
|
button.secondary:active:not(:disabled) {
|
||||||
background: var(--color-accent-soft);
|
background: var(--color-card-muted);
|
||||||
}
|
}
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
button:hover:not(:disabled) {
|
button:hover:not(:disabled) {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
button.secondary:hover:not(:disabled) {
|
||||||
|
border-color: var(--color-coral);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
button:disabled {
|
button:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
.error {
|
.error {
|
||||||
color: var(--color-error-text);
|
color: var(--color-coral);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
min-height: 1.2em;
|
min-height: 1.2em;
|
||||||
|
|||||||
+5
-6
@@ -12,12 +12,11 @@
|
|||||||
lors du déploiement, hors scope de ce fichier front.
|
lors du déploiement, hors scope de ce fichier front.
|
||||||
-->
|
-->
|
||||||
<meta name="robots" content="noindex, nofollow">
|
<meta name="robots" content="noindex, nofollow">
|
||||||
<!-- Deux meta theme-color (au lieu d'une seule) : teinte la barre
|
<!-- Thème unique sombre "Polaroid Néon" (voir src/e/style.css) : une seule
|
||||||
navigateur/PWA selon le thème système, en cohérence avec le mode sombre
|
meta theme-color, comme src/galerie/index.html. -->
|
||||||
ajouté passe 3 (voir src/e/style.css). -->
|
<meta name="theme-color" content="#12100E">
|
||||||
<meta name="theme-color" content="#faf6f0" media="(prefers-color-scheme: light)">
|
<link rel="preload" href="/vendor/fonts/generalsans-700.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
<meta name="theme-color" content="#1b120b" media="(prefers-color-scheme: dark)">
|
<link rel="preload" href="/vendor/fonts/caveat-latin-variable.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
<link rel="preload" href="/vendor/fonts/fraunces-latin-600-normal.woff2" as="font" type="font/woff2" crossorigin>
|
|
||||||
<link rel="stylesheet" href="/e/style.css">
|
<link rel="stylesheet" href="/e/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
+201
-356
@@ -1,200 +1,101 @@
|
|||||||
/* Page upload invité — mobile-first, sans dépendance externe.
|
/* Page upload invité — direction artistique "Polaroid Néon"
|
||||||
Système de design partagé avec la galerie admin (src/admin/gallery/style.css) :
|
(.claude/skills/photobooth-da/SKILL.md). Remplace les 3 passes DA
|
||||||
mêmes tokens de couleur/rayon/ombre, pour une identité cohérente entre les
|
précédentes (palette corail/prune/doré + Fraunces, voir historique
|
||||||
deux écrans (voir docs/decisions.md pour le contexte produit).
|
git) : cet écran suit désormais src/galerie/style.css comme référence
|
||||||
|
de cohérence (premier écran construit dans cette DA, validé par
|
||||||
|
Kévin — "c'est vraiment top comme ça !").
|
||||||
|
|
||||||
Direction créative (passe 2, 2026-09-16) — voir rapport de la passe pour
|
Choix pris pendant cette passe, à signaler à Kévin :
|
||||||
le détail complet, résumé ici :
|
- Thème unique sombre (color-scheme: dark), comme src/galerie/style.css,
|
||||||
Retour direct de Kévin sur la 1ère passe : trop "démo sage", pas assez
|
plutôt que le double thème clair/sombre (prefers-color-scheme) de
|
||||||
"envie de participer". Consigne resserrée en cours de route : viser
|
l'ancienne DA. Le skill ne demande nulle part de garder un thème
|
||||||
PUNCHY / FRIENDLY / FUN, pas un premium feutré silencieux. Traduction :
|
clair, et le premier écran validé n'en a pas — cohérence retenue
|
||||||
- Palette plus affirmée : on garde la famille chaude (cohérente avec
|
plutôt qu'une redondance non demandée. À confirmer si un thème clair
|
||||||
l'identité perso de Kévin / Rêves Liquides) mais on la sature — un
|
est en fait souhaité pour cet écran précis.
|
||||||
corail vif en primaire plutôt que le brun terracotta sourd de la V1,
|
- Titre et éléments de "chrome" en texte plein (pas de dégradé
|
||||||
avec un prune et un doré en accents secondaires (confettis, badges).
|
corail→doré comme l'ancienne DA) : le skill met en garde contre le
|
||||||
- Formes plus rondes/organiques (rayons agrandis, boutons pilule).
|
"glow/neon CSS artificiel" et l'écran de référence (galerie) n'utilise
|
||||||
- Micro-animations qui ont du peps : coche qui "pop" avec rebond,
|
aucun dégradé de texte ni halo radial en fond — même logique
|
||||||
confettis colorés au succès, spinner de chargement, easing "overshoot"
|
appliquée ici pour rester cohérent plutôt que de réintroduire cet
|
||||||
sur les interactions plutôt que du linear plat.
|
effet.
|
||||||
- Ton de voix plus souriant dans les micro-copies (succès, limite
|
|
||||||
atteinte) — cf. src/e/upload.js pour les textes.
|
|
||||||
- Police d'accent Fraunces (serif à forte personnalité, chaleureuse et
|
|
||||||
un peu "pop") en plus de la pile système pour les titres/moments clés
|
|
||||||
— auto-hébergée en .woff2, 2 graisses (~41 Ko au total), voir
|
|
||||||
src/vendor/fonts/ et src/vendor/NOTICE.md. Le corps de texte reste
|
|
||||||
100% système (poids nul).
|
|
||||||
|
|
||||||
Passe 3, 2026-09-16 — retour Kévin : "top ! rajoute des animations, de la
|
Contrastes vérifiés par calcul WCAG AA (même méthode que
|
||||||
couleur [...] brainstorm sur le choix des couleurs et de la typo, ajoute
|
src/galerie/style.css) : texte clair (#FAF6F0/#E8DFD3) sur fond sombre
|
||||||
un mode sombre [...] fait moi quelque chose de vendeur et de friendly
|
(#12100E) est très largement au-dessus du seuil ; texte sombre (#12100E)
|
||||||
(type iPhone)." Palette/typo déjà validées passe 2 : le brainstorm de
|
sur les 3 couleurs d'accent (corail/jaune/vert) passe confortablement
|
||||||
cette passe (voir rapport de passe pour le détail des 2 directions
|
(6.3:1 à 13.2:1) — utilisé systématiquement pour le texte des CTA en
|
||||||
alternatives écartées) a confirmé la famille corail/prune/doré + Fraunces
|
couleur pleine. Les fonds teintés à faible opacité (états erreur/limite/
|
||||||
plutôt que d'ajouter de nouvelles teintes ou une police supplémentaire —
|
succès) restent très proches du noir une fois mélangés à #12100E ; le
|
||||||
"plus de couleur" est obtenu en réutilisant plus largement cette même
|
texte de ces blocs reste donc en couleur claire standard (--color-text/
|
||||||
palette (halo radial en fond, focus ring teinté, confettis étoffés)
|
--color-muted), jamais en couleur d'accent pleine, par prudence. */
|
||||||
plutôt qu'en important une 4e couleur qui romprait l'identité perso de
|
|
||||||
Kévin. Traduction concrète de cette passe :
|
|
||||||
- Mode sombre réel via prefers-color-scheme (pas d'inversion brute) :
|
|
||||||
fond brun quasi-noir (jamais bleu-nuit, pour rester dans la famille
|
|
||||||
chaude de la marque), texte/accents reclaircis et vérifiés au ratio de
|
|
||||||
contraste (WCAG AA, cf. rapport de passe pour le détail des calculs).
|
|
||||||
- Niveau de finition "type iPhone" au sens exécution, pas esthétique iOS
|
|
||||||
: pas de glassmorphism/blur ni de police système Apple. Concrètement :
|
|
||||||
easing dédié aux transitions d'état (--ease-standard, plus posé que le
|
|
||||||
--ease-bounce déjà en place et réservé aux pops/rebonds), halo de
|
|
||||||
couleur subtil en arrière-plan de page, focus ring teinté sur les
|
|
||||||
champs, micro-interactions de hover en plus du :active existant
|
|
||||||
(uniquement sous @media (hover: hover), donc jamais sur mobile tactile
|
|
||||||
— l'invité ne voit que les états focus/active déjà en place), entrées
|
|
||||||
en fondu/translation des sections principales au chargement. */
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Fraunces";
|
font-family: "General Sans";
|
||||||
src: url("/vendor/fonts/fraunces-latin-600-normal.woff2") format("woff2");
|
src: url("/vendor/fonts/generalsans-700.woff2") format("woff2");
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F,
|
|
||||||
U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Fraunces";
|
font-family: "Caveat";
|
||||||
src: url("/vendor/fonts/fraunces-latin-500-italic.woff2") format("woff2");
|
src: url("/vendor/fonts/caveat-latin-variable.woff2") format("woff2");
|
||||||
font-weight: 500;
|
font-weight: 400 700;
|
||||||
font-style: italic;
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
src: url("/vendor/fonts/inter-latin-variable.woff2") format("woff2");
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F,
|
|
||||||
U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* "light dark" (et non "light" seul) : indique au navigateur que les deux
|
color-scheme: dark;
|
||||||
thèmes sont pris en charge, pour que les contrôles natifs (scrollbar,
|
|
||||||
éventuels <select>) s'adaptent aussi, pas seulement nos propres
|
|
||||||
couleurs. Les valeurs ci-dessous sont le thème clair ; le thème sombre
|
|
||||||
est redéfini intégralement dans le bloc @media (prefers-color-scheme:
|
|
||||||
dark) plus bas — jamais un simple filtre d'inversion. */
|
|
||||||
color-scheme: light dark;
|
|
||||||
|
|
||||||
/* Couleurs — famille chaude toujours ancrée dans l'identité de Kévin,
|
/* Mêmes noms/valeurs que src/galerie/style.css pour la cohérence entre
|
||||||
mais poussée en saturation pour un rendu festif plutôt que sobre. */
|
écrans (voir consigne de la passe). */
|
||||||
--color-bg: #fff8f0;
|
--color-bg: #12100e;
|
||||||
--color-surface: #ffffff;
|
--color-ink: #12100e; /* texte sombre sur surfaces claires/accents */
|
||||||
--color-surface-muted: #fdecdd;
|
--color-text: #faf6f0;
|
||||||
--color-text: #2b2016;
|
--color-muted: #e8dfd3;
|
||||||
--color-muted: #8a7869;
|
--color-muted-2: #a89e90;
|
||||||
--color-border: #f1ddc6;
|
|
||||||
|
|
||||||
--color-accent: #e35f2b;
|
--color-coral: #ff5e5b;
|
||||||
--color-accent-hover: #c74c1e;
|
--color-yellow: #ffd166;
|
||||||
--color-accent-light: #ff8a52;
|
--color-mint: #06d6a0;
|
||||||
--color-accent-soft: #ffe3d0;
|
|
||||||
--color-accent-contrast: #fffaf6;
|
|
||||||
|
|
||||||
--color-plum: #7c2f56;
|
--color-border: #e8dfd3;
|
||||||
--color-plum-soft: #f8e3ee;
|
|
||||||
|
|
||||||
--color-gold: #f0a91e;
|
--radius: 4px; /* réservé aux éléments façon polaroid, non utilisé ici */
|
||||||
--color-gold-soft: #fef0d3;
|
--radius-ui: 14px;
|
||||||
|
|
||||||
--color-error-bg: #fdeae6;
|
|
||||||
--color-error-text: #a3341c;
|
|
||||||
--color-success-bg: #fff1de;
|
|
||||||
--color-success-text: #8a4a10;
|
|
||||||
--color-limit-bg: #fbe9d8;
|
|
||||||
--color-limit-text: #8a4a10;
|
|
||||||
|
|
||||||
/* Bouton "danger" (Réessayer) : variable dédiée plutôt que de réutiliser
|
|
||||||
--color-error-text tel quel comme fond de bouton — nécessaire en thème
|
|
||||||
sombre où le texte d'erreur s'éclaircit (pour rester lisible sur fond
|
|
||||||
sombre) et ne fonctionne plus comme couleur de fond de bouton avec du
|
|
||||||
texte blanc (contraste vérifié, voir rapport de passe). */
|
|
||||||
--color-danger: #a3341c;
|
|
||||||
--color-danger-contrast: #fff;
|
|
||||||
|
|
||||||
--radius-sm: 12px;
|
|
||||||
--radius: 20px;
|
|
||||||
--radius-pill: 999px;
|
--radius-pill: 999px;
|
||||||
|
|
||||||
--shadow-sm: 0 2px 6px rgba(163, 78, 30, 0.1);
|
--shadow-soft: 0 10px 24px rgba(0, 0, 0, 0.35);
|
||||||
--shadow-md: 0 10px 28px rgba(163, 78, 30, 0.16);
|
--shadow-card: 0 6px 16px rgba(0, 0, 0, 0.4);
|
||||||
|
|
||||||
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
/* Easing "posé" pour les transitions d'état/hover (fondus, lifts) — le
|
|
||||||
rebond de --ease-bounce reste réservé aux moments ludiques (pop-in,
|
|
||||||
coche de succès) pour ne pas le diluer. */
|
|
||||||
--ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
|
--ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
|
||||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
--font-display: "General Sans", -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
"Helvetica Neue", Arial, sans-serif;
|
--font-hand: "Caveat", "Segoe Script", cursive;
|
||||||
--font-display: "Fraunces", Georgia, "Times New Roman", serif;
|
--font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
}
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------
|
/* Tokens spécifiques à cet écran (formulaire, états), pas repris de
|
||||||
Thème sombre — palette pensée pour l'obscurité (pas une inversion des
|
src/galerie/style.css qui n'en a pas besoin. */
|
||||||
couleurs claires) : fond brun quasi-noir pour rester dans la famille
|
--color-surface: #1e1b18;
|
||||||
chaude de la marque plutôt qu'un noir bleuté générique, texte et accents
|
--color-surface-muted: #241f1a;
|
||||||
reclaircis et vérifiés au ratio de contraste WCAG AA (>= 4.5:1 pour le
|
--color-border-ui: rgba(250, 246, 240, 0.16);
|
||||||
texte courant, >= 3:1 pour le grand texte/les éléments d'UI ; calculs
|
--color-border-ui-strong: rgba(250, 246, 240, 0.28);
|
||||||
détaillés dans le rapport de passe). Répond aux deux demandes de Kévin à
|
|
||||||
la fois : un vrai mode sombre ET un rendu "moins agressif" en usage réel
|
|
||||||
(salle tamisée en soirée). ----------------------------------------- */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--color-bg: #1b120b;
|
|
||||||
--color-surface: #26190f;
|
|
||||||
--color-surface-muted: #32211a;
|
|
||||||
--color-text: #f7ead9;
|
|
||||||
--color-muted: #b39d84;
|
|
||||||
--color-border: #40291a;
|
|
||||||
|
|
||||||
--color-accent: #ff7a42;
|
--color-error-bg: rgba(255, 94, 91, 0.14);
|
||||||
--color-accent-hover: #ffa06e;
|
--color-limit-bg: rgba(255, 209, 102, 0.16);
|
||||||
--color-accent-light: #ffab7a;
|
--color-success-bg: rgba(6, 214, 160, 0.12);
|
||||||
--color-accent-soft: rgba(255, 122, 66, 0.18);
|
|
||||||
--color-accent-contrast: #241206;
|
|
||||||
|
|
||||||
--color-plum: #f0b8d8;
|
--shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
--color-plum-soft: rgba(240, 184, 216, 0.14);
|
|
||||||
|
|
||||||
--color-gold: #ffcf6b;
|
|
||||||
--color-gold-soft: #3a2a12;
|
|
||||||
|
|
||||||
--color-error-bg: #3a1712;
|
|
||||||
--color-error-text: #ff9b86;
|
|
||||||
--color-success-bg: #2e2110;
|
|
||||||
--color-success-text: #f2d9b8;
|
|
||||||
--color-limit-bg: #3a2a12;
|
|
||||||
--color-limit-text: #ffd98a;
|
|
||||||
|
|
||||||
--color-danger: #ff6b52;
|
|
||||||
--color-danger-contrast: #2b0f08;
|
|
||||||
|
|
||||||
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.45);
|
|
||||||
--shadow-md: 0 14px 36px rgba(0, 0, 0, 0.55);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fonds d'icônes état erreur/limite : calculés à partir des couleurs
|
|
||||||
claires d'origine, non pilotables via une seule variable — surchargés
|
|
||||||
ici pour rester cohérents en sombre plutôt que de laisser un rouge/or
|
|
||||||
"clair" plaqué sur fond sombre. */
|
|
||||||
.state-block--error .state-icon--error {
|
|
||||||
background: rgba(255, 155, 134, 0.16);
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-block--limit .state-icon--limit {
|
|
||||||
background: rgba(255, 217, 138, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-modal {
|
|
||||||
background: rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
body::before {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -206,32 +107,13 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
position: relative;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-ui);
|
||||||
background: var(--color-bg);
|
background: var(--color-bg);
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Halo de couleur en arrière-plan — "plus de couleur" sans ajouter de
|
|
||||||
teinte à la palette : deux dégradés radiaux réutilisant les couleurs
|
|
||||||
d'accent déjà en place (corail + doré), très doux, purement décoratifs.
|
|
||||||
Objectif "type iPhone" : une page peut être vivante sans être plate,
|
|
||||||
sans pour autant recourir à un vrai fond image (poids nul, CSS pur).
|
|
||||||
z-index négatif + fixed : reste derrière le contenu, ne capte aucun
|
|
||||||
événement (pointer-events: none), ne bouge pas au scroll. */
|
|
||||||
body::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
z-index: -1;
|
|
||||||
pointer-events: none;
|
|
||||||
background: radial-gradient(60% 38% at 50% -8%, var(--color-accent-soft) 0%, transparent 72%),
|
|
||||||
radial-gradient(46% 30% at 100% 100%, var(--color-gold-soft) 0%, transparent 70%);
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
max-width: 480px;
|
max-width: 480px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -242,10 +124,6 @@ body::before {
|
|||||||
.page__header {
|
.page__header {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 1.6rem;
|
margin-bottom: 1.6rem;
|
||||||
/* Entrée en fondu/translation au chargement — discrète, une seule fois
|
|
||||||
par affichage (rejoue si la page est masquée/réaffichée via l'attribut
|
|
||||||
hidden, ce qui reste cohérent : chaque "nouvel écran" mérite sa petite
|
|
||||||
entrée). */
|
|
||||||
animation: fade-rise 0.5s var(--ease-standard) both;
|
animation: fade-rise 0.5s var(--ease-standard) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,24 +138,20 @@ body::before {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bloc de marque — discret, rassure l'invité (outil "pro") et signe le
|
|
||||||
produit pour les organisateurs/prestataires qui verront la page.
|
|
||||||
Volontairement minuscule : ce n'est pas l'écran de l'invité qui doit
|
|
||||||
porter la marque de Kévin, c'est un clin d'œil en filigrane. */
|
|
||||||
.brand {
|
.brand {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.4rem;
|
gap: 0.4rem;
|
||||||
margin-bottom: 0.7rem;
|
margin-bottom: 0.7rem;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand__mark {
|
.brand__mark {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: var(--color-accent);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand__name {
|
.brand__name {
|
||||||
@@ -285,39 +159,28 @@ body::before {
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.13em;
|
letter-spacing: 0.13em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
font-family: var(--font-ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page__header h1 {
|
.page__header h1 {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: 2rem;
|
font-weight: 700;
|
||||||
font-weight: 600;
|
font-size: 1.9rem;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
/* Titre en dégradé corail -> doré : la touche "pop" la plus visible de la
|
|
||||||
page, réservée à ce seul élément pour ne pas diluer son effet. Fallback
|
|
||||||
: couleur pleine (--color-accent) si background-clip:text n'est pas
|
|
||||||
supporté (support large sur mobile Safari/Chrome en pratique). */
|
|
||||||
color: var(--color-accent);
|
|
||||||
background: linear-gradient(100deg, var(--color-accent) 20%, var(--color-gold) 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page__kicker {
|
.page__kicker {
|
||||||
font-family: var(--font-display);
|
color: var(--color-muted);
|
||||||
font-style: italic;
|
font-size: 0.95rem;
|
||||||
font-weight: 500;
|
margin: 0.4rem 0 0;
|
||||||
font-size: 1.05rem;
|
|
||||||
color: var(--color-plum);
|
|
||||||
margin: 0.35rem 0 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-block {
|
.state-block {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 1.5rem 1.2rem;
|
padding: 1.5rem 1.2rem;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,18 +190,17 @@ body::before {
|
|||||||
|
|
||||||
.state-block--error {
|
.state-block--error {
|
||||||
background: var(--color-error-bg);
|
background: var(--color-error-bg);
|
||||||
color: var(--color-error-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-block--error.state-block--limit {
|
.state-block--error.state-block--limit {
|
||||||
background: var(--color-limit-bg);
|
background: var(--color-limit-bg);
|
||||||
color: var(--color-limit-text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-block--success {
|
.state-block--success {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: linear-gradient(180deg, var(--color-success-bg), var(--color-surface) 75%);
|
background: linear-gradient(180deg, var(--color-success-bg), transparent 75%);
|
||||||
color: var(--color-success-text);
|
color: var(--color-text);
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
padding-top: 1.75rem;
|
padding-top: 1.75rem;
|
||||||
}
|
}
|
||||||
@@ -351,16 +213,14 @@ body::before {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spinner de chargement — anneau CSS pur, aucune dépendance. Remplace le
|
/* Spinner de chargement — anneau CSS pur, aucune dépendance. */
|
||||||
simple texte "Chargement…" par un repère visuel qui bouge : la première
|
|
||||||
impression de la page ne doit jamais sembler figée/en panne. */
|
|
||||||
.spinner {
|
.spinner {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 26px;
|
width: 26px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
margin-bottom: 0.6rem;
|
margin-bottom: 0.6rem;
|
||||||
border: 3px solid var(--color-accent-soft);
|
border: 3px solid rgba(255, 94, 91, 0.22);
|
||||||
border-top-color: var(--color-accent);
|
border-top-color: var(--color-coral);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: spin 0.8s linear infinite;
|
animation: spin 0.8s linear infinite;
|
||||||
}
|
}
|
||||||
@@ -373,9 +233,8 @@ body::before {
|
|||||||
|
|
||||||
/* Icônes des états erreur / limite atteinte — les deux existent toujours
|
/* Icônes des états erreur / limite atteinte — les deux existent toujours
|
||||||
dans le DOM, affichées/masquées via la classe portée par le bloc parent
|
dans le DOM, affichées/masquées via la classe portée par le bloc parent
|
||||||
(state-block--limit vs par défaut = erreur). Le choix entre les deux se
|
(state-block--limit vs par défaut = erreur). Aucune logique déplacée
|
||||||
fait côté JS uniquement en togglant cette classe (aucune autre logique
|
dans le CSS, uniquement le rendu visuel. */
|
||||||
déplacée dans le CSS). */
|
|
||||||
.state-icon {
|
.state-icon {
|
||||||
display: none;
|
display: none;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
@@ -388,8 +247,8 @@ body::before {
|
|||||||
|
|
||||||
.state-block--error .state-icon--error {
|
.state-block--error .state-icon--error {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: rgba(163, 52, 28, 0.12);
|
background: rgba(255, 94, 91, 0.16);
|
||||||
color: var(--color-error-text);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-block--error.state-block--limit .state-icon--error {
|
.state-block--error.state-block--limit .state-icon--error {
|
||||||
@@ -398,9 +257,9 @@ body::before {
|
|||||||
|
|
||||||
.state-block--limit .state-icon--limit {
|
.state-block--limit .state-icon--limit {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: rgba(138, 74, 16, 0.14);
|
background: rgba(255, 209, 102, 0.18);
|
||||||
color: var(--color-gold);
|
color: var(--color-yellow);
|
||||||
animation: pop-in 0.5s var(--ease-bounce) both;
|
animation: pop-in 0.5s var(--ease-spring) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-icon svg {
|
.state-icon svg {
|
||||||
@@ -415,10 +274,10 @@ body::before {
|
|||||||
animation: fade-rise 0.5s var(--ease-standard) 0.08s both;
|
animation: fade-rise 0.5s var(--ease-standard) 0.08s both;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Même bug que .welcome-modal (voir commentaire plus haut) : présent depuis
|
/* Bug réel corrigé (2026-09-16, conservé lors du passage à la DA "Polaroid
|
||||||
le tout premier commit de ce fichier. form.hidden = true (JS) ne masquait
|
Néon") : une déclaration `display` en CSS auteur passe toujours devant
|
||||||
jamais réellement le formulaire, qui restait affiché en display:flex en
|
`[hidden] { display: none }` du navigateur. Sans cette règle explicite,
|
||||||
permanence, superposé aux états chargement/erreur/succès. */
|
`form.hidden = true` (JS) ne masquait jamais réellement le formulaire. */
|
||||||
.upload-form[hidden] {
|
.upload-form[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -436,20 +295,19 @@ body::before {
|
|||||||
|
|
||||||
.field .optional {
|
.field .optional {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Regroupe prénom + petit mot dans une même carte : crée un second niveau
|
/* Regroupe prénom + petit mot dans une même carte : second niveau de
|
||||||
de hiérarchie visuelle (la photo reste l'action principale au-dessus,
|
hiérarchie visuelle (la photo reste l'action principale au-dessus). */
|
||||||
ces champs facultatifs sont secondaires et "posés" ensemble). */
|
|
||||||
.field-group {
|
.field-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border-ui);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
padding: 1.1rem;
|
padding: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,21 +315,18 @@ input[type="text"],
|
|||||||
textarea {
|
textarea {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
padding: 0.7rem 0.8rem;
|
padding: 0.7rem 0.8rem;
|
||||||
border: 1.5px solid var(--color-border);
|
border: 1.5px solid var(--color-border-ui);
|
||||||
border-radius: var(--radius-sm);
|
border-radius: 10px;
|
||||||
background: var(--color-surface);
|
background: var(--color-bg);
|
||||||
color: inherit;
|
color: inherit;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: border-color 0.18s var(--ease-standard), box-shadow 0.18s var(--ease-standard);
|
transition: border-color 0.18s var(--ease-standard), box-shadow 0.18s var(--ease-standard);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anneau de focus teinté (en plus du changement de bordure) : détail de
|
|
||||||
finition "type iPhone" — un champ actif doit se voir sans ambiguïté,
|
|
||||||
avec une transition douce plutôt qu'un changement sec. */
|
|
||||||
input[type="text"]:focus,
|
input[type="text"]:focus,
|
||||||
textarea:focus {
|
textarea:focus {
|
||||||
border-color: var(--color-accent);
|
border-color: var(--color-coral);
|
||||||
box-shadow: 0 0 0 4px var(--color-accent-soft);
|
box-shadow: 0 0 0 4px rgba(255, 94, 91, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.visually-hidden {
|
.visually-hidden {
|
||||||
@@ -491,12 +346,10 @@ textarea:focus {
|
|||||||
gap: 0.6rem;
|
gap: 0.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Boutons "Prendre une photo" / "Depuis la galerie" — forme pilule (identité
|
/* Boutons "Prendre une photo" / "Depuis la galerie" — la capture directe
|
||||||
plus ronde/organique que la V1) avec une hiérarchie claire : la capture
|
est l'action attendue pour la quasi-totalité des invités pendant
|
||||||
directe est l'action attendue pour la quasi-totalité des invités pendant
|
l'événement, donc traitée en primaire (corail plein, texte sombre) ;
|
||||||
l'événement (le moment se vit là, tout de suite), donc traitée en
|
la galerie reste secondaire mais tout aussi accessible en un tap. */
|
||||||
primaire pleine couleur ; la galerie reste secondaire mais tout aussi
|
|
||||||
accessible en un tap (contrainte actée le 2026-09-16). */
|
|
||||||
.btn-source {
|
.btn-source {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -510,20 +363,20 @@ textarea:focus {
|
|||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
border-radius: var(--radius-pill);
|
border-radius: var(--radius-pill);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.12s var(--ease-bounce), box-shadow 0.12s ease, background 0.12s ease;
|
transition: transform 0.12s var(--ease-spring), box-shadow 0.12s ease, background 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-source--primary {
|
.btn-source--primary {
|
||||||
border: none;
|
border: none;
|
||||||
background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent));
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-source--secondary {
|
.btn-source--secondary {
|
||||||
border: 1.5px solid var(--color-plum);
|
border: 1.5px solid var(--color-border-ui-strong);
|
||||||
background: var(--color-surface);
|
background: transparent;
|
||||||
color: var(--color-plum);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-source:active {
|
.btn-source:active {
|
||||||
@@ -531,34 +384,30 @@ textarea:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-source--primary:active {
|
.btn-source--primary:active {
|
||||||
background: linear-gradient(135deg, var(--color-accent), var(--color-accent-hover));
|
background: #ff7673;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-source--secondary:active {
|
.btn-source--secondary:active {
|
||||||
background: var(--color-plum-soft);
|
background: var(--color-surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* États hover — uniquement pour les pointeurs qui en ont un (souris/trackpad
|
/* États hover — uniquement pour les pointeurs qui en ont un (souris/trackpad
|
||||||
d'un prospect qui consulte la page sur desktop lors d'une démo) : jamais
|
d'un prospect qui consulte la page sur desktop lors d'une démo) : jamais
|
||||||
sur mobile tactile, où seuls :active/:focus-visible s'appliquent déjà.
|
sur mobile tactile. */
|
||||||
Lift discret + easing posé (pas de rebond ici, réservé aux pops). */
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
.btn-source--primary:hover {
|
.btn-source--primary:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-source--secondary:hover {
|
.btn-source--secondary:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
background: var(--color-plum-soft);
|
background: var(--color-surface);
|
||||||
|
border-color: var(--color-coral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Icônes SVG inline (aucune requête réseau) : remplacent les emoji des
|
/* Icônes SVG inline (aucune requête réseau), héritent de currentColor. */
|
||||||
boutons "Prendre une photo" / "Depuis la galerie". Le rendu des emoji
|
|
||||||
varie fortement selon l'OS (Android/iOS/Windows) — pas assez maîtrisé
|
|
||||||
pour une pièce de portfolio. Les icônes héritent de currentColor, donc
|
|
||||||
suivent l'état du bouton sans CSS supplémentaire. */
|
|
||||||
.btn-icon {
|
.btn-icon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
@@ -567,7 +416,7 @@ textarea:focus {
|
|||||||
|
|
||||||
.file-chosen-label {
|
.file-chosen-label {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
margin: 0.5rem 0 0;
|
margin: 0.5rem 0 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@@ -580,7 +429,7 @@ textarea {
|
|||||||
input:focus-visible,
|
input:focus-visible,
|
||||||
textarea:focus-visible,
|
textarea:focus-visible,
|
||||||
button:focus-visible {
|
button:focus-visible {
|
||||||
outline: 3px solid var(--color-plum);
|
outline: 3px solid var(--color-coral);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,9 +437,9 @@ button:focus-visible {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 320px;
|
max-height: 320px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
background: var(--color-surface-muted);
|
background: var(--color-surface-muted);
|
||||||
animation: pop-in 0.35s var(--ease-bounce) both;
|
animation: pop-in 0.35s var(--ease-spring) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legal-notice {
|
.legal-notice {
|
||||||
@@ -600,7 +449,7 @@ button:focus-visible {
|
|||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted);
|
||||||
background: var(--color-surface-muted);
|
background: var(--color-surface-muted);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
padding: 0.85rem 0.9rem;
|
padding: 0.85rem 0.9rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@@ -610,7 +459,7 @@ button:focus-visible {
|
|||||||
height: 18px;
|
height: 18px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-top: 0.1rem;
|
margin-top: 0.1rem;
|
||||||
color: var(--color-plum);
|
color: var(--color-muted-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.legal-link {
|
.legal-link {
|
||||||
@@ -625,7 +474,7 @@ button:focus-visible {
|
|||||||
font: inherit;
|
font: inherit;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-underline-offset: 2px;
|
text-underline-offset: 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -633,21 +482,21 @@ button:focus-visible {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.legal-link .legal-notice__icon {
|
.legal-link .legal-notice__icon {
|
||||||
color: var(--color-muted);
|
color: var(--color-muted-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
.legal-link:hover {
|
.legal-link:hover {
|
||||||
color: var(--color-plum);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.legal-link:hover .legal-notice__icon {
|
.legal-link:hover .legal-notice__icon {
|
||||||
color: var(--color-plum);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
#welcome-modal-dismiss:hover {
|
#welcome-modal-dismiss:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,17 +510,13 @@ button:focus-visible {
|
|||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: rgba(43, 32, 22, 0.45);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
animation: fade-in 0.2s ease both;
|
animation: fade-in 0.2s ease both;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bug réel corrigé (2026-09-16) : une déclaration `display` en CSS auteur
|
/* Même bug que .upload-form (voir commentaire plus haut), présent depuis le
|
||||||
passe toujours devant la règle `[hidden] { display: none }` du navigateur
|
tout premier commit : sans cette règle, welcomeModal.hidden = true (JS)
|
||||||
(l'origine "auteur" l'emporte sur l'origine "user-agent" dans la
|
ne masquait jamais visuellement la modale. */
|
||||||
cascade, indépendamment de la spécificité). Sans cette règle explicite,
|
|
||||||
`welcomeModal.hidden = true` en JS ne masquait jamais visuellement la
|
|
||||||
modale : le bouton "C'est parti" fonctionnait bien (l'état se mettait à
|
|
||||||
jour) mais rien ne changeait à l'écran. */
|
|
||||||
.welcome-modal[hidden] {
|
.welcome-modal[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -683,26 +528,25 @@ button:focus-visible {
|
|||||||
max-height: 88vh;
|
max-height: 88vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border-radius: var(--radius) var(--radius) 0 0;
|
border-radius: var(--radius-ui) var(--radius-ui) 0 0;
|
||||||
padding: 1.5rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
|
padding: 1.5rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
animation: slide-up 0.35s var(--ease-bounce) both;
|
animation: slide-up 0.35s var(--ease-spring) both;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.9rem;
|
gap: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Liseré dégradé en haut de la carte — même traitement que les cartes de la
|
/* Liseré corail en haut de la carte — même traitement de "chrome" que la
|
||||||
galerie admin (src/admin/gallery/style.css), pour une petite touche de
|
galerie admin (src/admin/gallery/style.css), touche de couleur cohérente
|
||||||
couleur cohérente entre les deux écrans sur un élément de chrome (pas de
|
entre écrans sur un élément de bordure, pas de contenu. */
|
||||||
contenu), plutôt qu'un ajout ponctuel isolé. */
|
|
||||||
.welcome-modal__card::before {
|
.welcome-modal__card::before {
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin: -1.5rem -1.25rem 1.1rem;
|
margin: -1.5rem -1.25rem 1.1rem;
|
||||||
background: linear-gradient(90deg, var(--color-accent), var(--color-gold));
|
background: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 520px) {
|
@media (min-width: 520px) {
|
||||||
@@ -710,7 +554,7 @@ button:focus-visible {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.welcome-modal__card {
|
.welcome-modal__card {
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius-ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,46 +562,38 @@ button:focus-visible {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Peaufinage passe 3 (la modale était fonctionnelle mais minimale) : la
|
|
||||||
marque prend la forme d'un badge rond coloré plutôt qu'une petite icône
|
|
||||||
nue — cohérent avec le ton "app premium" recherché, sans nouvel élément
|
|
||||||
HTML (juste du style appliqué au SVG existant). */
|
|
||||||
.welcome-modal .brand__mark {
|
.welcome-modal .brand__mark {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding: 7px;
|
padding: 7px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--color-accent-soft);
|
background: rgba(255, 94, 91, 0.16);
|
||||||
color: var(--color-accent);
|
color: var(--color-coral);
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-modal__title {
|
.welcome-modal__title {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
color: var(--color-accent);
|
|
||||||
background: linear-gradient(100deg, var(--color-accent) 20%, var(--color-gold) 100%);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-modal__text {
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.welcome-modal__text {
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-muted);
|
||||||
|
}
|
||||||
|
|
||||||
#welcome-modal-dismiss {
|
#welcome-modal-dismiss {
|
||||||
background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent));
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
box-shadow: var(--shadow-sm);
|
box-shadow: var(--shadow-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#welcome-modal-dismiss:active {
|
#welcome-modal-dismiss:active {
|
||||||
background: linear-gradient(135deg, var(--color-accent), var(--color-accent-hover));
|
background: #ff7673;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
@@ -774,7 +610,7 @@ button:focus-visible {
|
|||||||
min-height: 1.2em;
|
min-height: 1.2em;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--color-plum);
|
color: var(--color-yellow);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@@ -787,7 +623,7 @@ button {
|
|||||||
padding: 0.9rem 1rem;
|
padding: 0.9rem 1rem;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.12s var(--ease-bounce), background 0.12s ease, opacity 0.12s ease;
|
transition: transform 0.12s var(--ease-spring), background 0.12s ease, opacity 0.12s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#submit-btn,
|
#submit-btn,
|
||||||
@@ -796,20 +632,20 @@ button {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent));
|
background: var(--color-coral);
|
||||||
color: var(--color-accent-contrast);
|
color: var(--color-ink);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#submit-btn:active:not(:disabled),
|
#submit-btn:active:not(:disabled),
|
||||||
#add-another-btn:active {
|
#add-another-btn:active {
|
||||||
transform: scale(0.97);
|
transform: scale(0.97);
|
||||||
background: linear-gradient(135deg, var(--color-accent), var(--color-accent-hover));
|
background: #ff7673;
|
||||||
}
|
}
|
||||||
|
|
||||||
#submit-btn:disabled {
|
#submit-btn:disabled {
|
||||||
opacity: 0.6;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
@@ -818,12 +654,10 @@ button {
|
|||||||
#submit-btn:hover:not(:disabled),
|
#submit-btn:hover:not(:disabled),
|
||||||
#add-another-btn:hover {
|
#add-another-btn:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Micro-nudge de l'icône avion au survol : détail qui n'existe que pour
|
/* Micro-nudge de l'icône avion au survol : desktop uniquement. */
|
||||||
les visiteurs desktop (donc surtout les prospects en démo), sans
|
|
||||||
dépendance JS supplémentaire. */
|
|
||||||
#submit-btn:hover:not(:disabled) .btn-icon {
|
#submit-btn:hover:not(:disabled) .btn-icon {
|
||||||
transform: translate(2px, -2px);
|
transform: translate(2px, -2px);
|
||||||
}
|
}
|
||||||
@@ -834,14 +668,18 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#retry-btn {
|
#retry-btn {
|
||||||
background: var(--color-danger);
|
background: var(--color-coral);
|
||||||
color: var(--color-danger-contrast);
|
color: var(--color-ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
#retry-btn:active {
|
||||||
|
background: #ff7673;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
Écran de succès — LE moment à soigner : c'est la dernière impression
|
Écran de succès — LE moment à soigner : c'est la dernière impression
|
||||||
que garde l'invité. Coche qui "pop" avec rebond + petite volée de
|
que garde l'invité. Coche qui "pop" avec rebond + petite volée de
|
||||||
confettis colorés (pur CSS, aucune dépendance JS supplémentaire).
|
confettis dans les 3 couleurs d'accent de la DA (pur CSS).
|
||||||
------------------------------------------------------------------ */
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
.success-check {
|
.success-check {
|
||||||
@@ -849,7 +687,7 @@ button {
|
|||||||
width: 76px;
|
width: 76px;
|
||||||
height: 76px;
|
height: 76px;
|
||||||
margin: 0 auto 0.9rem;
|
margin: 0 auto 0.9rem;
|
||||||
animation: pop-in 0.55s var(--ease-bounce) both;
|
animation: pop-in 0.55s var(--ease-spring) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.success-check svg {
|
.success-check svg {
|
||||||
@@ -859,15 +697,15 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.success-check__circle {
|
.success-check__circle {
|
||||||
stroke: var(--color-accent);
|
stroke: var(--color-mint);
|
||||||
fill: var(--color-gold-soft);
|
fill: rgba(6, 214, 160, 0.14);
|
||||||
stroke-dasharray: 145;
|
stroke-dasharray: 145;
|
||||||
stroke-dashoffset: 145;
|
stroke-dashoffset: 145;
|
||||||
animation: draw 0.5s ease-out 0.1s forwards;
|
animation: draw 0.5s ease-out 0.1s forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.success-check__mark {
|
.success-check__mark {
|
||||||
stroke: var(--color-accent);
|
stroke: var(--color-mint);
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke-dasharray: 32;
|
stroke-dasharray: 32;
|
||||||
stroke-dashoffset: 32;
|
stroke-dashoffset: 32;
|
||||||
@@ -912,51 +750,51 @@ button {
|
|||||||
|
|
||||||
.confetti span:nth-child(1) {
|
.confetti span:nth-child(1) {
|
||||||
left: 18%;
|
left: 18%;
|
||||||
background: var(--color-accent);
|
background: var(--color-coral);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
animation-delay: 0.05s;
|
animation-delay: 0.05s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(2) {
|
.confetti span:nth-child(2) {
|
||||||
left: 32%;
|
left: 32%;
|
||||||
top: 0.2rem;
|
top: 0.2rem;
|
||||||
background: var(--color-gold);
|
background: var(--color-yellow);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation-delay: 0.15s;
|
animation-delay: 0.15s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(3) {
|
.confetti span:nth-child(3) {
|
||||||
left: 48%;
|
left: 48%;
|
||||||
background: var(--color-plum);
|
background: var(--color-mint);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
animation-delay: 0.02s;
|
animation-delay: 0.02s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(4) {
|
.confetti span:nth-child(4) {
|
||||||
left: 62%;
|
left: 62%;
|
||||||
background: var(--color-accent-light);
|
background: var(--color-coral);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation-delay: 0.22s;
|
animation-delay: 0.22s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(5) {
|
.confetti span:nth-child(5) {
|
||||||
left: 74%;
|
left: 74%;
|
||||||
background: var(--color-gold);
|
background: var(--color-yellow);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
animation-delay: 0.1s;
|
animation-delay: 0.1s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(6) {
|
.confetti span:nth-child(6) {
|
||||||
left: 86%;
|
left: 86%;
|
||||||
background: var(--color-plum);
|
background: var(--color-mint);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation-delay: 0.28s;
|
animation-delay: 0.28s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(7) {
|
.confetti span:nth-child(7) {
|
||||||
left: 10%;
|
left: 10%;
|
||||||
top: 0.3rem;
|
top: 0.3rem;
|
||||||
background: var(--color-gold);
|
background: var(--color-yellow);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation-delay: 0.18s;
|
animation-delay: 0.18s;
|
||||||
}
|
}
|
||||||
.confetti span:nth-child(8) {
|
.confetti span:nth-child(8) {
|
||||||
left: 94%;
|
left: 94%;
|
||||||
background: var(--color-accent);
|
background: var(--color-coral);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
animation-delay: 0.08s;
|
animation-delay: 0.08s;
|
||||||
}
|
}
|
||||||
@@ -977,15 +815,22 @@ button {
|
|||||||
|
|
||||||
.success-title {
|
.success-title {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
|
font-weight: 700;
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
font-weight: 600;
|
color: var(--color-text);
|
||||||
color: var(--color-accent-hover);
|
|
||||||
margin: 0 0 0.3rem;
|
margin: 0 0 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Touche manuscrite ponctuelle (Caveat) sur le petit mot de succès — ton
|
||||||
|
"friendly" demandé, sans en abuser (seul élément du texte à l'utiliser
|
||||||
|
sur cet écran, comme sur les légendes de la galerie invité). */
|
||||||
.success-text {
|
.success-text {
|
||||||
font-size: 0.95rem;
|
font-family: var(--font-hand);
|
||||||
margin: 0 0 1.3rem;
|
font-weight: 600;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
color: var(--color-muted);
|
||||||
|
margin: 0 0 1.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
|||||||
Reference in New Issue
Block a user