Files
SteUP_Dotnet/SteUp.Shared/wwwroot/css/base.css
T
MarcoE 2a0054aa30 Rifacimento della UI secondo STILE_UI.md
Adotta lo stile condiviso delle app Integry: superfici piatte, raggi ampi,
spaziature a scala fissa, gerarchia data dallo spazio prima che dalla
decorazione. La palette storica di SteUP resta intatta; sono stati aggiunti
solo i ruoli che mancavano (workspace, surfaceMuted, divider, inkMuted e le
triplette dei toni semantici).

Fondamenta
- tokens.css: ruoli colore, scale di spazio/raggi/tipografia, curve di
  movimento e scala z-index semantica. Unica fonte di verita': pilotano
  anche le variabili CSS di MudBlazor.
- Inter variabile ospitata in locale (133KB) al posto di Nunito da Google
  Fonts: l'app lavora offline, un font che arriva dalla rete in campo non
  arriva.
- base.css: shell applicativa e comportamenti da app nativa — niente
  selezione testo, niente menu al tocco lungo, niente lampo grigio sul tap,
  niente rimbalzo elastico, niente zoom a doppio tocco, scroll con inerzia.
- mudblazor-overrides.css: MudBlazor appiattito (elevation 0, nessun tint,
  target 44/48, etichette in caso naturale).
- Rimossi Bootstrap (CSS, icone e JS) e i 996 righe di CSS con ambito per
  componente del vecchio sistema: erano tutti inutilizzati.

Struttura
- Navigazione flottante in basso con icona piena sulla voce attiva; da 720px
  diventa colonna laterale. Il MudFabMenu e' sostituito da un bottom sheet:
  stessa funzione, bersagli molto piu' grandi.
- Testata alta col titolo a sinistra, fusa con la pagina.
- Nel form scheda il salvataggio sta in una barra ancorata in fondo, non in
  coda a uno scroll lungo.
- Scelta di punto vendita e articoli a schermo intero con ricerca; la
  selezione multipla usa righe da 56px invece di un menu a tendina.
- Urgenza scelta a pillole invece che da una select.

Stato e riscontro
- StatusBadgeHelper: tono, icona ed etichetta di ogni stato in un punto solo,
  cosi' lo stesso stato si presenta identico ovunque.
- Scheletri al posto degli spinner; l'overlay bloccante dice sempre cosa sta
  facendo; gli stati vuoti suggeriscono la mossa successiva.
- Rimosso il ritardo artificiale di 250ms in InspectionCard, che non
  attendeva nulla.

DESIGN.md riscritto sul nuovo sistema.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:09:26 +02:00

277 lines
6.9 KiB
CSS

