| @@ -53,6 +53,10 @@ body { |
| 53 | color: var(--color-text); | 53 | color: var(--color-text); |
| 54 | font-family: var(--font-body); | 54 | font-family: var(--font-body); |
| 55 | font-size: 15px; line-height: 1.55; | 55 | font-size: 15px; line-height: 1.55; |
| | 56 | + /* Le body ne scrolle jamais : le scroll vit dans .app-main. Sans ça, iOS |
| | 57 | + (PWA) fait rebondir les éléments fixed avec la page — tab bar qui saute |
| | 58 | + et fond gris visible dessous. */ |
| | 59 | + overflow: hidden; |
| 56 | } | 60 | } |
| 57 | h1, h2, h3, h4 { | 61 | h1, h2, h3, h4 { |
| 58 | font-family: var(--font-heading); font-weight: var(--font-heading-weight); | 62 | font-family: var(--font-heading); font-weight: var(--font-heading-weight); |
| @@ -126,10 +130,10 @@ input[type=number] { -moz-appearance: textfield; appearance: textfield; } |
| 126 | | 130 | |
| 127 | /* ═══ Couche applicative time-time ═══ */ | 131 | /* ═══ Couche applicative time-time ═══ */ |
| 128 | | 132 | |
| 129 | -.viewport { min-height: 100dvh; display: flex; justify-content: center; background: var(--color-neutral-300); } | 133 | +.viewport { height: 100%; display: flex; justify-content: center; background: var(--color-neutral-300); } |
| 130 | .shell { | 134 | .shell { |
| 131 | - width: 100%; max-width: 430px; min-height: 100dvh; background: var(--color-bg); | 135 | + width: 100%; max-width: 430px; height: 100%; background: var(--color-bg); |
| 132 | - display: flex; flex-direction: column; position: relative; | 136 | + display: flex; flex-direction: column; position: relative; overflow: hidden; |
| 133 | /* Barre de statut translucide (PWA iOS) : le contenu passe dessous. */ | 137 | /* Barre de statut translucide (PWA iOS) : le contenu passe dessous. */ |
| 134 | padding-top: env(safe-area-inset-top, 0px); | 138 | padding-top: env(safe-area-inset-top, 0px); |
| 135 | } | 139 | } |
| @@ -144,8 +148,12 @@ input[type=number] { -moz-appearance: textfield; appearance: textfield; } |
| 144 | .app-topline .who { margin-left: auto; font-size: 12px; opacity: .6; } | 148 | .app-topline .who { margin-left: auto; font-size: 12px; opacity: .6; } |
| 145 | .app-header h1 { margin: 0; font-size: 29px; letter-spacing: -0.02em; } | 149 | .app-header h1 { margin: 0; font-size: 29px; letter-spacing: -0.02em; } |
| 146 | | 150 | |
| 147 | -/* 168px : la pill timer flotte au-dessus de la tab bar, le contenu passe dessous. */ | 151 | +/* 168px : la pill timer flotte au-dessus de la tab bar, le contenu passe |
| 148 | -.app-main { flex: 1; min-height: 0; padding: 0 var(--space-4) 168px; } | 152 | + dessous. Seul conteneur scrollable de l'app (cf. body overflow hidden). */ |
| | 153 | +.app-main { |
| | 154 | + flex: 1; min-height: 0; padding: 0 var(--space-4) 168px; |
| | 155 | + overflow-y: auto; -webkit-overflow-scrolling: touch; |
| | 156 | +} |
| 149 | | 157 | |
| 150 | /* — timer — */ | 158 | /* — timer — */ |
| 151 | .timer-slot { | 159 | .timer-slot { |
| @@ -278,8 +286,10 @@ input[type=number] { -moz-appearance: textfield; appearance: textfield; } |
| 278 | | 286 | |
| 279 | /* — login — */ | 287 | /* — login — */ |
| 280 | .login { | 288 | .login { |
| 281 | - flex: 1; display: flex; flex-direction: column; justify-content: center; | 289 | + flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: safe center; |
| 282 | padding: var(--space-8) var(--space-6) 64px; | 290 | padding: var(--space-8) var(--space-6) 64px; |
| | 291 | + /* La coquille ne scrolle plus : au clavier ouvert, c'est ici que ça défile. */ |
| | 292 | + overflow-y: auto; |
| 283 | } | 293 | } |
| 284 | .login-icon { | 294 | .login-icon { |
| 285 | width: 72px; height: 72px; border-radius: 999px; background: var(--color-accent); | 295 | width: 72px; height: 72px; border-radius: 999px; background: var(--color-accent); |