# Komponenten: Wetter-Klon (Compose, Material 3 Expressive) Tokens: `tokens.json` → `Tokens.kt` (über `gen_theme.py`). Komponenten verwenden nur Rollen (`WColor.onScene`), nie rohe Hex-Werte. Icons: Material Symbols Rounded (Apache 2.0) für die UI. Die Wettericons sind eigene oder [Meteocons](https://github.com/basmilius/weather-icons) (MIT), animiert über Lottie. Kein Google-Artwork. Schrift: Roboto Flex (OFL). Texte sind alle neu geschrieben, auf Deutsch. ## Grundregel Kontrast über Szenen Text auf dem animierten Himmel nutzt `on-scene`, bei hellen Szenen (Schnee, Nebel, unterer Tagesverlauf) `on-scene-dark`. Die Szene meldet ihre Helligkeit (`scene.isLight`), und das Theme wählt danach. Beim klaren Tageshimmel oben besteht weißer Text nur als Großtext (3,9:1). Kleiner Text dort braucht deshalb einen Scrim, einen Verlauf von 0 auf 25 % Schwarz hinter dem Hero-Kopf. Karten auf der Szene: `scene-card` mit 85 % Deckkraft plus Blur (API 31+, `RenderEffect`). Ohne Blur wird `scene-card` voll deckend gezeigt. --- ``` WeatherScene (animierter Hintergrund) variants clear, partly-cloudy, cloudy, rain, drizzle, snow, sleet, storm, fog × day/night; intensity 0..1 layers sky gradient (scene-*-top/bottom) → sun/moon+stars → clouds (AGSL noise) → precipitation particles → lightning flash → fog states playing, paused (off-screen / lifecycle STOPPED), reduced (battery saver, "Animationen entfernen", setting off → static gradient), transitioning (crossfade 600ms between conditions) motion parallax 0.3× on scroll, wind direction tilts rain, haptic tick on lightning (if vibrations on, never during severe alert) a11y decorative: no semantics; condition always also stated in text perf adaptive quality (particle count by frame time), 30fps cap on low-end used on S01, S02 (row backgrounds, static), S12 (pre-rendered bitmap) HeroBlock content city name (title) + location pin if current, temperature (display 96sp, wdth 125), condition (headline), "Gefühlt 12°" + H/T (body) states loading (shimmer on numbers, scene neutral), filled, stale ("Stand: vor 2 Std" chip), offline (cloud-off icon chip), no-permission (CTA "Standort erlauben") tokens on-scene / on-scene-dark, space 24 top motion temperature counts up on first load (300ms), collapses into app bar on scroll (large → small top app bar) a11y one merged semantics node: "Berlin, 14 Grad, leicht bewölkt, gefühlt 12, Höchstwert 17, Tiefstwert 9" used on S01 AlertBanner variants minor (alert-minor), moderate/severe (alert-severe), extreme (alert-extreme) content icon, event ("Sturmböen"), agency + validity ("DWD · bis 18:00"), chevron states single, stacked (n more), expanded (inline first lines), expired (removed with fade) tokens radius lg, padding 16 a11y liveRegion polite on appear; whole banner is one button "Warnung: Sturmböen, Deutscher Wetterdienst, bis 18 Uhr. Details" used on S01 (top of cards, replaces Brief), S11 BriefCard content 1–2 sentences, generated (e.g. "Ab 15 Uhr Regen, abends trocken. Morgen 6° kühler.") states loading (two shimmer lines), filled, hidden (alert active or setting off) tokens scene-card, body, radius xl used on S01 HourlyStrip content per hour: time label, icon, temp, precip % if ≥ 20 %; sunrise/sunset inserted as items; "Jetzt" first states loading, filled, scroll; selected-hour (tap shows detail tooltip) extra temperature line chart behind items (Canvas, smooth cubic) a11y LazyRow, each item "15 Uhr, 14 Grad, Regen 40 Prozent" used on S01 (fixed position), S04, S12 (widget variant) DayRow / DailyList content weekday ("Heute", "Mo"), icon, precip %, low temp, range bar (gradient cold→warm over the 10-day min..max, dot = current temp today), high temp states default, pressed (ripple), expanded (inline hourly, optional) a11y "Montag, Regen 60 Prozent, 8 bis 15 Grad" used on S01, S12 MetricCard (base for all detail cards) variants small 1×1, wide 2×1; shapes per tokens.shape (squircle, cookie, arch, pill) slots header (icon + label), value (metric 32sp), visual (gauge/chart), footer (one-line explanation) states default, pressed (morph radius→md, spring-fast), dragging (elevation card-drag, scale 1.04, haptic), placeholder (dashed border while dragging), loading, unavailable ("In deiner Region nicht verfügbar") tokens scene-card / scene-card-light, on-scene, radius lg a11y button → opens S05; reorder via accessibility actions "Nach oben/unten verschieben" used on S01, S10 instances Precip next-hour bar chart (minutely_15) + "Regen in ~20 Min" / total today Wind compass dial with arrow, speed, gusts, Beaufort label UV cookie shape, arc 0–11+, colour by band (uv-high etc.), "Sonnenschutz 11–16 Uhr" Humidity value + dew point, vertical fill Pressure dial with trend arrow (rising/falling over 3h) Visibility value + description Sun arch with sun position dot, sunrise/sunset times, day length AQI pill scale (aqi-good..aqi-bad), value, main pollutant Pollen top 3 types with level dots (Europe only, else hidden) Map static radar preview thumbnail → opens S06 RadarMap (S06) content MapLibre + OSM base (light/dark style), RainViewer overlay, location dot, attribution controls timeline scrubber (past 2h … +30min), play/pause FAB, time label, legend states loading tiles, playing, paused, no-coverage, offline a11y scrubber is a Slider with "13:40, Vorhersage" values used on S06 CityRow content name, admin area, local time, temp, condition icon, H/T; current-location row with pin and not deletable states default, pressed, swiping (red bg + trash icon reveal), deleted (snackbar "Gelöscht · Rückgängig"), dragging (reorder) bg static mini scene gradient for the city's condition motion shared element (name + temp) into S01 used on S02 SearchField + ResultList states empty (recents), typing (debounced 300ms, progress), results, no results ("Kein Ort gefunden"), error (retry) a11y SearchBar (M3), results announce count used on S03 TopAppBar variants transparent over scene (S01), surface (S02, S08) content menu/list button, city title (collapsed), settings icon (no account avatar) used on S01, S02, S08 PagerIndicator dots for saved cities, current one wide (expressive pill); swipe between cities used on S01 Settings rows variants radio group, switch, link row, section header states default, disabled (with reason text), focused used on S08, S09 Snackbar, Dialog (permission rationale), Shimmer placeholder: M3 standard with tokens. ``` ## Widgets (Glance) ``` Widget shell radius widget (24dp, follows system launcher radius on Android 12+) styles dynamic_color (surface-container from wallpaper), condition (pre-rendered scene bitmap + on-scene text), transparent (text with shadow) states loading ("…"), filled, stale (small clock icon), no location ("Ort wählen"), error (tap to retry) tap opens S01 for that city; refresh icon only on ≥ 4×2 NowWidget 2×1: icon + temp | 2×2: + city, condition, H/T HourlyWidget 4×2: now block + 6 hours (icon, temp, time) DailyWidget 4×2: now + 5 days | 4×3: + range bars FullWidget 4×4: now, 5 hours, 5 days, alert line if active GlanceWidget 4×1: "Fr., 17. Okt. · ☀ 14°" one line, alert replaces date (two lines: event, agency) type display-widget 44sp for temps, label for times; size by SizeMode.Responsive breakpoints a11y contentDescription on root summarising the widget config S12-config activity: location picker, style, live preview, "Fertig" ``` ## Screens → Komponenten (Status) | Screen | Komponenten | | --- | --- | | S01 | WeatherScene, TopAppBar, HeroBlock, AlertBanner, BriefCard, HourlyStrip, DailyList, MetricCard×n, PagerIndicator | | S02 | TopAppBar, CityRow, SearchField | | S03 | SearchField, ResultList | | S04/S05 | HourlyStrip, chart, MetricCard expanded | | S06 | RadarMap | | S08/S09 | Settings rows | | S10 | MetricCard (dragging/placeholder) | | S11 | AlertBanner expanded, text | | S12 | Widgets | ## Abgleich mit Screenshots (ref-01..04), überschreibt Abweichungen oben Gemessen an `replica/screens/ref-*.png`. Das Layout-Muster übernehmen wir, die Grafik zeichnen wir selbst. - **HeroBlock:** zentrierte Spalte. Oben die Wetterlage (22sp), darunter die Temperatur sehr groß und **fett** (112sp, 700, nicht dünn) mit dem Wettericon direkt rechts daneben, etwa 40 % der Ziffernhöhe, oben ausgerichtet. Dann „Gefühlt 19°“ und „Höchstwert 22° · Tiefstwert 14°“. Am Tag ist der Text dunkel auf hellem Himmel, nachts weiß. Es gibt keinen Scrim, die hellen Szenen sind entsprechend hell gewählt. - **Szene:** ruhiger, weicher Verlauf mit großen, unscharfen, langsam treibenden Formen (Wolkenschemen, Hügel). Keine fotorealistische Darstellung. Bei Niederschlag fallen dezente Partikel. - **Karten-Container:** deckend (`card` bzw. `dark-card`, warm getöntes Neutral), Radius 28, Padding 20. Die Kopfzeile besteht aus einem Outline-Icon und dem Titel (card-title). Zwischen den Karten 12 dp Abstand, nach außen 16 dp Rand. - **HourlyStrip:** Die Spalten zeigen Temperatur, darunter Icon, darunter Niederschlag in % (`precip-text`, klein), darunter die Uhrzeit. Die aktuelle Stunde trägt einen **Cookie-Chip** (`now-chip`) hinter der Temperatur, das Label heißt „Jetzt“. - **DailyList:** **horizontal** scrollende Reihe vertikaler **Kapseln** (`pill`, Radius 24, ca. 56×190 dp). In jeder Kapsel stehen Höchstwert, Tiefstwert (muted), Icon, Niederschlag in % und Tag plus Datum. Ein Tipp auf die Kapsel öffnet S04. - **DayDetail (S04, bestätigt):** oben eine Kapselreihe, die gewählte Kapsel ist hervorgehoben (`pill-selected`). Darunter Datum, Ort, „24°/14°“ (day-range 56sp) mit Icon, Wetterlage, die stündliche Vorhersage für diesen Tag und darunter dieselben Detailkarten. - **Detailkarten:** Raster mit 2 Spalten aus quadratischen Kacheln, **Formen statt einheitlicher Karten**: - Wind: Kreis, darin ein abgerundetes Dreieck als Blob (`fill-*`), gedreht in die Windrichtung, mittig Wert und Einheit, darunter „Aus NW“ - UV: Cookie mit 12 Wellen, Wert und Stufe, Punkte auf einem unteren Bogen, der aktive Punkt farbig - Sichtweite: Kreis mit gewellter Innenfläche (`fill-tertiary`), Wert und Einheit - Luftfeuchte: Rechteck, Füllstand mit gewellter Oberkante, Höhe = %, unten ein runder Chip mit dem Taupunkt - Luftdruck: Kreis mit 270°-Bogenanzeige, Wert groß, Einheit darunter - Sonne: Rechteck mit gefülltem Sinus-Hügel über der Horizontlinie, der Nachtteil dunkler, Sonnenpunkt auf der Kurve, Aufgang und Untergang als Zeiten - Luftqualität: Rechteck mit Verlaufsbalken und Knopf, Wert, Einstufung („Gute Luftqualität“); ohne Daten wird „– –“ gezeigt - **NowcastCard (neu):** „Regen ab 09:15“ als Titel, Untertitel „Leichter Regen von 09:15 bis 10:45“. Ein Punkt-Balkendiagramm zeigt die nächsten 2–3 Stunden in 15-Minuten-Schritten, die Y-Achse in drei Stufen (leicht, mäßig, stark). Ein Marker-Chip am Beginn, die X-Achse mit Uhrzeiten. Die Karte erscheint nur, wenn in den nächsten 3 Stunden Niederschlag kommt. Daten: Open-Meteo `minutely_15`. - **BriefCard:** wie eine normale Karte mit Icon, Titel „Kurz gesagt“ und einem Chevron zum Auf- und Zuklappen. Darunter 2–3 Sätze Text in body. - **Vorschau eines Orts (S15, neu):** Ein gesuchter Ort öffnet die volle Ansicht mit einem Button „Speichern“ oben rechts (gefüllter Pill-Button, Tonal). - **Abweichungen, die bewusst eigen bleiben:** eigene Icons und Szenen, ein eigener Akzent erst in `/replica-brand`, eigene Texte. Die Kartenformen sind M3-Expressive-Standardformen (`MaterialShapes`: Cookie, Circle, Triangle, Wavy), damit ist nichts vom Original nachgezeichnet.