8cfce316fa
Sul fuoco si vedevano due bordi: quello del campo piu' l'anello globale che l'input riceve per conto suo, con raggio e colore diversi. Dove e' il contenitore a segnare il fuoco — accesso, ricerca, barcode, gruppi del form — l'anello sull'input non serve: il fuoco resta visibile dal bordo del campo. Campi da 74 a 56 punti: padding piu' stretto, riga del valore alta quanto il testo che contiene. Il bottone che mostra la password sborda nel padding invece di alzare la riga, cosi' il campo password non e' piu' alto degli altri due e il bersaglio resta da 44. "Accedi" disabilitato era navy pieno con testo bianco: sembrava pronto, e il tocco a vuoto sembrava un guasto. Ora e' chiaramente inerte. Con la tastiera aperta il marchio finiva tagliato sopra e non si poteva risalire: il pannello si centra con i margini automatici invece che con align-items, cosi' lo scroll arriva anche in cima. Via anche la barra di scorrimento, come nel resto delle schermate. Verificata sul terminale, a riposo e col campo attivo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
300 lines
7.9 KiB
CSS
300 lines
7.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: 500;
|
|
}
|
|
|
|
.t-label-md {
|
|
font-size: var(--label-md-size);
|
|
line-height: 1.25;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 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: 400;
|
|
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;
|
|
}
|
|
|
|
/* L'anello segna un comando raggiunto da tastiera. Va messo sui controlli, non
|
|
su qualunque elemento che il motore decida di mettere a fuoco: la WebView
|
|
sposta il fuoco anche su contenitori non interattivi (per esempio la testata,
|
|
dopo la chiusura di un dialog) e li' l'anello indica un bersaglio che non
|
|
esiste. */
|
|
a:focus-visible,
|
|
button:focus-visible,
|
|
input:focus-visible,
|
|
select:focus-visible,
|
|
textarea:focus-visible,
|
|
[role="button"]:focus-visible,
|
|
[tabindex]:not([tabindex="-1"]):focus-visible {
|
|
outline: 2px solid var(--focus-ring);
|
|
outline-offset: 2px;
|
|
border-radius: var(--radius-compact);
|
|
}
|
|
|
|
/* Dove e' il contenitore a segnare il fuoco — campo di accesso, ricerca,
|
|
barcode, gruppo di form — l'anello sull'input disegnerebbe un secondo bordo
|
|
dentro il primo, con raggio e colore diversi. Il fuoco resta visibile: lo
|
|
mostra il bordo del campo. */
|
|
.onboarding__field input:focus-visible,
|
|
.search-field input:focus-visible,
|
|
.barcode-field input:focus-visible,
|
|
.form-group input:focus-visible,
|
|
.form-group textarea:focus-visible {
|
|
outline: none;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
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;
|
|
}
|
|
}
|