Dashboard: refonte design « instrument 1-bit » (jauges graduées, polices vendorisées, glyphes météo)

- Identité noir & blanc pur (zéro gris, anti-ghosting e-ink) ; hachures pour conso/alarme
- Typo vendorisée : Archivo (mots) + JetBrains Mono (nombres tabulaires), @font-face base64
- Jauge signature : noir = restant, repère seuil 20 %, hachures sous le seuil
- Météo : glyphes 1-bit en silhouette (weather.kind) au lieu d'emoji couleur
- Layout rééquilibré (plus de débordement), états dégradés soignés
- dev/preview.py : aperçu hors-ligne du template
This commit is contained in:
jerem
2026-06-15 22:56:56 +02:00
parent 0f6286c154
commit 3782738d57
11 changed files with 357 additions and 161 deletions

37
backend/fonts.py Normal file
View File

@@ -0,0 +1,37 @@
"""Génère le bloc CSS @font-face avec les woff2 vendorisés embarqués en data-URI.
Playwright rend via page.set_content() (pas de base URL) : les chemins de police
relatifs ne se résolvent pas. On embarque donc les woff2 en base64 directement dans
le CSS. Résultat mémoïsé (les fichiers ne changent pas au runtime)."""
from __future__ import annotations
import base64
from functools import lru_cache
from pathlib import Path
FONTS_DIR = Path(__file__).parent / "static" / "fonts"
# (famille CSS, fichier, graisse)
_FACES = [
("Archivo", "archivo-700.woff2", 700),
("Archivo", "archivo-800.woff2", 800),
("JetBrains Mono", "jbmono-400.woff2", 400),
("JetBrains Mono", "jbmono-500.woff2", 500),
("JetBrains Mono", "jbmono-700.woff2", 700),
("JetBrains Mono", "jbmono-800.woff2", 800),
]
@lru_cache(maxsize=1)
def font_face_css() -> str:
"""CSS @font-face complet (data-URI) à injecter dans le <style> du template."""
blocks = []
for family, filename, weight in _FACES:
data = (FONTS_DIR / filename).read_bytes()
b64 = base64.b64encode(data).decode("ascii")
blocks.append(
"@font-face{font-family:'%s';font-style:normal;font-weight:%d;"
"font-display:block;src:url(data:font/woff2;base64,%s) format('woff2');}"
% (family, weight, b64)
)
return "\n".join(blocks)