fix(bienvenida): bottom-anchor content and add the blurred backdrop
Audit 14.2 (t4 lines 693/706): content was top-anchored in a plain SingleChildScrollView; the prototype anchors it to the bottom with two flexible spacers, so the CTA sits at the screen edge. Restructured as a scrollable Expanded region (safe on short screens / large text scale) with the CTA pinned below it, always at the bottom. Audit 14.1 (t4 lines 687-689): added the full-bleed blurred banner backdrop, reusing aurora_wave_banner.png (the same asset the deleted PluriScreenHeader used) since this app has no bundled equivalent of the prototype's mockup-only banner.jpg. No monetization content touched (PRO pill, "14 días", pricing card, free-version link all remain absent per the binding no-monetization decision).
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -47,78 +49,103 @@ class PantallaBienvenida extends StatelessWidget {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.fromLTRB(24, 48, 24, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/icons/pluriwave_app_mark.png',
|
||||
width: 76,
|
||||
height: 76,
|
||||
errorBuilder:
|
||||
(_, __, ___) => Icon(
|
||||
Icons.graphic_eq_rounded,
|
||||
size: 76,
|
||||
color: t.electricMagenta,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 22),
|
||||
Text(
|
||||
l10n.welcomeHeadline,
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.w800,
|
||||
height: 1.05,
|
||||
letterSpacing: -1.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
l10n.welcomeBody,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onSurface.withValues(alpha: 0.72),
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
FilaCaracteristicaBienvenida(
|
||||
icon: Icons.equalizer_rounded,
|
||||
iconColor: t.electricMagenta,
|
||||
titulo: l10n.welcomeBullet1Title,
|
||||
subtitulo: l10n.welcomeBullet1Subtitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilaCaracteristicaBienvenida(
|
||||
icon: Icons.directions_car_rounded,
|
||||
iconColor: t.liveGreen,
|
||||
titulo: l10n.welcomeBullet2Title,
|
||||
subtitulo: l10n.welcomeBullet2Subtitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilaCaracteristicaBienvenida(
|
||||
icon: Icons.alarm_rounded,
|
||||
iconColor: t.warmCoral,
|
||||
titulo: l10n.welcomeBullet3Title,
|
||||
subtitulo: l10n.welcomeBullet3Subtitle,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
SizedBox(
|
||||
height: 58,
|
||||
child: FilledButton(
|
||||
onPressed: () => _empezar(context),
|
||||
child: Text(
|
||||
l10n.welcomeCtaLabel,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
const _FondoBienvenida(),
|
||||
SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 28),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Audit 14.2 (t4 lines 693/706): the prototype anchors
|
||||
// this content to the BOTTOM with two flexible spacers,
|
||||
// so the CTA sits at the screen edge. The scrollable
|
||||
// Expanded region above the CTA keeps this safe on short
|
||||
// screens / large text scale instead of a rigid Spacer
|
||||
// that could overflow.
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(top: 48),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/icons/pluriwave_app_mark.png',
|
||||
key: const ValueKey('welcome-logo'),
|
||||
width: 76,
|
||||
height: 76,
|
||||
errorBuilder:
|
||||
(_, __, ___) => Icon(
|
||||
Icons.graphic_eq_rounded,
|
||||
size: 76,
|
||||
color: t.electricMagenta,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 22),
|
||||
Text(
|
||||
l10n.welcomeHeadline,
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.w800,
|
||||
height: 1.05,
|
||||
letterSpacing: -1.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
l10n.welcomeBody,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onSurface.withValues(
|
||||
alpha: 0.72,
|
||||
),
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
FilaCaracteristicaBienvenida(
|
||||
icon: Icons.equalizer_rounded,
|
||||
iconColor: t.electricMagenta,
|
||||
titulo: l10n.welcomeBullet1Title,
|
||||
subtitulo: l10n.welcomeBullet1Subtitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilaCaracteristicaBienvenida(
|
||||
icon: Icons.directions_car_rounded,
|
||||
iconColor: t.liveGreen,
|
||||
titulo: l10n.welcomeBullet2Title,
|
||||
subtitulo: l10n.welcomeBullet2Subtitle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilaCaracteristicaBienvenida(
|
||||
icon: Icons.alarm_rounded,
|
||||
iconColor: t.warmCoral,
|
||||
titulo: l10n.welcomeBullet3Title,
|
||||
subtitulo: l10n.welcomeBullet3Subtitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(
|
||||
height: 58,
|
||||
child: FilledButton(
|
||||
onPressed: () => _empezar(context),
|
||||
child: Text(
|
||||
l10n.welcomeCtaLabel,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w800,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -186,3 +213,52 @@ class FilaCaracteristicaBienvenida extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Full-bleed blurred backdrop (audit 14.1, t4 lines 687-689). Reuses the
|
||||
/// bundled `aurora_wave_banner.png` — the same asset the now-deleted
|
||||
/// `PluriScreenHeader` used (Tier 1, S2) — rather than the prototype's own
|
||||
/// mockup-only `assets/banner.jpg`, which this app does not bundle. Mirrors
|
||||
/// `_FondoArteDifuminado` in `pantalla_alarma_sonando.dart`: blur + a
|
||||
/// deepViolet gradient, no noise layer, purely decorative and not
|
||||
/// spec-tested beyond its own presence.
|
||||
class _FondoBienvenida extends StatelessWidget {
|
||||
const _FondoBienvenida();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tokens = context.pluriTokens;
|
||||
return Positioned.fill(
|
||||
key: const ValueKey('welcome-background-art'),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
ImageFiltered(
|
||||
imageFilter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
|
||||
child: Opacity(
|
||||
opacity: 0.4,
|
||||
child: Image.asset(
|
||||
'assets/images/aurora_wave_banner.png',
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) => const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
tokens.deepViolet.withValues(alpha: 0.45),
|
||||
tokens.deepViolet.withValues(alpha: 0.9),
|
||||
tokens.deepViolet,
|
||||
],
|
||||
stops: const [0, 0.46, 1],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user