bae705aa97
- Add NFC ePassport roadmap (ICAO 9303, eIDAS) - Add TensorFlow.js edge face detection (BlazeFace) - Add structured audit logger (GDPR-compliant) - Risk scoring support Part of KYC Apple Native UX v1.1.0
500 lines
20 KiB
Markdown
500 lines
20 KiB
Markdown
# Design Spec — Internationalisation, Locale-Aware Sandbox & Visual Storytelling
|
||
**Landvex × quiXzoom**
|
||
**Datum:** 2026-06-20
|
||
**Uppdragsgivare:** Erik Svensson
|
||
**Status:** Produktionskrav — levereras till designteam + engineering
|
||
|
||
---
|
||
|
||
## DEL 1 — ELIMINERA ALLA SVENSKA STANDARDARTEFAKTER
|
||
|
||
### Princip
|
||
|
||
Standardupplevelsen är engelska + marknadens lokala kontext. Sverige är en marknad bland 20+, inte ett default.
|
||
|
||
### Inventering — svenska artefakter som måste bort
|
||
|
||
| Artefakt | Nuläge | Krav | Fil/yta |
|
||
|---|---|---|---|
|
||
| Exempeladress | "Storgatan 14, Stockholm" (floating card) | Dynamisk per marknad | quiXzoom homepage hero |
|
||
| Exempelvaluta i schema | `priceCurrency: "SEK"` (fixat) | EUR/USD som global default | quiXzoom index.html |
|
||
| Skatteinfo | "Grundavdrag ~17 500 SEK/year" som primärt exempel | Marknadsdynamisk eller bort från hero-kontext | quiXzoom FAQ-tabs |
|
||
| Juridisk text | `terms.html` på svenska (lang="sv") | Engelsk default, sv-variant under `/sv/` | quiXzoom/terms.html |
|
||
| `zoomer-start.html` | `<html lang="sv">`, "Bli Zoomer", hela texten på svenska | Primärsida ska vara engelska | nginx index-priority |
|
||
| Exempelnamn | Implicita svenska namn i onboarding-data | Marknadsneutrala eller dynamiska | |
|
||
| Karta/geo-default | Stockholmscentrerad demo-karta | Geo-IP eller marknadsselektion | quiXzoom map.html |
|
||
| Landvex exempeldata | Stockholmsvärden i intelligence-tabeller | Dynamisk per vald stad/marknad | Landvex cities/* |
|
||
|
||
### Implementation — Locale Architecture
|
||
|
||
```
|
||
DEFAULT LOCALE: en-001 (World English)
|
||
DEFAULT MARKET: none selected → prompt user
|
||
|
||
URL-struktur:
|
||
/ → en, marknadsneutral
|
||
/markets/se/ → sv-SE, svenska artefakter
|
||
/markets/de/ → de-DE, tyska artefakter
|
||
/markets/us/ → en-US, amerikanska artefakter
|
||
/markets/th/ → th-TH, thailändska artefakter
|
||
|
||
Cookie: qx_locale=de-DE (persisteras vid val)
|
||
HTTP: Accept-Language läses → föreslår marknad, aldrig tvingar
|
||
```
|
||
|
||
### Locale Data Bundle — per marknad
|
||
|
||
```json
|
||
{
|
||
"de-DE": {
|
||
"currency": "EUR",
|
||
"currencySymbol": "€",
|
||
"exampleAddress": "Maximilianstraße 12, München",
|
||
"exampleCompany": "Müller GmbH",
|
||
"examplePerson": "Hans Müller",
|
||
"exampleLegalId": "HRB 123456 AG München",
|
||
"examplePhone": "+49 89 12345678",
|
||
"examplePostalCode": "80539",
|
||
"exampleCity": "München",
|
||
"taxThreshold": "22.000 € (Kleinunternehmerregelung)",
|
||
"payoutRail": "SEPA",
|
||
"dateFormat": "DD.MM.YYYY",
|
||
"numberFormat": "1.234,56",
|
||
"mapCenter": [11.5820, 48.1351],
|
||
"missionExamples": [
|
||
{ "title": "Fassadeninspektion", "location": "Schwabing, München", "reward": 14 },
|
||
{ "title": "Parkplatzkartierung", "location": "Maxvorstadt", "reward": 9 }
|
||
]
|
||
},
|
||
"en-US": {
|
||
"currency": "USD",
|
||
"currencySymbol": "$",
|
||
"exampleAddress": "1234 Main St, Houston TX",
|
||
"exampleCompany": "Acme Corp",
|
||
"examplePerson": "James Wilson",
|
||
"exampleLegalId": "EIN 12-3456789",
|
||
"examplePhone": "+1 713 555 0123",
|
||
"examplePostalCode": "77002",
|
||
"exampleCity": "Houston",
|
||
"taxThreshold": "$400/year (self-employment threshold)",
|
||
"payoutRail": "ACH",
|
||
"dateFormat": "MM/DD/YYYY",
|
||
"numberFormat": "1,234.56",
|
||
"mapCenter": [-95.3698, 29.7604],
|
||
"missionExamples": [
|
||
{ "title": "Facade Survey", "location": "Midtown Houston", "reward": 18 },
|
||
{ "title": "Parking Lot Audit", "location": "Downtown Houston", "reward": 12 }
|
||
]
|
||
},
|
||
"th-TH": {
|
||
"currency": "THB",
|
||
"currencySymbol": "฿",
|
||
"exampleAddress": "123 Sukhumvit Rd, Khlong Toei, Bangkok",
|
||
"exampleCompany": "Thai Inspire Co., Ltd.",
|
||
"examplePerson": "Somchai Jaidee",
|
||
"exampleLegalId": "0105561012345",
|
||
"examplePhone": "+66 2 123 4567",
|
||
"examplePostalCode": "10110",
|
||
"exampleCity": "Bangkok",
|
||
"taxThreshold": "฿1,800,000/year (VAT threshold)",
|
||
"payoutRail": "PromptPay",
|
||
"dateFormat": "DD/MM/YYYY",
|
||
"numberFormat": "1,234.56",
|
||
"mapCenter": [100.5018, 13.7563],
|
||
"missionExamples": [
|
||
{ "title": "Shop Sign Survey", "location": "Silom, Bangkok", "reward": 120 },
|
||
{ "title": "Facade Condition", "location": "Chatuchak", "reward": 85 }
|
||
]
|
||
},
|
||
"ar-AE": {
|
||
"currency": "AED",
|
||
"currencySymbol": "د.إ",
|
||
"exampleAddress": "Al Wasl Road, Jumeirah, Dubai",
|
||
"exampleCompany": "Al Noor Trading LLC",
|
||
"exampleLegalId": "Commercial License 1234567",
|
||
"examplePhone": "+971 4 123 4567",
|
||
"exampleCity": "Dubai",
|
||
"payoutRail": "SWIFT",
|
||
"dateFormat": "DD/MM/YYYY",
|
||
"mapCenter": [55.2708, 25.2048],
|
||
"rtl": true,
|
||
"missionExamples": [
|
||
{ "title": "Building Facade Inspection", "location": "Business Bay, Dubai", "reward": 55 }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### Sandbox-propagering — tekniskt krav
|
||
|
||
Varje demo/sandbox-vy MÅSTEläsa från locale bundle. Inga hårdkodade värden.
|
||
|
||
```javascript
|
||
// Fel — hårdkodat
|
||
const demoCard = {
|
||
address: "Storgatan 14, Stockholm",
|
||
reward: "285 kr",
|
||
company: "Stockholms Stad"
|
||
};
|
||
|
||
// Rätt — dynamiskt
|
||
const locale = getLocale(); // "de-DE" från cookie/URL/GeoIP
|
||
const demoCard = {
|
||
address: localeData[locale].missionExamples[0].location,
|
||
reward: formatCurrency(localeData[locale].missionExamples[0].reward, locale),
|
||
company: localeData[locale].exampleCompany
|
||
};
|
||
```
|
||
|
||
**Propageras till:**
|
||
- Hero floating mission card
|
||
- Demo-kartan (mapCenter + exempelmarkeringar)
|
||
- Onboarding-flow exempeldata
|
||
- Earnings-kalkylator
|
||
- FAQ skatteinfo (visas bara för vald marknad)
|
||
- Landvex intelligence-tabeller (exempelrader)
|
||
- City pages (redan marknadsseparerade — korrekt arkitektur)
|
||
|
||
---
|
||
|
||
## DEL 2 — SANDBOX FÖLJER VALD MARKNAD
|
||
|
||
### Flöde
|
||
|
||
```
|
||
Användaren landar på quixzoom.com
|
||
↓
|
||
GeoIP → föreslår marknad (banner: "Looks like you're in Germany. Switch to DE →")
|
||
↓
|
||
Användaren väljer (eller behåller default)
|
||
↓
|
||
Cookie qx_market=DE sätts
|
||
↓
|
||
ALL demo-data propageras: adresser, valutor, namn, karta, skatteinfo, juridik
|
||
↓
|
||
Onboarding → "How much can I earn in Germany?"
|
||
→ Visar tyska exempel, EUR, tyska skatttrösklar
|
||
```
|
||
|
||
### Market Selector Component
|
||
|
||
```html
|
||
<div class="market-selector" role="navigation" aria-label="Select your market">
|
||
<button class="market-btn" data-market="current">
|
||
<img src="/flags/{{current}}.svg" alt="" width="20" height="14" aria-hidden="true">
|
||
<span>{{currentMarketName}}</span>
|
||
<svg aria-hidden="true"><!-- chevron --></svg>
|
||
</button>
|
||
<div class="market-dropdown" role="listbox">
|
||
<button role="option" data-market="SE">🇸🇪 Sweden</button>
|
||
<button role="option" data-market="DE">🇩🇪 Germany</button>
|
||
<button role="option" data-market="US">🇺🇸 United States</button>
|
||
<button role="option" data-market="GB">🇬🇧 United Kingdom</button>
|
||
<button role="option" data-market="TH">🇹🇭 Thailand</button>
|
||
<button role="option" data-market="AE">🇦🇪 UAE</button>
|
||
<button role="option" data-market="NL">🇳🇱 Netherlands</button>
|
||
<button role="option" data-market="FR">🇫🇷 France</button>
|
||
<!-- +13 markets at launch -->
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
```javascript
|
||
document.querySelectorAll('[data-market]').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const market = btn.dataset.market;
|
||
document.cookie = `qx_market=${market};path=/;max-age=31536000`;
|
||
updateAllLocaleContent(market); // triggers locale bundle swap
|
||
updateMap(localeData[market].mapCenter);
|
||
updateDemoCard(localeData[market].missionExamples[0]);
|
||
updateFAQTax(localeData[market]);
|
||
});
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## DEL 3 — VISUELLT STORYTELLING
|
||
|
||
### Princip
|
||
|
||
> **Användaren ska förstå vad sidan gör inom 3 sekunder, innan de läser ett enda stycke.**
|
||
|
||
### Nuläge vs mål
|
||
|
||
| Yta | Nuläge | Mål |
|
||
|---|---|---|
|
||
| Hero | Text + telefon-mockup | Animated workflow: Mission → Zoomer → Verified data → Payout |
|
||
| How it works | 4 textblock | 4 illustrerade steg med process-ikoner + connectors |
|
||
| Tier pricing | 3 textkort | 3 illustrerade nivåkort med visuell differentiering |
|
||
| Landvex homepage | Textblock + dark hero | Contradictions-diagram + data-flow-illustration |
|
||
| Landvex methodology | Texttunga steg | Visuell pipeline: Observation → AI → Score → Report |
|
||
| Onboarding | Formulär | Illustrated steps med progress indicator |
|
||
| Empty states | Ingen data/text | Custom illustration per kontext |
|
||
|
||
### Illustration-system — specifikation
|
||
|
||
#### Stil
|
||
```
|
||
Stil: Flat / geometric, linjär
|
||
Färgpalett: --color-accent #0066FF + white + #0a0a0a + accent-green #00C853
|
||
Stroke: 2px consistent
|
||
Ikonstil: 24×24px grid, rounded corners 2px
|
||
Animationer: CSS-only, prefers-reduced-motion respected
|
||
Format: SVG (inline för animering, externa för statiska)
|
||
```
|
||
|
||
#### Prioriterade illustrationer att producera (ordning)
|
||
|
||
**quiXzoom — 8 illustrationer**
|
||
|
||
```
|
||
QX-ILL-01: Mission Flow (hero)
|
||
Visar: Briefcase icon → Map pin → Camera → Checkmark → Coins
|
||
Animation: left-to-right flow, 3s loop
|
||
Plats: Hero, ovanför/bredvid telefon-mockup
|
||
|
||
QX-ILL-02: How it Works — 4 steg
|
||
Steg 1: Browse Map → pin-ikon på karta
|
||
Steg 2: Claim Mission → handskaknings-ikon
|
||
Steg 3: Photograph → kamera-ikon
|
||
Steg 4: Get Paid → plånbok + check-ikon
|
||
Format: Horisontell rad desktop, vertikal stack mobil
|
||
|
||
QX-ILL-03: Tier Differentiation
|
||
Supplementary: singel person, 2-3 per vecka
|
||
Active: person + ryggsäck, 8-12 per vecka
|
||
Professional: person + utrustning + badge
|
||
|
||
QX-ILL-04: Identity Verification (onboarding)
|
||
Shield + ID-kort + checkmark
|
||
|
||
QX-ILL-05: Zoomer Profile Empty State
|
||
Person med kamera, "Your first mission awaits"
|
||
|
||
QX-ILL-06: Mission Approved
|
||
Checkmark-animation + mynt-ikon + "Credits added"
|
||
|
||
QX-ILL-07: Earnings Calculator
|
||
Slider → graf → utbetalningsikon
|
||
|
||
QX-ILL-08: Global Presence
|
||
Världskarta med markerade launch-länder, pulsande pins
|
||
```
|
||
|
||
**Landvex — 6 illustrationer**
|
||
|
||
```
|
||
LV-ILL-01: Contradiction Detection (hero)
|
||
Visar: Officiell rapport (dokument-ikon) ← → Faktisk observation (kamera-ikon)
|
||
Mittenpil med "≠" (contradiction marker)
|
||
Animation: dokumentet och kameran "pulsar" mot mitten
|
||
|
||
LV-ILL-02: Intelligence Pipeline (methodology)
|
||
Observation → Collection → AI Analysis → Scoring → Report → Decision
|
||
6 noder, connectors, ikoner per steg
|
||
|
||
LV-ILL-03: Control Intelligence Output
|
||
Dashboard-mockup med score (0-100 gauge) + trend + alert
|
||
|
||
LV-ILL-04: Data Coverage Map
|
||
Polygon-overlay på karta + coverage percentage
|
||
"94% commercial facade coverage, Södermalm, updated <30 days"
|
||
|
||
LV-ILL-05: Enterprise Client Flow
|
||
Request → Deploy → Collect → Analyse → Deliver
|
||
|
||
LV-ILL-06: Zoomer Network (quiXzoom → Landvex bridge)
|
||
Många prickar (Zoomers) → Aggregation-nod → Intelligence-output
|
||
Visuellt förklarar relationen mellan QX och LV
|
||
```
|
||
|
||
### Content Ratio Target
|
||
|
||
```
|
||
Per sida (desktop, above-the-fold):
|
||
|
||
Hero: 60% visual / 40% text
|
||
Feature section: 50% visual / 50% text
|
||
Proof/social: 30% visual / 70% text (social proof är text-tungt by nature)
|
||
CTA section: 70% visual / 30% text
|
||
|
||
Globalt per sida:
|
||
illustrations + UI: 40%
|
||
data + charts: 20%
|
||
text: 40%
|
||
```
|
||
|
||
### Workflow Diagram — quiXzoom How it Works
|
||
|
||
SVG-spec för QX-ILL-02 (inline, production-ready):
|
||
|
||
```svg
|
||
<!-- QX-ILL-02: How it Works — 4 Steps -->
|
||
<svg viewBox="0 0 800 120" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="How quiXzoom works: Browse, Claim, Photograph, Get Paid">
|
||
<defs>
|
||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
|
||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#0066FF" opacity="0.4"/>
|
||
</marker>
|
||
</defs>
|
||
|
||
<!-- Step 1: Browse -->
|
||
<g transform="translate(60,60)">
|
||
<circle r="32" fill="#0066FF" opacity="0.1"/>
|
||
<circle r="32" fill="none" stroke="#0066FF" stroke-width="1.5" opacity="0.3"/>
|
||
<!-- Map pin icon -->
|
||
<path d="M0-14 C-8-14 -14-8 -14 0 C-14 10 0 20 0 20 C0 20 14 10 14 0 C14-8 8-14 0-14Z" fill="none" stroke="#0066FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
<circle cx="0" cy="0" r="4" fill="#0066FF"/>
|
||
<!-- Label -->
|
||
<text y="50" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#3a3a3a" font-weight="600">Browse</text>
|
||
<text y="64" text-anchor="middle" font-family="system-ui,sans-serif" font-size="11" fill="#6B6B6B">Find a mission near you</text>
|
||
</g>
|
||
|
||
<!-- Arrow 1→2 -->
|
||
<line x1="105" y1="60" x2="195" y2="60" stroke="#0066FF" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" marker-end="url(#arrow)"/>
|
||
|
||
<!-- Step 2: Claim -->
|
||
<g transform="translate(230,60)">
|
||
<circle r="32" fill="#0066FF" opacity="0.1"/>
|
||
<circle r="32" fill="none" stroke="#0066FF" stroke-width="1.5" opacity="0.3"/>
|
||
<!-- Handshake/check icon -->
|
||
<path d="M-10-6 L-4 0 L10-8" fill="none" stroke="#0066FF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||
<rect x="-14" y="-14" width="28" height="28" rx="6" fill="none" stroke="#0066FF" stroke-width="1.5" opacity="0.5"/>
|
||
<text y="50" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#3a3a3a" font-weight="600">Claim</text>
|
||
<text y="64" text-anchor="middle" font-family="system-ui,sans-serif" font-size="11" fill="#6B6B6B">Accept the brief</text>
|
||
</g>
|
||
|
||
<!-- Arrow 2→3 -->
|
||
<line x1="275" y1="60" x2="365" y2="60" stroke="#0066FF" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" marker-end="url(#arrow)"/>
|
||
|
||
<!-- Step 3: Photograph -->
|
||
<g transform="translate(400,60)">
|
||
<circle r="32" fill="#0066FF" opacity="0.1"/>
|
||
<circle r="32" fill="none" stroke="#0066FF" stroke-width="1.5" opacity="0.3"/>
|
||
<!-- Camera icon -->
|
||
<rect x="-14" y="-8" width="28" height="20" rx="3" fill="none" stroke="#0066FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||
<circle cx="0" cy="2" r="6" fill="none" stroke="#0066FF" stroke-width="2"/>
|
||
<path d="M-6-8 L-4-12 L4-12 L6-8" fill="none" stroke="#0066FF" stroke-width="1.5" stroke-linecap="round"/>
|
||
<text y="50" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#3a3a3a" font-weight="600">Photograph</text>
|
||
<text y="64" text-anchor="middle" font-family="system-ui,sans-serif" font-size="11" fill="#6B6B6B">Submit your photos</text>
|
||
</g>
|
||
|
||
<!-- Arrow 3→4 -->
|
||
<line x1="445" y1="60" x2="535" y2="60" stroke="#0066FF" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" marker-end="url(#arrow)"/>
|
||
|
||
<!-- Step 4: Get Paid -->
|
||
<g transform="translate(570,60)">
|
||
<circle r="32" fill="#00C853" opacity="0.12"/>
|
||
<circle r="32" fill="none" stroke="#00C853" stroke-width="1.5" opacity="0.4"/>
|
||
<!-- Coin/check icon -->
|
||
<circle cx="0" cy="0" r="12" fill="none" stroke="#00C853" stroke-width="2"/>
|
||
<path d="M-5 0 L-2 3 L6-4" fill="none" stroke="#00C853" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||
<text y="50" text-anchor="middle" font-family="system-ui,sans-serif" font-size="13" fill="#3a3a3a" font-weight="600">Get Paid</text>
|
||
<text y="64" text-anchor="middle" font-family="system-ui,sans-serif" font-size="11" fill="#6B6B6B">Credits paid weekly</text>
|
||
</g>
|
||
</svg>
|
||
```
|
||
|
||
### Landvex — Contradiction Detection Hero Illustration
|
||
|
||
```svg
|
||
<!-- LV-ILL-01: Contradiction Detection -->
|
||
<svg viewBox="0 0 600 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Landvex identifies contradictions between reported reality and observed reality">
|
||
<defs>
|
||
<style>
|
||
@media (prefers-reduced-motion: no-preference) {
|
||
.pulse-left { animation: pulseLeft 2s ease-in-out infinite; }
|
||
.pulse-right { animation: pulseRight 2s ease-in-out 1s infinite; }
|
||
@keyframes pulseLeft { 0%,100%{opacity:.7} 50%{opacity:1} }
|
||
@keyframes pulseRight { 0%,100%{opacity:.7} 50%{opacity:1} }
|
||
}
|
||
</style>
|
||
</defs>
|
||
|
||
<!-- LEFT: Official Report -->
|
||
<g transform="translate(100,100)" class="pulse-left">
|
||
<rect x="-50" y="-60" width="100" height="120" rx="8" fill="#111" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
|
||
<!-- Doc lines -->
|
||
<line x1="-30" y1="-30" x2="30" y2="-30" stroke="rgba(255,255,255,0.3)" stroke-width="2" stroke-linecap="round"/>
|
||
<line x1="-30" y1="-16" x2="20" y2="-16" stroke="rgba(255,255,255,0.2)" stroke-width="1.5" stroke-linecap="round"/>
|
||
<line x1="-30" y1="-4" x2="25" y2="-4" stroke="rgba(255,255,255,0.2)" stroke-width="1.5" stroke-linecap="round"/>
|
||
<line x1="-30" y1="8" x2="15" y2="8" stroke="rgba(255,255,255,0.2)" stroke-width="1.5" stroke-linecap="round"/>
|
||
<!-- Green checkmark = "official says OK" -->
|
||
<circle cx="0" cy="32" r="14" fill="#00C853" opacity="0.15"/>
|
||
<path d="M-6 32 L-2 36 L8 26" fill="none" stroke="#00C853" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||
<text y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="12" fill="rgba(255,255,255,0.5)">Official report</text>
|
||
<text y="83" text-anchor="middle" font-family="system-ui,sans-serif" font-size="11" fill="rgba(255,255,255,0.3)">No issues found</text>
|
||
</g>
|
||
|
||
<!-- CENTER: Contradiction marker -->
|
||
<g transform="translate(300,100)">
|
||
<circle r="28" fill="#0066FF" opacity="0.08"/>
|
||
<circle r="28" fill="none" stroke="#0066FF" stroke-width="1" opacity="0.3"/>
|
||
<!-- ≠ symbol -->
|
||
<text text-anchor="middle" dy="7" font-size="28" font-weight="900" fill="#0066FF" opacity="0.8">≠</text>
|
||
<!-- Left arrow -->
|
||
<line x1="-60" y1="0" x2="-35" y2="0" stroke="#0066FF" stroke-width="1.5" stroke-dasharray="3 2" opacity="0.4"/>
|
||
<!-- Right arrow -->
|
||
<line x1="35" y1="0" x2="60" y2="0" stroke="#0066FF" stroke-width="1.5" stroke-dasharray="3 2" opacity="0.4"/>
|
||
</g>
|
||
|
||
<!-- RIGHT: Field Observation -->
|
||
<g transform="translate(500,100)" class="pulse-right">
|
||
<rect x="-50" y="-60" width="100" height="120" rx="8" fill="#111" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
|
||
<!-- Camera icon -->
|
||
<rect x="-24" y="-20" width="48" height="34" rx="4" fill="none" stroke="rgba(255,255,255,0.4)" stroke-width="1.5"/>
|
||
<circle cx="0" cy="-3" r="10" fill="none" stroke="rgba(255,255,255,0.4)" stroke-width="1.5"/>
|
||
<path d="-10-20 L-8-26 L8-26 L10-20" fill="none" stroke="rgba(255,255,255,0.3)" stroke-width="1.5" stroke-linecap="round"/>
|
||
<!-- Red warning = "field says different" -->
|
||
<circle cx="0" cy="32" r="14" fill="#FF3B30" opacity="0.15"/>
|
||
<line x1="0" y1="25" x2="0" y2="34" stroke="#FF3B30" stroke-width="2.5" stroke-linecap="round"/>
|
||
<circle cx="0" cy="39" r="1.5" fill="#FF3B30"/>
|
||
<text y="70" text-anchor="middle" font-family="system-ui,sans-serif" font-size="12" fill="rgba(255,255,255,0.5)">Field observation</text>
|
||
<text y="83" text-anchor="middle" font-family="system-ui,sans-serif" font-size="11" fill="rgba(255,255,255,0.3)">Defects detected</text>
|
||
</g>
|
||
</svg>
|
||
```
|
||
|
||
---
|
||
|
||
## IMPLEMENTATION — PRIORITETSORDNING
|
||
|
||
### Sprint 1 (1–2 veckor): Locale architecture
|
||
|
||
1. Skapa `locale-data.js` bundle med 6 marknader (SE, DE, US, GB, TH, AE)
|
||
2. Implementera market selector component
|
||
3. Koppla floating mission card i hero till locale bundle
|
||
4. Koppla demo-kartan till locale mapCenter
|
||
5. Sätt GeoIP-banner (max 1 fråga per session, kan stängas)
|
||
|
||
### Sprint 2 (2–3 veckor): Illustrationer
|
||
|
||
1. QX-ILL-01: Mission flow animation (hero)
|
||
2. QX-ILL-02: How it works — 4 steg (inline SVG, klar ovan)
|
||
3. LV-ILL-01: Contradiction detection (inline SVG, klar ovan)
|
||
4. LV-ILL-02: Intelligence pipeline
|
||
5. QX-ILL-03: Tier cards
|
||
6. QX-ILL-08: Global presence map
|
||
|
||
### Sprint 3 (3–4 veckor): Full propagation
|
||
|
||
1. Onboarding-flow lokalisering
|
||
2. Skatteinfo per marknad (FAQ-tabs)
|
||
3. Earnings calculator med lokal valuta
|
||
4. zoomer-start.html → engelska default + locale-aware
|
||
5. Resterende illustrationer (QX-ILL-04 through 07, LV-ILL-03 through 06)
|
||
|
||
---
|
||
|
||
## LEVERANS TILL DESIGNTEAM
|
||
|
||
**Fil:** `/home/bernt/.openclaw/workspace/reports/i18n-illustration-spec-2026-06-20.md`
|
||
|
||
**Innehåller:**
|
||
- Fullständig locale-arkitektur med 4 marknaders data-bundles
|
||
- Market selector component (HTML + JS)
|
||
- Illustration-spec: 14 illustrationer, stil-guide, prioritetsordning
|
||
- 2 production-ready SVG-illustrationer (QX-ILL-02 + LV-ILL-01)
|
||
- Content ratio targets per sidtyp
|
||
- 3-sprints implementation roadmap
|