- Interface web (serveur_web.py, Flask, gabarits dans web/) : dépôt de GIF, PNG animés et séquences de PNG, aperçus animés, ordre de lecture, activer / désactiver, corbeille, « jouer maintenant » et « suivante ». Service systemd vitrine-web, activé par installer.sh. - Lecteur : réagit aux demandes de la page web (post-it dans /run/vitrine-pixels), écrit l'animation en cours, éteint la matrice proprement sur SIGTERM. - Matrice posée debout : réglage ROTATION (90 = image 8 × 32) dans matrice.py ; images couchées tournées automatiquement ; exemples, animations codées, aperçus et page web adaptés au format vertical. - Compatibilité Raspbian 11 Bullseye : partition /boot, Pillow 8.1, Flask 1.1. - Doc : nouveau guide INTERFACE_WEB.md ; README, GUIDE_KRITA, MODE_VITRINE, CODER_EN_PYTHON mis à jour (format 8 × 32, adresses Wi-Fi / câble du Pi). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
173 lines
6.3 KiB
CSS
173 lines
6.3 KiB
CSS
/* =============================================================================
|
||
Feuille de style de l'interface web « Vitrine pixels »
|
||
Les couleurs sont rangées dans des « variables » (--fond, --texte…) :
|
||
on les redéfinit pour le mode sombre, sans toucher au reste.
|
||
============================================================================= */
|
||
|
||
:root {
|
||
--fond: #f4f1ea;
|
||
--carte: #ffffff;
|
||
--texte: #1d1b18;
|
||
--discret: #6b665d;
|
||
--bord: #ddd6c8;
|
||
--accent: #e8462b; /* le rouge-orangé d'une LED allumée */
|
||
--accent-texte: #ffffff;
|
||
--vert: #1f8a4c;
|
||
--alerte: #b3261e;
|
||
--ecran: #101010; /* le noir de la matrice */
|
||
--rayon: 12px;
|
||
color-scheme: light;
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--fond: #141312;
|
||
--carte: #1f1d1b;
|
||
--texte: #f1ede6;
|
||
--discret: #a39d92;
|
||
--bord: #36322d;
|
||
--accent: #ff5a3c;
|
||
--vert: #4cc283;
|
||
--alerte: #ff8a80;
|
||
color-scheme: dark;
|
||
}
|
||
}
|
||
|
||
* { box-sizing: border-box; }
|
||
|
||
body {
|
||
margin: 0;
|
||
background: var(--fond);
|
||
color: var(--texte);
|
||
font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||
}
|
||
|
||
code { font-size: 0.9em; }
|
||
|
||
/* ---------- en-tête ---------- */
|
||
header {
|
||
position: sticky; top: 0; z-index: 10;
|
||
display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
|
||
gap: 8px 24px;
|
||
padding: 12px 20px;
|
||
background: var(--ecran);
|
||
color: #f1ede6;
|
||
}
|
||
h1 { margin: 0; font-size: 1.3rem; display: flex; align-items: center; gap: 10px; }
|
||
.logo {
|
||
width: 32px; height: 8px;
|
||
background:
|
||
radial-gradient(circle, var(--accent) 1.6px, transparent 2px) 0 0 / 4px 4px;
|
||
}
|
||
.statut { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
||
.statut form { margin: 0; }
|
||
.pastille {
|
||
width: 10px; height: 10px; border-radius: 50%;
|
||
background: #4cc283; box-shadow: 0 0 8px #4cc283;
|
||
}
|
||
|
||
main { max-width: 980px; margin: 0 auto; padding: 8px 16px 32px; }
|
||
section { margin-top: 28px; }
|
||
h2 { font-size: 1.15rem; margin: 0 0 12px; display: flex; align-items: center; gap: 8px; }
|
||
h3 { margin: 0 0 6px; font-size: 1rem; }
|
||
.compte {
|
||
font-size: 0.8rem; font-weight: 600;
|
||
background: var(--bord); border-radius: 99px; padding: 1px 9px;
|
||
}
|
||
.aide, .vide, footer { color: var(--discret); font-size: 0.9rem; }
|
||
|
||
/* ---------- messages ---------- */
|
||
/* En bas de l'écran, toujours visibles même si la page a défilé. */
|
||
.messages {
|
||
position: fixed; z-index: 20; left: 50%; bottom: 16px; transform: translateX(-50%);
|
||
width: min(560px, calc(100% - 32px));
|
||
display: flex; flex-direction: column; gap: 8px;
|
||
}
|
||
.message {
|
||
margin: 0; padding: 10px 14px;
|
||
border-radius: var(--rayon); border-left: 5px solid var(--vert);
|
||
background: var(--carte); box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
|
||
}
|
||
.message.erreur { border-left-color: var(--alerte); }
|
||
|
||
/* ---------- formulaires d'ajout ---------- */
|
||
.deux-colonnes { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; }
|
||
.carte {
|
||
background: var(--carte); border: 1px solid var(--bord);
|
||
border-radius: var(--rayon); padding: 16px;
|
||
display: flex; flex-direction: column; gap: 10px;
|
||
}
|
||
.carte .aide { margin: 0; }
|
||
.depot {
|
||
display: block; position: relative; cursor: pointer;
|
||
border: 2px dashed var(--bord); border-radius: var(--rayon);
|
||
padding: 18px; text-align: center; color: var(--discret);
|
||
}
|
||
.depot:hover { border-color: var(--accent); color: var(--texte); }
|
||
.depot input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; }
|
||
.champs { display: flex; gap: 10px; flex-wrap: wrap; }
|
||
.champs label { display: flex; flex-direction: column; font-size: 0.85rem; color: var(--discret); flex: 1; }
|
||
.champs input {
|
||
margin-top: 4px; padding: 8px; font: inherit; color: var(--texte);
|
||
background: var(--fond); border: 1px solid var(--bord); border-radius: 8px;
|
||
}
|
||
|
||
/* ---------- boutons ---------- */
|
||
.bouton {
|
||
font: inherit; cursor: pointer;
|
||
padding: 7px 14px; border-radius: 8px;
|
||
border: 1px solid var(--bord); background: var(--carte); color: var(--texte);
|
||
}
|
||
header .bouton { background: #2a2826; border-color: #3d3935; color: #f1ede6; }
|
||
.bouton:hover:not(:disabled) { border-color: var(--accent); }
|
||
.bouton:disabled { opacity: 0.35; cursor: default; }
|
||
.bouton.principal { background: var(--accent); border-color: var(--accent); color: var(--accent-texte); font-weight: 600; }
|
||
.bouton.icone { width: 38px; height: 38px; padding: 0; font-size: 1rem; }
|
||
.bouton.jouer { color: var(--vert); }
|
||
.bouton.supprimer { color: var(--alerte); }
|
||
|
||
/* ---------- listes d'animations ---------- */
|
||
.liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
||
.fiche {
|
||
display: grid; align-items: center; gap: 8px 14px;
|
||
grid-template-columns: 28px 256px 1fr auto;
|
||
background: var(--carte); border: 1px solid var(--bord);
|
||
border-radius: var(--rayon); padding: 10px 12px;
|
||
scroll-margin-top: 80px;
|
||
}
|
||
.fiche.joue { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
|
||
.fiche.eteinte .apercu { opacity: 0.55; }
|
||
.numero { font-weight: 700; color: var(--discret); text-align: center; }
|
||
.apercu {
|
||
width: 256px; height: 64px; display: block;
|
||
background: var(--ecran); border-radius: 4px;
|
||
image-rendering: pixelated; /* garder les pixels nets, pas de flou */
|
||
}
|
||
.details { display: flex; flex-direction: column; min-width: 0; }
|
||
.details strong { overflow-wrap: anywhere; }
|
||
.infos { font-size: 0.85rem; color: var(--discret); }
|
||
.alerte { font-size: 0.85rem; color: var(--alerte); }
|
||
.boutons { display: flex; gap: 6px; flex-wrap: wrap; }
|
||
.boutons form { margin: 0; }
|
||
|
||
/* Matrice DEBOUT (8 × 32) : aperçus verticaux, plus étroits. */
|
||
.debout .fiche { grid-template-columns: 28px 48px 1fr auto; }
|
||
.debout .apercu { width: 48px; height: 192px; }
|
||
|
||
/* Sur téléphone : les boutons passent sous l'aperçu. */
|
||
@media (max-width: 640px) {
|
||
.couchee .fiche { grid-template-columns: 24px 1fr; }
|
||
.couchee .apercu { width: 100%; height: auto; aspect-ratio: 4 / 1; grid-column: 2; }
|
||
.couchee .details, .couchee .boutons { grid-column: 1 / -1; }
|
||
.debout .fiche { grid-template-columns: 20px 48px 1fr; }
|
||
.debout .boutons { grid-column: 1 / -1; }
|
||
}
|
||
|
||
footer {
|
||
max-width: 980px; margin: 0 auto; padding: 16px;
|
||
border-top: 1px solid var(--bord);
|
||
display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 10px;
|
||
}
|
||
footer form { display: flex; align-items: center; gap: 10px; margin: 0; }
|
||
footer p { margin: 0; }
|