fix(bienvenida): match body/bullet type sizes and clip the logo mark

Tier 4 visual fidelity, audit 14.4/14.5/14.6/14.8 (t4 lines 693-701):
body copy is 14.5px (was bodyMedium's 14), bullet titles are
13.5px/w800 and subtitles 11.5px (was 14/w800 and 12), the gap between
bullets tightens from 16 to 12, and the 76x76 logo mark is now clipped
to a 20px rounded rect instead of painted square.
This commit is contained in:
2026-07-30 13:02:40 +02:00
parent 038ec7f3b8
commit 7ff156852f
2 changed files with 97 additions and 13 deletions
+29 -13
View File
@@ -71,17 +71,23 @@ class PantallaBienvenida extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
Image.asset( // Audit 14.8 (t4 line 693): the prototype clips
'assets/icons/pluriwave_app_mark.png', // its logo mark to a 20px rounded rect; the build
key: const ValueKey('welcome-logo'), // used to paint it square.
width: 76, ClipRRect(
height: 76, borderRadius: BorderRadius.circular(20),
errorBuilder: child: Image.asset(
(_, __, ___) => Icon( 'assets/icons/pluriwave_app_mark.png',
Icons.graphic_eq_rounded, key: const ValueKey('welcome-logo'),
size: 76, width: 76,
color: t.electricMagenta, height: 76,
), errorBuilder:
(_, __, ___) => Icon(
Icons.graphic_eq_rounded,
size: 76,
color: t.electricMagenta,
),
),
), ),
const SizedBox(height: 22), const SizedBox(height: 22),
Text( Text(
@@ -95,7 +101,10 @@ class PantallaBienvenida extends StatelessWidget {
const SizedBox(height: 12), const SizedBox(height: 12),
Text( Text(
l10n.welcomeBody, l10n.welcomeBody,
// Audit 14.4 (t4 line 697): 14.5px, not
// bodyMedium's 14.
style: theme.textTheme.bodyMedium?.copyWith( style: theme.textTheme.bodyMedium?.copyWith(
fontSize: 14.5,
color: theme.colorScheme.onSurface.withValues( color: theme.colorScheme.onSurface.withValues(
alpha: 0.72, alpha: 0.72,
), ),
@@ -109,14 +118,16 @@ class PantallaBienvenida extends StatelessWidget {
titulo: l10n.welcomeBullet1Title, titulo: l10n.welcomeBullet1Title,
subtitulo: l10n.welcomeBullet1Subtitle, subtitulo: l10n.welcomeBullet1Subtitle,
), ),
const SizedBox(height: 16), // Audit 14.6 (t4 line 701): 12px between bullets,
// not 16.
const SizedBox(height: 12),
FilaCaracteristicaBienvenida( FilaCaracteristicaBienvenida(
icon: Icons.directions_car_rounded, icon: Icons.directions_car_rounded,
iconColor: t.liveGreen, iconColor: t.liveGreen,
titulo: l10n.welcomeBullet2Title, titulo: l10n.welcomeBullet2Title,
subtitulo: l10n.welcomeBullet2Subtitle, subtitulo: l10n.welcomeBullet2Subtitle,
), ),
const SizedBox(height: 16), const SizedBox(height: 12),
FilaCaracteristicaBienvenida( FilaCaracteristicaBienvenida(
icon: Icons.alarm_rounded, icon: Icons.alarm_rounded,
iconColor: t.warmCoral, iconColor: t.warmCoral,
@@ -196,13 +207,18 @@ class FilaCaracteristicaBienvenida extends StatelessWidget {
children: [ children: [
Text( Text(
titulo, titulo,
// Audit 14.5 (t4 line 700): 13.5px/w800, not bodyMedium's
// 14/w800.
style: theme.textTheme.bodyMedium?.copyWith( style: theme.textTheme.bodyMedium?.copyWith(
fontSize: 13.5,
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
), ),
), ),
Text( Text(
subtitulo, subtitulo,
// Audit 14.5 (t4 line 700): 11.5px, not bodySmall's 12.
style: theme.textTheme.bodySmall?.copyWith( style: theme.textTheme.bodySmall?.copyWith(
fontSize: 11.5,
color: theme.colorScheme.onSurface.withValues(alpha: 0.58), color: theme.colorScheme.onSurface.withValues(alpha: 0.58),
), ),
), ),
@@ -65,6 +65,74 @@ void main() {
}, },
); );
testWidgets(
'visual fidelity (audit 14.4/14.5): body copy is 14.5px, bullet titles '
'are 13.5px/w800, bullet subtitles are 11.5px (t4 lines 697/700-702)',
(tester) async {
final navegacion = EstadoNavegacionRaiz();
addTearDown(navegacion.dispose);
await tester.pumpWidget(_app(navegacion: navegacion));
await tester.pumpAndSettle();
final l10n = lookupAppLocalizations(const Locale('es'));
final body = tester.widget<Text>(
find.textContaining('53.412 emisoras de 238 países'),
);
expect(body.style?.fontSize, 14.5);
final tituloBullet = tester.widget<Text>(
find.text(l10n.welcomeBullet1Title),
);
expect(tituloBullet.style?.fontSize, 13.5);
expect(tituloBullet.style?.fontWeight, FontWeight.w800);
final subtituloBullet = tester.widget<Text>(
find.text(l10n.welcomeBullet1Subtitle),
);
expect(subtituloBullet.style?.fontSize, 11.5);
},
);
testWidgets(
'visual fidelity (audit 14.6): the 3 feature bullets are spaced 12px '
'apart, not 16 (t4 line 701)',
(tester) async {
final navegacion = EstadoNavegacionRaiz();
addTearDown(navegacion.dispose);
await tester.pumpWidget(_app(navegacion: navegacion));
await tester.pumpAndSettle();
final bullets = find.byType(FilaCaracteristicaBienvenida);
final gap =
tester.getTopLeft(bullets.at(1)).dy -
tester.getBottomLeft(bullets.at(0)).dy;
expect(gap, 12);
},
);
testWidgets(
'visual fidelity (audit 14.8): the logo mark is clipped to a 20px '
'rounded rect, not painted square (t4 line 693)',
(tester) async {
final navegacion = EstadoNavegacionRaiz();
addTearDown(navegacion.dispose);
await tester.pumpWidget(_app(navegacion: navegacion));
await tester.pumpAndSettle();
final clip = tester.widget<ClipRRect>(
find.ancestor(
of: find.byKey(const ValueKey('welcome-logo')),
matching: find.byType(ClipRRect),
),
);
expect(clip.borderRadius, BorderRadius.circular(20));
},
);
testWidgets('rendered content contains no monetization strings', ( testWidgets('rendered content contains no monetization strings', (
tester, tester,
) async { ) async {