# 03 — Described Wireframes These are textual wireframes: precise enough for a frontend engineer to build layout and component structure without a Figma file, and to serve as the reference if/when visual designs are produced. Coordinates use a 4 px spacing grid; breakpoints: **mobile** < 768 px (primary), **desktop** ≥ 1024 px, tablet interpolates. Component names in `MonoCase` are the canonical React component names for the implementation milestone. --- ## 1. Global shell ``` MOBILE (portrait, 390×844 reference) ┌─────────────────────────────────────┐ │ TopBar (h:56, floating over map) │ │ ┌────────┐ ┌─────────────┐ ┌─────┐ │ │ │ ☰ Menu │ │ SearchBox │ │ 🪁▾ │ │ ← ProfileSelector chip │ └────────┘ └─────────────┘ └─────┘ │ │ │ │ MapCanvas │ │ (full viewport bleed) │ │ │ │ ┌──┐ │ │ │⊕ │ zoom / geolocate / layers │ ← MapControls, right edge, │ │⌖ │ vertical stack, 44px tap │ bottom-aligned above sheet │ │▦ │ │ │ └──┘ │ │ ┌─────────────────────────────────┐ │ │ │ BottomSheet (collapsed: h:96) │ │ ← context-dependent content │ └─────────────────────────────────┘ │ └─────────────────────────────────────┘ ``` - `TopBar` floats with 12 px inset and rounded container; map runs edge-to-edge behind it (field-of-view matters to flyers scanning terrain). - `ProfileSelector`: chip showing active kite-type icon + short label ("Stunt"). Tap opens a 4-option sheet with one-line wind-band descriptions ("Stunt kites · best 6–18 mph"). Selection is global state. - Persistent **attribution line** (OSM + weather provider) bottom-left, 10 px text, always visible per license — never under the sheet. - "List" toggle (a11y requirement) sits inside the search results / menu: renders all in-viewport spots as a sorted card list, fully replacing map interaction. Desktop shell: `TopBar` becomes a fixed header; the bottom sheet's roles move to a **left side panel** (w: 400 px) that hosts search results, spot detail, or forecast; map fills the remainder. --- ## 2. Map view (F1) **Marker anatomy** (`SpotMarker`): ``` ┌────────┐ │ 72 │ ← score, 14px bold, color-scale background └───╲────┘ ╲ ← pointer tail to exact point ``` - Circle Ø32 px at zoom ≥ 12, Ø24 below. Score text auto-contrasts (white/black) against band color. - Unknown conditions: gray badge with "–". - Hard-block active (offshore/storm/over-wind): badge shows ⚠ glyph instead of number, red, regardless of any numeric residue — danger is never just a low number (principle P3). - Selected marker scales 1.25× and gains a ring. **Cluster badge** (`SpotCluster`): Ø40 px, shows count ("12") with a thin outer ring colored by the *best* score inside; tap = zoom to expand. **Collapsed bottom sheet content (map context)** — `NearbyStrip`, h: 96: ``` ┌──────────────────────────────────────────────┐ │ Nearby spots Best now ▸│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ 81 ▲NW │ │ 64 ▲W │ │ 38 ▲N │ │ – ▲? │ │ ← horizontally │ │ Delta │ │ River- │ │ Hilltop│ │ Bay │ │ scrollable │ │ Park │ │ front │ │ │ │ Beach │ │ SpotChip cards │ │ 1.2 km │ │ 3.4 km │ │ 5.1 km │ │ 8 km │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ │ └──────────────────────────────────────────────┘ ``` Sorted by score desc, then distance. "Best now ▸" jumps the map to the top spot. Tapping a chip selects that marker and expands the sheet to spot detail. **Empty state** (no spots in viewport): sheet shows "No mapped spots here yet" + "Suggest a spot" CTA (auth-gated, F8) + link to nearest spot with distance/bearing. --- ## 3. Spot detail (F2) Mobile: `BottomSheet` at half (≈55%) then full height; drag handle on top; map stays visible and centered on the spot at half height. Desktop: left side panel, scrollable. ``` ┌─────────────────────────────────────┐ │ ── (drag handle) │ │ Delta Park ☆ ⋮ │ ← name, favorite, overflow │ Park · Grass · 1.2 km away │ (share, report, edit) │─────────────────────────────────────│ │ ┌──────┐ GOOD FOR STUNT KITES │ ← ScoreHero │ │ 72 │ Steady 11 mph WNW. │ badge Ø64 + 1-line summary │ └──────┘ Updated 6 min ago ● │ data-age + confidence dot │ │ │ [⚠ SAFETY BANNER — conditional] │ ← full-width red band w/ icon; │ Offshore wind — do not launch. │ only when hard-block active │ │ │ Wind Gusts Direction │ ← ConditionGrid, 3-col │ 11 mph 14 mph ↘ WNW │ big numerals 22px │ Temp Rain Gust ratio │ │ 18°C 0% 1.27 │ │ │ │ ▸ Why this score? │ ← ScoreBreakdown (collapsed) │ ┌─────────────────────────────────┐ │ expanded: factor rows │ │ Wind 11 mph ideal band +0 │ │ each: label · value · │ │ Gust ratio 1.27 smooth −0 │ │ judgment · point delta; │ │ Rain none −0 │ │ rows sum to score, footer │ │ Obstacles: tree line W −5 │ │ shows "Rubric v1" link │ │ Base 77 → Score 72 │ │ │ └─────────────────────────────────┘ │ │ │ │ NEXT 12 HOURS more ▸ │ ← ForecastStrip: 12 hour │ ▁▃▅▇▇▆▅▅▃▂▁▁ (colored mini-bars) │ columns colored by score; │ 12 15 18 21 00 03 │ tap → Forecast panel (§4) │ │ │ ABOUT THIS SPOT │ ← SpotInfo │ Large open lawn, ~300 m clear in │ │ all directions. Best in W–NW wind. │ │ Size: Large · Surface: Grass │ │ Hazards: │ ← HazardList, typed chips │ ⚡ Power lines (E edge) │ with icon + locator text │ 🌳 Tree line (W, dirty wind) │ │ Legality: Flying permitted; city │ │ park rules apply [source ↗] │ │ Access: Free parking N lot │ │ │ │ RECENT REPORTS (P1) │ ← ReportList: avatar, time, │ "Smooth all morning" – 2 h ago │ felt-wind chip, text │ [+ Report conditions] │ │ │ │ ✎ Edit spot · History · ODbL/OSM │ ← provenance footer └─────────────────────────────────────┘ ``` Interaction notes: - `ScoreHero` badge tap = expand `ScoreBreakdown` (same as the "Why this score?" row). - Direction arrow in `ConditionGrid` points **where wind blows toward** with the label clarifying origin ("from WNW") — both shown to prevent the classic convention confusion; tooltip explains. - Safety banner is `role="alert"`, not dismissible while active, precedes all content after the hero in DOM order. - Water spots add a row to `SpotInfo`: shore orientation diagram — small circular compass with shoreline chord and shaded "danger sector" (offshore directions); current wind arrow overlaid. --- ## 4. Forecast panel (F6) Mobile: full-screen route pushed over the sheet (`/spot/{slug}/forecast`), back arrow returns to detail. Desktop: replaces side-panel content with a wider (560 px) panel. ``` ┌─────────────────────────────────────┐ │ ← Delta Park — Forecast 🪁▾ │ ← profile switch available here │─────────────────────────────────────│ │ BEST WINDOWS (next 3 days) │ ← BestWindows: top-3 callouts │ ① Sat 14–17 Excellent · 12–14 NW │ tap scrolls graph to window │ ② Sun 10–13 Good · 9–11 W │ │ ③ Today 16–18 Good · 10 mph WNW │ │─────────────────────────────────────│ │ DayStrip (horizontal scroll) │ │ ┌────┐┌────┐┌────┐┌────┐┌────┐ │ per card: weekday, icon, │ │ Fri││ Sat││ Sun││ Mon││ Tue│ … │ wind min–max, direction │ │ ☀ ││ ☀ ││ 🌦 ││ ☁ ││ ☁ │ │ arrow, day score dot; │ │8-12││12-15││9-14││4-7 ││3-6 │ │ selected card highlighted, │ │ ●72││ ●85││ ●61││ ●22││ ●15│ │ days 6–7 hollow dots │ └────┘└────┘└────┘└────┘└────┘ │ (low confidence) │─────────────────────────────────────│ │ HourlyGraph (canvas, h:240) │ │ mph │ │ 25 ┤····························· │ ← hard ceiling line (profile) │ 20 ┤ ▄▄▄ │ │ 15 ┤▒▒▒▒▒▒▄▀▀▀▀▄▄▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ │ ← shaded ideal band (profile) │ 10 ┤ ──gust line─╲___ │ mean line solid, gust line │ 5 ┤ ──mean line──────╲__ │ dashed, band fill between │ 0 └┬───┬───┬───┬───┬───┬───┬── │ │ 12 15 18 21 00 03 06 │ │ bg │██│██│▓▓│▓▓│░░│░░│░░│ │ ← per-hour column tint = │ ↗ ↗ → → ↘ ↘ ↘ │ hourly score color; │ ▂ ▅▂ │ direction arrows / 3 h; │ rain probability bars │ rain bars, second axis │─────────────────────────────────────│ │ ScrubTooltip (on touch/hover): │ │ ┌───────────────────────────┐ │ │ │ Sat 15:00 · Score 85 │ │ │ │ 13 mph, gust 16 (×1.23) │ │ │ │ from NW · 0% rain · 19°C │ │ │ └───────────────────────────┘ │ │─────────────────────────────────────│ │ Model: Open-Meteo best_match │ ← AttributionFooter: │ (ICON-EU) · issued 06:00 UTC │ provider, model, issue │ Times: Europe/Madrid │ time, timezone notice └─────────────────────────────────────┘ ``` Interaction notes: - Graph pans horizontally through 168 h; pinch-zoom adjusts time scale between 24 h and 96 h visible. Rendered on `` for performance (NFR-P1); an off-screen data table mirrors it for screen readers. - Selecting a `DayStrip` card animates the graph viewport to that day. - Switching profile re-tints background columns, redraws ideal band/ceiling, and recomputes BestWindows — all client-side from cached hourly data. --- ## 5. Auxiliary screens (P1, brief) - **Compare view (F7):** vertical stack of up to 4 `CompareRow`s: spot name, current badge, 24 h score sparkline, distance. Columns align for scanning; "+ Add spot" returns to map in pick-mode. - **Spot editor (F8):** stepper form — ① location pin + optional polygon draw, ② basics (name, type, surface, size), ③ water settings (shore orientation via draggable compass chord), ④ hazards (typed multi-select + locator text), ⑤ legality + sources, ⑥ review & submit. Each step validates; draft autosaved locally. - **Report composer (F9):** single sheet — felt-wind segmented control (Calm/Light/Moderate/Fresh/Strong), quality segmented control (Smooth/Gusty/Turbulent), crowd slider, optional text/photo, one "Post" button. - **Settings:** units, default profile, language, theme (light/dark/auto — dark matters at dusk sessions), account & data (export/delete). ## 6. Accessibility & responsive rules - Every interactive target ≥ 44×44 px; sheet snap points operable via keyboard (`ArrowUp/Down` when handle focused). - Score colors always paired with the text label; color-blind-safe palette (verified against deuteranopia simulation) defined in the design-tokens file at implementation. - Map-free **List view** mirrors all F1 information; forecast graph mirrored by a data table; all icons have text alternatives. - High-contrast outdoor mode: light theme uses ≥ 7:1 contrast for primary text (sunlight readability).