# Design: premium-award-ui-icons-code-review ## Objetivo Elevar PluriWave a una maqueta/UI premium de nivel award: radio global, audio vivo, favoritos, búsqueda, reproductor, EQ y ajustes con una dirección visual propia: **“Ondas vivas globales”**. La UI debe sentirse como lujo digital oscuro: vidrio profundo, ondas concéntricas, energía magenta/coral y una familia de iconos propia. Primero fundamentos: **tokens, tema, componentes e iconografía**. Nada de maquillaje suelto arriba de widgets existentes. ## Contexto técnico verificado - App Flutter/Dart con `Provider` + `ChangeNotifier`. - Tema actual en `lib/app.dart` usa Material 3 dark + `ColorScheme.fromSeed`. - Navegación actual usa `Icons.*` de Material. - Assets declarados: `assets/images/` y `assets/icons/`. - Tests existentes bajo `test/`. - Riesgo actual a hardenear: `_PaginaPrincipalState.didChangeDependencies()` escucha `errorStream` sin guardar/cancelar suscripción local; debe moverse a `initState` con `StreamSubscription` y cancelarse en `dispose`. ## Dirección de arte ### Concepto **Ondas vivas globales**: PluriWave conecta emisoras del mundo a través de ondas sonoras visibles, como una red orbital sobre vidrio oscuro. Visualmente: - Fondo oscuro violeta-negro. - Esferas/global waves con gradientes controlados. - Superficies glassmorphism sobrias, no “neón barato”. - Brillos premium: pocos, intencionales, con blur suave. - Iconos coherentes: ondas concéntricas + geometría redondeada. ### Paleta base Definir tokens, no colores hardcodeados. ```dart voidBlack: #07040F deepViolet: #140722 midnightPurple: #211039 royalViolet: #6E35FF electricMagenta: #FF2BD6 warmCoral: #FF7A59 softRose: #FFD0E8 auroraCyan: #35E8FF glassWhite: rgba(255,255,255,0.08) glassStroke: rgba(255,255,255,0.16) dangerCoral: #FF5A6A successMint: #5FFFCB ``` ### Gradientes - `heroGlobalWave`: deep violet → royal violet → magenta. - `activeGlow`: electric magenta → warm coral. - `glassSurface`: white 10% → white 4%. - `playerOrb`: royal violet → magenta → coral. - `eqSpectrum`: cyan → magenta → coral. ### Tipografía Mantener Inter si ya está instalado, pero con escala propia: - Display: hero/player titles. - Title: cards, screen headers. - Body: station metadata. - Label: chips, nav, settings. Decisión: tipografía sobria. El lujo viene de composición, contraste y ritmo, no de fuentes extravagantes. ## Tokens y tema Crear capa de tema propia: ```text lib/tema/pluriwave_tokens.dart lib/tema/pluriwave_theme.dart lib/tema/pluriwave_motion.dart ``` Usar `ThemeExtension` para colores premium, gradientes, radios, blur/elevation/glow, spacing y duraciones de motion. Tokens sugeridos: ```text spacing: 4, 8, 12, 16, 20, 24, 32 radius: 12, 16, 20, 28, 999 stroke: 1, 1.5, 2 blur: 12, 20, 32 glow: subtle, active, hero motion: fast 120ms, base 220ms, expressive 420ms ``` Regla: cualquier pantalla/componente nuevo consume tokens. No hardcodear paleta en widgets. ## Sistema de componentes ### App shell - `PluriWaveScaffold`. - Fondo premium persistente: gradiente oscuro base, ondas radiales sutiles, puntos/orbitas globales con opacidad baja. - Respeta safe areas. - Evita rebuilds caros del fondo. ### Superficies - `PluriGlassSurface`: color glass tokenizado, borde translúcido, blur moderado, sombra/glow opcional. - Variantes: `subtle`, `elevated`, `active`, `danger`. ### Navegación - Reemplazar Material Icons por `PluriIcon`. - Bottom nav glass flotante. - Estado activo: icono filled, glow magenta/coral, label con contraste alto. - Estado inactivo: outline, baja opacidad, pero accesible. ### Tarjeta de emisora - `PluriStationCard` con nombre, país/idioma/tag, estado reproduciendo, favorito y mini onda/visualizer. - Variantes: compacta, destacada, reorderable favorite. - Debe tener semantics claros: estación, país, acción reproducir, favorito. ### Mini reproductor - Glass pill persistente. - Orb/onda animada cuando reproduce. - Botón play/pause con `PluriIcon.playerOrb`. - Evitar animaciones pesadas; envolver visualizer en `RepaintBoundary`. ### Reproductor - Pantalla hero con globo/orbe de ondas, metadata de emisora, controles primarios, acceso EQ, favorito y timer. - La jerarquía debe hacer obvio qué está sonando. ### EQ - `PluriEqPanel`. - Sliders con onda/spectrum. - Presets como chips premium. - Toggle “preset propio de esta emisora”. - Estado unavailable accesible cuando EQ no está disponible. ### Estados vacíos/error - No usar pantallas muertas. - Empty state con icono propio + copy corto. - Error offline con acción retry. - Loading con shimmer sutil. ## Pantallas ### Inicio - Hero “PluriWave” con globo de ondas. - Sección Tendencias. - Sección Populares. - Accesos rápidos por país/tag. - Mini reproductor siempre abajo si hay emisora activa. ### Buscar - Search premium con chips: país, idioma, tag. - Loading controlado. - Evitar stale results: la última búsqueda gana. ### Favoritos - Lista reorderable. - Drag handle propio. - Persistencia de orden. - Si falla persistencia: rollback visual y snackbar. - Evitar duplicados por `uuid`. ### Reproductor - Foco absoluto en la emisora actual. - Controles grandes y accesibles. - Visualizer vivo, pero pausado/reducido si accesibilidad reduce motion. ### Ajustes - Cards agrupadas: audio/EQ, import/export, timer, app info. - Iconos propios por grupo. ## Sistema de iconos Crear `PluriIcon` como contrato visual propio, con variantes `outline`, `filled`, `activeGlow`. Iconos core: ```text homeWave, searchOrbit, heartSignal, playerOrb, eqConstellation, settingsPrism, sleepMoonWave, globeRadio, stationTower, importWave, exportWave, timerRing, errorPulse ``` Geometría: - Grid base 24x24. - Stroke 2px. - Caps y joins redondeados. - Motivo común: ondas concéntricas/orbitas. - Filled no debe ser solo outline pintado. - Active glow se logra con composición, no con bitmap borroso incontrolable. Implementación recomendada: - Core UI icons: code-native Flutter widgets/painters o assets vectoriales controlados. - Assets generados por IA: usar para hero, mockups, marketing, splash o iconos complejos, pasando por pipeline de validación. - Tradeoff: los iconos code-native son menos “ilustración AI”, pero ganan recolor, accesibilidad, consistencia y tests. ## Prompt para mockup premium ```text Create a premium mobile app UI mockup for "PluriWave", a global radio streaming app. Art direction: living global audio waves, luxury dark glass, deep violet black background, electric magenta, royal violet, warm coral highlights, subtle cyan accents. The app includes home, search, favorites, now playing, equalizer, and settings surfaces. Use elegant glassmorphism, restrained glow, layered depth, rounded premium cards, orbiting wave motifs, global radio map energy, custom wave-based icons, outline and filled active icon states. Make it look like an award-winning product design case study, polished, editorial, cinematic, high-end digital luxury. No fake brand logos, no illegible paragraphs, minimal readable labels only: Inicio, Buscar, Favoritos, Ajustes, PluriWave. Vertical smartphone composition, 9:16, crisp details, professional product mockup, dark premium UI, controlled highlights, no clutter. ``` ## Prompt para icon sheet ```text Generate a 4x4 icon sheet for a premium global radio app called PluriWave. Style: custom icon family, rounded geometry, concentric audio waves, globe/orbit motifs, deep violet strokes with electric magenta and warm coral active accents. Icons: home wave, search orbit, heart signal, player orb, equalizer constellation, settings prism, sleep moon wave, globe radio, station tower, import wave, export wave, timer ring, error pulse, favorite filled, play filled, pause filled. Each icon must be centered in its own cell, isolated, same visual weight, no text. Use pure chroma green #00FF00 as the full background, with thick #00FF00 gutters and outer border between every icon. No icon, shadow, glow, or stroke may touch or cross gutters. Clean high-resolution sheet, sharp edges, premium app icon design, consistent family. ``` Negative prompt: ```text No text, no letters, no logos, no watermark, no overlapping cells, no cropped icons, no icons touching borders, no inconsistent perspective, no messy neon, no excessive glow, no background other than pure #00FF00. ``` ## Asset pipeline Pipeline obligatorio: ```text generate → detect gutters → crop cells → chroma-to-alpha → trim transparent bounds → center subject → pad to target canvas → export PNG/WebP → generate contact sheet → validate ``` Validaciones: - No píxeles #00FF00 residuales. - Ningún subject toca borde. - Bounding box razonable: no menor a 45% ni mayor a 82% del canvas. - Centro visual estable. - Familia coherente en peso, radio, glow y escala. - Rechazar sheet malo; no “arreglar a mano” crops rotos. ## Hardening técnico ### Listener leaks Mover listeners de UI desde `didChangeDependencies` a `initState` cuando no dependan de InheritedWidget dinámico, guardar `StreamSubscription`, cancelar en `dispose`. ### Estado stale Para búsqueda/carga async: usar request id incremental o token de última operación, ignorar respuestas viejas, limpiar loading solo si la respuesta corresponde al request vigente, evitar `notifyListeners` después de dispose. ### Favoritos reorder Persistir orden explícito, reorder optimista con rollback si falla, nunca duplicar `uuid`, tests para reorder, remove, import/export y estado actual. ### Accesibilidad Labels semánticos en iconos, tap targets mínimos 48x48, contraste suficiente, reducir/parar animaciones si `MediaQuery.disableAnimations` o reduced motion, no comunicar estado activo solo con color/glow. ### Performance `const` donde aplique, `RepaintBoundary` en visualizers/glows animados, blur limitado y tokenizado, precache de assets críticos, evitar rebuilds globales innecesarios del player/nav.