/* =============================================================================
SteUP — Base
Reset, shell applicativa, tipografia e comportamenti "da app nativa".
========================================================================== */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
height: 100%;
overflow: hidden;
/* La WebView non deve comportarsi come un browser: niente rimbalzo elastico
ai bordi, niente pull-to-refresh, niente zoom a doppio tocco. */
overscroll-behavior: none;
touch-action: manipulation;
-webkit-text-size-adjust: 100%;
}
body {
height: 100%;
margin: 0;
overflow: hidden;
background-color: var(--workspace);
color: var(--ink);
font-family: var(--font-sans);
font-size: var(--body-lg-size);
line-height: var(--body-lg-height);
font-weight: 400;
/* Inter: cifre a larghezza fissa, cosi' i contatori non "ballano" mentre
si aggiornano, e forme delle lettere piu' leggibili in piccolo. */
font-feature-settings: "tnum" 1, "cv05" 1;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
/* Niente selezione del testo, niente menu contestuale al tocco lungo,
niente lampo grigio sul tap: sono i tre segnali che tradiscono una
pagina web dentro un'app. */
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
cursor: default;
}
/* Il contenuto dei dati resta selezionabile: un barcode o un codice servono
anche da copiare. */
.selectable,
input,
textarea {
user-select: text;
-webkit-user-select: text;
-webkit-touch-callout: default;
}
#app {
height: 100dvh;
overflow: hidden;
}
img {
max-width: 100%;
display: block;
}
[hidden] {
display: none !important;
}
/* -----------------------------------------------------------------------------
Tipografia — scala fissa (STILE_UI §4)
La gerarchia si fa con peso e dimensione, mai con il maiuscolo spaziato.
-------------------------------------------------------------------------- */
.t-headline-md {
font-size: var(--headline-md-size);
line-height: var(--headline-md-height);
font-weight: 700;
letter-spacing: -0.02em;
}
.t-headline-sm {
font-size: var(--headline-sm-size);
line-height: var(--headline-sm-height);
font-weight: 700;
letter-spacing: -0.02em;
}
.t-title-lg {
font-size: var(--title-lg-size);
line-height: var(--title-lg-height);
font-weight: 700;
letter-spacing: -0.01em;
}
.t-title-md {
font-size: var(--title-md-size);
line-height: var(--title-md-height);
font-weight: 700;
}
.t-body-lg {
font-size: var(--body-lg-size);
line-height: var(--body-lg-height);
font-weight: 400;
}
.t-body-md {
font-size: var(--body-md-size);
line-height: var(--body-md-height);
font-weight: 400;
}
.t-label-lg {
font-size: var(--label-lg-size);
line-height: 1.25;
font-weight: 600;
}
.t-label-md {
font-size: var(--label-md-size);
line-height: 1.25;
font-weight: 600;
}
/* Identificativo tecnico sopra il titolo di una card (STILE_UI §4) */
.t-ident {
font-size: var(--label-sm-size);
line-height: 1.3;
font-weight: 700;
letter-spacing: 0.3px;
color: var(--ink-muted);
}
.t-muted {
color: var(--ink-muted);
}
/* Il testo secondario si distingue per colore, mai per opacita'. */
.t-meta {
font-size: var(--body-md-size);
line-height: var(--body-md-height);
font-weight: 600;
color: var(--ink-muted);
}
/* Prosa: righe non piu' lunghe di 65-75 caratteri. */
.t-prose {
max-width: 68ch;
text-wrap: pretty;
}
h1, h2, h3 {
text-wrap: balance;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin: 0;
}
/* -----------------------------------------------------------------------------
Shell applicativa
-------------------------------------------------------------------------- */
.app-shell {
display: flex;
flex-direction: column;
height: 100dvh;
overflow: hidden;
background-color: var(--workspace);
}
/* Area scorrevole unica della schermata. Lo scroll con inerzia e il
contenimento evitano che il gesto "sfondi" sulla pagina sottostante. */
.app-scroll {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
scrollbar-width: none;
}
.app-scroll::-webkit-scrollbar {
display: none;
}
/* Contenitore di pagina (STILE_UI §6.1): su telefono e' trasparente, su
schermo largo tiene una colonna leggibile invece di allargarsi all'infinito. */
.page-width {
width: 100%;
max-width: var(--content-max);
margin-inline: auto;
padding-inline: var(--space-md);
}
/* Spazio in coda per non finire sotto la barra di navigazione flottante. */
.page-body {
padding-bottom: calc(var(--nav-clearance) + env(safe-area-inset-bottom, 0px));
}
/* Pagine senza barra di navigazione (login, form a schermo pieno). */
.page-body--flush {
padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom, 0px));
}
.stack {
display: flex;
flex-direction: column;
}
.stack-xs { gap: var(--space-xs); }
.stack-10 { gap: var(--space-10); }
.stack-sm { gap: var(--space-sm); }
.stack-md { gap: var(--space-md); }
.stack-lg { gap: var(--space-lg); }
/* -----------------------------------------------------------------------------
Focus
Visibile e coerente ovunque, senza sporcare il tocco: solo da tastiera.
-------------------------------------------------------------------------- */
:focus {
outline: none;
}
:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
border-radius: var(--radius-compact);
}
/* -----------------------------------------------------------------------------
Risposta al tocco
Feedback fisico immediato (principio "Feedback immediato a ogni scan"):
l'elemento cede sotto il dito e torna. Niente stati basati sull'hover, che
su un touch screen non esiste e lascia elementi "accesi" dopo il tocco.
-------------------------------------------------------------------------- */
.pressable {
transition: transform var(--duration-fast) var(--ease-out),
background-color var(--duration-fast) var(--ease-out);
}
.pressable:active {
transform: scale(0.98);
}
@media (hover: hover) and (pointer: fine) {
.pressable:hover {
background-color: var(--surface-muted);
}
}
/* -----------------------------------------------------------------------------
Movimento ridotto — non e' opzionale
-------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.pressable:active {
transform: none;
}
}