| @@ -54,7 +54,9 @@ body { |
| 54 | au-dessus de la zone du geste home — 100% laisserait une bande non | 54 | au-dessus de la zone du geste home — 100% laisserait une bande non |
| 55 | peinte en bas de l'écran. */ | 55 | peinte en bas de l'écran. */ |
| 56 | height: 100dvh; | 56 | height: 100dvh; |
| 57 | - background: var(--color-neutral-300); | 57 | + /* iOS peint la zone sous le viewport (geste home) avec le fond du canvas : |
| | 58 | + couleur de la tab bar pour qu'elle semble se prolonger jusqu'en bas. */ |
| | 59 | + background: var(--color-surface); |
| 58 | color: var(--color-text); | 60 | color: var(--color-text); |
| 59 | font-family: var(--font-body); | 61 | font-family: var(--font-body); |
| 60 | font-size: 15px; line-height: 1.55; | 62 | font-size: 15px; line-height: 1.55; |
| @@ -158,7 +160,7 @@ input[type=number] { -moz-appearance: textfield; appearance: textfield; } |
| 158 | Seul conteneur scrollable de l'app (cf. body overflow hidden). */ | 160 | Seul conteneur scrollable de l'app (cf. body overflow hidden). */ |
| 159 | .app-main { | 161 | .app-main { |
| 160 | flex: 1; min-height: 0; | 162 | flex: 1; min-height: 0; |
| 161 | - padding: 0 var(--space-4) calc(172px + env(safe-area-inset-bottom, 0px)); | 163 | + padding: 0 var(--space-4) calc(140px + var(--tabbar-pad)); |
| 162 | overflow-y: auto; -webkit-overflow-scrolling: touch; | 164 | overflow-y: auto; -webkit-overflow-scrolling: touch; |
| 163 | } | 165 | } |
| 164 | | 166 | |
| @@ -166,8 +168,8 @@ input[type=number] { -moz-appearance: textfield; appearance: textfield; } |
| 166 | .timer-slot { | 168 | .timer-slot { |
| 167 | position: absolute; left: 0; right: 0; margin: 0; | 169 | position: absolute; left: 0; right: 0; margin: 0; |
| 168 | padding: 0 var(--space-4); | 170 | padding: 0 var(--space-4); |
| 169 | - /* 104px : nettement décollé de la tab bar. */ | 171 | + /* ≈ 23px d'écart au-dessus de la tab bar, quel que soit l'appareil. */ |
| 170 | - bottom: calc(104px + env(safe-area-inset-bottom, 0px)); | 172 | + bottom: calc(72px + var(--tabbar-pad)); |
| 171 | display: flex; justify-content: center; pointer-events: none; z-index: 4; | 173 | display: flex; justify-content: center; pointer-events: none; z-index: 4; |
| 172 | } | 174 | } |
| 173 | /* Bandeau pleine largeur (lancer / en cours / mesure en attente). */ | 175 | /* Bandeau pleine largeur (lancer / en cours / mesure en attente). */ |
| @@ -225,11 +227,13 @@ input[type=number] { -moz-appearance: textfield; appearance: textfield; } |
| 225 | .measure-card .warn { margin-top: var(--space-2); font-size: 13px; opacity: .75; } | 227 | .measure-card .warn { margin-top: var(--space-2); font-size: 13px; opacity: .75; } |
| 226 | | 228 | |
| 227 | /* — tab bar — */ | 229 | /* — tab bar — */ |
| | 230 | +/* max(), pas une somme : quand le viewport s'arrête déjà au-dessus de la |
| | 231 | + zone home (PWA iOS), ajouter la safe area par-dessus doublerait le vide. */ |
| | 232 | +:root { --tabbar-pad: max(calc(var(--space-3) + 6px), env(safe-area-inset-bottom, 0px)); } |
| 228 | .tabbar { | 233 | .tabbar { |
| 229 | position: absolute; bottom: 0; left: 0; right: 0; | 234 | position: absolute; bottom: 0; left: 0; right: 0; |
| 230 | display: flex; | 235 | display: flex; |
| 231 | - padding: var(--space-2) var(--space-2) | 236 | + padding: var(--space-2) var(--space-2) var(--tabbar-pad); |
| 232 | - calc(var(--space-3) + 6px + env(safe-area-inset-bottom, 0px)); | | |
| 233 | background: var(--color-surface); | 237 | background: var(--color-surface); |
| 234 | border-top-left-radius: var(--radius-lg); border-top-right-radius: var(--radius-lg); | 238 | border-top-left-radius: var(--radius-lg); border-top-right-radius: var(--radius-lg); |
| 235 | box-shadow: var(--shadow-md); | 239 | box-shadow: var(--shadow-md); |