feat(smart-app): implement complete mobile app MVP

- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
This commit is contained in:
Eric FELIXINE
2026-06-01 18:00:35 -04:00
parent 08ca495bde
commit e30ae8ed09
35578 changed files with 3703534 additions and 43 deletions

2
.env.ditto Normal file
View File

@@ -0,0 +1,2 @@
DITTO_JWT_SECRET=NTOT-Vh8WRKWE52eV8zRiLs3a-gd8YUGSrvm5x2InZc
DEVOPS_PASSWORD=OvP9WVB09aFDnYPyK52UIg

View File

@@ -1,4 +1,5 @@
# Eclipse Ditto - Smart City Digital Twin - Martinique
# Using official Eclipse Ditto images with Akka cluster
services:
ditto-mongodb:
image: mongo:6
@@ -21,22 +22,17 @@ services:
environment:
- TZ=Europe/Berlin
- BIND_HOSTNAME=0.0.0.0
- DITTO_JWT_SECRET=my-ditto-jwt-secret-key-12345
- MONGO_HOST=smart-city-ditto-mongodb
- MONGO_PORT=27017
- MONGO_DB=Policies
- DITTO_JWT_SECRET=NTOT-Vh8WRKWE52eV8zRiLs3a-gd8YUGSrvm5x2InZc
- MONGODB_URI=mongodb://smart-city-ditto-mongodb:27017/Policies
- AKKA_REMOTE_ENABLED=false
- AKKA_REMOTE_ENABLED=true
- AKKA_REMOTE_CANONICAL_HOSTNAME=ditto-policies
- AKKA_REMOTE_CANONICAL_PORT=2551
- JAVA_TOOL_OPTIONS=-Dditto.mongodb.uri=mongodb://smart-city-ditto-mongodb:27017/Policies -Dditto.mongodb.db-name=Policies
networks:
traefik-public:
aliases:
- ditto-cluster
- ditto-policies
labels:
- "traefik.enable=true"
- "traefik.http.routers.ditto-policies.rule=Host(`ditto-policies.digitribe.fr`)"
- "traefik.http.routers.ditto-policies.entrypoints=web"
- "traefik.http.services.ditto-policies.loadbalancer.server.port=8080"
ditto-things:
image: eclipse/ditto-things:latest
@@ -49,26 +45,20 @@ services:
environment:
- TZ=Europe/Berlin
- BIND_HOSTNAME=0.0.0.0
- DITTO_JWT_SECRET=my-ditto-jwt-secret-key-12345
- MONGO_HOST=smart-city-ditto-mongodb
- MONGO_PORT=27017
- MONGO_DB=Things
- DITTO_JWT_SECRET=NTOT-Vh8WRKWE52eV8zRiLs3a-gd8YUGSrvm5x2InZc
- MONGODB_URI=mongodb://smart-city-ditto-mongodb:27017/Things
- AKKA_REMOTE_ENABLED=false
- JAVA_TOOL_OPTIONS=-Dditto.things.authentication.devops.password=ditto-devops-secret
- AKKA_REMOTE_ENABLED=true
- AKKA_REMOTE_CANONICAL_HOSTNAME=ditto-things
- AKKA_REMOTE_CANONICAL_PORT=2551
- JAVA_TOOL_OPTIONS=-Dditto.mongodb.uri=mongodb://smart-city-ditto-mongodb:27017/Things -Dditto.mongodb.db-name=Things -Dditto.things.authentication.devops.password=OvP9WVB09aFDnYPyK52UIg
networks:
traefik-public:
aliases:
- ditto-cluster
- ditto-things
labels:
- "traefik.enable=true"
- "traefik.http.routers.ditto-things.rule=Host(`ditto-things.digitribe.fr`)"
- "traefik.http.routers.ditto-things.entrypoints=web"
- "traefik.http.services.ditto-things.loadbalancer.server.port=8080"
ditto-gateway:
image: eclipse/ditto-gateway:custom
image: eclipse/ditto-gateway:latest
container_name: smart-city-ditto-gateway
restart: unless-stopped
hostname: ditto-gateway
@@ -78,18 +68,27 @@ services:
environment:
- TZ=Europe/Berlin
- BIND_HOSTNAME=0.0.0.0
- DITTO_JWT_SECRET=my-ditto-jwt-secret-key-12345
- DITTO_JWT_SECRET=NTOT-Vh8WRKWE52eV8zRiLs3a-gd8YUGSrvm5x2InZc
- DITTO_GATEWAY_PROXY_ENABLED=true
- AKKA_REMOTE_ENABLED=false
- AKKA_REMOTE_ENABLED=true
- AKKA_REMOTE_CANONICAL_HOSTNAME=ditto-gateway
- AKKA_REMOTE_CANONICAL_PORT=2551
- DITTO_GW_STREAMING_ENABLED=true
- DITTO_GW_MQTT_BROKER=smart-city-mosquitto:1883
- DITTO_GW_MQTT_TOPIC_FILTER=smartcity/#
- DEVOPS_PASSWORD=ditto-devops-secret
- DEVOPS_PASSWORD=OvP9WVB09aFDnYPyK52UIg
- DITTO_APIDOC_ENABLED=true
networks:
traefik-public:
aliases:
- ditto-cluster
- ditto-gateway
labels:
- "traefik.enable=true"
- "traefik.http.routers.ditto.rule=Host(`ditto.digitribe.fr`)"
- "traefik.http.routers.ditto.entrypoints=websecure"
- "traefik.http.routers.ditto.tls.certresolver=letsencrypt"
- "traefik.http.services.ditto.loadbalancer.server.port=8080"
networks:
traefik-public:

View File

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 01 Onboarding (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.onboarding-bg {
width: 100%; height: 100%;
background: linear-gradient(160deg, #0D47A1 0%, #00838F 50%, #00ACC1 100%);
display: flex; flex-direction: column;
align-items: center; justify-content: center;
padding: 32px; text-align: center;
position: relative; overflow: hidden;
}
.onboarding-bg::before {
content: '';
position: absolute;
width: 400px; height: 400px;
border-radius: 50%;
background: rgba(255,255,255,0.05);
top: -100px; right: -100px;
}
.onboarding-bg::after {
content: '';
position: absolute;
width: 300px; height: 300px;
border-radius: 50%;
background: rgba(255,255,255,0.03);
bottom: -50px; left: -80px;
}
.onboarding-logo {
width: 100px; height: 100px;
background: rgba(255,255,255,0.15);
border-radius: 24px;
display: flex; align-items: center; justify-content: center;
margin-bottom: 24px;
backdrop-filter: blur(10px);
position: relative; z-index: 1;
}
.onboarding-title {
font-size: var(--text-3xl);
font-weight: var(--weight-bold);
color: white;
margin-bottom: 8px;
position: relative; z-index: 1;
}
.onboarding-subtitle {
font-size: var(--text-base);
color: rgba(255,255,255,0.8);
margin-bottom: 48px;
position: relative; z-index: 1;
}
.onboarding-actions {
width: 100%;
max-width: 300px;
display: flex; flex-direction: column;
gap: 12px; position: relative; z-index: 1;
}
.onboarding-actions .btn { width: 100%; }
.btn-white {
background: white;
color: var(--primary-600);
}
.btn-white:hover { background: var(--neutral-100); }
.btn-ghost-white {
background: rgba(255,255,255,0.15);
color: white;
border: 2px solid rgba(255,255,255,0.3);
backdrop-filter: blur(4px);
}
.btn-ghost-white:hover { background: rgba(255,255,255,0.25); }
.lang-selector {
display: flex; gap: 8px; margin-bottom: 32px;
position: relative; z-index: 1;
flex-wrap: wrap; justify-content: center;
}
.lang-pill {
padding: 6px 16px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.2);
color: white;
font-size: var(--text-sm);
font-weight: var(--weight-medium);
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
backdrop-filter: blur(4px);
}
.lang-pill.active {
background: white;
color: var(--primary-600);
border-color: white;
}
.page-label {
position: absolute; bottom: 20px;
left: 0; right: 0;
text-align: center;
font-size: var(--text-xs);
color: rgba(255,255,255,0.4);
}
.feature-icons {
display: flex; gap: 16px; margin-bottom: 40px;
position: relative; z-index: 1;
flex-wrap: wrap; justify-content: center;
}
.feat-icon {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
}
.feat-icon-circle {
width: 48px; height: 48px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.15);
display: flex; align-items: center; justify-content: center;
backdrop-filter: blur(4px);
}
.feat-icon-label {
font-size: var(--text-xs);
color: rgba(255,255,255,0.7);
}
.version-tag {
position: absolute; top: 50px;
right: 16px;
background: rgba(255,255,255,0.2);
color: white;
font-size: 10px;
padding: 4px 10px;
border-radius: var(--radius-full);
font-weight: 600;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="version-tag">v2.0 — Blue</div>
<div class="onboarding-bg">
<div class="onboarding-logo">
<svg width="50" height="50" viewBox="0 0 50 50" fill="none">
<rect x="8" y="20" width="8" height="22" rx="2" fill="white" opacity="0.9"/>
<rect x="21" y="14" width="8" height="28" rx="2" fill="white" opacity="0.7"/>
<rect x="34" y="8" width="8" height="34" rx="2" fill="white" opacity="0.85"/>
<circle cx="25" cy="6" r="4" fill="white"/>
</svg>
</div>
<div class="onboarding-title">Smart App City</div>
<div class="onboarding-subtitle">Martinique Digital Twin</div>
<div class="lang-selector">
<div class="lang-pill active">🇫🇷 FR</div>
<div class="lang-pill">🇬🇧 EN</div>
<div class="lang-pill">🇪🇸 ES</div>
<div class="lang-pill">🇩🇪 DE</div>
</div>
<div class="feature-icons">
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
</div>
<span class="feat-icon-label">City</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
</div>
<span class="feat-icon-label">IoT</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
</div>
<span class="feat-icon-label">AI Chat</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
</div>
<span class="feat-icon-label">Market</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
</div>
<span class="feat-icon-label">ODK</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>
</div>
<span class="feat-icon-label">Alertes</span>
</div>
</div>
<div class="onboarding-actions">
<button class="btn btn-white">Commencer</button>
<button class="btn btn-ghost-white">Se connecter</button>
</div>
<div class="page-label">01 — Onboarding / Splash · Blue v2</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 01 Onboarding</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.onboarding-bg {
width: 100%; height: 100%;
background: linear-gradient(160deg, #051C38 0%, #0D47A1 40%, #00838F 100%);
display: flex; flex-direction: column;
align-items: center; justify-content: center;
padding: 32px; text-align: center;
position: relative; overflow: hidden;
}
.onboarding-bg::before {
content: '';
position: absolute;
width: 400px; height: 400px;
border-radius: 50%;
background: rgba(255,255,255,0.04);
top: -100px; right: -100px;
}
.onboarding-bg::after {
content: '';
position: absolute;
width: 300px; height: 300px;
border-radius: 50%;
background: rgba(255,255,255,0.03);
bottom: -50px; left: -80px;
}
.wave-decoration {
position: absolute; bottom: 0; left: 0; right: 0;
height: 120px;
overflow: hidden;
}
.wave-decoration svg {
width: 100%; height: 100%;
}
.onboarding-logo {
width: 100px; height: 100px;
background: rgba(255,255,255,0.12);
border-radius: 28px;
display: flex; align-items: center; justify-content: center;
margin-bottom: 24px;
backdrop-filter: blur(12px);
position: relative; z-index: 1;
border: 1px solid rgba(255,255,255,0.15);
}
.onboarding-title {
font-size: var(--text-3xl);
font-weight: var(--weight-bold);
color: white;
margin-bottom: 6px;
position: relative; z-index: 1;
}
.onboarding-subtitle {
font-size: var(--text-base);
color: rgba(255,255,255,0.7);
margin-bottom: 8px;
position: relative; z-index: 1;
}
.onboarding-tagline {
font-size: var(--text-sm);
color: rgba(255,255,255,0.5);
margin-bottom: 32px;
position: relative; z-index: 1;
}
.onboarding-actions {
width: 100%;
max-width: 300px;
display: flex; flex-direction: column;
gap: 12px; position: relative; z-index: 1;
}
.onboarding-actions .btn { width: 100%; }
.btn-white {
background: white;
color: var(--primary-600);
font-weight: 700;
}
.btn-white:hover { background: var(--primary-50); }
.btn-ghost-white {
background: rgba(255,255,255,0.1);
color: white;
border: 2px solid rgba(255,255,255,0.25);
backdrop-filter: blur(4px);
}
.btn-ghost-white:hover { background: rgba(255,255,255,0.2); }
.lang-selector {
display: flex; gap: 8px; margin-bottom: 28px;
position: relative; z-index: 1;
flex-wrap: wrap; justify-content: center;
}
.lang-pill {
padding: 6px 16px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.15);
color: white;
font-size: var(--text-sm);
font-weight: var(--weight-medium);
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
backdrop-filter: blur(4px);
}
.lang-pill.active {
background: white;
color: var(--primary-600);
border-color: white;
}
.feature-icons {
display: flex; gap: 16px; margin-bottom: 32px;
position: relative; z-index: 1;
flex-wrap: wrap; justify-content: center;
}
.feat-icon {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
}
.feat-icon-circle {
width: 48px; height: 48px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.12);
display: flex; align-items: center; justify-content: center;
backdrop-filter: blur(4px);
border: 1px solid rgba(255,255,255,0.1);
}
.feat-icon-label {
font-size: 10px;
color: rgba(255,255,255,0.6);
}
.page-label {
position: absolute; bottom: 20px;
left: 0; right: 0;
text-align: center;
font-size: var(--text-xs);
color: rgba(255,255,255,0.3);
}
.version-badge {
position: absolute; top: 50px; right: 16px;
background: rgba(255,255,255,0.15);
color: rgba(255,255,255,0.7);
font-size: 10px;
padding: 4px 10px;
border-radius: var(--radius-full);
font-weight: 600;
z-index: 2;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="version-badge">v2.0</div>
<div class="onboarding-bg">
<div class="onboarding-logo">
<svg width="52" height="52" viewBox="0 0 52 52" fill="none">
<rect x="8" y="22" width="9" height="22" rx="3" fill="white" opacity="0.9"/>
<rect x="21.5" y="15" width="9" height="29" rx="3" fill="white" opacity="0.7"/>
<rect x="35" y="8" width="9" height="36" rx="3" fill="white" opacity="0.85"/>
<circle cx="26" cy="5" r="4.5" fill="white"/>
</svg>
</div>
<div class="onboarding-title">Smart App City</div>
<div class="onboarding-subtitle">Martinique Digital Twin</div>
<div class="onboarding-tagline">Votre ville intelligente · Connectée · Durable</div>
<div class="lang-selector">
<div class="lang-pill active">🇫🇷 FR</div>
<div class="lang-pill">🇬🇧 EN</div>
<div class="lang-pill">🇪🇸 ES</div>
<div class="lang-pill">🇩🇪 DE</div>
</div>
<div class="feature-icons">
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
</div>
<span class="feat-icon-label">City</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
</div>
<span class="feat-icon-label">IoT</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
</div>
<span class="feat-icon-label">AI Chat</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
</div>
<span class="feat-icon-label">Marché</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><rect x="1" y="4" width="22" height="16" rx="3"/><path d="M1 10h22"/><circle cx="12" cy="15" r="1.5"/></svg>
</div>
<span class="feat-icon-label">Wallet</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/></svg>
</div>
<span class="feat-icon-label">Services</span>
</div>
</div>
<div class="onboarding-actions">
<button class="btn btn-white">Commencer</button>
<button class="btn btn-ghost-white">Se connecter</button>
</div>
<div class="page-label">01 — Onboarding v2 / Blue</div>
<!-- Wave decoration -->
<div class="wave-decoration">
<svg viewBox="0 0 390 120" preserveAspectRatio="none">
<path d="M0 60 Q60 20 130 50 Q200 80 260 40 Q320 10 390 50 L390 120 L0 120Z" fill="rgba(255,255,255,0.04)"/>
<path d="M0 80 Q80 50 150 70 Q220 90 300 60 Q350 45 390 65 L390 120 L0 120Z" fill="rgba(255,255,255,0.03)"/>
</svg>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,186 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 01 Onboarding</title>
<link rel="stylesheet" href="shared.css">
<style>
.onboarding-bg {
width: 100%; height: 100%;
background: linear-gradient(160deg, #1B5E20 0%, #00838F 50%, #00ACC1 100%);
display: flex; flex-direction: column;
align-items: center; justify-content: center;
padding: 32px; text-align: center;
position: relative; overflow: hidden;
}
.onboarding-bg::before {
content: '';
position: absolute;
width: 400px; height: 400px;
border-radius: 50%;
background: rgba(255,255,255,0.05);
top: -100px; right: -100px;
}
.onboarding-bg::after {
content: '';
position: absolute;
width: 300px; height: 300px;
border-radius: 50%;
background: rgba(255,255,255,0.03);
bottom: -50px; left: -80px;
}
.onboarding-logo {
width: 100px; height: 100px;
background: rgba(255,255,255,0.15);
border-radius: 24px;
display: flex; align-items: center; justify-content: center;
margin-bottom: 24px;
backdrop-filter: blur(10px);
position: relative; z-index: 1;
}
.onboarding-title {
font-size: var(--text-3xl);
font-weight: var(--weight-bold);
color: white;
margin-bottom: 8px;
position: relative; z-index: 1;
}
.onboarding-subtitle {
font-size: var(--text-base);
color: rgba(255,255,255,0.8);
margin-bottom: 48px;
position: relative; z-index: 1;
}
.onboarding-actions {
width: 100%;
max-width: 300px;
display: flex; flex-direction: column;
gap: 12px; position: relative; z-index: 1;
}
.onboarding-actions .btn { width: 100%; }
.btn-white {
background: white;
color: var(--primary-600);
}
.btn-white:hover { background: var(--neutral-100); }
.btn-ghost-white {
background: rgba(255,255,255,0.15);
color: white;
border: 2px solid rgba(255,255,255,0.3);
backdrop-filter: blur(4px);
}
.btn-ghost-white:hover { background: rgba(255,255,255,0.25); }
.lang-selector {
display: flex; gap: 8px; margin-bottom: 32px;
position: relative; z-index: 1;
flex-wrap: wrap; justify-content: center;
}
.lang-pill {
padding: 6px 16px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.2);
color: white;
font-size: var(--text-sm);
font-weight: var(--weight-medium);
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
backdrop-filter: blur(4px);
}
.lang-pill.active {
background: white;
color: var(--primary-600);
border-color: white;
}
.page-label {
position: absolute; bottom: 20px;
left: 0; right: 0;
text-align: center;
font-size: var(--text-xs);
color: rgba(255,255,255,0.4);
}
.feature-icons {
display: flex; gap: 24px; margin-bottom: 40px;
position: relative; z-index: 1;
}
.feat-icon {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
}
.feat-icon-circle {
width: 48px; height: 48px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.15);
display: flex; align-items: center; justify-content: center;
backdrop-filter: blur(4px);
}
.feat-icon-label {
font-size: var(--text-xs);
color: rgba(255,255,255,0.7);
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="onboarding-bg">
<div class="onboarding-logo">
<svg width="50" height="50" viewBox="0 0 50 50" fill="none">
<rect x="8" y="20" width="8" height="22" rx="2" fill="white" opacity="0.9"/>
<rect x="21" y="14" width="8" height="28" rx="2" fill="white" opacity="0.7"/>
<rect x="34" y="8" width="8" height="34" rx="2" fill="white" opacity="0.85"/>
<circle cx="25" cy="6" r="4" fill="white"/>
</svg>
</div>
<div class="onboarding-title">Smart App City</div>
<div class="onboarding-subtitle">Martinique Digital Twin</div>
<div class="lang-selector">
<div class="lang-pill active">🇫🇷 FR</div>
<div class="lang-pill">🇬🇧 EN</div>
<div class="lang-pill">🇪🇸 ES</div>
<div class="lang-pill">🇩🇪 DE</div>
</div>
<div class="feature-icons">
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
</div>
<span class="feat-icon-label">City</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
</div>
<span class="feat-icon-label">IoT</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
</div>
<span class="feat-icon-label">AI Chat</span>
</div>
<div class="feat-icon">
<div class="feat-icon-circle">
<svg class="icon" viewBox="0 0 24 24" stroke="white"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
</div>
<span class="feat-icon-label">Market</span>
</div>
</div>
<div class="onboarding-actions">
<button class="btn btn-white">Commencer</button>
<button class="btn btn-ghost-white">Se connecter</button>
</div>
<div class="page-label">01 — Onboarding / Splash</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,407 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 02 Home Dashboard (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.dashboard-header {
padding: 16px;
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
color: white;
}
.dashboard-header-top {
display: flex; justify-content: space-between;
align-items: center; margin-bottom: 16px;
}
.greeting { font-size: var(--text-sm); opacity: 0.85; }
.user-name { font-size: var(--text-lg); font-weight: var(--weight-bold); }
.search-bar {
display: flex; align-items: center; gap: 8px;
background: rgba(255,255,255,0.2);
border-radius: var(--radius-full);
padding: 10px 16px;
backdrop-filter: blur(4px);
}
.search-bar input {
background: none; border: none; outline: none;
color: white; font-size: var(--text-sm);
width: 100%;
}
.search-bar input::placeholder { color: rgba(255,255,255,0.6); }
.metrics-row {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 8px; padding: 0 16px;
margin-top: -20px; margin-bottom: 16px;
}
.metric-card {
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: 14px 8px;
text-align: center;
box-shadow: var(--shadow-md);
border: 1px solid var(--neutral-100);
}
.metric-card-value {
font-size: var(--text-xl);
font-weight: var(--weight-bold);
}
.metric-card-label {
font-size: 9px;
color: var(--neutral-500);
margin-top: 2px;
}
.trend-up { color: var(--alert-success); }
.trend-down { color: var(--alert-danger); }
.section-title-row {
display: flex; justify-content: space-between;
align-items: center; padding: 0 16px 12px;
}
.section-title { font-size: var(--text-md); font-weight: var(--weight-bold); }
.see-all { font-size: var(--text-sm); color: var(--primary-500); font-weight: var(--weight-medium); }
.sensor-card {
flex-shrink: 0;
width: 150px;
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: 14px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.sensor-header {
display: flex; justify-content: space-between;
align-items: flex-start; margin-bottom: 10px;
}
.sensor-icon {
width: 36px; height: 36px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 18px;
}
.sensor-value { font-size: var(--text-xl); font-weight: var(--weight-bold); }
.sensor-unit { font-size: var(--text-xs); color: var(--neutral-500); }
.sensor-name { font-size: var(--text-xs); color: var(--neutral-600); margin-top: 4px; }
.sensor-location { font-size: 10px; color: var(--neutral-400); }
.quick-actions {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 12px; padding: 0 16px 16px;
}
.quick-action {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
cursor: pointer;
}
.quick-action-icon {
width: 52px; height: 52px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
color: white; font-size: 22px;
}
.quick-action-label { font-size: 10px; color: var(--neutral-600); text-align: center; }
.alert-banner {
margin: 0 16px 12px;
background: rgba(211,47,47,0.08);
border: 1px solid rgba(211,47,47,0.2);
border-radius: var(--radius-lg);
padding: 12px 14px;
display: flex; gap: 10px; align-items: flex-start;
}
.alert-text { font-size: var(--text-sm); color: var(--alert-danger); font-weight: var(--weight-medium); }
.alert-sub { font-size: var(--text-xs); color: var(--neutral-600); }
.live-indicator {
display: flex; align-items: center; gap: 6px;
font-size: var(--text-xs);
color: var(--alert-success);
font-weight: var(--weight-medium);
}
.live-dot {
width: 8px; height: 8px;
background: var(--alert-success);
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.section-padded { padding: 0 16px 12px; }
.weather-widget {
margin: 0 16px 12px;
background: linear-gradient(135deg, #1565C0, #0288D1);
border-radius: var(--radius-xl);
padding: 16px;
color: white;
display: flex; justify-content: space-between; align-items: center;
}
.weather-temp { font-size: var(--text-4xl); font-weight: var(--weight-bold); }
.weather-details { font-size: var(--text-sm); opacity: 0.8; }
.weather-emoji { font-size: 48px; }
.service-shortcuts {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 10px; padding: 0 16px 16px;
}
.service-shortcut {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
cursor: pointer;
}
.service-shortcut-icon {
width: 48px; height: 48px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
font-size: 20px;
}
.service-shortcut-label { font-size: 9px; color: var(--neutral-600); text-align: center; line-height: 1.2; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="dashboard-header">
<div class="dashboard-header-top">
<div>
<div class="greeting">Bonjour 👋</div>
<div class="user-name">Eric F.</div>
</div>
<div style="display:flex;gap:12px;align-items:center;">
<div class="live-indicator">
<div class="live-dot"></div>
EN DIRECT
</div>
<div style="position:relative;">
<svg class="icon-lg" viewBox="0 0 24 24"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
<div class="badge" style="position:absolute;top:-4px;right:-4px;">3</div>
</div>
</div>
</div>
<div class="search-bar">
<svg class="icon" viewBox="0 0 24 24" style="color:rgba(255,255,255,0.7)"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" placeholder="Rechercher un capteur, lieu, service...">
</div>
</div>
<!-- Content -->
<div class="content-area" style="background:var(--neutral-50);">
<!-- Metrics -->
<div class="metrics-row">
<div class="metric-card">
<div class="metric-card-value" style="color:var(--primary-500)">60</div>
<div class="metric-card-label">Capteurs actifs</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--ocean-500)">24°</div>
<div class="metric-card-label">Temp. moyenne</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--alert-info)">98%</div>
<div class="metric-card-label">Uptime réseau</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--indigo-500)">12</div>
<div class="metric-card-label">Signalements</div>
</div>
</div>
<!-- Weather Widget -->
<div class="weather-widget">
<div>
<div class="weather-temp">28°</div>
<div class="weather-details">Fort-de-France</div>
<div class="weather-details">💧 65% · 💨 12 km/h</div>
</div>
<div class="weather-emoji"></div>
</div>
<!-- Alert Banner -->
<div class="alert-banner">
<svg class="icon" viewBox="0 0 24 24" style="color:var(--alert-danger);flex-shrink:0;"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
<div>
<div class="alert-text">Qualité air — Fort-de-France</div>
<div class="alert-sub">Indice élevé détecté · Secteur Centre-Ville · Il y a 12 min</div>
</div>
</div>
<!-- Quick Actions -->
<div class="section-padded" style="margin-top:8px;margin-bottom:12px;">
<div class="section-title" style="margin-bottom:12px;">Accès rapide</div>
</div>
<div class="quick-actions" style="padding:0 16px 16px;">
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#1565C0,#42A5F5);">🗺️</div>
<span class="quick-action-label">Carte Live</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#00ACC1,#4DD0E1);">🏪</div>
<span class="quick-action-label">Marché</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#3949AB,#7986CB);">🤖</div>
<span class="quick-action-label">AI Chat</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#00838F,#26C6DA);">📸</div>
<span class="quick-action-label">Signaler</span>
</div>
</div>
<!-- All Services Shortcuts -->
<div class="section-padded" style="margin-bottom:8px;">
<div class="section-title" style="margin-bottom:12px;">Tous les services</div>
</div>
<div class="service-shortcuts" style="padding:0 16px 16px;">
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#E3F2FD;">🌡️</div>
<span class="service-shortcut-label">Météo</span>
</div>
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#E8EAF6;">🚌</div>
<span class="service-shortcut-label">Transport</span>
</div>
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#FFF3E0;"></div>
<span class="service-shortcut-label">Énergie</span>
</div>
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#FCE4EC;">🏥</div>
<span class="service-shortcut-label">Santé</span>
</div>
</div>
<div class="service-shortcuts" style="padding:0 16px 16px;">
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#E0F7FA;">🅿️</div>
<span class="service-shortcut-label">Parking</span>
</div>
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#E8F5E9;">🌳</div>
<span class="service-shortcut-label">Environnement</span>
</div>
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#F3E5F5;">🎉</div>
<span class="service-shortcut-label">Événements</span>
</div>
<div class="service-shortcut">
<div class="service-shortcut-icon" style="background:#FFF9C4;">📊</div>
<span class="service-shortcut-label">Statistiques</span>
</div>
</div>
<!-- Sensors scroll -->
<div class="section-title-row">
<div class="section-title">Capteurs en direct 📍</div>
<div class="see-all">Voir tout →</div>
</div>
<div class="scroll-row" style="padding-bottom:16px;">
<div style="width:16px;flex-shrink:0;"></div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E3F2FD;color:#1565C0;">🌡️</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">24.3°</div>
<div class="sensor-unit">Température</div>
<div class="sensor-name">Temp-001</div>
<div class="sensor-location">Fort-de-France · Centre</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E0F7FA;color:#00838F;">💨</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">42</div>
<div class="sensor-unit">AQI (bon)</div>
<div class="sensor-name">AirQ-012</div>
<div class="sensor-location">Pointe des Nègres</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E8EAF6;color:#3949AB;"></div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">3.2</div>
<div class="sensor-unit">kW/h</div>
<div class="sensor-name">Ener-005</div>
<div class="sensor-location">Schœlcher · Zone Industrielle</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#FCE4EC;color:#C62828;">💧</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">65%</div>
<div class="sensor-unit">Humidité</div>
<div class="sensor-name">Hum-003</div>
<div class="sensor-location">Schœlcher · Campus</div>
</div>
<div style="width:16px;flex-shrink:0;"></div>
</div>
<!-- Map Mini Preview -->
<div class="section-title-row">
<div class="section-title">Aperçu carte</div>
<div class="see-all">Ouvrir →</div>
</div>
<div class="card" style="margin:0 16px 16px;height:160px;background:linear-gradient(135deg,#E3F2FD,#E0F7FA);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;">
<svg width="100%" height="100%" viewBox="0 0 320 160" style="position:absolute;top:0;left:0;">
<path d="M80 130 Q100 90 140 75 Q180 55 220 60 Q260 65 280 90 Q300 115 290 135 Q270 150 230 148 Q190 150 150 140 Q110 145 80 130Z" fill="rgba(21,101,192,0.15)" stroke="rgba(21,101,192,0.3)" stroke-width="2"/>
<circle cx="150" cy="95" r="6" fill="#1565C0" opacity="0.8"><animate attributeName="r" values="6;10;6" dur="2s" repeatCount="indefinite"/></circle>
<circle cx="230" cy="105" r="6" fill="#00ACC1" opacity="0.8"><animate attributeName="r" values="6;10;6" dur="2.5s" repeatCount="indefinite"/></circle>
<circle cx="190" cy="120" r="5" fill="#3949AB" opacity="0.8"><animate attributeName="r" values="5;9;5" dur="1.8s" repeatCount="indefinite"/></circle>
<text x="148" y="85" font-size="8" fill="#0D47A1" text-anchor="middle" font-weight="600">FDF</text>
<text x="228" y="128" font-size="7" fill="#666" text-anchor="middle">Schœlcher</text>
</svg>
<div style="position:absolute;bottom:10px;right:10px;background:white;border-radius:8px;padding:6px 12px;font-size:11px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,0.1);">
🗺️ 4 zones actives
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div class="page-label" style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">02 — Home Dashboard · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,389 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 02 Home Dashboard</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.dashboard-header {
padding: 16px;
background: linear-gradient(135deg, var(--primary-600), var(--ocean-500));
color: white;
}
.dashboard-header-top {
display: flex; justify-content: space-between;
align-items: center; margin-bottom: 16px;
}
.greeting { font-size: var(--text-sm); opacity: 0.85; }
.user-name { font-size: var(--text-lg); font-weight: var(--weight-bold); }
.search-bar {
display: flex; align-items: center; gap: 8px;
background: rgba(255,255,255,0.2);
border-radius: var(--radius-full);
padding: 10px 16px;
backdrop-filter: blur(4px);
}
.search-bar input {
background: none; border: none; outline: none;
color: white; font-size: var(--text-sm); width: 100%;
}
.search-bar input::placeholder { color: rgba(255,255,255,0.6); }
.metrics-row {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 8px; padding: 0 16px;
margin-top: -20px; margin-bottom: 16px;
}
.metric-card {
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: 12px 8px;
text-align: center;
box-shadow: var(--shadow-md);
border: 1px solid var(--neutral-100);
}
.metric-card-value {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
}
.metric-card-label {
font-size: 9px;
color: var(--neutral-500);
margin-top: 2px;
}
.section-title-row {
display: flex; justify-content: space-between;
align-items: center; padding: 0 16px 12px;
}
.section-title { font-size: var(--text-md); font-weight: var(--weight-bold); }
.see-all { font-size: var(--text-sm); color: var(--primary-500); font-weight: var(--weight-medium); }
.sensor-card {
flex-shrink: 0; width: 155px;
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: 14px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.sensor-header {
display: flex; justify-content: space-between;
align-items: flex-start; margin-bottom: 10px;
}
.sensor-icon {
width: 36px; height: 36px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 18px;
}
.sensor-value { font-size: var(--text-xl); font-weight: var(--weight-bold); }
.sensor-unit { font-size: var(--text-xs); color: var(--neutral-500); }
.sensor-name { font-size: var(--text-xs); color: var(--neutral-600); margin-top: 4px; }
.sensor-location { font-size: 10px; color: var(--neutral-400); }
.quick-actions {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 10px; padding: 0 16px 16px;
}
.quick-action {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
cursor: pointer;
}
.quick-action-icon {
width: 52px; height: 52px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
color: white; font-size: 22px;
}
.quick-action-label { font-size: 10px; color: var(--neutral-600); text-align: center; }
.alert-banner {
margin: 0 16px 12px;
background: rgba(211,47,47,0.08);
border: 1px solid rgba(211,47,47,0.2);
border-radius: var(--radius-lg);
padding: 12px 14px;
display: flex; gap: 10px; align-items: flex-start;
}
.alert-text { font-size: var(--text-sm); color: var(--alert-danger); font-weight: var(--weight-medium); }
.alert-sub { font-size: var(--text-xs); color: var(--neutral-600); }
.live-indicator {
display: flex; align-items: center; gap: 6px;
font-size: var(--text-xs);
color: var(--alert-success);
font-weight: var(--weight-medium);
}
.live-dot {
width: 8px; height: 8px;
background: var(--alert-success);
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.section-padded { padding: 0 16px 12px; }
/* Service cards for new services */
.service-quick-card {
flex-shrink: 0;
width: 140px;
border-radius: var(--radius-lg);
padding: 14px;
color: white;
position: relative;
overflow: hidden;
}
.service-quick-card .svc-icon { font-size: 28px; margin-bottom: 8px; }
.service-quick-card .svc-name { font-size: var(--text-sm); font-weight: var(--weight-bold); }
.service-quick-card .svc-desc { font-size: 10px; opacity: 0.8; margin-top: 2px; }
.service-quick-card .svc-badge {
position: absolute; top: 10px; right: 10px;
background: rgba(255,255,255,0.2);
padding: 2px 8px;
border-radius: var(--radius-full);
font-size: 9px; font-weight: 600;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
<svg width="20" height="10" viewBox="0 0 20 10"><rect x="0" y="0" width="17" height="10" rx="2" stroke="#333" stroke-width="1" fill="none"/><rect x="18" y="3" width="2" height="4" rx="1" fill="#333"/><rect x="1.5" y="1.5" width="10" height="7" rx="1" fill="#333"/></svg>
</div>
</div>
<!-- Header -->
<div class="dashboard-header">
<div class="dashboard-header-top">
<div>
<div class="greeting">Bonjour 👋</div>
<div class="user-name">Eric F.</div>
</div>
<div style="display:flex;gap:12px;align-items:center;">
<div class="live-indicator">
<div class="live-dot"></div>
EN DIRECT
</div>
<div style="position:relative;">
<svg class="icon-lg" viewBox="0 0 24 24"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
<div class="badge" style="position:absolute;top:-4px;right:-4px;">3</div>
</div>
</div>
</div>
<div class="search-bar">
<svg class="icon" viewBox="0 0 24 24" style="color:rgba(255,255,255,0.7)"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" placeholder="Rechercher un capteur, lieu, service...">
<svg class="icon" viewBox="0 0 24 24" style="color:rgba(255,255,255,0.5)"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="16" y2="12"/><line x1="4" y1="18" x2="12" y2="18"/></svg>
</div>
</div>
<!-- Content -->
<div class="content-area" style="background:var(--neutral-50);">
<!-- Metrics -->
<div class="metrics-row">
<div class="metric-card">
<div class="metric-card-value" style="color:var(--primary-500)">60</div>
<div class="metric-card-label">Capteurs</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--ocean-500)">24°</div>
<div class="metric-card-label">Temp.</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--alert-success)">98%</div>
<div class="metric-card-label">Uptime</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--indigo-500)">42</div>
<div class="metric-card-label">AQI</div>
</div>
</div>
<!-- Alert Banner -->
<div class="alert-banner">
<svg class="icon" viewBox="0 0 24 24" style="color:var(--alert-danger);flex-shrink:0;"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
<div>
<div class="alert-text">Qualité air — Fort-de-France</div>
<div class="alert-sub">Indice élevé détecté · Secteur Centre-Ville · Il y a 12 min</div>
</div>
</div>
<!-- Quick Actions — expanded to 6 -->
<div class="section-padded" style="margin-top:8px;margin-bottom:12px;">
<div class="section-title" style="margin-bottom:12px;">Accès rapide</div>
</div>
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;padding:0 16px 16px;">
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#1565C0,#42A5F5);">🗺️</div>
<span class="quick-action-label">Carte Live</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#00ACC1,#4DD0E1);">🏪</div>
<span class="quick-action-label">Marché</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#3949AB,#7986CB);">🤖</div>
<span class="quick-action-label">AI Chat</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#F57C00,#FFAB40);">📸</div>
<span class="quick-action-label">Signaler</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#00838F,#26C6DA);">🚌</div>
<span class="quick-action-label">Transport</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#2E7D32,#66BB6A);"></div>
<span class="quick-action-label">Énergie</span>
</div>
</div>
<!-- New: Services rapides -->
<div class="section-title-row">
<div class="section-title">Services de la ville</div>
<div class="see-all">Tout voir →</div>
</div>
<div class="scroll-row" style="padding-bottom:16px;">
<div style="width:16px;flex-shrink:0;"></div>
<div class="service-quick-card" style="background:linear-gradient(135deg,#1565C0,#0D47A1);">
<div class="svc-badge">DPI</div>
<div class="svc-icon">💳</div>
<div class="svc-name">Wallet</div>
<div class="svc-desc">Paiements DPI</div>
</div>
<div class="service-quick-card" style="background:linear-gradient(135deg,#00838F,#006064);">
<div class="svc-badge">Temps réel</div>
<div class="svc-icon">🚌</div>
<div class="svc-name">Bus Ligne A1</div>
<div class="svc-desc">3 min · FDF</div>
</div>
<div class="service-quick-card" style="background:linear-gradient(135deg,#2E7D32,#1B5E20);">
<div class="svc-badge">IoT</div>
<div class="svc-icon"></div>
<div class="svc-name">Énergie</div>
<div class="svc-desc">Mon quartier</div>
</div>
<div class="service-quick-card" style="background:linear-gradient(135deg,#C62828,#B71C1C);">
<div class="svc-badge">Urgence</div>
<div class="svc-icon">🏥</div>
<div class="svc-name">Santé</div>
<div class="svc-desc">Pharmacies</div>
</div>
<div style="width:16px;flex-shrink:0;"></div>
</div>
<!-- Sensors scroll -->
<div class="section-title-row">
<div class="section-title">Capteurs en direct 📍</div>
<div class="see-all">Voir tout →</div>
</div>
<div class="scroll-row" style="padding-bottom:16px;">
<div style="width:16px;flex-shrink:0;"></div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E3F2FD;color:#1565C0;">🌡️</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">24.3°</div>
<div class="sensor-unit">Température</div>
<div class="sensor-name">Temp-001</div>
<div class="sensor-location">Fort-de-France · Centre</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E0F7FA;color:#00838F;">💨</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">42</div>
<div class="sensor-unit">AQI (bon)</div>
<div class="sensor-name">AirQ-012</div>
<div class="sensor-location">Pointe des Nègres</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#FFF3E0;color:#E65100;">💡</div>
<div class="online-dot" style="background:var(--alert-warning)"></div>
</div>
<div class="sensor-value">87%</div>
<div class="sensor-unit">Luminosité</div>
<div class="sensor-name">Lux-008</div>
<div class="sensor-location">Boulevard Général de Gaulle</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E8EAF6;color:#3949AB;">💧</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">65%</div>
<div class="sensor-unit">Humidité</div>
<div class="sensor-name">Hum-003</div>
<div class="sensor-location">Schœlcher · Campus</div>
</div>
<div style="width:16px;flex-shrink:0;"></div>
</div>
<!-- Map Mini Preview -->
<div class="section-title-row">
<div class="section-title">Aperçu carte</div>
<div class="see-all">Ouvrir →</div>
</div>
<div class="card" style="margin:0 16px 16px;height:150px;background:linear-gradient(135deg,#E3F2FD,#E0F7FA);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;">
<svg width="100%" height="100%" viewBox="0 0 320 150" style="position:absolute;top:0;left:0;">
<path d="M80 120 Q100 80 140 65 Q180 45 220 50 Q260 55 280 80 Q300 105 290 125 Q270 140 230 138 Q190 140 150 130 Q110 135 80 120Z" fill="rgba(21,101,192,0.15)" stroke="rgba(21,101,192,0.3)" stroke-width="2"/>
<circle cx="150" cy="85" r="6" fill="#1565C0" opacity="0.8"><animate attributeName="r" values="6;10;6" dur="2s" repeatCount="indefinite"/></circle>
<circle cx="230" cy="95" r="6" fill="#00ACC1" opacity="0.8"><animate attributeName="r" values="6;10;6" dur="2.5s" repeatCount="indefinite"/></circle>
<circle cx="190" cy="110" r="5" fill="#3949AB" opacity="0.8"><animate attributeName="r" values="5;9;5" dur="1.8s" repeatCount="indefinite"/></circle>
<circle cx="120" cy="105" r="5" fill="#F57C00" opacity="0.8"><animate attributeName="r" values="5;9;5" dur="2.2s" repeatCount="indefinite"/></circle>
<text x="148" y="75" font-size="8" fill="#0D47A1" text-anchor="middle" font-weight="600">FDF</text>
<text x="228" y="118" font-size="7" fill="#666" text-anchor="middle">Schœlcher</text>
</svg>
<div style="position:absolute;bottom:10px;right:10px;background:white;border-radius:8px;padding:6px 12px;font-size:11px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,0.1);">
🗺️ 4 zones actives
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">02 — Home Dashboard v2 / Blue</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,333 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 02 Home Dashboard</title>
<link rel="stylesheet" href="shared.css">
<style>
.dashboard-header {
padding: 16px;
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
color: white;
}
.dashboard-header-top {
display: flex; justify-content: space-between;
align-items: center; margin-bottom: 16px;
}
.greeting { font-size: var(--text-sm); opacity: 0.85; }
.user-name { font-size: var(--text-lg); font-weight: var(--weight-bold); }
.search-bar {
display: flex; align-items: center; gap: 8px;
background: rgba(255,255,255,0.2);
border-radius: var(--radius-full);
padding: 10px 16px;
backdrop-filter: blur(4px);
}
.search-bar input {
background: none; border: none; outline: none;
color: white; font-size: var(--text-sm);
width: 100%;
}
.search-bar input::placeholder { color: rgba(255,255,255,0.6); }
.metrics-row {
display: grid; grid-template-columns: repeat(3, 1fr);
gap: 8px; padding: 0 16px;
margin-top: -20px; margin-bottom: 16px;
}
.metric-card {
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: 14px 10px;
text-align: center;
box-shadow: var(--shadow-md);
border: 1px solid var(--neutral-100);
}
.metric-card-value {
font-size: var(--text-xl);
font-weight: var(--weight-bold);
}
.metric-card-label {
font-size: 10px;
color: var(--neutral-500);
margin-top: 2px;
}
.trend-up { color: var(--alert-success); }
.trend-down { color: var(--alert-danger); }
.section-title-row {
display: flex; justify-content: space-between;
align-items: center; padding: 0 16px 12px;
}
.section-title { font-size: var(--text-md); font-weight: var(--weight-bold); }
.see-all { font-size: var(--text-sm); color: var(--primary-500); font-weight: var(--weight-medium); }
.sensor-card {
flex-shrink: 0;
width: 160px;
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: 14px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.sensor-header {
display: flex; justify-content: space-between;
align-items: flex-start; margin-bottom: 10px;
}
.sensor-icon {
width: 36px; height: 36px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 18px;
}
.sensor-value { font-size: var(--text-xl); font-weight: var(--weight-bold); }
.sensor-unit { font-size: var(--text-xs); color: var(--neutral-500); }
.sensor-name { font-size: var(--text-xs); color: var(--neutral-600); margin-top: 4px; }
.sensor-location { font-size: 10px; color: var(--neutral-400); }
.quick-actions {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 12px; padding: 0 16px 16px;
}
.quick-action {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
cursor: pointer;
}
.quick-action-icon {
width: 52px; height: 52px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
color: white; font-size: 22px;
}
.quick-action-label { font-size: 10px; color: var(--neutral-600); text-align: center; }
.alert-banner {
margin: 0 16px 12px;
background: rgba(211,47,47,0.08);
border: 1px solid rgba(211,47,47,0.2);
border-radius: var(--radius-lg);
padding: 12px 14px;
display: flex; gap: 10px; align-items: flex-start;
}
.alert-text { font-size: var(--text-sm); color: var(--alert-danger); font-weight: var(--weight-medium); }
.alert-sub { font-size: var(--text-xs); color: var(--neutral-600); }
.live-indicator {
display: flex; align-items: center; gap: 6px;
font-size: var(--text-xs);
color: var(--alert-success);
font-weight: var(--weight-medium);
}
.live-dot {
width: 8px; height: 8px;
background: var(--alert-success);
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.section-padded { padding: 0 16px 12px; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
<svg width="20" height="10" viewBox="0 0 20 10"><rect x="0" y="0" width="17" height="10" rx="2" stroke="#333" stroke-width="1" fill="none"/><rect x="18" y="3" width="2" height="4" rx="1" fill="#333"/><rect x="1.5" y="1.5" width="10" height="7" rx="1" fill="#333"/></svg>
</div>
</div>
<!-- Header -->
<div class="dashboard-header">
<div class="dashboard-header-top">
<div>
<div class="greeting">Bonjour 👋</div>
<div class="user-name">Eric F.</div>
</div>
<div style="display:flex;gap:12px;align-items:center;">
<div class="live-indicator">
<div class="live-dot"></div>
EN DIRECT
</div>
<div style="position:relative;">
<svg class="icon-lg" viewBox="0 0 24 24"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
<div class="badge" style="position:absolute;top:-4px;right:-4px;">3</div>
</div>
</div>
</div>
<div class="search-bar">
<svg class="icon" viewBox="0 0 24 24" style="color:rgba(255,255,255,0.7)"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" placeholder="Rechercher un capteur, lieu, service...">
<svg class="icon" viewBox="0 0 24 24" style="color:rgba(255,255,255,0.5)"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="16" y2="12"/><line x1="4" y1="18" x2="12" y2="18"/></svg>
</div>
</div>
<!-- Content -->
<div class="content-area" style="background:var(--neutral-50);">
<!-- Metrics -->
<div class="metrics-row">
<div class="metric-card">
<div class="metric-card-value" style="color:var(--primary-500)">60</div>
<div class="metric-card-label">Capteurs actifs</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--ocean-500)">24°</div>
<div class="metric-card-label">Temp. moyenne</div>
</div>
<div class="metric-card">
<div class="metric-card-value" style="color:var(--alert-success)">98%</div>
<div class="metric-card-label">Uptime réseau</div>
</div>
</div>
<!-- Alert Banner -->
<div class="alert-banner">
<svg class="icon" viewBox="0 0 24 24" style="color:var(--alert-danger);flex-shrink:0;"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
<div>
<div class="alert-text">Qualité air — Fort-de-France</div>
<div class="alert-sub">Indice élevé détecté · Secteur Centre-Ville · Il y a 12 min</div>
</div>
</div>
<!-- Quick Actions -->
<div class="section-padded" style="margin-top:8px;margin-bottom:12px;">
<div class="section-title" style="margin-bottom:12px;">Accès rapide</div>
</div>
<div class="quick-actions" style="padding:0 16px 16px;">
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#2E7D32,#66BB6A);">🗺️</div>
<span class="quick-action-label">Carte Live</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#00ACC1,#4DD0E1);">🏪</div>
<span class="quick-action-label">Marché</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#7C4DFF,#B388FF);">🤖</div>
<span class="quick-action-label">AI Chat</span>
</div>
<div class="quick-action">
<div class="quick-action-icon" style="background:linear-gradient(135deg,#FF6D00,#FFAB40);">📸</div>
<span class="quick-action-label">Signaler</span>
</div>
</div>
<!-- Sensors scroll -->
<div class="section-title-row">
<div class="section-title">Capteurs en direct 📍</div>
<div class="see-all">Voir tout →</div>
</div>
<div class="scroll-row" style="padding-bottom:16px;">
<div style="width:16px;flex-shrink:0;"></div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E3F2FD;color:#1565C0;">🌡️</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">24.3°</div>
<div class="sensor-unit">Température</div>
<div class="sensor-name">Temp-001</div>
<div class="sensor-location">Fort-de-France · Centre</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#E8F5E9;color:#2E7D32;">💨</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">42</div>
<div class="sensor-unit">AQI (bon)</div>
<div class="sensor-name">AirQ-012</div>
<div class="sensor-location">Pointe des Nègres</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#FFF3E0;color:#E65100;">💡</div>
<div class="online-dot" style="background:var(--alert-warning)"></div>
</div>
<div class="sensor-value">87%</div>
<div class="sensor-unit">Luminosité</div>
<div class="sensor-name">Lux-008</div>
<div class="sensor-location">Boulevard Général de Gaulle</div>
</div>
<div class="sensor-card">
<div class="sensor-header">
<div class="sensor-icon" style="background:#FCE4EC;color:#C62828;">💧</div>
<div class="online-dot"></div>
</div>
<div class="sensor-value">65%</div>
<div class="sensor-unit">Humidité</div>
<div class="sensor-name">Hum-003</div>
<div class="sensor-location">Schœlcher · Campus</div>
</div>
<div style="width:16px;flex-shrink:0;"></div>
</div>
<!-- Map Mini Preview -->
<div class="section-title-row">
<div class="section-title">Aperçu carte</div>
<div class="see-all">Ouvrir →</div>
</div>
<div class="card" style="margin:0 16px 16px;height:160px;background:linear-gradient(135deg,#E8F5E9,#E0F7FA);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;">
<svg width="100%" height="100%" viewBox="0 0 320 160" style="position:absolute;top:0;left:0;">
<!-- Simplified Martinique outline -->
<path d="M80 130 Q100 90 140 75 Q180 55 220 60 Q260 65 280 90 Q300 115 290 135 Q270 150 230 148 Q190 150 150 140 Q110 145 80 130Z" fill="rgba(46,125,50,0.2)" stroke="rgba(46,125,50,0.4)" stroke-width="2"/>
<!-- Sensor dots -->
<circle cx="150" cy="95" r="6" fill="#2E7D32" opacity="0.8"><animate attributeName="r" values="6;10;6" dur="2s" repeatCount="indefinite"/></circle>
<circle cx="230" cy="105" r="6" fill="#00ACC1" opacity="0.8"><animate attributeName="r" values="6;10;6" dur="2.5s" repeatCount="indefinite"/></circle>
<circle cx="190" cy="120" r="5" fill="#FF6D00" opacity="0.8"><animate attributeName="r" values="5;9;5" dur="1.8s" repeatCount="indefinite"/></circle>
<circle cx="120" cy="115" r="5" fill="#7C4DFF" opacity="0.8"><animate attributeName="r" values="5;9;5" dur="2.2s" repeatCount="indefinite"/></circle>
<!-- Map labels -->
<text x="148" y="85" font-size="8" fill="#1B5E20" text-anchor="middle">FDF</text>
<text x="228" y="128" font-size="7" fill="#666" text-anchor="middle">Schœlcher</text>
</svg>
<div style="position:absolute;bottom:10px;right:10px;background:white;border-radius:8px;padding:6px 12px;font-size:11px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,0.1);">
🗺️ 4 zones actives
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div class="page-label" style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">02 — Home Dashboard</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,197 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 03 Carte Interactive (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.map-container {
position: absolute;
top: 44px; bottom: 80px; left: 0; right: 0;
background: #D4EEF7;
overflow: hidden;
}
.map-toolbar {
position: absolute;
top: 12px; left: 12px; right: 12px;
z-index: 20;
display: flex;
gap: 8px;
align-items: center;
}
.map-search {
flex: 1;
background: white;
border-radius: var(--radius-full);
padding: 10px 16px;
display: flex; align-items: center; gap: 8px;
box-shadow: var(--shadow-md);
font-size: var(--text-sm);
color: var(--neutral-500);
}
.map-fab {
width: 44px; height: 44px;
border-radius: var(--radius-full);
background: white;
box-shadow: var(--shadow-md);
display: flex; align-items: center; justify-content: center;
cursor: pointer;
font-size: 20px;
}
.map-overlay-info {
position: absolute;
bottom: 16px; left: 12px; right: 12px;
z-index: 20;
}
.sensor-marker {
position: absolute;
cursor: pointer;
transition: transform 0.2s;
}
.sensor-marker:hover { transform: scale(1.2); }
.legend {
position: absolute;
top: 70px; right: 12px;
z-index: 20;
background: white;
border-radius: var(--radius-lg);
padding: 12px;
box-shadow: var(--shadow-md);
font-size: var(--text-xs);
}
.legend-item {
display: flex; align-items: center; gap: 6px;
margin-bottom: 6px;
}
.legend-dot {
width: 10px; height: 10px;
border-radius: 50%;
}
.filter-chips {
position: absolute;
top: 68px; left: 12px;
z-index: 20;
display: flex; gap: 6px;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<div class="map-container">
<svg width="100%" height="100%" viewBox="0 0 390 580" preserveAspectRatio="xMidYMid slice">
<rect width="390" height="580" fill="#D4EEF7"/>
<path d="M60 420 Q80 350 130 310 Q170 275 220 265 Q270 255 310 280 Q340 300 350 340 Q360 370 340 400 Q320 430 280 440 Q240 455 200 445 Q160 440 120 435 Q80 435 60 420Z" fill="#BBDEFB" stroke="#64B5F6" stroke-width="1.5"/>
<path d="M120 340 Q140 320 170 315 Q200 310 230 320" stroke="#90CAF9" stroke-width="1" fill="none" stroke-dasharray="4 2"/>
<path d="M100 430 L130 435 L160 430 L190 435 L220 425 L250 430" stroke="white" stroke-width="2.5" fill="none" opacity="0.6"/>
<path d="M130 310 Q150 330 160 360 Q165 380 155 400" stroke="white" stroke-width="2.5" fill="none" opacity="0.7"/>
<path d="M220 265 Q230 290 235 320 Q238 350 240 380" stroke="white" stroke-width="2.5" fill="none" opacity="0.7"/>
<text x="155" y="295" font-size="10" fill="#0D47A1" font-weight="600" text-anchor="middle">Fort-de-France</text>
<text x="260" y="320" font-size="9" fill="#1565C0" font-weight="500" text-anchor="middle">Schœlcher</text>
<text x="120" y="370" font-size="8" fill="#1976D2" text-anchor="middle">Lamentin</text>
</svg>
<!-- Sensor markers -->
<div style="position:absolute;top:35%;left:38%;z-index:10;">
<div style="width:14px;height:14px;background:#1565C0;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);position:relative;">
<div style="position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#1565C0;color:white;font-size:9px;padding:3px 8px;border-radius:6px;white-space:nowrap;font-weight:600;">🌡️ 24.3°</div>
</div>
</div>
<div style="position:absolute;top:42%;left:58%;z-index:10;">
<div style="width:14px;height:14px;background:#00ACC1;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:50%;left:45%;z-index:10;">
<div style="width:14px;height:14px;background:#3949AB;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:38%;left:30%;z-index:10;">
<div style="width:14px;height:14px;background:#00838F;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:55%;left:62%;z-index:10;">
<div style="width:12px;height:12px;background:#D32F2F;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<!-- User location -->
<div style="position:absolute;top:44%;left:42%;z-index:15;">
<div style="width:20px;height:20px;background:#1565C0;border-radius:50%;border:3px solid white;box-shadow:0 0 0 4px rgba(21,101,192,0.2), 0 2px 8px rgba(0,0,0,0.3);"></div>
</div>
<!-- Toolbar -->
<div class="map-toolbar">
<div class="map-search">
<svg class="icon-sm" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Rechercher un lieu...
</div>
<div class="map-fab">📍</div>
<div class="map-fab">🔄</div>
</div>
<!-- Filter chips -->
<div class="filter-chips">
<div class="chip" style="background:var(--primary-500);color:white;border:none;">Tous</div>
<div class="chip">🌡️ Temp</div>
<div class="chip">💨 Air</div>
<div class="chip">💡 Lumière</div>
</div>
<!-- Legend -->
<div class="legend">
<div style="font-weight:600;margin-bottom:8px;font-size:11px;">Légende</div>
<div class="legend-item"><div class="legend-dot" style="background:#1565C0"></div> Température</div>
<div class="legend-item"><div class="legend-dot" style="background:#00ACC1"></div> Qualité air</div>
<div class="legend-item"><div class="legend-dot" style="background:#3949AB"></div> Énergie</div>
<div class="legend-item"><div class="legend-dot" style="background:#00838F"></div> Humidité</div>
<div class="legend-item"><div class="legend-dot" style="background:#D32F2F"></div> Alerte</div>
</div>
<!-- Bottom info card -->
<div class="map-overlay-info">
<div class="card" style="padding:14px;">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div>
<div style="font-weight:700;font-size:var(--text-base);">Capteur sélectionné</div>
<div style="font-size:var(--text-sm);color:var(--neutral-500);">Temp-001 · Fort-de-France Centre</div>
</div>
<div style="text-align:right;">
<div style="font-size:var(--text-xl);font-weight:700;color:var(--primary-500);">24.3°C</div>
<div style="font-size:10px;color:var(--alert-success);font-weight:600;">● En ligne</div>
</div>
</div>
<div style="display:flex;gap:8px;margin-top:10px;">
<div style="flex:1;background:var(--neutral-50);border-radius:8px;padding:8px;text-align:center;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--ocean-500);">42%</div>
<div style="font-size:9px;color:var(--neutral-500);">Humidité</div>
</div>
<div style="flex:1;background:var(--neutral-50);border-radius:8px;padding:8px;text-align:center;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--alert-success);">Bon</div>
<div style="font-size:9px;color:var(--neutral-500);">Qualité air</div>
</div>
<div style="flex:1;background:var(--neutral-50);border-radius:8px;padding:8px;text-align:center;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--neutral-700);">12 min</div>
<div style="font-size:9px;color:var(--neutral-500);">Dernière MAJ</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">03 — Carte Interactive · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,237 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 03 Carte Interactive</title>
<link rel="stylesheet" href="shared.css">
<style>
.map-container {
position: absolute;
top: 44px; bottom: 80px; left: 0; right: 0;
background: #E8F5E9;
overflow: hidden;
}
.map-toolbar {
position: absolute;
top: 12px; left: 12px; right: 12px;
z-index: 20;
display: flex;
gap: 8px;
align-items: center;
}
.map-search {
flex: 1;
background: white;
border-radius: var(--radius-full);
padding: 10px 16px;
display: flex; align-items: center; gap: 8px;
box-shadow: var(--shadow-md);
font-size: var(--text-sm);
color: var(--neutral-500);
}
.map-fab {
width: 44px; height: 44px;
border-radius: var(--radius-full);
background: white;
box-shadow: var(--shadow-md);
display: flex; align-items: center; justify-content: center;
cursor: pointer;
font-size: 20px;
}
.map-overlay-info {
position: absolute;
bottom: 16px; left: 12px; right: 12px;
z-index: 20;
}
sensor-marker {
position: absolute;
cursor: pointer;
transition: transform 0.2s;
}
.sensor-marker:hover { transform: scale(1.2); }
.legend {
position: absolute;
top: 70px; right: 12px;
z-index: 20;
background: white;
border-radius: var(--radius-lg);
padding: 12px;
box-shadow: var(--shadow-md);
font-size: var(--text-xs);
}
.legend-item {
display: flex; align-items: center; gap: 6px;
margin-bottom: 6px;
}
.legend-dot {
width: 10px; height: 10px;
border-radius: 50%;
}
.filter-chips {
position: absolute;
top: 68px; left: 12px;
z-index: 20;
display: flex; gap: 6px;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Map -->
<div class="map-container">
<svg width="100%" height="100%" viewBox="0 0 390 580" preserveAspectRatio="xMidYMid slice">
<!-- Ocean -->
<rect width="390" height="580" fill="#D4EEF7"/>
<!-- Martinique island shape -->
<path d="M60 420 Q80 350 130 310 Q170 275 220 265 Q270 255 310 280 Q340 300 350 340 Q360 370 340 400 Q320 430 280 440 Q240 455 200 445 Q160 440 120 435 Q80 435 60 420Z" fill="#C8E6C9" stroke="#81C784" stroke-width="1.5"/>
<!-- Interior details -->
<path d="M120 340 Q140 320 170 315 Q200 310 230 320" stroke="#A5D6A7" stroke-width="1" fill="none" stroke-dasharray="4 2"/>
<path d="M150 380 Q170 365 200 360 Q230 355 255 365" stroke="#A5D6A7" stroke-width="1" fill="none" stroke-dasharray="4 2"/>
<!-- Roads -->
<path d="M130 310 Q150 330 160 360 Q165 380 155 400" stroke="white" stroke-width="2.5" fill="none" opacity="0.7"/>
<path d="M220 265 Q230 290 235 320 Q238 350 240 380" stroke="white" stroke-width="2.5" fill="none" opacity="0.7"/>
<path d="M170 315 Q190 325 210 330 Q230 335 255 340" stroke="white" stroke-width="2" fill="none" opacity="0.5"/>
<path d="M280 290 Q270 310 265 340 Q262 365 260 390" stroke="white" stroke-width="2" fill="none" opacity="0.5"/>
<!-- Zone labels -->
<text x="155" y="295" font-size="10" fill="#2E7D32" font-weight="600" text-anchor="middle">Fort-de-France</text>
<text x="260" y="320" font-size="9" fill="#388E3C" font-weight="500" text-anchor="middle">Schœlcher</text>
<text x="120" y="370" font-size="8" fill="#558B2F" text-anchor="middle">Lamentin</text>
<text x="200" y="420" font-size="8" fill="#558B2F" text-anchor="middle">Ducos</text>
<!-- Parks/green areas -->
<circle cx="180" cy="340" r="15" fill="#A5D6A7" opacity="0.4"/>
<circle cx="250" cy="370" r="12" fill="#A5D6A7" opacity="0.3"/>
</svg>
<!-- Sensor markers on map -->
<div style="position:absolute;top:35%;left:38%;z-index:10;">
<div style="width:14px;height:14px;background:#2E7D32;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);position:relative;">
<div style="position:absolute;top:-30px;left:50%;transform:translateX(-50%);background:#2E7D32;color:white;font-size:9px;padding:3px 8px;border-radius:6px;white-space:nowrap;font-weight:600;">🌡️ 24.3°</div>
</div>
</div>
<div style="position:absolute;top:42%;left:58%;z-index:10;">
<div style="width:14px;height:14px;background:#00ACC1;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:50%;left:45%;z-index:10;">
<div style="width:14px;height:14px;background:#FF6D00;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:38%;left:30%;z-index:10;">
<div style="width:14px;height:14px;background:#7C4DFF;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:55%;left:62%;z-index:10;">
<div style="width:12px;height:12px;background:#D32F2F;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<div style="position:absolute;top:46%;left:52%;z-index:10;">
<div style="width:12px;height:12px;background:#2E7D32;border-radius:50%;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,0.3);"></div>
</div>
<!-- User location -->
<div style="position:absolute;top:44%;left:42%;z-index:15;">
<div style="width:20px;height:20px;background:#1565C0;border-radius:50%;border:3px solid white;box-shadow:0 0 0 4px rgba(21,101,192,0.2), 0 2px 8px rgba(0,0,0,0.3);"></div>
</div>
<!-- Toolbar -->
<div class="map-toolbar">
<div class="map-search">
<svg class="icon-sm" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Rechercher un lieu...
</div>
<div class="map-fab">📍</div>
<div class="map-fab">🔄</div>
</div>
<!-- Filter chips -->
<div class="filter-chips">
<div class="chip" style="background:var(--primary-500);color:white;border:none;">Tous</div>
<div class="chip">🌡️ Temp</div>
<div class="chip">💨 Air</div>
<div class="chip">💡 Lumière</div>
</div>
<!-- Legend -->
<div class="legend">
<div style="font-weight:600;margin-bottom:8px;font-size:11px;">Légende</div>
<div class="legend-item"><div class="legend-dot" style="background:#2E7D32"></div> Température</div>
<div class="legend-item"><div class="legend-dot" style="background:#00ACC1"></div> Qualité air</div>
<div class="legend-item"><div class="legend-dot" style="background:#FF6D00"></div> Luminosité</div>
<div class="legend-item"><div class="legend-dot" style="background:#7C4DFF"></div> Humidité</div>
<div class="legend-item"><div class="legend-dot" style="background:#D32F2F"></div> Alerte</div>
</div>
<!-- Bottom info card -->
<div class="map-overlay-info">
<div class="card" style="padding:14px;">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div>
<div style="font-weight:700;font-size:var(--text-base);">Capteur sélectionné</div>
<div style="font-size:var(--text-sm);color:var(--neutral-500);">Temp-001 · Fort-de-France Centre</div>
</div>
<div style="text-align:right;">
<div style="font-size:var(--text-xl);font-weight:700;color:var(--primary-500);">24.3°C</div>
<div style="font-size:10px;color:var(--alert-success);font-weight:600;">● En ligne</div>
</div>
</div>
<div style="display:flex;gap:8px;margin-top:10px;">
<div style="flex:1;background:var(--neutral-50);border-radius:8px;padding:8px;text-align:center;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--ocean-500);">42%</div>
<div style="font-size:9px;color:var(--neutral-500);">Humidité</div>
</div>
<div style="flex:1;background:var(--neutral-50);border-radius:8px;padding:8px;text-align:center;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--alert-success);">Bon</div>
<div style="font-size:9px;color:var(--neutral-500);">Qualité air</div>
</div>
<div style="flex:1;background:var(--neutral-50);border-radius:8px;padding:8px;text-align:center;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--neutral-700);">12 min</div>
<div style="font-size:9px;color:var(--neutral-500);">Dernière MAJ</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">03 — Carte Interactive</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 04 Marketplace (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.market-header { padding: 16px; background: var(--primary-500); color: white; }
.market-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.search-bar { display: flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.2); border-radius: 20px; padding: 10px 16px; }
.search-bar input { background: none; border: none; outline: none; color: white; font-size: 13px; width: 100%; }
.search-bar input::placeholder { color: rgba(255,255,255,0.6); }
.category-tabs { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 12px 16px; background: var(--primary-500); }
.category-tabs::-webkit-scrollbar { display: none; }
.cat-tab { flex-shrink: 0; padding: 8px 16px; border-radius: 20px; font-size: 13px; font-weight: 500; background: rgba(255,255,255,0.2); color: white; cursor: pointer; white-space: nowrap; }
.cat-tab.active { background: white; color: var(--primary-600); }
.featured-card { background: linear-gradient(135deg, var(--primary-500), var(--ocean-500)); border-radius: 20px; padding: 20px; color: white; margin: 16px; position: relative; overflow: hidden; }
.featured-card::after { content: ''; position: absolute; width: 150px; height: 150px; border-radius: 50%; background: rgba(255,255,255,0.08); top: -40px; right: -30px; }
.featured-tag { display: inline-block; background: rgba(255,255,255,0.2); border-radius: 20px; padding: 4px 10px; font-size: 10px; font-weight: 600; margin-bottom: 8px; }
.featured-title { font-size: 18px; font-weight: 700; margin-bottom: 4px; }
.featured-desc { font-size: 13px; opacity: 0.8; margin-bottom: 12px; }
.product-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding: 0 16px 16px; }
.product-card { background: white; border-radius: 16px; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,0.06); border: 1px solid var(--neutral-100); }
.product-img { height: 100px; display: flex; align-items: center; justify-content: center; font-size: 36px; }
.product-info { padding: 10px; }
.product-name { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
.product-shop { font-size: 11px; color: var(--neutral-500); margin-bottom: 4px; }
.product-meta { display: flex; justify-content: space-between; align-items: center; }
.product-price { font-size: 14px; font-weight: 700; color: var(--primary-500); }
.product-rating { font-size: 11px; color: var(--alert-warning); }
.product-distance { font-size: 10px; color: var(--neutral-400); }
.service-card { display: flex; gap: 12px; background: white; border-radius: 12px; padding: 14px; margin: 0 16px 8px; border: 1px solid var(--neutral-100); }
.service-icon { width: 48px; height: 48px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0; }
.service-info { flex: 1; }
.service-name { font-size: 14px; font-weight: 600; margin-bottom: 2px; }
.service-desc { font-size: 12px; color: var(--neutral-500); margin-bottom: 4px; }
.service-tags { display: flex; gap: 4px; }
.service-tag { font-size: 9px; padding: 2px 8px; border-radius: 12px; background: var(--ocean-50); color: var(--ocean-600); font-weight: 600; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<div class="market-header">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div class="market-title">Marché Local 🏪</div>
<div style="position:relative;">
<svg class="icon" viewBox="0 0 24 24"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
<div class="badge" style="position:absolute;top:-6px;right:-6px;">2</div>
</div>
</div>
<div class="search-bar">
<svg class="icon-sm" viewBox="0 0 24 24" style="color:rgba(255,255,255,0.7)"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input type="text" placeholder="Produits, services, commerces...">
</div>
<div class="category-tabs">
<div class="cat-tab active">🍎 Alimentaire</div>
<div class="cat-tab">🚌 Transport</div>
<div class="cat-tab">🏥 Santé</div>
<div class="cat-tab">⚡ Énergie</div>
<div class="cat-tab">🎭 Culture</div>
<div class="cat-tab">🔧 Services</div>
</div>
</div>
<div class="content-area" style="top:170px;background:var(--neutral-50);">
<div class="featured-card">
<div class="featured-tag">⭐ Marché Local</div>
<div class="featured-title">Marché de Sainte-Marie</div>
<div class="featured-desc">Produits locaux · Producteurs martiniquais · Livraison 2h</div>
<div style="display:flex;gap:8px;">
<button class="btn" style="background:white;color:var(--primary-600);padding:8px 16px;font-size:13px;min-height:36px;">Explorer</button>
<button class="btn" style="background:rgba(255,255,255,0.2);color:white;padding:8px 16px;font-size:13px;min-height:36px;">Infos</button>
</div>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;padding:0 16px 12px;">
<div style="font-size:16px;font-weight:700;">Produits frais 🥭</div>
<div style="font-size:13px;color:var(--primary-500);font-weight:500;">Voir tout →</div>
</div>
<div class="product-grid">
<div class="product-card"><div class="product-img" style="background:linear-gradient(135deg,#FFF3E0,#FFE0B2);">🥭</div><div class="product-info"><div class="product-name">Mangue José</div><div class="product-shop">Bourg de Sainte-Marie</div><div class="product-meta"><div class="product-price">4.50€</div><div class="product-rating">⭐ 4.8</div></div><div class="product-distance">📍 2.3 km</div></div></div>
<div class="product-card"><div class="product-img" style="background:linear-gradient(135deg,#E3F2FD,#BBDEFB);">🍌</div><div class="product-info"><div class="product-name">Banane Plantain</div><div class="product-shop">Habitation Limbé</div><div class="product-meta"><div class="product-price">3.20€</div><div class="product-rating">⭐ 4.6</div></div><div class="product-distance">📍 5.1 km</div></div></div>
<div class="product-card"><div class="product-img" style="background:linear-gradient(135deg,#FCE4EC,#F8BBD0);">🍅</div><div class="product-info"><div class="product-name">Tomates locales</div><div class="product-shop">Jardin du Lamentin</div><div class="product-meta"><div class="product-price">2.80€</div><div class="product-rating">⭐ 4.9</div></div><div class="product-distance">📍 3.7 km</div></div></div>
<div class="product-card"><div class="product-img" style="background:linear-gradient(135deg,#E0F7FA,#B2EBF2);">🐟</div><div class="product-info"><div class="product-name">Poisson frais</div><div class="product-shop">Pêcheur du Carbet</div><div class="product-meta"><div class="product-price">12.00€</div><div class="product-rating">⭐ 4.7</div></div><div class="product-distance">📍 8.2 km</div></div></div>
</div>
<div style="font-size:16px;font-weight:700;padding:0 16px 12px;">Services proches 🔧</div>
<div class="service-card"><div class="service-icon" style="background:#E3F2FD;">🚌</div><div class="service-info"><div class="service-name">Transport collectif — Ligne A1</div><div class="service-desc">FDF ↔ Trinité · Toutes les 15 min</div><div class="service-tags"><div class="service-tag">Marché</div><div class="service-tag">DPI</div><div class="service-tag">Temps réel</div></div></div></div>
<div class="service-card"><div class="service-icon" style="background:#E8EAF6;"></div><div class="service-info"><div class="service-name">Borne recharge — Centre-ville</div><div class="service-desc">4 bornes disponibles · 22kW AC</div><div class="service-tags"><div class="service-tag">OTN</div><div class="service-tag">Paiement mobile</div></div></div></div>
<div class="service-card"><div class="service-icon" style="background:#FCE4EC;">🏥</div><div class="service-info"><div class="service-name">Pharmacie de garde — FDF</div><div class="service-desc">Ouverte 24h/24 · Av. des Caraïbes</div><div class="service-tags"><div class="service-tag">Urgence</div><div class="service-tag">1.2 km</div></div></div></div>
<div style="height:16px;"></div>
</div>
<div class="bottom-nav">
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">04 — Marketplace · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,355 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 04 Marketplace Beckn/DPI</title>
<link rel="stylesheet" href="shared.css">
<style>
.market-header {
padding: 16px;
background: white;
border-bottom: 1px solid var(--neutral-200);
}
.market-search {
display: flex; align-items: center; gap: 8px;
background: var(--neutral-100);
border-radius: var(--radius-full);
padding: 10px 16px;
font-size: var(--text-sm);
color: var(--neutral-500);
margin-bottom: 12px;
}
.category-tabs {
display: flex; gap: 8px;
overflow-x: auto;
scrollbar-width: none;
}
.category-tabs::-webkit-scrollbar { display: none; }
.cat-tab {
flex-shrink: 0;
padding: 8px 16px;
border-radius: var(--radius-full);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
background: var(--neutral-100);
color: var(--neutral-600);
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
}
.cat-tab.active {
background: var(--primary-500);
color: white;
}
.market-content {
padding: 16px;
}
.featured-card {
background: linear-gradient(135deg, #1B5E20, #00838F);
border-radius: var(--radius-xl);
padding: 20px;
color: white;
margin-bottom: 16px;
position: relative;
overflow: hidden;
}
.featured-card::after {
content: '';
position: absolute;
width: 150px; height: 150px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
top: -40px; right: -30px;
}
.featured-tag {
display: inline-block;
background: rgba(255,255,255,0.2);
border-radius: var(--radius-full);
padding: 4px 10px;
font-size: 10px;
font-weight: 600;
margin-bottom: 8px;
}
.featured-title {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
margin-bottom: 4px;
}
.featured-desc {
font-size: var(--text-sm);
opacity: 0.8;
margin-bottom: 12px;
}
.product-card {
background: white;
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.product-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.product-img {
height: 120px;
display: flex; align-items: center; justify-content: center;
font-size: 40px;
}
.product-info { padding: 12px; }
.product-name {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.product-shop {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-bottom: 6px;
}
.product-meta {
display: flex; justify-content: space-between;
align-items: center;
}
.product-price {
font-size: var(--text-md);
font-weight: var(--weight-bold);
color: var(--primary-500);
}
.product-rating {
font-size: var(--text-xs);
color: var(--alert-warning);
}
.product-distance {
font-size: 10px;
color: var(--neutral-400);
}
.service-card {
display: flex; gap: 12px;
background: white;
border-radius: var(--radius-lg);
padding: 14px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
margin-bottom: 10px;
cursor: pointer;
}
.service-icon {
width: 48px; height: 48px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 22px;
flex-shrink: 0;
}
.service-info { flex: 1; }
.service-name {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.service-desc {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-bottom: 4px;
}
.service-tags {
display: flex; gap: 4px;
}
.service-tag {
font-size: 9px;
padding: 2px 8px;
border-radius: var(--radius-full);
background: var(--ocean-50);
color: var(--ocean-600);
font-weight: 600;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="market-header">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div style="font-size:var(--text-lg);font-weight:700;">Marché Local 🏪</div>
<div style="position:relative;">
<svg class="icon" viewBox="0 0 24 24"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
<div class="badge" style="position:absolute;top:-6px;right:-6px;">2</div>
</div>
</div>
<div class="market-search">
<svg class="icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
Produits, services, commerces...
</div>
<div class="category-tabs">
<div class="cat-tab active">🍎 Alimentaire</div>
<div class="cat-tab">🚌 Transport</div>
<div class="cat-tab">🏥 Santé</div>
<div class="cat-tab">⚡ Énergie</div>
<div class="cat-tab">🎭 Culture</div>
<div class="cat-tab">🔧 Services</div>
</div>
</div>
<!-- Content -->
<div class="content-area" style="background:var(--neutral-50);top:140px;">
<div class="market-content">
<!-- Featured -->
<div class="featured-card">
<div class="featured-tag">⭐ Beckn Protocol</div>
<div class="featured-title">Marché de Sainte-Marie</div>
<div class="featured-desc">Produits locaux · Producteurs martiniquais · Livraison 2h</div>
<div style="display:flex;gap:8px;">
<button class="btn" style="background:white;color:var(--primary-600);padding:8px 16px;font-size:13px;min-height:36px;">Explorer</button>
<button class="btn" style="background:rgba(255,255,255,0.2);color:white;padding:8px 16px;font-size:13px;min-height:36px;">Infos</button>
</div>
</div>
<!-- Section -->
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div style="font-size:var(--text-md);font-weight:700;">Produits frais 🥭</div>
<div style="font-size:var(--text-sm);color:var(--primary-500);font-weight:500;">Voir tout →</div>
</div>
<!-- Product Grid -->
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px;">
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#FFF3E0,#FFE0B2);">🥭</div>
<div class="product-info">
<div class="product-name">Mangue José</div>
<div class="product-shop">Bourg de Sainte-Marie</div>
<div class="product-meta">
<div class="product-price">4.50€</div>
<div class="product-rating">⭐ 4.8</div>
</div>
<div class="product-distance">📍 2.3 km</div>
</div>
</div>
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#E8F5E9,#C8E6C9);">🍌</div>
<div class="product-info">
<div class="product-name">Banane Plantain</div>
<div class="product-shop">Habitation Limbé</div>
<div class="product-meta">
<div class="product-price">3.20€</div>
<div class="product-rating">⭐ 4.6</div>
</div>
<div class="product-distance">📍 5.1 km</div>
</div>
</div>
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#FCE4EC,#F8BBD0);">🍅</div>
<div class="product-info">
<div class="product-name">Tomates locales</div>
<div class="product-shop">Jardin du Lamentin</div>
<div class="product-meta">
<div class="product-price">2.80€</div>
<div class="product-rating">⭐ 4.9</div>
</div>
<div class="product-distance">📍 3.7 km</div>
</div>
</div>
<div class="product-card">
<div class="product-img" style="background:linear-gradient(135deg,#E3F2FD,#BBDEFB);">🐟</div>
<div class="product-info">
<div class="product-name">Poisson frais</div>
<div class="product-shop">Pêcheur du Carbet</div>
<div class="product-meta">
<div class="product-price">12.00€</div>
<div class="product-rating">⭐ 4.7</div>
</div>
<div class="product-distance">📍 8.2 km</div>
</div>
</div>
</div>
<!-- Services Section -->
<div style="font-size:var(--text-md);font-weight:700;margin-bottom:12px;">Services proches 🔧</div>
<div class="service-card">
<div class="service-icon" style="background:#E3F2FD;">🚌</div>
<div class="service-info">
<div class="service-name">Transport collectif — Ligne A1</div>
<div class="service-desc">FDF ↔ Trinité · Toutes les 15 min</div>
<div class="service-tags">
<div class="service-tag">Beckn</div>
<div class="service-tag">DPI</div>
<div class="service-tag">Temps réel</div>
</div>
</div>
</div>
<div class="service-card">
<div class="service-icon" style="background:#E8F5E9;"></div>
<div class="service-info">
<div class="service-name">Borne recharge — Centre-ville</div>
<div class="service-desc">4 bornes disponibles · 22kW AC</div>
<div class="service-tags">
<div class="service-tag">OTN</div>
<div class="service-tag">Paiement mobile</div>
</div>
</div>
</div>
<div class="service-card">
<div class="service-icon" style="background:#FFF3E0;">🏥</div>
<div class="service-info">
<div class="service-name">Pharmacie de garde — FDF</div>
<div class="service-desc">Ouverte 24h/24 · Av. des Caraïbes</div>
<div class="service-tags">
<div class="service-tag">Urgence</div>
<div class="service-tag">1.2 km</div>
</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">04 — Marketplace Beckn/DPI</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,326 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 05 AI Chat (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.chat-header {
display: flex; align-items: center; gap: 12px;
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
padding: 14px 16px; color: white;
}
.chat-avatar {
width: 42px; height: 42px; border-radius: var(--radius-full);
background: linear-gradient(135deg, rgba(255,255,255,0.3), rgba(255,255,255,0.15));
border: 2px solid rgba(255,255,255,0.4);
display: flex; align-items: center; justify-content: center;
font-size: 20px;
}
.chat-agent-name { font-size: var(--text-md); font-weight: 700; }
.chat-agent-status { font-size: 11px; opacity: 0.8; display: flex; align-items: center; gap: 4px; }
.chat-area {
padding: 16px 12px;
background: var(--neutral-50);
display: flex; flex-direction: column;
gap: 12px;
}
.msg-row {
display: flex; gap: 8px; align-items: flex-end;
max-width: 88%;
}
.msg-row.bot { align-self: flex-start; }
.msg-row.user { align-self: flex-end; flex-direction: row-reverse; }
.msg-avatar {
width: 30px; height: 30px; border-radius: var(--radius-full);
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
display: flex; align-items: center; justify-content: center;
font-size: 14px; flex-shrink: 0; color: white;
}
.msg-bubble {
padding: 10px 14px; border-radius: 18px;
font-size: var(--text-sm); line-height: 1.45;
}
.msg-row.bot .msg-bubble {
background: white; color: var(--neutral-900);
border: 1px solid var(--neutral-200);
border-bottom-left-radius: 6px;
box-shadow: var(--shadow-sm);
}
.msg-row.user .msg-bubble {
background: var(--primary-500); color: white;
border-bottom-right-radius: 6px;
}
.msg-time { font-size: 10px; color: var(--neutral-400); padding: 2px 6px; }
.quick-replies {
display: flex; flex-wrap: wrap; gap: 6px;
padding: 0 12px; margin-top: 6px;
}
.qr-btn {
padding: 7px 14px; border-radius: var(--radius-full);
border: 1.5px solid var(--primary-500);
background: var(--primary-50); color: var(--primary-600);
font-size: var(--text-sm); font-weight: 500; cursor: pointer;
transition: all 0.2s; white-space: nowrap;
}
.qr-btn:hover { background: var(--primary-500); color: white; }
.inline-card {
background: white; border-radius: var(--radius-lg);
border: 1px solid var(--neutral-200); overflow: hidden;
box-shadow: var(--shadow-sm);
max-width: 320px;
}
.inline-card-header {
padding: 10px 14px;
display: flex; align-items: center; gap: 8px;
font-size: var(--text-sm); font-weight: 600;
}
.inline-card-body { padding: 0 14px 12px; }
.iot-row {
display: flex; justify-content: space-between;
align-items: center; padding: 6px 0;
border-bottom: 1px solid var(--neutral-100);
font-size: var(--text-sm);
}
.iot-row:last-child { border-bottom: none; }
.iot-value { font-weight: 700; }
.iot-value.green { color: var(--alert-success); }
.iot-value.orange { color: var(--alert-warning); }
.iot-value.blue { color: var(--primary-500); }
.iot-value.ocean { color: var(--ocean-500); }
.typing-indicator {
display: flex; align-items: center; gap: 4px;
padding: 14px 16px;
background: white; border-radius: 18px;
border: 1px solid var(--neutral-200);
border-bottom-left-radius: 6px;
width: fit-content; margin-left: 38px;
}
.typing-dot {
width: 8px; height: 8px;
border-radius: 50%; background: var(--neutral-400);
animation: typingBounce 1.4s infinite;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingBounce {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-5px); }
}
.chat-input-row {
display: flex; gap: 8px; align-items: center;
padding: 10px 12px; background: white;
border-top: 1px solid var(--neutral-200);
margin-top: auto;
}
.chat-input {
flex: 1; padding: 10px 16px;
border-radius: var(--radius-full);
border: 1.5px solid var(--neutral-300);
font-size: var(--text-sm); outline: none;
transition: border-color 0.2s;
}
.chat-input:focus { border-color: var(--primary-500); }
.send-btn {
width: 42px; height: 42px; border-radius: var(--radius-full);
background: var(--primary-500); color: white;
display: flex; align-items: center; justify-content: center;
border: none; cursor: pointer; flex-shrink: 0;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Chat Header -->
<div class="chat-header">
<div class="chat-avatar">🤖</div>
<div>
<div class="chat-agent-name">AI Assistant · Smart City</div>
<div class="chat-agent-status"><div class="live-dot"></div>En ligne</div>
</div>
<div style="margin-left:auto;display:flex;gap:12px;">
<svg class="icon-lg" viewBox="0 0 24 24"><path d="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z"/><path d="M19 10v2a7 7 0 01-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>
<svg class="icon-lg" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
</div>
</div>
<!-- Chat Content -->
<div class="content-area" style="background:var(--neutral-50);display:flex;flex-direction:column;">
<div class="chat-area" style="flex:1;">
<!-- Bot message 1 -->
<div class="msg-row bot">
<div class="msg-avatar">🤖</div>
<div>
<div class="msg-bubble">Bonjour Eric ! 👋 Je suis votre assistant Smart City. Comment puis-je vous aider aujourd'hui à Fort-de-France ?</div>
<div class="msg-time">09:12</div>
</div>
</div>
<!-- User message 1 -->
<div class="msg-row user">
<div>
<div class="msg-bubble">Quelle est la qualité de l'air en ce moment ?</div>
</div>
</div>
<!-- Bot message 2 with inline IoT card -->
<div class="msg-row bot">
<div class="msg-avatar">🤖</div>
<div style="max-width:92%;">
<div class="msg-bubble" style="border-bottom-left-radius:6px;margin-bottom:8px;">Les données de nos capteurs IoT en temps réel :</div>
<div class="inline-card">
<div class="inline-card-header">
<div style="width:32px;height:32px;border-radius:10px;background:#E3F2FD;display:flex;align-items:center;justify-content:center;font-size:16px;">📍</div>
<div>Capteurs Air — Fort-de-France</div>
<div class="live-dot" style="margin-left:auto;"></div>
</div>
<div class="inline-card-body">
<div class="iot-row">
<span>🌫️ PM2.5</span>
<span class="iot-value green">12 µg/m³</span>
</div>
<div class="iot-row">
<span>💨 AQI Global</span>
<span class="iot-value green">42 (Bon)</span>
</div>
<div class="iot-row">
<span>🌡° Température</span>
<span class="iot-value blue">26.5°C</span>
</div>
<div class="iot-row">
<span>💧 Humidité</span>
<span class="iot-value ocean">68%</span>
</div>
<div class="iot-row">
<span>⚡ CO₂</span>
<span class="iot-value orange">485 ppm</span>
</div>
</div>
</div>
<div class="msg-time" style="margin-top:4px;">09:13</div>
</div>
</div>
<!-- User message 2 -->
<div class="msg-row user">
<div class="msg-bullet"><div class="msg-bubble">Où puis-je trouver un parking proche ?</div></div>
</div>
<!-- Bot message 3 -->
<div class="msg-row bot">
<div class="msg-avatar">🤖</div>
<div style="max-width:92%;">
<div class="msg-bubble">Voici les parkings disponibles à proximité :</div>
<div class="inline-card" style="margin-top:8px;">
<div class="inline-card-header">
<div style="width:32px;height:32px;border-radius:10px;background:#E8EAF6;display:flex;align-items:center;justify-content:center;font-size:16px;">🅿️</div>
<div>Parkings proches · Centre-Ville</div>
</div>
<div class="inline-card-body">
<div class="iot-row">
<span>🏢 Parking Gudel</span>
<span class="iot-value green">42 places</span>
</div>
<div class="iot-row">
<span>🚗 Place Perrinon</span>
<span class="iot-value orange">12 places</span>
</div>
<div class="iot-row">
<span>🏛️ Parking Préfecture</span>
<span class="iot-value green">68 places</span>
</div>
<div class="iot-row">
<span>🎭 Parking CTC</span>
<span class="iot-value blue">24 places</span>
</div>
</div>
</div>
<div class="msg-time" style="margin-top:4px;">09:14</div>
</div>
</div>
<!-- Typing indicator -->
<div class="typing-indicator">
<div class="typing-dot"></div>
<div class="typing-dot"></div>
<div class="typing-dot"></div>
</div>
<!-- Quick Replies -->
<div class="quick-replies">
<button class="qr-btn">🌤️ Météo</button>
<button class="qr-btn">🚌 TCO horaires</button>
<button class="qr-btn">🚗 Trafic</button>
<button class="qr-btn">🌱 Énergie</button>
<button class="qr-btn">📢 Signalement</button>
<button class="qr-btn">🍽️ Marché</button>
</div>
</div>
<!-- Input -->
<div class="chat-input-row">
<style>
.chat-input-row { display:flex; gap:8px; align-items:center; padding:10px 12px; background:white; border-top:1px solid var(--neutral-200); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<button style="width:38px;height:38px;border-radius:var(--radius-full);border:none;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--primary-500);flex-shrink:0;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>
</button>
<input class="chat-input" type="text" placeholder="Écrire un message...">
<button class="send-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div class="page-label" style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">05 — AI Chat · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,334 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 05 AI Chat Assistant</title>
<link rel="stylesheet" href="shared.css">
<style>
.chat-header {
padding: 14px 16px;
background: white;
border-bottom: 1px solid var(--neutral-200);
display: flex; align-items: center; gap: 12px;
}
.chat-avatar {
width: 40px; height: 40px;
border-radius: var(--radius-full);
background: linear-gradient(135deg, #7C4DFF, #B388FF);
display: flex; align-items: center; justify-content: center;
color: white; font-size: 20px;
flex-shrink: 0;
}
.chat-status {
width: 10px; height: 10px;
background: var(--alert-success);
border-radius: 50%;
position: absolute;
bottom: 0; right: 0;
border: 2px solid white;
}
.chat-messages {
padding: 16px;
display: flex; flex-direction: column;
gap: 12px;
min-height: 400px;
}
.msg-row {
display: flex; gap: 8px;
align-items: flex-end;
}
.msg-row.user { flex-direction: row-reverse; }
.msg-avatar {
width: 28px; height: 28px;
border-radius: var(--radius-full);
display: flex; align-items: center; justify-content: center;
font-size: 14px; flex-shrink: 0;
}
.msg-bubble {
max-width: 75%;
padding: 10px 14px;
border-radius: var(--radius-lg);
font-size: var(--text-sm);
line-height: 1.45;
position: relative;
}
.msg-row:not(.user) .msg-bubble {
background: var(--neutral-100);
color: var(--neutral-800);
border-bottom-left-radius: 4px;
}
.msg-row.user .msg-bubble {
background: linear-gradient(135deg, var(--primary-500), var(--primary-600));
color: white;
border-bottom-right-radius: 4px;
}
.msg-time {
font-size: 9px;
color: var(--neutral-400);
margin-top: 4px;
}
.msg-row.user .msg-time { text-align: right; }
.quick-replies {
display: flex; flex-wrap: wrap; gap: 6px;
padding: 0 16px 12px;
}
.quick-reply {
padding: 8px 14px;
border-radius: var(--radius-full);
background: var(--primary-50);
color: var(--primary-600);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
cursor: pointer;
border: 1px solid var(--primary-100);
white-space: nowrap;
}
.typing-indicator {
display: flex; gap: 4px;
padding: 12px 16px;
background: var(--neutral-100);
border-radius: var(--radius-lg);
border-bottom-left-radius: 4px;
width: fit-content;
}
.typing-dot {
width: 6px; height: 6px;
background: var(--neutral-400);
border-radius: 50%;
animation: typingBounce 1.4s infinite;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingBounce {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-6px); }
}
.chat-input-area {
position: absolute;
bottom: 80px; left: 0; right: 0;
background: white;
border-top: 1px solid var(--neutral-200);
padding: 10px 12px;
display: flex; gap: 8px; align-items: flex-end;
}
.chat-input {
flex: 1;
border: 2px solid var(--neutral-200);
border-radius: var(--radius-full);
padding: 10px 16px;
font-size: var(--text-sm);
resize: none;
max-height: 80px;
font-family: var(--font-family);
outline: none;
}
.chat-input:focus { border-color: var(--primary-500); }
.send-btn {
width: 42px; height: 42px;
border-radius: var(--radius-full);
background: var(--primary-500);
border: none;
display: flex; align-items: center; justify-content: center;
cursor: pointer;
flex-shrink: 0;
}
.inline-card {
background: var(--neutral-0);
border-radius: var(--radius-md);
overflow: hidden;
border: 1px solid var(--neutral-200);
margin-top: 8px;
}
.inline-card-map {
height: 80px;
background: linear-gradient(135deg,#E8F5E9,#E0F7FA);
display: flex; align-items: center; justify-content: center;
font-size: 12px; color: var(--neutral-500);
}
.inline-card-info { padding: 8px 12px; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Chat Header -->
<div class="chat-header">
<div style="position:relative;">
<div class="chat-avatar">🤖</div>
<div class="chat-status"></div>
</div>
<div style="flex:1;">
<div style="font-weight:700;font-size:var(--text-base);">City Assistant</div>
<div style="font-size:var(--text-xs);color:var(--alert-success);font-weight:500;">En ligne · Propulsé par RAG</div>
</div>
<div style="display:flex;gap:8px;">
<svg class="icon" viewBox="0 0 24 24"><path d="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z"/><path d="M19 10v2a7 7 0 01-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>
<svg class="icon" viewBox="0 0 24 24"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>
</div>
</div>
<!-- Messages -->
<div class="content-area" style="top:71px;bottom:140px;background:var(--neutral-50);">
<div class="chat-messages">
<!-- Welcome -->
<div class="msg-row">
<div class="msg-avatar" style="background:linear-gradient(135deg,#7C4DFF,#B388FF);">🤖</div>
<div>
<div class="msg-bubble">
Bonjour Eric ! 👋 Je suis votre assistant Smart City. Je peux vous aider avec :
<br><br>
🌡️ Les données en temps réel<br>
🗺️ Les infos géolocalisées<br>
🏪 Les services du marché local<br>
📊 Les statistiques de la ville<br><br>
Comment puis-je vous aider ?
</div>
<div class="msg-time">09:30</div>
</div>
</div>
<!-- User question -->
<div class="msg-row user">
<div>
<div class="msg-bubble">Quelle est la qualité de l'air à Fort-de-France ?</div>
<div class="msg-time">09:32</div>
</div>
</div>
<!-- AI response with data -->
<div class="msg-row">
<div class="msg-avatar" style="background:linear-gradient(135deg,#7C4DFF,#B388FF);">🤖</div>
<div>
<div class="msg-bubble">
📊 <strong>Qualité de l'air — Fort-de-France</strong><br><br>
Indice AQI : <strong>42 (Bon)</strong> 🟢<br><br>
🌡️ Temp : 24.3°C<br>
💧 Humidité : 65%<br>
💨 PM2.5 : 8 µg/m³<br>
🔄 Dernière mise à jour : il y a 3 min<br><br>
<em>Source : Capteur AirQ-012 · IoT Network</em>
</div>
<div class="inline-card">
<div class="inline-card-map">
<span>🗺️ Aperçu zone FDF Centre — <span style="color:var(--alert-success);font-weight:700;">BON</span></span>
</div>
<div class="inline-card-info" style="display:flex;gap:8px;">
<div style="flex:1;text-align:center;background:var(--neutral-50);border-radius:6px;padding:6px;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--alert-success);">42</div>
<div style="font-size:9px;color:var(--neutral-500);">AQI</div>
</div>
<div style="flex:1;text-align:center;background:var(--neutral-50);border-radius:6px;padding:6px;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--ocean-500);">24°</div>
<div style="font-size:9px;color:var(--neutral-500);">Temp</div>
</div>
<div style="flex:1;text-align:center;background:var(--neutral-50);border-radius:6px;padding:6px;">
<div style="font-size:var(--text-sm);font-weight:700;color:var(--neutral-700);">65%</div>
<div style="font-size:9px;color:var(--neutral-500);">Humidité</div>
</div>
</div>
</div>
<div class="msg-time">09:32</div>
</div>
</div>
<!-- User question 2 -->
<div class="msg-row user">
<div>
<div class="msg-bubble">Où trouver des fruits locaux près de chez moi ?</div>
<div class="msg-time">09:35</div>
</div>
</div>
<!-- AI response with map card -->
<div class="msg-row">
<div class="msg-avatar" style="background:linear-gradient(135deg,#7C4DFF,#B388FF);">🤖</div>
<div>
<div class="msg-bubble">
🍎 J'ai trouvé 3 producteurs près de vous !<br><br>
<strong>1. Marché Sainte-Marie</strong> 📍 2.3 km<br>
Mangue José, Banane... ⭐ 4.8<br><br>
<strong>2. Jardin du Lamentin</strong> 📍 3.7 km<br>
Tomates locales, herbes... ⭐ 4.9<br><br>
<strong>3. Habitation Limbé</strong> 📍 5.1 km<br>
Plantains, ignames... ⭐ 4.6<br><br>
Souhaitez-vous voir sur la carte ? 🗺️
</div>
<div class="msg-time">09:35</div>
</div>
</div>
<!-- Typing -->
<div class="msg-row">
<div class="msg-avatar" style="background:linear-gradient(135deg,#7C4DFF,#B388FF);">🤖</div>
<div class="typing-indicator">
<div class="typing-dot"></div>
<div class="typing-dot"></div>
<div class="typing-dot"></div>
</div>
</div>
</div>
<!-- Quick Replies -->
<div class="quick-replies">
<div class="quick-reply">🚌 Prochain bus</div>
<div class="quick-reply">🌧️ Météo</div>
<div class="quick-re-signaler un problème</div>
<div class="quick-reply">📊 Statistiques</div>
</div>
</div>
<!-- Input -->
<div class="chat-input-area">
<textarea class="chat-input" placeholder="Posez votre question..." rows="1"></textarea>
<div class="send-btn">
<svg class="icon" viewBox="0 0 24 24" style="color:white;"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:216px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-300);">05 — AI Chat Assistant (RAG)</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,358 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 06 Profil (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.profil-header {
background: linear-gradient(160deg, var(--primary-700) 0%, var(--ocean-600) 50%, var(--ocean-500) 100%);
padding: 24px 20px 20px;
color: white; position: relative;
}
.profil-avatar-wrap {
display: flex; align-items: center; gap: 14px;
}
.profil-avatar {
width: 68px; height: 68px; border-radius: var(--radius-full);
background: rgba(255,255,255,0.2);
border: 3px solid rgba(255,255,255,0.4);
display: flex; align-items: center; justify-content: center;
font-size: 32px;
}
.profil-name { font-size: var(--text-lg); font-weight: 700; }
.profil-email { font-size: var(--text-sm); opacity: 0.75; }
.profil-level {
margin-top: 4px; font-size: 11px;
display: inline-flex; align-items: center; gap: 4px;
background: rgba(255,255,255,0.15);
padding: 3px 10px; border-radius: var(--radius-full);
}
.profil-stats {
display: grid; grid-template-columns: repeat(3, 1fr);
gap: 8px; padding: 0 16px;
margin-top: -20px; margin-bottom: 16px;
position: relative; z-index: 2;
}
.stat-card {
background: white; border-radius: var(--radius-lg);
padding: 14px 8px; text-align: center;
box-shadow: var(--shadow-md);
border: 1px solid var(--neutral-100);
}
.stat-value { font-size: var(--text-xl); font-weight: 700; }
.stat-label { font-size: 9px; color: var(--neutral-500); margin-top: 2px; }
.profil-section {
padding: 0 16px 16px;
}
.profil-section-title {
font-size: 12px; font-weight: 700;
color: var(--primary-500);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 8px; display: flex;
align-items: center; gap: 6px;
}
.profil-card {
background: white; border-radius: var(--radius-lg);
border: 1px solid var(--neutral-100);
overflow: hidden;
}
.profil-item {
display: flex; align-items: center; gap: 12px;
padding: 14px 16px;
border-bottom: 1px solid var(--neutral-100);
cursor: pointer; transition: background 0.15s;
}
.profil-item:last-child { border-bottom: none; }
.profil-item:hover { background: var(--neutral-50); }
.profil-item-icon {
width: 36px; height: 36px; border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 18px; flex-shrink: 0;
}
.profil-item-text { flex: 1; }
.profil-item-title { font-size: var(--text-sm); font-weight: 600; }
.profil-item-sub { font-size: 11px; color: var(--neutral-500); }
.profil-item-right {
font-size: var(--text-sm); color: var(--neutral-500);
display: flex; align-items: center; gap: 4px;
}
.toggle-switch {
width: 44px; height: 24px; border-radius: 12px;
background: var(--neutral-300); position: relative;
cursor: pointer; transition: background 0.2s; flex-shrink: 0;
}
.toggle-switch.on { background: var(--primary-500); }
.toggle-switch::after {
content: ''; width: 20px; height: 20px;
border-radius: 50%; background: white;
position: absolute; top: 2px; left: 2px;
transition: transform 0.2s;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.toggle-switch.on::after { transform: translateX(20px); }
.lang-grid {
display: grid; grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.lang-option {
padding: 10px; border-radius: var(--radius-md);
border: 2px solid var(--neutral-200);
background: white; text-align: center;
cursor: pointer; transition: all 0.2s;
}
.lang-option.active {
border-color: var(--primary-500);
background: var(--primary-50);
}
.lang-flag { font-size: 20px; }
.lang-code { font-size: 11px; font-weight: 600; margin-top: 2px; }
.section-divider { height: 8px; background: var(--neutral-50); }
.profil-badge {
display: inline-flex; align-items: center; gap: 3px;
padding: 2px 8px; border-radius: var(--radius-full);
font-size: 10px; font-weight: 600;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="profil-header">
<div style="display:flex;justify-content:flex-end;margin-bottom:8px;">
<svg class="icon-lg" style="cursor:pointer;" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
</div>
<div class="profil-avatar-wrap">
<div class="profil-avatar">👨🏻‍💻</div>
<div>
<div class="profil-name">Eric Ferdinand</div>
<div class="profil-email">eric@smartappcity.com</div>
<div class="profil-level">🏆 Contributeur · Niveau 5</div>
</div>
</div>
</div>
<!-- Content -->
<div class="content-area" style="background:var(--neutral-50);">
<!-- Stats -->
<div class="profil-stats">
<div class="stat-card">
<div class="stat-value" style="color:var(--primary-500)">27</div>
<div class="stat-label">Signalements</div>
</div>
<div class="stat-card">
<div class="stat-value" style="color:var(--ocean-500)">1,420</div>
<div class="stat-label">Points</div>
</div>
<div class="stat-card">
<div class="stat-value" style="color:var(--indigo-500)">84</div>
<div class="stat-label">Visites</div>
</div>
</div>
<!-- Langue -->
<div class="profil-section">
<div class="profil-section-title">🌐 Langue</div>
<div class="lang-grid">
<div class="lang-option active">
<div class="lang-flag">🇫🇷</div>
<div class="lang-code">FR</div>
</div>
<div class="lang-option">
<div class="lang-flag">🇬🇧</div>
<div class="lang-code">EN</div>
</div>
<div class="lang-option">
<div class="lang-flag">🇪🇸</div>
<div class="lang-code">ES</div>
</div>
<div class="lang-option">
<div class="lang-flag">🇩🇪</div>
<div class="lang-code">DE</div>
</div>
</div>
</div>
<div class="section-divider"></div>
<!-- Mon compte -->
<div class="profil-section">
<div class="profil-section-title">👤 Mon compte</div>
<div class="profil-card">
<div class="profil-item">
<div class="profil-item-icon" style="background:#E3F2FD;">✏️</div>
<div class="profil-item-text">
<div class="profil-item-title">Modifier le profil</div>
<div class="profil-item-sub">Nom, avatar, email</div>
</div>
<div class="profil-item-right"></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#FFF3E0;">🔑</div>
<div class="profil-item-text">
<div class="profil-item-title">Sécurité & mot de passe</div>
<div class="profil-item-sub">2FA, changement</div>
</div>
<div class="profil-item-right"></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#E8F5E9;">📋</div>
<div class="profil-item-text">
<div class="profil-item-title">Données personnelles</div>
<div class="profil-item-sub">RGPD, export</div>
</div>
<div class="profil-item-right"></div>
</div>
</div>
</div>
<div class="section-divider"></div>
<!-- Préférences -->
<div class="profil-section">
<div class="profil-section-title">⚙️ Préférences</div>
<div class="profil-card">
<div class="profil-item">
<div class="profil-item-icon" style="background:#E8EAF6;">🌙</div>
<div class="profil-item-text">
<div class="profil-item-title">Mode sombre</div>
<div class="profil-item-sub">Thème foncé</div>
</div>
<div class="toggle-switch on"></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#E3F2FD;">🔔</div>
<div class="profil-item-text">
<div class="profil-item-title">Notifications</div>
<div class="profil-item-sub">Push & alertes</div>
</div>
<div class="toggle-switch on"></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#E0F7FA;">📍</div>
<div class="profil-item-text">
<div class="profil-item-title">Géolocalisation</div>
<div class="profil-item-sub">Services proches</div>
</div>
<div class="toggle-switch on"></div>
</div>
</div>
</div>
<div class="section-divider"></div>
<!-- Paiements / DPI -->
<div class="profil-section">
<div class="profil-section-title">🔗 Paiements / DPI / OTN</div>
<div class="profil-card">
<div class="profil-item">
<div class="profil-item-icon" style="background:#1565C0;color:white;">💳</div>
<div class="profil-item-text">
<div class="profil-item-title">Portefeuille numérique</div>
<div class="profil-item-sub">Solde Wallet · Identité DPI</div>
</div>
<div class="profil-item-right"><span style="font-weight:700;color:var(--primary-500);">45,80 €</span></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#3949AB;color:white;">🛒</div>
<div class="profil-item-text">
<div class="profil-item-title">Mes commandes</div>
<div class="profil-item-sub">3 en cours · 12 terminées</div>
</div>
<div class="profil-item-right"><span class="badge" style="position:static;">3</span></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#00ACC1;color:white;">🪪</div>
<div class="profil-item-text">
<div class="profil-item-title">Identité DID</div>
<div class="profil-item-sub">did:smartcity:mq:0x8f2a...</div>
</div>
<div class="profil-item-right"><span class="profil-badge" style="background:#E8F5E9;color:#2E7D32;">✓ Vérifié</span></div>
</div>
</div>
</div>
<div class="section-divider"></div>
<!-- Signalements ODK -->
<div class="profil-section">
<div class="profil-section-title">📸 Signalements ODK</div>
<div class="profil-card">
<div class="profil-item">
<div class="profil-item-icon" style="background:#FFF3E0;">📋</div>
<div class="profil-item-text">
<div class="profil-item-title">Mes signalements</div>
<div class="profil-item-sub">27 soumis · 18 résolus</div>
</div>
<div class="profil-item-right"></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#E3F2FD;">📝</div>
<div class="profil-item-text">
<div class="profil-item-title">Formulaires ODK</div>
<div class="profil-item-sub">Saisie terrain hors-ligne</div>
</div>
<div class="profil-item-right"></div>
</div>
<div class="profil-item">
<div class="profil-item-icon" style="background:#E8F5E9;"></div>
<div class="profil-item-text">
<div class="profil-item-title">Validés</div>
<div class="profil-item-sub">Approuvés par la collectivité</div>
</div>
<div class="profil-item-right"><span class="profil-badge" style="background:#E8F5E9;color:#2E7D32;">18</span></div>
</div>
</div>
</div>
<div style="height:24px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div class="page-label" style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">06 — Profil Utilisateur · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,354 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 06 Profil Utilisateur</title>
<link rel="stylesheet" href="shared.css">
<style>
.profile-header {
padding: 20px 16px;
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
color: white;
text-align: center;
}
.profile-avatar {
width: 80px; height: 80px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.2);
display: flex; align-items: center; justify-content: center;
font-size: 36px;
margin: 0 auto 12px;
border: 3px solid rgba(255,255,255,0.3);
}
.profile-name {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
margin-bottom: 2px;
}
.profile-email {
font-size: var(--text-sm);
opacity: 0.8;
margin-bottom: 8px;
}
.profile-badge {
display: inline-block;
background: rgba(255,255,255,0.2);
border-radius: var(--radius-full);
padding: 4px 12px;
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
}
.stat-row {
display: flex;
justify-content: center;
gap: 32px;
margin-top: 16px;
}
.stat-item { text-align: center; }
.stat-value {
font-size: var(--text-xl);
font-weight: var(--weight-bold);
}
.stat-label {
font-size: var(--text-xs);
opacity: 0.7;
}
.menu-section { padding: 16px; }
.menu-section-title {
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
color: var(--neutral-400);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 8px;
padding-left: 4px;
}
.menu-item {
display: flex; align-items: center; gap: 14px;
padding: 14px 12px;
border-radius: var(--radius-md);
cursor: pointer;
transition: background 0.15s;
}
.menu-item:hover { background: var(--neutral-50); }
.menu-icon {
width: 38px; height: 38px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.menu-text { flex: 1; }
.menu-label {
font-size: var(--text-sm);
font-weight: var(--weight-medium);
}
.menu-sub {
font-size: var(--text-xs);
color: var(--neutral-400);
}
.menu-arrow {
color: var(--neutral-300);
}
.menu-value {
font-size: var(--text-sm);
color: var(--neutral-500);
margin-right: 4px;
}
.lang-flags {
display: flex; gap: 6px;
}
.lang-flag {
width: 24px; height: 24px;
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: 12px;
cursor: pointer;
opacity: 0.5;
transition: opacity 0.2s;
}
.lang-flag.active { opacity: 1; box-shadow: 0 0 0 2px var(--primary-500); }
.toggle-switch {
width: 44px; height: 24px;
border-radius: 12px;
background: var(--primary-500);
position: relative;
cursor: pointer;
}
.toggle-switch::after {
content: '';
position: absolute;
width: 20px; height: 20px;
border-radius: 50%;
background: white;
top: 2px; right: 2px;
transition: all 0.2s;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Profile Header -->
<div class="profile-header">
<div class="profile-avatar">👤</div>
<div class="profile-name">Eric FELIXINE</div>
<div class="profile-email">efelixine@digitribe.fr</div>
<div class="profile-badge">🏙️ Citoyen Smart City</div>
<div class="stat-row">
<div class="stat-item">
<div class="stat-value">12</div>
<div class="stat-label">Signalements</div>
</div>
<div class="stat-item">
<div class="stat-value">3.2k</div>
<div class="stat-label">Points</div>
</div>
<div class="stat-item">
<div class="stat-value">48</div>
<div class="stat-label">Visites</div>
</div>
</div>
</div>
<!-- Content -->
<div class="content-area" style="top:230px;background:var(--neutral-50);">
<!-- Langue -->
<div class="menu-section">
<div class="menu-section-title">Langue / Language / Idioma / Sprache</div>
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
<div class="menu-item">
<div class="menu-text">
<div class="menu-label">Langue de l'application</div>
<div class="menu-sub">Sélectionnez votre langue</div>
</div>
<div class="lang-flags">
<div class="lang-flag active" style="background:#E3F2FD;">🇫🇷</div>
<div class="lang-flag" style="background:#FCE4EC;">🇬🇧</div>
<div class="lang-flag" style="background:#FFF9C4;">🇪🇸</div>
<div class="lang-flag" style="background:#F3E5F5;">🇩🇪</div>
</div>
<span class="menu-arrow"></span>
</div>
</div>
</div>
<!-- Mon compte -->
<div class="menu-section">
<div class="menu-section-title">Mon compte</div>
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
<div class="menu-item">
<div class="menu-icon" style="background:#E3F2FD;">👤</div>
<div class="menu-text">
<div class="menu-label">Informations personnelles</div>
</div>
<span class="menu-arrow"></span>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#E8F5E9;">🏙️</div>
<div class="menu-text">
<div class="menu-label">Ma ville</div>
</div>
<span class="menu-value">Fort-de-France</span>
<span class="menu-arrow"></span>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#FFF3E0;">📊</div>
<div class="menu-text">
<div class="menu-label">Mon activité</div>
<div class="menu-sub">Signalements, visites, contributions</div>
</div>
<span class="menu-arrow"></span>
</div>
</div>
</div>
<!-- Préférences -->
<div class="menu-section">
<div class="menu-section-title">Préférences</div>
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
<div class="menu-item">
<div class="menu-icon" style="background:#F3E5F5;">🌙</div>
<div class="menu-text">
<div class="menu-label">Mode sombre</div>
</div>
<div class="toggle-switch"></div>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#FCE4EC;">🔔</div>
<div class="menu-text">
<div class="menu-label">Notifications</div>
<div class="menu-sub">Alertes, événements, mises à jour</div>
</div>
<div class="toggle-switch"></div>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#FFF9C4;">📍</div>
<div class="menu-text">
<div class="menu-label">Géolocalisation</div>
<div class="menu-sub">Services basés sur la position</div>
</div>
<div class="toggle-switch"></div>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#E0F7FA;">🗺️</div>
<div class="menu-text">
<div class="menu-label">Unités</div>
</div>
<span class="menu-value">Métrique</span>
<span class="menu-arrow"></span>
</div>
</div>
</div>
<!-- Beckn / DPI -->
<div class="menu-section">
<div class="menu-section-title">Beckn · DPI · OTN</div>
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
<div class="menu-item">
<div class="menu-icon" style="background:#E8F5E9;">💳</div>
<div class="menu-text">
<div class="menu-label">Portefeuille numérique</div>
<div class="menu-sub">Paiements Beckn/DPI</div>
</div>
<span class="menu-arrow"></span>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#E3F2FD;">📦</div>
<div class="menu-text">
<div class="menu-label">Mes commandes</div>
<div class="menu-sub">Historique des transactions</div>
</div>
<span class="menu-arrow"></span>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#F3E5F5;">🔐</div>
<div class="menu-text">
<div class="menu-label">Identité décentralisée (DID)</div>
</div>
<span class="menu-arrow"></span>
</div>
</div>
</div>
<!-- ODK / Signalements -->
<div class="menu-section">
<div class="menu-section-title">Signalements</div>
<div style="background:white;border-radius:var(--radius-lg);overflow:hidden;border:1px solid var(--neutral-100);">
<div class="menu-item">
<div class="menu-icon" style="background:#FFF3E0;">📸</div>
<div class="menu-text">
<div class="menu-label">Mes signalements</div>
<div class="menu-sub">12 signalements soumis</div>
</div>
<span class="menu-value">12</span>
<span class="menu-arrow"></span>
</div>
<div style="height:1px;background:var(--neutral-100);margin:0 12px;"></div>
<div class="menu-item">
<div class="menu-icon" style="background:#FCE4EC;">📋</div>
<div class="menu-text">
<div class="menu-label">Formulaires ODK</div>
</div>
<span class="menu-arrow"></span>
</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">06 — Profil & Paramètres</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,278 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 07 Notifications (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.notif-header {
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
padding: 16px; color: white;
display: flex; justify-content: space-between; align-items: center;
}
.notif-title { font-size: 20px; font-weight: 700; }
.notif-sub { font-size: 12px; opacity: 0.8; }
.mark-read-btn {
background: rgba(255,255,255,0.2); color: white;
border: none; padding: 6px 14px; border-radius: var(--radius-full);
font-size: 12px; font-weight: 500; cursor: pointer;
}
.notif-tabs {
display: flex; gap: 0;
background: white;
border-bottom: 1px solid var(--neutral-200);
}
.notif-tab {
flex: 1; text-align: center;
padding: 12px 4px; font-size: 11px; font-weight: 600;
color: var(--neutral-500); cursor: pointer;
border-bottom: 3px solid transparent;
transition: all 0.2s;
position: relative;
}
.notif-tab.active {
color: var(--primary-500);
border-bottom-color: var(--primary-500);
}
.notif-tab .tab-badge {
position: absolute; top: 6px; right: 50%; transform:translate(12px,0);
background: var(--alert-danger); color: white;
font-size: 9px; min-width: 16px; height: 16px;
border-radius: var(--radius-full);
display: flex; align-items: center; justify-content: center;
padding: 0 4px;
}
.notif-list { padding: 12px 0; }
.notif-date-group {
padding: 8px 16px 4px;
font-size: 11px; font-weight: 600;
color: var(--primary-500);
text-transform: uppercase; letter-spacing: 0.5px;
}
.notif-item {
display: flex; gap: 12px; padding: 12px 16px;
border-bottom: 1px solid var(--neutral-100);
transition: background 0.15s; cursor: pointer;
}
.notif-item:hover { background: var(--neutral-50); }
.notif-item.unread { background: var(--primary-50); }
.notif-item.unread:hover { background: var(--primary-100); }
.notif-icon-wrap {
width: 42px; height: 42px; border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 18px; flex-shrink: 0;
}
.notif-content { flex: 1; min-width: 0; }
.notif-text { font-size: var(--text-sm); font-weight: 500; line-height: 1.35; }
.notif-text strong { font-weight: 700; }
.notif-meta { font-size: 11px; color: var(--neutral-500); margin-top: 3px; display: flex; align-items: center; gap: 6px; }
.notif-dot { width: 6px; height: 6px; border-radius: 50%; }
.notif-chevron {
color: var(--neutral-300); font-size: 16px; align-self: center;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="notif-header">
<div>
<div class="notif-title">Notifications</div>
<div class="notif-sub">12 non lues</div>
</div>
<button class="mark-read-btn">Tout marquer lu</button>
</div>
<!-- Tabs -->
<div class="content-area" style="background:var(--neutral-50);">
<div class="notif-tabs">
<div class="notif-tab active">
Tout
<div class="tab-badge">12</div>
</div>
<div class="notif-tab">
Alertes
<div class="tab-badge">5</div>
</div>
<div class="notif-tab">
Données
<div class="tab-badge">3</div>
</div>
<div class="notif-tab">
Marché
<div class="tab-badge">2</div>
</div>
<div class="notif-tab">
Système
<div class="tab-badge" style="display:none;">2</div>
</div>
</div>
<div class="notif-list" style="padding-top:4px;">
<!-- Aujourd'hui -->
<div class="notif-date-group">Aujourd'hui — 27 mai</div>
<div class="notif-item unread">
<div class="notif-icon-wrap" style="background:#FFEBEE;">🚨</div>
<div class="notif-content">
<div class="notif-text"><strong>Alerte inondation</strong> détectée dans votre secteur (Le Lamentin). Veuillez suivre les consignes de sécurité.</div>
<div class="notif-meta"><span class="notif-dot" style="background:var(--alert-danger);"></span> Il y a 12 min · Alerte</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item unread">
<div class="notif-icon-wrap" style="background:#FFF3E0;"></div>
<div class="notif-content">
<div class="notif-text">Pic de <strong>consommation électrique</strong> détecté · Secteur Schœlcher. Réduisez vos usages non essentiels.</div>
<div class="notif-meta"><span class="notif-dot" style="background:var(--alert-warning);"></span> Il y a 34 min · Données</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item unread">
<div class="notif-icon-wrap" style="background:#E8EAF6;">🏪</div>
<div class="notif-content">
<div class="notif-text">Nouveau <strong>producteur disponible</strong> sur le marché : Coopérative Bio Le Vauclin — 12 produits frais.</div>
<div class="notif-meta"><span class="notif-dot" style="background:var(--primary-500);"></span> Il y a 1h · Marché Local</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#E0F7FA;">🌊</div>
<div class="notif-content">
<div class="notif-text">Niveau de <strong>qualité de l'eau</strong> mis à jour · Pointe des Nègres : Bon état confirmé.</div>
<div class="notif-meta"><span class="notif-dot" style="background:var(--ocean-500);"></span> Il y a 2h · Données IoT</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item unread">
<div class="notif-icon-wrap" style="background:#E8F5E9;">🎉</div>
<div class="notif-content">
<div class="notif-text"><strong>Fort-de-France</strong> vient d'être ajouté à vos favoris événements. 3 événements cette semaine.</div>
<div class="notif-meta"><span class="notif-dot" style="background:var(--alert-success);"></span> Il y a 3h · Système</div>
</div>
<div class="notif-chevron"></div>
</div>
<!-- Hier -->
<div class="notif-date-group">Hier — 26 mai</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#E3F2FD;">🔧</div>
<div class="notif-content">
<div class="notif-text">Votre <strong>signalement #1047</strong> (Éclairage public — Rue Case) est passé en statut "En cours".</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--alert-warning);display:inline-block;"></span> Il y a 18h · Signalement ODK</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#FFF3E0;">💰</div>
<div class="notif-content">
<div class="notif-text">Commande <strong>#BKN-2045</strong> confirmée sur le marché local. Livraison prévue demain matin.</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--primary-500);display:inline-block;"></span> Hier 16h · Marché</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item unread">
<div class="notif-icon-wrap" style="background:#E8EAF6;">📡</div>
<div class="notif-content">
<div class="notif-text"><strong>Capteur AirQ-012</strong> hors ligne depuis 2h. Intervention technique en cours.</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--alert-danger);display:inline-block;"></span> Hier 14h · Données IoT</div>
</div>
<div class="notif-chevron"></div>
</div>
<!-- Plus ancien -->
<div class="notif-date-group">Cette semaine</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#E0F7FA;">🌡️</div>
<div class="notif-content">
<div class="notif-text">Seuil <strong>température</strong> franchi à 32°C. Activation du plan canicule sur Fort-de-France.</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--alert-warning);display:inline-block;"></span> Il y a 3 jours · Alerte</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#E8F5E9;"></div>
<div class="notif-content">
<div class="notif-text">Signalement <strong>#1042</strong> (Nid de poules — Pointe des Nègres) <strong>résolu</strong> par les services techniques.</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--alert-success);display:inline-block;"></span> Il y a 4 jours · ODK</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#E3F2FD;">🔔</div>
<div class="notif-content">
<div class="notif-text">Mise à jour système <strong>v2.3.1</strong> installée. Nouvelles fonctionnalités : AI Chat amélioré, carte 3D.</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--neutral-400);display:inline-block;"></span> Il y a 5 jours · Système</div>
</div>
<div class="notif-chevron"></div>
</div>
<div class="notif-item">
<div class="notif-icon-wrap" style="background:#FCE4EC;">🌺</div>
<div class="notif-content">
<div class="notif-text">Fêtes de Fort : <strong>programme 2026</strong> disponible. Inscription ouverte aux événements culturels.</div>
<div class="notif-meta"><span style="width:6px;height:6px;border-radius:50%;background:var(--indigo-500);display:inline-block;"></span> Il y a 5 jours · Culture</div>
</div>
<div class="notif-chevron"></div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div class="page-label" style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">07 — Notifications · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,248 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 07 Notifications</title>
<link rel="stylesheet" href="shared.css">
<style>
.notif-header {
padding: 16px;
background: white;
border-bottom: 1px solid var(--neutral-200);
}
.notif-title {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
margin-bottom: 4px;
}
.notif-sub {
font-size: var(--text-sm);
color: var(--neutral-500);
}
.notif-tabs {
display: flex; gap: 8px;
padding: 12px 16px;
background: white;
border-bottom: 1px solid var(--neutral-200);
}
.notif-tab {
padding: 8px 16px;
border-radius: var(--radius-full);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
background: var(--neutral-100);
color: var(--neutral-600);
cursor: pointer;
transition: all 0.2s;
}
.notif-tab.active {
background: var(--primary-500);
color: white;
}
.notif-item {
display: flex; gap: 12px;
padding: 14px 16px;
background: white;
border-bottom: 1px solid var(--neutral-100);
cursor: pointer;
transition: background 0.15s;
}
.notif-item:hover { background: var(--neutral-50); }
.notif-item.unread { background: rgba(2,136,209,0.04); }
.notif-icon {
width: 44px; height: 44px;
border-radius: var(--radius-full);
display: flex; align-items: center; justify-content: center;
font-size: 20px;
flex-shrink: 0;
}
.notif-content { flex: 1; }
.notif-text {
font-size: var(--text-sm);
line-height: 1.4;
margin-bottom: 4px;
}
.notif-time {
font-size: var(--text-xs);
color: var(--neutral-400);
}
.notif-dot {
width: 8px; height: 8px;
border-radius: 50%;
background: var(--alert-info);
flex-shrink: 0;
margin-top: 6px;
}
.section-divider {
padding: 10px 16px;
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
color: var(--neutral-400);
text-transform: uppercase;
letter-spacing: 0.5px;
background: var(--neutral-50);
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="notif-header">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div>
<div class="notif-title">Notifications</div>
<div class="notif-sub">3 non lues · Dernières 24h</div>
</div>
<div style="font-size:var(--text-sm);color:var(--primary-500);font-weight:500;cursor:pointer;">Tout marquer lu</div>
</div>
</div>
<!-- Tabs -->
<div class="notif-tabs">
<div class="notif-tab active">Tout</div>
<div class="notif-tab">🚨 Alertes</div>
<div class="notif-tab">📊 Données</div>
<div class="notif-tab">🏪 Marché</div>
<div class="notif-tab">🔄 Système</div>
</div>
<!-- Notifications list -->
<div class="content-area" style="top:152px;background:var(--neutral-50);">
<!-- Alert - Unread -->
<div class="section-divider">Aujourd'hui</div>
<div class="notif-item unread">
<div class="notif-icon" style="background:rgba(211,47,47,0.1);">🚨</div>
<div class="notif-content">
<div class="notif-text"><strong>Alerte qualité d'air</strong> — Secteur Centre-Ville FDF. Indice AQI élevé détecté (78). Restez vigilant.</div>
<div class="notif-time">Il y a 12 min · IoT Alert</div>
</div>
<div class="notif-dot"></div>
</div>
<div class="notif-item unread">
<div class="notif-icon" style="background:rgba(245,124,0,0.1);"></div>
<div class="notif-content">
<div class="notif-text"><strong>Consommation électrique anormale</strong> — Zone Schœlcher. +34% par rapport à la moyenne.</div>
<div class="notif-time">Il y a 28 min · Smart Grid</div>
</div>
<div class="notif-dot"></div>
</div>
<div class="notif-item unread">
<div class="notif-icon" style="background:rgba(2,136,209,0.1);">🚌</div>
<div class="notif-content">
<div class="notif-text"><strong>Retard ligne A1</strong> — 15 min de retard estimé entre FDF et Schœlcher.</div>
<div class="notif-time">Il y a 45 min · Transport</div>
</div>
<div class="notif-dot"></div>
</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(46,125,50,0.1);">🌡️</div>
<div class="notif-content">
<div class="notif-text">Température stable à <strong>24.2°C</strong> dans votre zone. Tous les capteurs fonctionnent normalement.</div>
<div class="notif-time">Il y a 1h · IoT Update</div>
</div>
</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(0,172,193,0.1);">💧</div>
<div class="notif-content">
<div class="notif-text"><strong>Pluie détectée</strong> — Secteur Nord. Prévision : 2h de précipitations modérées.</div>
<div class="notif-time">Il y a 2h · Météo</div>
</div>
</div>
<!-- Market notification -->
<div class="section-divider">Hier</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(124,77,255,0.1);">🏪</div>
<div class="notif-content">
<div class="notif-text"><strong>Nouveau producteur</strong> — "Jardin Créole" a rejoint le marché. Potirons, christophines !</div>
<div class="notif-time">Hier · Marché Local</div>
</div>
</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(211,47,47,0.1);">📸</div>
<div class="notif-content">
<div class="notif-text"><strong>Signalement traité</strong> — Votre signalement #008 "Nid de poule RN5" est en cours de traitement.</div>
<div class="notif-time">Hier · ODK</div>
</div>
</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(2,136,209,0.1);">📊</div>
<div class="notif-content">
<div class="notif-text"><strong>Rapport hebdomadaire</strong> — Votre résumé Smart City de la semaine est disponible.</div>
<div class="notif-time">Hier · Analytics</div>
</div>
</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(46,125,50,0.1);">🎉</div>
<div class="notif-content">
<div class="notif-text"><strong>Objectif atteint !</strong> — La ville a réduit ses émissions de CO₂ de 5% ce mois-ci.</div>
<div class="notif-time">2 jours · Environnement</div>
</div>
</div>
<div class="notif-item">
<div class="notif-icon" style="background:rgba(245,124,0,0.1);">🔧</div>
<div class="notif-content">
<div class="notif-text"><strong>Maintenance prévue</strong> — Capteurs zone Lamentin indisponibles le 30/05 de 2h à 4h.</div>
<div class="notif-time">2 jours · Système</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<!-- Bottom Nav (empty - accessed from bell icon) -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">07 — Notifications & Alertes</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 08 Signalements Citoyens (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.report-header { padding: 16px; background: var(--primary-500); color: white; }
.report-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.report-sub { font-size: 13px; opacity: 0.8; }
.report-types { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 16px; }
.report-type-card { background: white; border-radius: 16px; padding: 16px; text-align: center; box-shadow: 0 1px 4px rgba(0,0,0,0.06); border: 1px solid var(--neutral-100); cursor: pointer; }
.report-type-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
.report-type-icon { width: 48px; height: 48px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 24px; margin: 0 auto 10px; }
.report-type-name { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
.report-type-count { font-size: 11px; color: var(--neutral-400); }
.section-header-row { display: flex; justify-content: space-between; align-items: center; padding: 0 16px 10px; }
.section-header-title { font-size: 16px; font-weight: 700; }
.report-item { display: flex; gap: 12px; padding: 14px 16px; background: white; margin: 0 16px 8px; border-radius: 12px; border: 1px solid var(--neutral-100); }
.report-status-icon { width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; }
.report-content { flex: 1; }
.report-item-title { font-size: 13px; font-weight: 600; margin-bottom: 2px; }
.report-item-desc { font-size: 11px; color: var(--neutral-500); margin-bottom: 6px; }
.report-item-meta { display: flex; gap: 12px; align-items: center; }
.status-badge { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: 20px; font-size: 10px; font-weight: 600; }
.status-pending { background: rgba(245,124,0,0.1); color: var(--alert-warning); }
.status-progress { background: rgba(2,136,209,0.1); color: var(--alert-info); }
.status-done { background: rgba(46,125,50,0.1); color: var(--alert-success); }
.report-date { font-size: 10px; color: var(--neutral-400); }
.fab-btn { position: absolute; bottom: 100px; right: 16px; width: 56px; height: 56px; border-radius: 50%; background: linear-gradient(135deg, var(--primary-500), var(--primary-600)); box-shadow: 0 4px 16px rgba(21,101,192,0.4); display: flex; align-items: center; justify-content: center; font-size: 28px; color: white; cursor: pointer; z-index: 30; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<div class="report-header">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div>
<div class="report-title">Signalements 📸</div>
<div class="report-sub">ODK Central · 12 signalements actifs</div>
</div>
<div style="font-size:13px;opacity:0.8;font-weight:600;">+ Nouveau</div>
</div>
</div>
<div class="content-area" style="top:88px;background:var(--neutral-50);">
<div style="padding:16px 16px 8px;font-size:16px;font-weight:700;">Catégories</div>
<div class="report-types">
<div class="report-type-card"><div class="report-type-icon" style="background:rgba(211,47,47,0.1);">🕳️</div><div class="report-type-name">Voirie</div><div class="report-type-count">3 signalements</div></div>
<div class="report-type-card"><div class="report-type-icon" style="background:rgba(245,124,0,0.1);">💡</div><div class="report-type-name">Éclairage</div><div class="report-type-count">2 signalements</div></div>
<div class="report-type-card"><div class="report-type-icon" style="background:rgba(2,136,209,0.1);">🌊</div><div class="report-type-name">Inondation</div><div class="report-type-count">1 signalement</div></div>
<div class="report-type-card"><div class="report-type-icon" style="background:rgba(46,125,50,0.1);">🌳</div><div class="report-type-name">Espaces verts</div><div class="report-type-count">4 signalements</div></div>
<div class="report-type-card"><div class="report-type-icon" style="background:rgba(124,77,255,0.1);">🗑️</div><div class="report-type-name">Propreté</div><div class="report-type-count">2 signalements</div></div>
<div class="report-type-card"><div class="report-type-icon" style="background:rgba(0,172,193,0.1);">⚠️</div><div class="report-type-name">Autre</div><div class="report-type-count">+ Ajouter</div></div>
</div>
<div class="section-header-row">
<div class="section-header-title">Mes signalements récents</div>
<div style="font-size:13px;color:var(--primary-500);font-weight:500;">Voir tout →</div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(245,124,0,0.1);">🕳️</div>
<div class="report-content"><div class="report-item-title">Nid de poule — RN5</div><div class="report-item-desc">Gros nid de poule dangereux pour les 2 roues</div><div class="report-item-meta"><div class="status-badge status-progress">🔄 En cours</div><div class="report-date">28 mai</div></div></div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(2,136,209,0.1);">💡</div>
<div class="report-content"><div class="report-item-title">Lampadaire en panne — Av. des Caraïbes</div><div class="report-item-desc">3 lampadaires éteints depuis 3 jours</div><div class="report-item-meta"><div class="status-badge status-pending">⏳ En attente</div><div class="report-date">27 mai</div></div></div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(46,125,50,0.1);">🌳</div>
<div class="report-content"><div class="report-item-title">Arbre dangereux — Parc Floral</div><div class="report-item-desc">Branche morte au-dessus du chemin piéton</div><div class="report-item-meta"><div class="status-badge status-done">✅ Résolu</div><div class="report-date">22 mai</div></div></div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(124,77,255,0.1);">🗑️</div>
<div class="report-content"><div class="report-item-title">Dépôt sauvage — Quartier Corotte</div><div class="report-item-desc">Gravats et encombrants abandonnés</div><div class="report-item-meta"><div class="status-badge status-progress">🔄 En cours</div><div class="report-date">20 mai</div></div></div>
</div>
<div style="padding:16px;">
<div style="background:white;border-radius:16px;padding:16px;border:1px solid var(--neutral-100);">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">
<div style="width:36px;height:36px;background:linear-gradient(135deg,var(--primary-500),var(--primary-400));border-radius:8px;display:flex;align-items:center;justify-content:center;color:white;font-size:18px;">📋</div>
<div><div style="font-weight:700;font-size:13px;">Formulaire rapide</div><div style="font-size:11px;color:var(--neutral-500);">ODK Form · 30 secondes</div></div>
</div>
<div style="display:flex;gap:8px;">
<button class="btn btn-primary" style="flex:1;font-size:13px;min-height:40px;">📸 Photo + GPS</button>
<button class="btn btn-secondary" style="flex:1;font-size:13px;min-height:40px;">📝 Texte seul</button>
</div>
</div>
</div>
<div style="height:80px;"></div>
</div>
<div class="fab-btn">+</div>
<div class="bottom-nav">
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">08 — Signalements Citoyens (ODK) · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,312 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 08 Signalements Citoyens</title>
<link rel="stylesheet" href="shared.css">
<style>
.report-header {
padding: 16px;
background: white;
border-bottom: 1px solid var(--neutral-200);
}
.report-title {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
margin-bottom: 4px;
}
.report-sub {
font-size: var(--text-sm);
color: var(--neutral-500);
}
.report-types {
display: grid; grid-template-columns: 1fr 1fr;
gap: 10px; padding: 16px;
}
.report-type-card {
background: white;
border-radius: var(--radius-lg);
padding: 16px;
text-align: center;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
cursor: pointer;
transition: all 0.2s;
}
.report-type-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
border-color: var(--primary-200);
}
.report-type-icon {
width: 48px; height: 48px;
border-radius: var(--radius-full);
display: flex; align-items: center; justify-content: center;
font-size: 24px;
margin: 0 auto 10px;
}
.report-type-name {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.report-type-count {
font-size: var(--text-xs);
color: var(--neutral-400);
}
.section-header-row {
display: flex; justify-content: space-between;
align-items: center; padding: 0 16px 10px;
}
.section-header-title {
font-size: var(--text-md);
font-weight: var(--weight-bold);
}
.report-item {
display: flex; gap: 12px;
padding: 14px 16px;
background: white;
border-bottom: 1px solid var(--neutral-100);
}
.report-status-icon {
width: 36px; height: 36px;
border-radius: var(--radius-full);
display: flex; align-items: center; justify-content: center;
font-size: 16px;
flex-shrink: 0;
}
.report-content { flex: 1; }
.report-item-title {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.report-item-desc {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-bottom: 6px;
}
.report-item-meta {
display: flex; gap: 12px; align-items: center;
}
.status-badge {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 10px;
border-radius: var(--radius-full);
font-size: 10px;
font-weight: var(--weight-semibold);
}
.status-pending { background: rgba(245,124,0,0.1); color: var(--alert-warning); }
.status-progress { background: rgba(2,136,209,0.1); color: var(--alert-info); }
.status-done { background: rgba(46,125,50,0.1); color: var(--alert-success); }
.report-date { font-size: 10px; color: var(--neutral-400); }
.fab-btn {
position: absolute;
bottom: 100px; right: 16px;
width: 56px; height: 56px;
border-radius: var(--radius-full);
background: linear-gradient(135deg, var(--primary-500), var(--primary-600));
box-shadow: 0 4px 16px rgba(46,125,50,0.4);
display: flex; align-items: center; justify-content: center;
font-size: 28px;
color: white;
cursor: pointer;
z-index: 30;
}
.empty-state {
text-align: center;
padding: 40px 20px;
color: var(--neutral-400);
}
.empty-state-icon { font-size: 48px; margin-bottom: 12px; }
.empty-state-text { font-size: var(--text-sm); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
<style>
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="report-header">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div>
<div class="report-title">Signalements 📸</div>
<div class="report-sub">ODK Central · 12 signalements actifs</div>
</div>
<div style="font-size:var(--text-sm);color:var(--primary-500);font-weight:600;">+ Nouveau</div>
</div>
</div>
<!-- Content -->
<div class="content-area" style="top:80px;background:var(--neutral-50);">
<!-- Report types -->
<div style="padding:16px 16px 8px;font-size:var(--text-md);font-weight:700;">Catégories</div>
<div class="report-types">
<div class="report-type-card">
<div class="report-type-icon" style="background:rgba(211,47,47,0.1);">🕳️</div>
<div class="report-type-name">Voirie</div>
<div class="report-type-count">3 signalements</div>
</div>
<div class="report-type-card">
<div class="report-type-icon" style="background:rgba(245,124,0,0.1);">💡</div>
<div class="report-type-name">Éclairage</div>
<div class="report-type-count">2 signalements</div>
</div>
<div class="report-type-card">
<div class="report-type-icon" style="background:rgba(2,136,209,0.1);">🌊</div>
<div class="report-type-name">Inondation</div>
<div class="report-type-count">1 signalement</div>
</div>
<div class="report-type-card">
<div class="report-type-icon" style="background:rgba(46,125,50,0.1);">🌳</div>
<div class="report-type-name">Espaces verts</div>
<div class="report-type-count">4 signalements</div>
</div>
<div class="report-type-card">
<div class="report-type-icon" style="background:rgba(124,77,255,0.1);">🗑️</div>
<div class="report-type-name">Propreté</div>
<div class="report-type-count">2 signalements</div>
</div>
<div class="report-type-card">
<div class="report-type-icon" style="background:rgba(0,172,193,0.1);">⚠️</div>
<div class="report-type-name">Autre</div>
<div class="report-type-count">+ Ajouter</div>
</div>
</div>
<!-- My reports -->
<div class="section-header-row">
<div class="section-header-title">Mes signalements récents</div>
<div style="font-size:var(--text-sm);color:var(--primary-500);font-weight:500;">Voir tout →</div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(245,124,0,0.1);">🕳️</div>
<div class="report-content">
<div class="report-item-title">Nid de poule — RN5</div>
<div class="report-item-desc">Gros nid de poule dangereux pour les 2 roues</div>
<div class="report-item-meta">
<div class="status-badge status-progress">🔄 En cours</div>
<div class="report-date">28 mai</div>
</div>
</div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(2,136,209,0.1);">💡</div>
<div class="report-content">
<div class="report-item-title">Lampadaire en panne — Av. des Caraïbes</div>
<div class="report-item-desc">3 lampadaires éteints depuis 3 jours</div>
<div class="report-item-meta">
<div class="status-badge status-pending">⏳ En attente</div>
<div class="report-date">27 mai</div>
</div>
</div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(46,125,50,0.1);">🌳</div>
<div class="report-content">
<div class="report-item-title">Arbre dangereux — Parc Floral</div>
<div class="report-item-desc">Branche morte au-dessus du chemin piéton</div>
<div class="report-item-meta">
<div class="status-badge status-done">✅ Résolu</div>
<div class="report-date">22 mai</div>
</div>
</div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(124,77,255,0.1);">🗑️</div>
<div class="report-content">
<div class="report-item-title">Dépôt sauvage — Quartier Corotte</div>
<div class="report-item-desc">Gravats et encombrants abandonnés</div>
<div class="report-item-meta">
<div class="status-badge status-progress">🔄 En cours</div>
<div class="report-date">20 mai</div>
</div>
</div>
</div>
<div class="report-item">
<div class="report-status-icon" style="background:rgba(211,47,47,0.1);">🌊</div>
<div class="report-content">
<div class="report-item-title">Inondation — Ruelle Périgny</div>
<div class="report-item-desc">Eau stagnante après pluie, risque sanitaire</div>
<div class="report-item-meta">
<div class="status-badge status-done">✅ Résolu</div>
<div class="report-date">15 mai</div>
</div>
</div>
</div>
<!-- ODK Form preview -->
<div style="padding:16px;">
<div style="background:white;border-radius:var(--radius-lg);padding:16px;border:1px solid var(--neutral-100);">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">
<div style="width:36px;height:36px;background:linear-gradient(135deg,#2E7D32,#66BB6A);border-radius:8px;display:flex;align-items:center;justify-content:center;color:white;font-size:18px;">📋</div>
<div>
<div style="font-weight:700;font-size:var(--text-sm);">Formulaire rapide</div>
<div style="font-size:var(--text-xs);color:var(--neutral-500);">ODK Form · 30 secondes</div>
</div>
</div>
<div style="display:flex;gap:8px;">
<button class="btn btn-primary" style="flex:1;font-size:13px;min-height:40px;">📸 Photo + GPS</button>
<button class="btn btn-secondary" style="flex:1;font-size:13px;min-height:40px;">📝 Texte seul</button>
</div>
</div>
</div>
<div style="height:80px;"></div>
</div>
<!-- FAB -->
<div class="fab-btn">+</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">08 — Signalements Citoyens (ODK)</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,174 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 09 Météo (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.weather-hero {
background: linear-gradient(160deg, #0D47A1 0%, #1565C0 40%, #0288D1 100%);
padding: 24px 20px 32px;
color: white;
text-align: center;
position: relative; overflow: hidden;
}
.weather-hero::before {
content: ''; position: absolute;
width: 200px; height: 200px; border-radius: 50%;
background: rgba(255,255,255,0.05);
top: -60px; right: -60px;
}
.weather-main-temp { font-size: 72px; font-weight: 200; line-height: 1; }
.weather-main-temp span { font-size: 32px; vertical-align: top; }
.weather-condition { font-size: 20px; margin: 8px 0 4px; }
.weather-location { font-size: 14px; opacity: 0.8; }
.weather-details-grid {
display: grid; grid-template-columns: repeat(3, 1fr);
gap: 12px; padding: 0 20px; margin-top: 20px;
}
.weather-detail-item {
background: rgba(255,255,255,0.12);
border-radius: 12px; padding: 12px;
text-align: center; backdrop-filter: blur(4px);
}
.weather-detail-value { font-size: 18px; font-weight: 700; }
.weather-detail-label { font-size: 10px; opacity: 0.7; margin-top: 2px; }
.forecast-section { padding: 16px; }
.forecast-title { font-size: var(--text-md); font-weight: 700; margin-bottom: 12px; }
.hourly-scroll {
display: flex; gap: 12px; overflow-x: auto;
padding-bottom: 12px; scrollbar-width: none;
}
.hourly-scroll::-webkit-scrollbar { display: none; }
.hourly-item {
flex-shrink: 0; width: 60px; text-align: center;
background: var(--neutral-50); border-radius: 12px; padding: 10px 6px;
}
.hourly-time { font-size: 11px; color: var(--neutral-500); margin-bottom: 4px; }
.hourly-icon { font-size: 24px; margin-bottom: 4px; }
.hourly-temp { font-size: 14px; font-weight: 600; }
.daily-forecast { padding: 0 16px 16px; }
.daily-item {
display: flex; align-items: center; justify-content: space-between;
padding: 12px 0; border-bottom: 1px solid var(--neutral-100);
}
.daily-day { font-size: 14px; font-weight: 500; width: 100px; }
.daily-icon { font-size: 24px; flex: 1; text-align: center; }
.daily-temps { font-size: 14px; }
.daily-temps-high { font-weight: 700; }
.daily-temps-low { color: var(--neutral-400); }
.weather-alert {
margin: 0 16px 12px;
background: rgba(245,124,0,0.08);
border: 1px solid rgba(245,124,0,0.2);
border-radius: 12px; padding: 12px 14px;
display: flex; gap: 10px; align-items: center;
}
.weather-alert-text { font-size: 13px; color: var(--alert-warning); font-weight: 500; }
.sensor-weather-grid {
display: grid; grid-template-columns: repeat(2, 1fr);
gap: 10px; padding: 0 16px 16px;
}
.sensor-w-card {
background: white; border-radius: 12px; padding: 14px;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.sensor-w-value { font-size: 24px; font-weight: 700; color: var(--primary-500); }
.sensor-w-label { font-size: 11px; color: var(--neutral-500); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<!-- Weather Hero -->
<div class="weather-hero">
<div class="weather-main-temp">28<span>°C</span></div>
<div class="weather-condition">⛅ Partiellement nuageux</div>
<div class="weather-location">📍 Fort-de-France, Martinique</div>
<div class="weather-details-grid">
<div class="weather-detail-item">
<div class="weather-detail-value">💧 65%</div>
<div class="weather-detail-label">Humidité</div>
</div>
<div class="weather-detail-item">
<div class="weather-detail-value">💨 12 km/h</div>
<div class="weather-detail-label">Vent</div>
</div>
<div class="weather-detail-item">
<div class="weather-detail-value">☀️ UV 8</div>
<div class="weather-detail-label">Index UV</div>
</div>
</div>
</div>
<div class="content-area" style="top:290px;background:var(--neutral-50);">
<!-- Alert -->
<div class="weather-alert">
<span style="font-size:20px;">🌧️</span>
<div class="weather-alert-text">Pluie prévue à 14h — 80% de probabilité</div>
</div>
<!-- Hourly -->
<div class="forecast-section">
<div class="forecast-title">Prévisions horaires</div>
<div class="hourly-scroll">
<div class="hourly-item"><div class="hourly-time">Maintenant</div><div class="hourly-icon"></div><div class="hourly-temp">28°</div></div>
<div class="hourly-item"><div class="hourly-time">10h</div><div class="hourly-icon">☀️</div><div class="hourly-temp">29°</div></div>
<div class="hourly-item"><div class="hourly-time">11h</div><div class="hourly-icon">☀️</div><div class="hourly-temp">30°</div></div>
<div class="hourly-item"><div class="hourly-time">12h</div><div class="hourly-icon"></div><div class="hourly-temp">31°</div></div>
<div class="hourly-item"><div class="hourly-time">13h</div><div class="hourly-icon">🌤️</div><div class="hourly-temp">30°</div></div>
<div class="hourly-item"><div class="hourly-time">14h</div><div class="hourly-icon">🌧️</div><div class="hourly-temp">27°</div></div>
<div class="hourly-item"><div class="hourly-time">15h</div><div class="hourly-icon">🌧️</div><div class="hourly-temp">26°</div></div>
<div class="hourly-item"><div class="hourly-time">16h</div><div class="hourly-icon"></div><div class="hourly-temp">26°</div></div>
<div class="hourly-item"><div class="hourly-time">17h</div><div class="hourly-icon">🌤️</div><div class="hourly-temp">25°</div></div>
<div class="hourly-item"><div class="hourly-time">18h</div><div class="hourly-icon">🌙</div><div class="hourly-temp">24°</div></div>
</div>
</div>
<!-- Daily -->
<div class="daily-forecast">
<div class="forecast-title">7 prochains jours</div>
<div class="daily-item"><div class="daily-day">Aujourd'hui</div><div class="daily-icon"></div><div class="daily-temps"><span class="daily-temps-high">31°</span> / 24°</div></div>
<div class="daily-item"><div class="daily-day">Jeudi</div><div class="daily-icon">🌧️</div><div class="daily-temps"><span class="daily-temps-high">28°</span> / 23°</div></div>
<div class="daily-item"><div class="daily-day">Vendredi</div><div class="daily-icon">🌧️</div><div class="daily-temps"><span class="daily-temps-high">27°</span> / 23°</div></div>
<div class="daily-item"><div class="daily-day">Samedi</div><div class="daily-icon"></div><div class="daily-temps"><span class="daily-temps-high">29°</span> / 24°</div></div>
<div class="daily-item"><div class="daily-day">Dimanche</div><div class="daily-icon">☀️</div><div class="daily-temps"><span class="daily-temps-high">30°</span> / 24°</div></div>
<div class="daily-item"><div class="daily-day">Lundi</div><div class="daily-icon">☀️</div><div class="daily-temps"><span class="daily-temps-high">31°</span> / 25°</div></div>
<div class="daily-item"><div class="daily-day">Mardi</div><div class="daily-icon"></div><div class="daily-temps"><span class="daily-temps-high">30°</span> / 24°</div></div>
</div>
<!-- IoT Sensors -->
<div class="forecast-section">
<div class="forecast-title">Capteurs météo en direct</div>
<div class="sensor-weather-grid">
<div class="sensor-w-card"><div class="sensor-w-value">28.2°</div><div class="sensor-w-label">Temp. ressentie</div></div>
<div class="sensor-w-card"><div class="sensor-w-value">1013</div><div class="sensor-w-label">Pression (hPa)</div></div>
<div class="sensor-w-card"><div class="sensor-w-value">2.1 mm</div><div class="sensor-w-label">Précipitations 24h</div></div>
<div class="sensor-w-card"><div class="sensor-w-value">8 km</div><div class="sensor-w-label">Visibilité</div></div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">09 — Météo · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,218 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 09 Services Hub</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.services-header {
padding: 16px;
background: linear-gradient(135deg, var(--primary-600), var(--indigo-500));
color: white;
}
.services-title { font-size: var(--text-xl); font-weight: var(--weight-bold); margin-bottom: 4px; }
.services-sub { font-size: var(--text-sm); opacity: 0.8; }
.category-grid {
display: grid; grid-template-columns: 1fr 1fr;
gap: 12px; padding: 16px;
}
.category-card {
background: white;
border-radius: var(--radius-xl);
padding: 18px 14px;
text-align: center;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
cursor: pointer;
transition: all 0.2s;
position: relative;
overflow: hidden;
}
.category-card:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-md);
}
.category-card::after {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 3px;
}
.cat-icon {
width: 52px; height: 52px;
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
font-size: 26px;
margin: 0 auto 10px;
}
.cat-name {
font-size: var(--text-sm);
font-weight: var(--weight-bold);
margin-bottom: 3px;
}
.cat-desc {
font-size: 10px;
color: var(--neutral-500);
line-height: 1.3;
}
.cat-badge {
display: inline-block;
margin-top: 6px;
padding: 2px 8px;
border-radius: var(--radius-full);
font-size: 9px;
font-weight: 600;
}
.section-heading {
padding: 8px 16px 10px;
font-size: var(--text-md);
font-weight: var(--weight-bold);
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<!-- Status Bar -->
<div class="status-bar">
<span>9:41</span>
<div style="display:flex;gap:4px;align-items:center;">
<svg width="16" height="12" viewBox="0 0 16 12"><rect x="0" y="4" width="3" height="8" rx="1" fill="#333"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1" fill="#333"/><rect x="9" y="0" width="3" height="12" rx="1" fill="#333"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" fill="#ccc"/></svg>
</div>
</div>
<!-- Header -->
<div class="services-header">
<div class="services-title">🏛️ Services de la Ville</div>
<div class="services-sub">Tous les services publics et privés au même endroit</div>
</div>
<!-- Content -->
<div class="content-area" style="top:88px;background:var(--neutral-50);">
<div class="section-heading">Services principaux</div>
<div class="category-grid">
<!-- Transport -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E3F2FD,#BBDEFB);">🚌</div>
<div class="cat-name">Transport</div>
<div class="cat-desc">Bus, TCSP, temps réel</div>
<span class="cat-badge" style="background:#E3F2FD;color:#1565C0;">3 lignes</span>
</div>
<!-- Énergie -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#FFF3E0,#FFE0B2);"></div>
<div class="cat-name">Énergie</div>
<div class="cat-desc">Conso, bornes, solaire</div>
<span class="cat-badge" style="background:#FFF3E0;color:#E65100;">IoT Live</span>
</div>
<!-- Santé -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#FCE4EC,#F8BBD0);">🏥</div>
<div class="cat-name">Santé</div>
<div class="cat-desc">Pharmacies, urgences, RDV</div>
<span class="cat-badge" style="background:#FCE4EC;color:#C62828;">24h/24</span>
</div>
<!-- Marché -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E0F7FA,#B2EBF2);">🏪</div>
<div class="cat-name">Marché Local</div>
<div class="cat-desc">Producteurs, livraison</div>
<span class="cat-badge" style="background:#E0F7FA;color:#00838F;">Marché</span>
</div>
<!-- Wallet -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E8EAF6,#C5CAE9);">💳</div>
<div class="cat-name">Wallet DPI</div>
<div class="cat-desc">Paiements, identité</div>
<span class="cat-badge" style="background:#E8EAF6;color:#3949AB;">OTN</span>
</div>
<!-- Signalements -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#FFF9C4,#FFF59D);">📸</div>
<div class="cat-name">Signalements</div>
<div class="cat-desc">ODK, voirie, propreté</div>
<span class="cat-badge" style="background:#FFF9C4;color:#F57F17;">12 actifs</span>
</div>
<!-- Culture -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#F3E5F5,#E1BEE7);">🎭</div>
<div class="cat-name">Culture</div>
<div class="cat-desc">Événements, musées, agenda</div>
<span class="cat-badge" style="background:#F3E5F5;color:#7B1FA2;">5 ce week-end</span>
</div>
<!-- Environnement -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E8F5E9,#C8E6C9);">🌿</div>
<div class="cat-name">Environnement</div>
<div class="cat-desc">Air, eau, déchets, météo</div>
<span class="cat-badge" style="background:#E8F5E9;color:#2E7D32;">60 capteurs</span>
</div>
</div>
<div class="section-heading">Services numériques</div>
<div class="category-grid">
<!-- AI Chat -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E8EAF6,#9FA8DA);">🤖</div>
<div class="cat-name">AI Assistant</div>
<div class="cat-desc">RAG, données temps réel</div>
<span class="cat-badge" style="background:#E8EAF6;color:#3949AB;">RAG</span>
</div>
<!-- Carte -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E0F7FA,#80DEEA);">🗺️</div>
<div class="cat-name">Carte Interactive</div>
<div class="cat-desc">IoT, zones, itinéraires</div>
<span class="cat-badge" style="background:#E0F7FA;color:#00838F;">Live</span>
</div>
<!-- Notifications -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E3F2FD,#90CAF9);">🔔</div>
<div class="cat-name">Alertes</div>
<div class="cat-desc">Push, SMS, email</div>
<span class="cat-badge" style="background:#E3F2FD;color:#1565C0;">3 non lues</span>
</div>
<!-- ODK -->
<div class="category-card">
<div class="cat-icon" style="background:linear-gradient(135deg,#E8F5E9,#A5D6A7);">📋</div>
<div class="cat-name">Formulaires</div>
<div class="cat-desc">Enquêtes, collecte data</div>
<span class="cat-badge" style="background:#E8F5E9;color:#2E7D32;">ODK</span>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg>
<span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg>
<span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>
<span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
<span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
<span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">09 — Services Hub v2 / Blue</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 10 Transport (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.transport-header {
background: linear-gradient(135deg, #1565C0, #0288D1);
padding: 16px; color: white;
}
.transport-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.transport-sub { font-size: 13px; opacity: 0.8; }
.line-card {
background: white; border-radius: 16px; padding: 16px;
margin: 12px 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.line-header { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.line-badge {
width: 40px; height: 40px; border-radius: 12px;
display: flex; align-items: center; justify-content: center;
font-size: 18px; font-weight: 700; color: white;
}
.line-name { font-size: 16px; font-weight: 700; }
.line-route { font-size: 12px; color: var(--neutral-500); }
.line-status { margin-left: auto; text-align: right; }
.status-ontime { color: var(--alert-success); font-size: 12px; font-weight: 600; }
.status-delayed { color: var(--alert-warning); font-size: 12px; font-weight: 600; }
.next-arrivals { display: flex; gap: 8px; }
.arrival-chip {
background: var(--primary-50); color: var(--primary-600);
padding: 4px 10px; border-radius: 8px; font-size: 12px; font-weight: 600;
}
.arrival-chip.soon { background: var(--alert-danger); color: white; }
.map-transport {
margin: 0 16px 12px; height: 180px; border-radius: 16px;
background: linear-gradient(135deg, #E3F2FD, #BBDEFB);
position: relative; overflow: hidden;
}
.nearby-stops { padding: 0 16px 16px; }
.stop-item {
display: flex; align-items: center; gap: 12px;
padding: 12px 0; border-bottom: 1px solid var(--neutral-100);
}
.stop-icon {
width: 36px; height: 36px; border-radius: 50%;
background: #E3F2FD; display: flex; align-items: center; justify-content: center;
font-size: 16px;
}
.stop-info { flex: 1; }
.stop-name { font-size: 14px; font-weight: 600; }
.stop-lines { font-size: 11px; color: var(--neutral-500); }
.stop-distance { font-size: 12px; color: var(--neutral-400); }
.ticket-card {
margin: 0 16px 12px;
background: linear-gradient(135deg, #1565C0, #3949AB);
border-radius: 16px; padding: 16px; color: white;
}
.ticket-title { font-size: 14px; font-weight: 700; margin-bottom: 8px; }
.ticket-options { display: flex; gap: 8px; }
.ticket-option {
background: rgba(255,255,255,0.15); border-radius: 10px;
padding: 8px 12px; text-align: center; flex: 1;
}
.ticket-price { font-size: 18px; font-weight: 700; }
.ticket-type { font-size: 10px; opacity: 0.7; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<div class="transport-header">
<div class="transport-title">🚌 Transport en commun</div>
<div class="transport-sub">Martinique · Temps réel</div>
</div>
<div class="content-area" style="top:80px;background:var(--neutral-50);">
<!-- Map -->
<div class="map-transport">
<svg width="100%" height="100%" viewBox="0 0 360 180">
<rect width="360" height="180" fill="#E3F2FD"/>
<!-- Roads -->
<path d="M20 90 Q100 70 180 80 Q260 90 340 75" stroke="white" stroke-width="4" fill="none" opacity="0.6"/>
<path d="M50 40 Q80 80 70 120 Q60 150 80 170" stroke="white" stroke-width="3" fill="none" opacity="0.5"/>
<path d="M200 30 Q220 70 230 110 Q240 150 260 170" stroke="white" stroke-width="3" fill="none" opacity="0.5"/>
<!-- Bus stops -->
<circle cx="60" cy="85" r="6" fill="#1565C0" stroke="white" stroke-width="2"/>
<circle cx="120" cy="78" r="6" fill="#1565C0" stroke="white" stroke-width="2"/>
<circle cx="180" cy="80" r="6" fill="#1565C0" stroke="white" stroke-width="2"/>
<circle cx="250" cy="82" r="6" fill="#1565C0" stroke="white" stroke-width="2"/>
<circle cx="310" cy="76" r="6" fill="#1565C0" stroke="white" stroke-width="2"/>
<!-- Bus icon -->
<rect x="145" y="68" width="24" height="14" rx="3" fill="#00ACC1" stroke="white" stroke-width="1.5"/>
<text x="157" y="79" font-size="8" fill="white" text-anchor="middle">🚌</text>
</svg>
</div>
<!-- Line A1 -->
<div class="line-card">
<div class="line-header">
<div class="line-badge" style="background:linear-gradient(135deg,#1565C0,#42A5F5);">A1</div>
<div><div class="line-name">Ligne A1</div><div class="line-route">FDF Centre ↔ Trinité</div></div>
<div class="line-status"><div class="status-ontime">● À l'heure</div><div style="font-size:10px;color:var(--neutral-400);">Toutes les 15 min</div></div>
</div>
<div class="next-arrivals">
<div class="arrival-chip soon">3 min</div>
<div class="arrival-chip">18 min</div>
<div class="arrival-chip">33 min</div>
</div>
</div>
<!-- Line B2 -->
<div class="line-card">
<div class="line-header">
<div class="line-badge" style="background:linear-gradient(135deg,#00838F,#26C6DA);">B2</div>
<div><div class="line-name">Ligne B2</div><div class="line-route">Schœlcher ↔ Lamentin</div></div>
<div class="line-status"><div class="status-delayed">⚠ Retard 5 min</div><div style="font-size:10px;color:var(--neutral-400);">Toutes les 20 min</div></div>
</div>
<div class="next-arrivals">
<div class="arrival-chip">8 min</div>
<div class="arrival-chip">28 min</div>
<div class="arrival-chip">48 min</div>
</div>
</div>
<!-- Tickets -->
<div class="ticket-card">
<div class="ticket-title">🎫 Titres de transport</div>
<div class="ticket-options">
<div class="ticket-option"><div class="ticket-price">1.50€</div><div class="ticket-type">Trajet simple</div></div>
<div class="ticket-option"><div class="ticket-price">4.50€</div><div class="ticket-type">Carnet 4 trajets</div></div>
<div class="ticket-option"><div class="ticket-price">35€</div><div class="ticket-type">Mois illimité</div></div>
</div>
</div>
<!-- Nearby stops -->
<div style="padding:0 16px 8px; font-size:16px; font-weight:700;">Arrêts proches 📍</div>
<div class="nearby-stops">
<div class="stop-item">
<div class="stop-icon">🚏</div>
<div class="stop-info"><div class="stop-name">Gare Maritime</div><div class="stop-lines">A1 · B2 · C3</div></div>
<div class="stop-distance">120 m</div>
</div>
<div class="stop-item">
<div class="stop-icon">🚏</div>
<div class="stop-info"><div class="stop-name">Place Perrinon</div><div class="stop-lines">A1 · C3</div></div>
<div class="stop-distance">340 m</div>
</div>
<div class="stop-item">
<div class="stop-icon">🚏</div>
<div class="stop-info"><div class="stop-name">Campus Schoelcher</div><div class="stop-lines">B2 · D4</div></div>
<div class="stop-distance">520 m</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">10 — Transport · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 10 Wallet DPI</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.wallet-header {
padding: 20px 16px;
background: linear-gradient(135deg, var(--primary-700), var(--indigo-600));
color: white;
text-align: center;
}
.wallet-balance-label { font-size: var(--text-sm); opacity: 0.8; margin-bottom: 4px; }
.wallet-balance { font-size: var(--text-4xl); font-weight: var(--weight-bold); margin-bottom: 4px; }
.wallet-balance-sub { font-size: var(--text-xs); opacity: 0.6; }
.wallet-actions {
display: flex; justify-content: center;
gap: 24px; margin-top: 20px;
}
.wallet-action {
display: flex; flex-direction: column;
align-items: center; gap: 6px;
cursor: pointer;
}
.wallet-action-icon {
width: 48px; height: 48px;
border-radius: var(--radius-full);
background: rgba(255,255,255,0.15);
display: flex; align-items: center; justify-content: center;
font-size: 22px;
backdrop-filter: blur(4px);
}
.wallet-action-label { font-size: 10px; opacity: 0.8; }
.tx-item {
display: flex; gap: 12px;
padding: 14px 16px;
background: white;
border-bottom: 1px solid var(--neutral-100);
align-items: center;
}
.tx-icon {
width: 40px; height: 40px;
border-radius: var(--radius-full);
display: flex; align-items: center; justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.tx-info { flex: 1; }
.tx-name { font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.tx-sub { font-size: var(--text-xs); color: var(--neutral-500); }
.tx-amount { font-size: var(--text-sm); font-weight: var(--weight-bold); }
.tx-amount.credit { color: var(--alert-success); }
.tx-amount.debit { color: var(--alert-danger); }
.qr-card {
margin: 16px;
background: white;
border-radius: var(--radius-xl);
padding: 20px;
text-align: center;
box-shadow: var(--shadow-md);
border: 1px solid var(--neutral-100);
}
.qr-placeholder {
width: 120px; height: 120px;
margin: 0 auto 12px;
background: linear-gradient(135deg, var(--primary-50), var(--indigo-50));
border-radius: var(--radius-lg);
display: flex; align-items: center; justify-content: center;
font-size: 48px;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<!-- Wallet Header -->
<div class="wallet-header">
<div class="wallet-balance-label">Solde Wallet</div>
<div class="wallet-balance">247.50 €</div>
<div class="wallet-balance-sub">Mis à jour il y a 2 min · Wallet DPI</div>
<div class="wallet-actions">
<div class="wallet-action">
<div class="wallet-action-icon">📤</div>
<span class="wallet-action-label">Envoyer</span>
</div>
<div class="wallet-action">
<div class="wallet-action-icon">📥</div>
<span class="wallet-action-label">Recevoir</span>
</div>
<div class="wallet-action">
<div class="wallet-action-icon">💳</div>
<span class="wallet-action-label">Payer</span>
</div>
<div class="wallet-action">
<div class="wallet-action-icon">🔄</div>
<span class="wallet-action-label">Échanger</span>
</div>
</div>
</div>
<!-- Content -->
<div class="content-area" style="top:210px;background:var(--neutral-50);">
<!-- QR Code -->
<div class="qr-card">
<div class="qr-placeholder">📱</div>
<div style="font-weight:700;font-size:var(--text-sm);margin-bottom:4px;">Mon QR Code</div>
<div style="font-size:11px;color:var(--neutral-500);">Scannez pour payer · OTN Identity</div>
</div>
<!-- DID Card -->
<div style="margin:0 16px 16px;background:linear-gradient(135deg,#1565C0,#3949AB);border-radius:var(--radius-xl);padding:16px;color:white;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div style="font-size:var(--text-sm);font-weight:700;">Identité Décentralisée</div>
<div style="background:rgba(255,255,255,0.2);padding:3px 10px;border-radius:var(--radius-full);font-size:9px;font-weight:600;">DID</div>
</div>
<div style="font-size:11px;opacity:0.8;font-family:var(--font-family-mono);word-break:break-all;">
did:otn:mq:0x7a3...f92d
</div>
<div style="margin-top:10px;display:flex;gap:8px;">
<button class="btn" style="background:rgba(255,255,255,0.2);color:white;padding:6px 14px;font-size:12px;min-height:34px;">Copier</button>
<button class="btn" style="background:rgba(255,255,255,0.2);color:white;padding:6px 14px;font-size:12px;min-height:34px;">Vérifier</button>
</div>
</div>
<!-- Transactions -->
<div style="display:flex;justify-content:space-between;align-items:center;padding:0 16px 10px;">
<div style="font-size:var(--text-md);font-weight:700;">Transactions récentes</div>
<div style="font-size:var(--text-sm);color:var(--primary-500);font-weight:500;">Tout voir →</div>
</div>
<div class="tx-item">
<div class="tx-icon" style="background:#E8F5E9;">🥭</div>
<div class="tx-info">
<div class="tx-name">Marché Sainte-Marie</div>
<div class="tx-sub">Mangue José · Il y a 2h</div>
</div>
<div class="tx-amount debit">-4.50 €</div>
</div>
<div class="tx-item">
<div class="tx-icon" style="background:#E3F2FD;">🚌</div>
<div class="tx-info">
<div class="tx-name">Bus Ligne A1</div>
<div class="tx-sub">Ticket mobile · Il y a 5h</div>
</div>
<div class="tx-amount debit">-1.80 €</div>
</div>
<div class="tx-item">
<div class="tx-icon" style="background:#FFF3E0;"></div>
<div class="tx-info">
<div class="tx-name">Recharge Borne</div>
<div class="tx-sub">Borne Centre-ville · Hier</div>
</div>
<div class="tx-amount debit">-3.20 €</div>
</div>
<div class="tx-item">
<div class="tx-icon" style="background:#E0F7FA;">📥</div>
<div class="tx-info">
<div class="tx-name">Reçu de Marie L.</div>
<div class="tx-sub">Remboursement · Hier</div>
</div>
<div class="tx-amount credit">+15.00 €</div>
</div>
<div class="tx-item">
<div class="tx-icon" style="background:#E8EAF6;">🏛️</div>
<div class="tx-info">
<div class="tx-name">Taxe Ville Verte</div>
<div class="tx-sub">Points convertis · 2 jours</div>
</div>
<div class="tx-amount credit">+25.00 €</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">10 — Wallet DPI v2 / Blue</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,265 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 11 Bus Tracker</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.bus-header {
padding: 16px;
background: linear-gradient(135deg, var(--ocean-600), var(--primary-500));
color: white;
}
.bus-title { font-size: var(--text-xl); font-weight: var(--weight-bold); margin-bottom: 4px; }
.bus-sub { font-size: var(--text-sm); opacity: 0.8; }
.line-selector {
display: flex; gap: 8px; padding: 12px 16px;
overflow-x: auto; scrollbar-width: none;
}
.line-badge {
flex-shrink: 0;
padding: 8px 16px;
border-radius: var(--radius-full);
font-size: var(--text-sm);
font-weight: var(--weight-bold);
cursor: pointer;
border: 2px solid var(--neutral-200);
background: white;
color: var(--neutral-600);
}
.line-badge.active {
background: var(--primary-500);
color: white;
border-color: var(--primary-500);
}
.line-badge .line-dot {
display: inline-block;
width: 10px; height: 10px;
border-radius: 50%;
margin-right: 6px;
}
.stop-item {
display: flex;
align-items: flex-start;
gap: 14px;
padding: 0 16px;
position: relative;
}
.stop-line {
display: flex;
flex-direction: column;
align-items: center;
width: 24px;
flex-shrink: 0;
}
.stop-dot {
width: 14px; height: 14px;
border-radius: 50%;
border: 3px solid var(--primary-500);
background: white;
z-index: 1;
}
.stop-dot.active {
background: var(--primary-500);
box-shadow: 0 0 0 4px rgba(21,101,192,0.2);
}
.stop-dot.past {
background: var(--neutral-300);
border-color: var(--neutral-300);
}
.stop-connector {
flex: 1;
width: 2px;
background: var(--neutral-200);
margin-top: -2px;
}
.stop-info {
padding-bottom: 20px;
flex: 1;
}
.stop-name {
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
margin-bottom: 2px;
}
.stop-time {
font-size: var(--text-xs);
color: var(--neutral-500);
}
.bus-eta {
display: inline-flex;
align-items: center;
gap: 4px;
background: var(--primary-50);
color: var(--primary-600);
padding: 3px 10px;
border-radius: var(--radius-full);
font-size: 11px;
font-weight: 700;
margin-top: 4px;
}
.bus-eta.now {
background: var(--alert-success);
color: white;
}
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<!-- Header -->
<div class="bus-header">
<div class="bus-title">🚌 Transport en Temps Réel</div>
<div class="bus-sub">Lignes de bus Martinique · Services Ville</div>
</div>
<!-- Line Selector -->
<div class="line-selector">
<div class="line-badge active"><span class="line-dot" style="background:#1565C0;"></span>A1</div>
<div class="line-badge"><span class="line-dot" style="background:#00ACC1;"></span>B2</div>
<div class="line-badge"><span class="line-dot" style="background:#F57C00;"></span>C3</div>
<div class="line-badge"><span class="line-dot" style="background:#2E7D32;"></span>D4</div>
<div class="line-badge"><span class="line-dot" style="background:#D32F2F;"></span>E5</div>
</div>
<!-- Map Preview -->
<div style="margin:0 16px 12px;height:120px;background:linear-gradient(135deg,#E3F2FD,#BBDEFB);border-radius:var(--radius-lg);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;">
<svg width="100%" height="100%" viewBox="0 0 358 120" style="position:absolute;">
<!-- Route path -->
<path d="M30 90 Q80 60 130 50 Q180 40 230 35 Q280 30 330 20" stroke="#1565C0" stroke-width="3" fill="none" stroke-dasharray="6 3" opacity="0.5"/>
<!-- Stops -->
<circle cx="30" cy="90" r="5" fill="#1565C0"/>
<circle cx="80" cy="68" r="4" fill="#1565C0" opacity="0.7"/>
<circle cx="130" cy="50" r="5" fill="#1565C0">
<animate attributeName="r" values="5;8;5" dur="2s" repeatCount="indefinite"/>
</circle>
<circle cx="180" cy="42" r="4" fill="#1565C0" opacity="0.7"/>
<circle cx="230" cy="35" r="4" fill="#90CAF9"/>
<circle cx="280" cy="30" r="4" fill="#90CAF9"/>
<circle cx="330" cy="20" r="4" fill="#90CAF9"/>
<!-- Bus icon -->
<g transform="translate(120, 36)">
<rect x="-12" y="-8" width="24" height="16" rx="4" fill="#1565C0"/>
<text x="0" y="4" text-anchor="middle" font-size="10" fill="white">🚌</text>
</g>
</svg>
<div style="position:absolute;bottom:8px;right:10px;background:white;border-radius:8px;padding:4px 10px;font-size:10px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,0.1);">
🟢 3 bus actifs
</div>
</div>
<!-- Stops list -->
<div style="padding:0 16px 8px;font-size:var(--text-md);font-weight:700;">Arrêts — Ligne A1</div>
<div class="content-area" style="top:290px;bottom:80px;background:var(--neutral-50);overflow-y:auto;">
<!-- Past stop -->
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot past"></div>
<div class="stop-connector" style="height:30px;"></div>
</div>
<div class="stop-info">
<div class="stop-name" style="color:var(--neutral-400);">Gare Maritime</div>
<div class="stop-time">Passé · 09:15</div>
</div>
</div>
<!-- Past stop -->
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot past"></div>
<div class="stop-connector" style="height:30px;"></div>
</div>
<div class="stop-info">
<div class="stop-name" style="color:var(--neutral-400);">Place Perrinon</div>
<div class="stop-time">Passé · 09:18</div>
</div>
</div>
<!-- Current stop -->
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot active"></div>
<div class="stop-connector" style="height:30px;"></div>
</div>
<div class="stop-info">
<div class="stop-name" style="color:var(--primary-600);">Fort-de-France Centre 📍</div>
<div class="stop-time">Vous êtes ici</div>
<div class="bus-eta now">🚌 Bus dans 3 min</div>
</div>
</div>
<!-- Next stops -->
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot"></div>
<div class="stop-connector" style="height:30px;"></div>
</div>
<div class="stop-info">
<div class="stop-name">Schœlcher — UFR</div>
<div class="stop-time">Estimé 09:28</div>
<div class="bus-eta">⏱️ 8 min</div>
</div>
</div>
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot"></div>
<div class="stop-connector" style="height:30px;"></div>
</div>
<div class="stop-info">
<div class="stop-name">Campus Schoelcher</div>
<div class="stop-time">Estimé 09:33</div>
<div class="bus-eta">⏱️ 13 min</div>
</div>
</div>
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot"></div>
<div class="stop-connector" style="height:30px;"></div>
</div>
<div class="stop-info">
<div class="stop-name">Trinité — Centre</div>
<div class="stop-time">Estimé 09:45</div>
<div class="bus-eta">⏱️ 25 min</div>
</div>
</div>
<div class="stop-item">
<div class="stop-line">
<div class="stop-dot"></div>
</div>
<div class="stop-info">
<div class="stop-name">Boulevard du Général de Gaulle</div>
<div class="stop-time">Estimé 09:52</div>
<div class="bus-eta">⏱️ 32 min</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">11 — Bus Tracker v2 / Blue</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 11 Énergie & Environnement (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.energy-header {
background: linear-gradient(135deg, #1565C0, #00838F);
padding: 16px; color: white;
}
.energy-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.energy-sub { font-size: 13px; opacity: 0.8; }
.energy-dashboard {
display: grid; grid-template-columns: repeat(2, 1fr);
gap: 10px; padding: 16px;
}
.energy-card {
background: white; border-radius: 16px; padding: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.energy-card-icon { font-size: 28px; margin-bottom: 8px; }
.energy-card-value { font-size: 24px; font-weight: 700; color: var(--primary-500); }
.energy-card-unit { font-size: 12px; color: var(--neutral-500); }
.energy-card-label { font-size: 11px; color: var(--neutral-500); margin-top: 4px; }
.energy-card-trend { font-size: 11px; margin-top: 4px; }
.trend-up { color: var(--alert-success); }
.trend-down { color: var(--alert-danger); }
.chart-container {
margin: 0 16px 16px; background: white; border-radius: 16px;
padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.chart-title { font-size: 14px; font-weight: 700; margin-bottom: 12px; }
.bar-chart { display: flex; align-items: flex-end; gap: 6px; height: 100px; }
.bar {
flex: 1; border-radius: 4px 4px 0 0;
background: linear-gradient(to top, var(--primary-500), var(--primary-300));
position: relative;
}
.bar-label {
position: absolute; bottom: -18px; left: 50%; transform: translateX(-50%);
font-size: 9px; color: var(--neutral-500);
}
.co2-gauge {
margin: 0 16px 16px; background: white; border-radius: 16px;
padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100); text-align: center;
}
.gauge-value { font-size: 36px; font-weight: 700; color: var(--alert-success); }
.gauge-label { font-size: 12px; color: var(--neutral-500); }
.gauge-bar {
height: 8px; background: var(--neutral-200); border-radius: 4px;
margin: 12px 0 8px; overflow: hidden;
}
.gauge-fill { height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--alert-success), var(--alert-warning), var(--alert-danger)); }
.waste-section { padding: 0 16px 16px; }
.waste-item {
display: flex; align-items: center; gap: 12px;
background: white; border-radius: 12px; padding: 12px;
margin-bottom: 8px; border: 1px solid var(--neutral-100);
}
.waste-icon { font-size: 24px; }
.waste-info { flex: 1; }
.waste-label { font-size: 13px; font-weight: 600; }
.waste-status { font-size: 11px; color: var(--neutral-500); }
.waste-level {
width: 60px; height: 8px; background: var(--neutral-200);
border-radius: 4px; overflow: hidden;
}
.waste-fill { height: 100%; border-radius: 4px; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<div class="energy-header">
<div class="energy-title">⚡ Énergie & Environnement</div>
<div class="energy-sub">Martinique · Données en temps réel</div>
</div>
<div class="content-area" style="top:80px;background:var(--neutral-50);">
<!-- Dashboard cards -->
<div class="energy-dashboard">
<div class="energy-card">
<div class="energy-card-icon"></div>
<div class="energy-card-value">3.2</div>
<div class="energy-card-unit">MW consommés</div>
<div class="energy-card-label">Consommation actuelle</div>
<div class="energy-card-trend trend-down">↓ -5% vs hier</div>
</div>
<div class="energy-card">
<div class="energy-card-icon">☀️</div>
<div class="energy-card-value">1.8</div>
<div class="energy-card-unit">MW solaire</div>
<div class="energy-card-label">Production solaire</div>
<div class="energy-card-trend trend-up">↑ +12% vs hier</div>
</div>
<div class="energy-card">
<div class="energy-card-icon">💧</div>
<div class="energy-card-value">98.2%</div>
<div class="energy-card-unit">Qualité eau</div>
<div class="energy-card-label">Indice qualité réseau</div>
<div class="energy-card-trend trend-up">↑ Excellent</div>
</div>
<div class="energy-card">
<div class="energy-card-icon">🌡️</div>
<div class="energy-card-value">24.3</div>
<div class="energy-card-unit">°C moyenne</div>
<div class="energy-card-label">Température ville</div>
<div class="energy-card-trend">→ Stable</div>
</div>
</div>
<!-- Consumption chart -->
<div class="chart-container">
<div class="chart-title">Consommation électrique — 24h</div>
<div class="bar-chart">
<div class="bar" style="height:30%;"><span class="bar-label">0h</span></div>
<div class="bar" style="height:25%;"><span class="bar-label">4h</span></div>
<div class="bar" style="height:35%;"><span class="bar-label">8h</span></div>
<div class="bar" style="height:55%;"><span class="bar-label">10h</span></div>
<div class="bar" style="height:70%;"><span class="bar-label">12h</span></div>
<div class="bar" style="height:65%;"><span class="bar-label">14h</span></div>
<div class="bar" style="height:80%;"><span class="bar-label">16h</span></div>
<div class="bar" style="height:90%;"><span class="bar-label">18h</span></div>
<div class="bar" style="height:100%;"><span class="bar-label">20h</span></div>
<div class="bar" style="height:75%;"><span class="bar-label">22h</span></div>
</div>
</div>
<!-- CO2 Gauge -->
<div class="co2-gauge">
<div class="gauge-value">-5.2%</div>
<div class="gauge-label">Réduction CO₂ ce mois-ci vs année dernière</div>
<div class="gauge-bar"><div class="gauge-fill" style="width:65%;"></div></div>
<div style="display:flex;justify-content:space-between;font-size:10px;color:var(--neutral-400);">
<span>0%</span><span>Objectif: -10%</span>
</div>
</div>
<!-- Waste management -->
<div style="padding:0 16px 8px; font-size:16px; font-weight:700;">🗑️ Gestion des déchets</div>
<div class="waste-section">
<div class="waste-item">
<div class="waste-icon">♻️</div>
<div class="waste-info"><div class="waste-label">Tri sélectif</div><div class="waste-status">Collecte demain · 7h</div></div>
<div class="waste-level"><div class="waste-fill" style="width:45%;background:var(--alert-success);"></div></div>
</div>
<div class="waste-item">
<div class="waste-icon">🗑️</div>
<div class="waste-info"><div class="waste-label">Ordures ménagères</div><div class="waste-status">Collecte demain · 6h</div></div>
<div class="waste-level"><div class="waste-fill" style="width:72%;background:var(--alert-warning);"></div></div>
</div>
<div class="waste-item">
<div class="waste-icon">🌿</div>
<div class="waste-info"><div class="waste-label">Déchets verts</div><div class="waste-status">Prochaine collecte: vendredi</div></div>
<div class="waste-level"><div class="waste-fill" style="width:30%;background:var(--alert-success);"></div></div>
</div>
</div>
<!-- Water quality -->
<div style="padding:0 16px 8px; font-size:16px; font-weight:700;">💧 Qualité de l'eau</div>
<div class="energy-dashboard" style="padding-top:0;">
<div class="energy-card">
<div class="energy-card-value" style="color:var(--ocean-500);">7.2</div>
<div class="energy-card-label">pH moyen réseau</div>
</div>
<div class="energy-card">
<div class="energy-card-value" style="color:var(--alert-success);">0.3</div>
<div class="energy-card-label">Chlore (mg/L)</div>
</div>
<div class="energy-card">
<div class="energy-card-value" style="color:var(--alert-success);">99.1%</div>
<div class="energy-card-label">Conformité bactério.</div>
</div>
<div class="energy-card">
<div class="energy-card-value" style="color:var(--primary-500);">12</div>
<div class="energy-card-label">Capteurs actifs</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">11 — Énergie & Environnement · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,197 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 12 Énergie Monitoring</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.energy-header {
padding: 16px;
background: linear-gradient(135deg, #F57C00, #E65100);
color: white;
}
.energy-title { font-size: var(--text-xl); font-weight: var(--weight-bold); margin-bottom: 4px; }
.energy-sub { font-size: var(--text-sm); opacity: 0.85; }
.consumption-card {
margin: 16px;
background: white;
border-radius: var(--radius-xl);
padding: 18px;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.consumption-value {
font-size: var(--text-4xl);
font-weight: var(--weight-bold);
color: var(--primary-600);
}
.consumption-unit { font-size: var(--text-base); color: var(--neutral-500); }
.consumption-bar {
height: 8px;
background: var(--neutral-100);
border-radius: var(--radius-full);
margin-top: 12px;
overflow: hidden;
}
.consumption-bar-fill {
height: 100%;
border-radius: var(--radius-full);
background: linear-gradient(90deg, var(--alert-success), var(--alert-warning), var(--alert-danger));
}
.zone-card {
display: flex; gap: 12px;
padding: 14px 16px;
background: white;
border-bottom: 1px solid var(--neutral-100);
align-items: center;
}
.zone-icon {
width: 44px; height: 44px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 20px;
flex-shrink: 0;
}
.zone-info { flex: 1; }
.zone-name { font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.zone-value { font-size: var(--text-xs); color: var(--neutral-500); }
.zone-status {
padding: 3px 10px;
border-radius: var(--radius-full);
font-size: 10px;
font-weight: 600;
}
.status-normal { background: rgba(46,125,50,0.1); color: var(--alert-success); }
.status-warn { background: rgba(245,124,0,0.1); color: var(--alert-warning); }
.status-alert { background: rgba(211,47,47,0.1); color: var(--alert-danger); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<!-- Header -->
<div class="energy-header">
<div class="energy-title">⚡ Monitoring Énergie</div>
<div class="energy-sub">Consommation en temps réel · Smart Grid Martinique</div>
</div>
<!-- Content -->
<div class="content-area" style="top:88px;background:var(--neutral-50);">
<!-- Main consumption -->
<div class="consumption-card">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
<div style="font-size:var(--text-sm);color:var(--neutral-600);">Consommation aujourd'hui</div>
<div style="background:#E3F2FD;padding:3px 10px;border-radius:var(--radius-full);font-size:10px;font-weight:600;color:#1565C0;">📡 IoT Live</div>
</div>
<div style="display:flex;align-items:baseline;gap:6px;">
<span class="consumption-value">12.4</span>
<span class="consumption-unit">kWh · -8% vs hier</span>
</div>
<div class="consumption-bar">
<div class="consumption-bar-fill" style="width:62%;"></div>
</div>
<div style="display:flex;justify-content:space-between;margin-top:6px;font-size:10px;color:var(--neutral-400);">
<span>0 kWh</span>
<span>Objectif: 20 kWh</span>
</div>
</div>
<!-- Solar production -->
<div style="margin:0 16px 16px;background:linear-gradient(135deg,#FFF9C4,#FFF176);border-radius:var(--radius-xl);padding:16px;border:1px solid #FDD835;">
<div style="display:flex;align-items:center;gap:10px;">
<div style="font-size:32px;">☀️</div>
<div>
<div style="font-weight:700;font-size:var(--text-base);">Production solaire</div>
<div style="font-size:28px;font-weight:700;color:#F57F17;">3.8 kWh</div>
<div style="font-size:11px;color:#F9A825;">5 panneaux · 87% efficiency</div>
</div>
</div>
</div>
<!-- Bornes -->
<div style="display:flex;gap:8px;padding:0 16px 12px;">
<div style="flex:1;background:white;border-radius:var(--radius-lg);padding:12px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);">
<div style="font-size:22px;margin-bottom:4px;">🔌</div>
<div style="font-size:var(--text-xl);font-weight:700;color:var(--primary-500);">4</div>
<div style="font-size:10px;color:var(--neutral-500);">Bornes libres</div>
</div>
<div style="flex:1;background:white;border-radius:var(--radius-lg);padding:12px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);">
<div style="font-size:22px;margin-bottom:4px;">🔋</div>
<div style="font-size:var(--text-xl);font-weight:700;color:var(--alert-success);">78%</div>
<div style="font-size:10px;color:var(--neutral-500);">Batterie ville</div>
</div>
<div style="flex:1;background:white;border-radius:var(--radius-lg);padding:12px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);">
<div style="font-size:22px;margin-bottom:4px;">🌡️</div>
<div style="font-size:var(--text-xl);font-weight:700;color:var(--ocean-500);">24°</div>
<div style="font-size:10px;color:var(--neutral-500);">Temp. réseau</div>
</div>
</div>
<!-- Zones -->
<div style="padding:0 16px 8px;font-size:var(--text-md);font-weight:700;">Par zone</div>
<div class="zone-card">
<div class="zone-icon" style="background:#E3F2FD;">🏙️</div>
<div class="zone-info">
<div class="zone-name">Fort-de-France Centre</div>
<div class="zone-value">4.2 kWh · Stable</div>
</div>
<div class="zone-status status-normal">Normal</div>
</div>
<div class="zone-card">
<div class="zone-icon" style="background:#FFF3E0;">🏫</div>
<div class="zone-info">
<div class="zone-name">Schœlcher — Campus</div>
<div class="zone-value">3.8 kWh · -12%</div>
</div>
<div class="zone-status status-normal">Normal</div>
</div>
<div class="zone-card">
<div class="zone-icon" style="background:#FFF9C4;">🏭</div>
<div class="zone-info">
<div class="zone-name">Zone Industrielle Lamentin</div>
<div class="zone-value">5.1 kWh · +34%</div>
</div>
<div class="zone-status status-warn">Élevé</div>
</div>
<div class="zone-card">
<div class="zone-icon" style="background:#FCE4EC;">🏥</div>
<div class="zone-info">
<div class="zone-name">CHU — Pothière</div>
<div class="zone-value">2.9 kWh · Stable</div>
</div>
<div class="zone-status status-normal">Normal</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">12 — Monitoring Énergie v2 / Blue</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,180 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 12 Santé & Bien-être (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.health-header {
background: linear-gradient(135deg, #00838F, #00ACC1);
padding: 16px; color: white;
}
.health-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.health-sub { font-size: 13px; opacity: 0.8; }
.health-alert-banner {
margin: 12px 16px;
background: linear-gradient(135deg, rgba(211,47,47,0.08), rgba(245,124,0,0.08));
border: 1px solid rgba(211,47,47,0.2);
border-radius: 12px; padding: 12px 14px;
display: flex; gap: 10px; align-items: center;
}
.health-alert-text { font-size: 13px; font-weight: 600; color: var(--alert-danger); }
.health-cards {
display: grid; grid-template-columns: repeat(2, 1fr);
gap: 10px; padding: 0 16px 16px;
}
.health-card {
background: white; border-radius: 16px; padding: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.health-card-icon { font-size: 28px; margin-bottom: 8px; }
.health-card-value { font-size: 22px; font-weight: 700; }
.health-card-label { font-size: 11px; color: var(--neutral-500); margin-top: 4px; }
.establishment-list { padding: 0 16px 16px; }
.est-item {
display: flex; align-items: center; gap: 12px;
background: white; border-radius: 12px; padding: 14px;
margin-bottom: 8px; border: 1px solid var(--neutral-100);
}
.est-icon {
width: 44px; height: 44px; border-radius: 12px;
display: flex; align-items: center; justify-content: center;
font-size: 20px;
}
.est-info { flex: 1; }
.est-name { font-size: 14px; font-weight: 600; }
.est-address { font-size: 11px; color: var(--neutral-500); }
.est-status { font-size: 11px; font-weight: 600; }
.est-open { color: var(--alert-success); }
.est-closed { color: var(--alert-danger); }
.est-distance { font-size: 11px; color: var(--neutral-400); }
.air-quality-health {
margin: 0 16px 16px; background: white; border-radius: 16px;
padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.aqi-display { display: flex; align-items: center; gap: 16px; }
.aqi-circle {
width: 80px; height: 80px; border-radius: 50%;
background: conic-gradient(var(--alert-success) 0deg 151deg, var(--neutral-200) 151deg 360deg);
display: flex; align-items: center; justify-content: center;
position: relative;
}
.aqi-circle::before {
content: ''; position: absolute;
width: 60px; height: 60px; border-radius: 50%; background: white;
}
.aqi-value { position: relative; z-index: 1; font-size: 24px; font-weight: 700; color: var(--alert-success); }
.aqi-label { font-size: 14px; font-weight: 600; }
.aqi-desc { font-size: 12px; color: var(--neutral-500); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<div class="health-header">
<div class="health-title">🏥 Santé & Bien-être</div>
<div class="health-sub">Martinique · Services de santé</div>
</div>
<div class="content-area" style="top:80px;background:var(--neutral-50);">
<!-- Health alert -->
<div class="health-alert-banner">
<span style="font-size:20px;">🦟</span>
<div class="health-alert-text">Alerte dengue — Cas confirmés en augmentation. Protégez-vous.</div>
</div>
<!-- Health metrics -->
<div class="health-cards">
<div class="health-card">
<div class="health-card-icon">🌡️</div>
<div class="health-card-value" style="color:var(--alert-success);">UV 8</div>
<div class="health-card-label">Index UV — Très élevé</div>
</div>
<div class="health-card">
<div class="health-card-icon">💨</div>
<div class="health-card-value" style="color:var(--alert-success);">AQI 42</div>
<div class="health-card-label">Qualité air — Bon</div>
</div>
<div class="health-card">
<div class="health-card-icon">💧</div>
<div class="health-card-value" style="color:var(--ocean-500);">98.2%</div>
<div class="health-card-label">Qualité eau — Excellent</div>
</div>
<div class="health-card">
<div class="health-card-icon">🌡️</div>
<div class="health-card-value" style="color:var(--primary-500);">28°C</div>
<div class="health-card-label">Température ressentie</div>
</div>
</div>
<!-- Air quality health card -->
<div class="air-quality-health">
<div style="font-size:14px; font-weight:700; margin-bottom:12px;">Qualité de l'air — Impact santé</div>
<div class="aqi-display">
<div class="aqi-circle"><div class="aqi-value">42</div></div>
<div>
<div class="aqi-label">Bon 🟢</div>
<div class="aqi-desc">Qualité de l'air satisfaisante. Peu ou pas de risque pour la santé.</div>
<div style="font-size:11px; color:var(--neutral-500); margin-top:4px;">Source: AirQ-012 · Il y a 3 min</div>
</div>
</div>
</div>
<!-- Nearby establishments -->
<div style="padding:0 16px 8px; font-size:16px; font-weight:700;">Établissements proches 📍</div>
<div class="establishment-list">
<div class="est-item">
<div class="est-icon" style="background:#FCE4EC;">🏥</div>
<div class="est-info"><div class="est-name">CHU de Martinique</div><div class="est-address">Route de Chateauboeuf, FDF</div></div>
<div><div class="est-status est-open">● Ouvert</div><div class="est-distance">1.2 km</div></div>
</div>
<div class="est-item">
<div class="est-icon" style="background:#E0F7FA;">💊</div>
<div class="est-info"><div class="est-name">Pharmacie de garde — FDF</div><div class="est-address">Av. des Caraïbes</div></div>
<div><div class="est-status est-open">● 24h/24</div><div class="est-distance">800 m</div></div>
</div>
<div class="est-item">
<div class="est-icon" style="background:#E8F5E9;">🚑</div>
<div class="est-info"><div class="est-name">SAMU / Urgences</div><div class="est-address">Numéro: 15 / 112</div></div>
<div><div class="est-status est-open">● Disponible</div><div class="est-distance"></div></div>
</div>
<div class="est-item">
<div class="est-icon" style="background:#FFF3E0;">🦷</div>
<div class="est-info"><div class="est-name">Cabinet dentaire — Schoelcher</div><div class="est-address">Campus universitaire</div></div>
<div><div class="est-status est-closed">○ Fermé</div><div class="est-distance">2.1 km</div></div>
</div>
</div>
<!-- Health tips -->
<div style="padding:0 16px 8px; font-size:16px; font-weight:700;">💡 Conseils santé</div>
<div style="margin:0 16px 16px; background:white; border-radius:12px; padding:14px; border:1px solid var(--neutral-100);">
<div style="font-size:13px; margin-bottom:8px;">☀️ <strong>UV élevé</strong> — Portez lunettes de soleil et crème solaire SPF 50+</div>
<div style="font-size:13px; margin-bottom:8px;">💧 <strong>Hydratation</strong> — Buvez au minimum 2L d'eau par jour avec cette chaleur</div>
<div style="font-size:13px;">🦟 <strong>Dengue</strong> — Utilisez des répulsifs et éliminez les eaux stagnantes</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">12 — Santé & Bien-être · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,184 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 13 Événements & Culture (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.event-header {
background: linear-gradient(135deg, #3949AB, #1565C0);
padding: 16px; color: white;
}
.event-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
.event-sub { font-size: 13px; opacity: 0.8; }
.event-filters {
display: flex; gap: 8px; padding: 12px 16px;
overflow-x: auto; scrollbar-width: none;
}
.event-filters::-webkit-scrollbar { display: none; }
.event-filter {
flex-shrink: 0; padding: 8px 16px; border-radius: 20px;
font-size: 13px; font-weight: 500;
background: var(--neutral-100); color: var(--neutral-600);
cursor: pointer; white-space: nowrap;
}
.event-filter.active { background: var(--primary-500); color: white; }
.featured-event {
margin: 0 16px 16px;
border-radius: 16px; overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
}
.featured-img {
height: 160px;
background: linear-gradient(135deg, #1565C0, #00ACC1);
display: flex; align-items: center; justify-content: center;
font-size: 64px; position: relative;
}
.featured-badge {
position: absolute; top: 12px; left: 12px;
background: rgba(255,255,255,0.9); color: var(--primary-600);
padding: 4px 12px; border-radius: 20px;
font-size: 11px; font-weight: 700;
}
.featured-info { background: white; padding: 16px; }
.featured-name { font-size: 18px; font-weight: 700; margin-bottom: 4px; }
.featured-meta { font-size: 12px; color: var(--neutral-500); margin-bottom: 8px; }
.featured-desc { font-size: 13px; color: var(--neutral-600); }
.event-item {
display: flex; gap: 12px; padding: 12px 16px;
background: white; margin: 0 16px 8px;
border-radius: 12px; border: 1px solid var(--neutral-100);
}
.event-date-box {
width: 52px; height: 52px; border-radius: 12px;
background: linear-gradient(135deg, var(--primary-500), var(--primary-400));
display: flex; flex-direction: column; align-items: center; justify-content: center;
color: white; flex-shrink: 0;
}
.event-date-day { font-size: 20px; font-weight: 700; line-height: 1; }
.event-date-month { font-size: 10px; text-transform: uppercase; opacity: 0.8; }
.event-info { flex: 1; }
.event-name { font-size: 14px; font-weight: 600; margin-bottom: 2px; }
.event-details { font-size: 11px; color: var(--neutral-500); }
.event-tag {
display: inline-block; padding: 2px 8px; border-radius: 6px;
font-size: 9px; font-weight: 600; margin-top: 4px;
}
.tag-music { background: #E8EAF6; color: #3949AB; }
.tag-sport { background: #E0F7FA; color: #00838F; }
.tag-culture { background: #FFF3E0; color: #E65100; }
.tag-food { background: #FCE4EC; color: #C62828; }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<div class="event-header">
<div class="event-title">🎉 Événements & Culture</div>
<div class="event-sub">Martinique · Agenda culturel</div>
</div>
<div class="content-area" style="top:80px;background:var(--neutral-50);">
<!-- Filters -->
<div class="event-filters">
<div class="event-filter active">Tous</div>
<div class="event-filter">🎵 Musique</div>
<div class="event-filter">⚽ Sport</div>
<div class="event-filter">🎭 Culture</div>
<div class="event-filter">🍽️ Gastronomie</div>
<div class="event-filter">🎓 Conférence</div>
</div>
<!-- Featured -->
<div class="featured-event">
<div class="featured-img">
<div class="featured-badge">⭐ À la une</div>
🎶
</div>
<div class="featured-info">
<div class="featured-name">Festival de Jazz de Martinique</div>
<div class="featured-meta">📅 15-17 juin 2026 · 📍 Fort-de-France, Savane</div>
<div class="featured-desc">3 jours de jazz avec des artistes internationaux et locaux. Entrée libre.</div>
</div>
</div>
<!-- Events list -->
<div style="padding:0 16px 8px; font-size:16px; font-weight:700;">Prochains événements</div>
<div class="event-item">
<div class="event-date-box"><div class="event-date-day">30</div><div class="event-date-month">Mai</div></div>
<div class="event-info">
<div class="event-name">Marché aux épices — Sainte-Marie</div>
<div class="event-details">🕐 8h-14h · 📍 Bourg de Sainte-Marie</div>
<span class="event-tag tag-food">🍽️ Gastronomie</span>
</div>
</div>
<div class="event-item">
<div class="event-date-box"><div class="event-date-day">02</div><div class="event-date-month">Juin</div></div>
<div class="event-info">
<div class="event-name">Course de Yoles — FDF</div>
<div class="event-details">🕐 10h-18h · 📍 Baie de Fort-de-France</div>
<span class="event-tag tag-sport">⚽ Sport</span>
</div>
</div>
<div class="event-item">
<div class="event-date-box"><div class="event-date-day">05</div><div class="event-date-month">Juin</div></div>
<div class="event-info">
<div class="event-name">Exposition Art Contemporain</div>
<div class="event-details">🕐 10h-19h · 📍 Fondation Clément, Le François</div>
<span class="event-tag tag-culture">🎭 Culture</span>
</div>
</div>
<div class="event-item">
<div class="event-date-box"><div class="event-date-day">08</div><div class="event-date-month">Juin</div></div>
<div class="event-info">
<div class="event-name">Concert Zouk — Stade Dillon</div>
<div class="event-details">🕐 20h-00h · 📍 Stade Pierre-Aliker</div>
<span class="event-tag tag-music">🎵 Musique</span>
</div>
</div>
<div class="event-item">
<div class="event-date-box"><div class="event-date-day">12</div><div class="event-date-month">Juin</div></div>
<div class="event-info">
<div class="event-name">Conférence Smart City & Climat</div>
<div class="event-details">🕐 14h-17h · 📍 Université des Antilles</div>
<span class="event-tag tag-culture">🎓 Conférence</span>
</div>
</div>
<div class="event-item">
<div class="event-date-box"><div class="event-date-day">15</div><div class="event-date-month">Juin</div></div>
<div class="event-info">
<div class="event-name">Fête de la Musique</div>
<div class="event-details">🕐 16h-02h · 📍 Toute la Martinique</div>
<span class="event-tag tag-music">🎵 Musique</span>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">13 — Événements & Culture · Blue v2</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,188 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City v2 — 13 Santé</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.health-header {
padding: 16px;
background: linear-gradient(135deg, #C62828, #B71C1C);
color: white;
}
.health-title { font-size: var(--text-xl); font-weight: var(--weight-bold); margin-bottom: 4px; }
.health-sub { font-size: var(--text-sm); opacity: 0.85; }
.pharmacy-card {
display: flex; gap: 12px;
padding: 14px 16px;
background: white;
border-bottom: 1px solid var(--neutral-100);
align-items: center;
}
.pharmacy-icon {
width: 44px; height: 44px;
border-radius: var(--radius-md);
display: flex; align-items: center; justify-content: center;
font-size: 20px;
flex-shrink: 0;
}
.pharmacy-info { flex: 1; }
.pharmacy-name { font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.pharmacy-addr { font-size: var(--text-xs); color: var(--neutral-500); }
.pharmacy-distance { font-size: 10px; color: var(--neutral-400); }
.open-badge {
padding: 3px 10px;
border-radius: var(--radius-full);
font-size: 10px;
font-weight: 600;
}
.open-now { background: rgba(46,125,50,0.1); color: var(--alert-success); }
.open-garde { background: rgba(245,124,0,0.1); color: var(--alert-warning); }
.open-closed { background: rgba(211,47,47,0.1); color: var(--alert-danger); }
.stats-row {
display: grid; grid-template-columns: repeat(3, 1fr);
gap: 10px; padding: 16px;
}
.stat-box {
background: white;
border-radius: var(--radius-lg);
padding: 14px 10px;
text-align: center;
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.stat-box-icon { font-size: 24px; margin-bottom: 6px; }
.stat-box-value { font-size: var(--text-xl); font-weight: 700; color: var(--primary-500); }
.stat-box-label { font-size: 10px; color: var(--neutral-500); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<!-- Header -->
<div class="health-header">
<div class="health-title">🏥 Services de Santé</div>
<div class="health-sub">Pharmacies, urgences, rendez-vous · Martinique</div>
</div>
<!-- Content -->
<div class="content-area" style="top:88px;background:var(--neutral-50);">
<!-- Quick stats -->
<div class="stats-row">
<div class="stat-box">
<div class="stat-box-icon">💊</div>
<div class="stat-box-value">3</div>
<div class="stat-box-label">Pharmacies de garde</div>
</div>
<div class="stat-box">
<div class="stat-box-icon">🚑</div>
<div class="stat-box-value">1</div>
<div class="stat-box-label">Urgences à proximité</div>
</div>
<div class="stat-box">
<div class="stat-box-icon">📅</div>
<div class="stat-box-value">12</div>
<div class="stat-box-label">RDV disponibles</div>
</div>
</div>
<!-- Emergency banner -->
<div style="margin:0 16px 12px;background:linear-gradient(135deg,#FFEBEE,#FFCDD2);border:1px solid #EF9A9A;border-radius:var(--radius-lg);padding:12px 14px;display:flex;align-items:center;gap:10px;">
<div style="font-size:28px;">🚨</div>
<div>
<div style="font-weight:700;font-size:var(--text-sm);color:#C62828;">Urgences CHU</div>
<div style="font-size:11px;color:#C62828;">0596 55 20 00 · Pothière · 4.2 km</div>
</div>
</div>
<!-- Pharmacies -->
<div style="padding:0 16px 8px;font-size:var(--text-md);font-weight:700;">Pharmacies de garde 🌙</div>
<div class="pharmacy-card">
<div class="pharmacy-icon" style="background:#E8F5E9;">💊</div>
<div class="pharmacy-info">
<div class="pharmacy-name">Pharmacie Centrale</div>
<div class="pharmacy-addr">Av. des Caraïbes, FDF</div>
<div class="pharmacy-distance">📍 1.2 km · 5 min</div>
</div>
<div class="open-badge open-garde">Garde</div>
</div>
<div class="pharmacy-card">
<div class="pharmacy-icon" style="background:#E3F2FD;">💊</div>
<div class="pharmacy-info">
<div class="pharmacy-name">Pharmacie du Port</div>
<div class="pharmacy-addr">Bd du Général de Gaulle, FDF</div>
<div class="pharmacy-distance">📍 1.8 km · 7 min</div>
</div>
<div class="open-badge open-now">Ouverte</div>
</div>
<div class="pharmacy-card">
<div class="pharmacy-icon" style="background:#FFF3E0;">💊</div>
<div class="pharmacy-info">
<div class="pharmacy-name">Pharmacie de l'Université</div>
<div class="pharmacy-addr">Campus Schoelcher</div>
<div class="pharmacy-distance">📍 6.3 km · 15 min</div>
</div>
<div class="open-badge open-now">Ouverte</div>
</div>
<!-- Health quick actions -->
<div style="padding:16px 16px 8px;font-size:var(--text-md);font-weight:700;">Services santé</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:0 16px 16px;">
<div style="background:white;border-radius:var(--radius-lg);padding:14px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);cursor:pointer;">
<div style="font-size:26px;margin-bottom:6px;">📅</div>
<div style="font-weight:600;font-size:var(--text-sm);">Prendre RDV</div>
<div style="font-size:10px;color:var(--neutral-500);">Médecin, dentiste...</div>
</div>
<div style="background:white;border-radius:var(--radius-lg);padding:14px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);cursor:pointer;">
<div style="font-size:26px;margin-bottom:6px;">🩺</div>
<div style="font-weight:600;font-size:var(--text-sm);">Téléconsultation</div>
<div style="font-size:10px;color:var(--neutral-500);">Médecin en ligne</div>
</div>
<div style="background:white;border-radius:var(--radius-lg);padding:14px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);cursor:pointer;">
<div style="font-size:26px;margin-bottom:6px;">📋</div>
<div style="font-weight:600;font-size:var(--text-sm);">Carnet santé</div>
<div style="font-size:10px;color:var(--neutral-500);">FHIR · Mon dossier</div>
</div>
<div style="background:white;border-radius:var(--radius-lg);padding:14px;text-align:center;box-shadow:var(--shadow-sm);border:1px solid var(--neutral-100);cursor:pointer;">
<div style="font-size:26px;margin-bottom:6px;">🧠</div>
<div style="font-weight:600;font-size:var(--text-sm);">Bien-être</div>
<div style="font-size:10px;color:var(--neutral-500);">Sport, nutrition</div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span>
</div>
<div class="bottom-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span>
</div>
<div class="bottom-nav-item active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span>
</div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">13 — Services Santé v2 / Blue</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,407 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Smart App City v2 — UI/UX Blue Palette</title>
<style>
@page { size: A4 landscape; margin: 8mm; }
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 11px; color: #212121; background: #fff; }
.page { page-break-after: always; padding: 12px; min-height: 100%; }
.page:last-child { page-break-after: auto; }
/* Cover */
.cover { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; text-align: center; background: linear-gradient(160deg, #051C38 0%, #0D47A1 40%, #00838F 100%); color: white; border-radius: 12px; padding: 30px; }
.cover h1 { font-size: 36px; font-weight: 700; margin-bottom: 6px; }
.cover h2 { font-size: 16px; font-weight: 400; opacity: 0.85; margin-bottom: 8px; }
.cover-tagline { font-size: 12px; opacity: 0.6; margin-bottom: 24px; }
.cover-feats { display: flex; gap: 20px; margin-bottom: 24px; flex-wrap: wrap; justify-content: center; }
.cover-feat { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 10px; }
.cover-feat-icon { width: 44px; height: 44px; background: rgba(255,255,255,0.12); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; }
.cover-meta { font-size: 11px; opacity: 0.5; }
/* Screen grid for PDF */
.screen-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.phone-canvas { width: 100%; }
.phone-frame-pdf {
width: 100%; aspect-ratio: 390/844;
border-radius: 16px; border: 2px solid #424242;
overflow: hidden; position: relative;
background: white; box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.phone-frame-pdf img {
width: 100%; height: 100%; object-fit: cover; display: block;
}
.screen-label {
text-align: center; margin-top: 6px;
font-size: 10px; font-weight: 600; color: #555;
}
.screen-page-label {
text-align: center; font-size: 8px; color: #999; margin-top: 2px;
}
/* Section title */
.section-title-pdf {
font-size: 18px; font-weight: 700; margin-bottom: 12px;
padding-bottom: 6px; border-bottom: 2px solid #1565C0;
color: #1565C0;
}
/* Color palette */
.palette-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 16px; }
.palette-item { text-align: center; }
.palette-swatch { width: 100%; height: 40px; border-radius: 6px; margin-bottom: 4px; border: 1px solid rgba(0,0,0,0.08); }
.palette-label { font-size: 8px; color: #666; font-weight: 500; }
/* Component library */
.comp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.comp-card {
background: #f8f9fa; border-radius: 10px;
padding: 14px; border: 1px solid #e0e0e0;
}
.comp-title { font-size: 11px; font-weight: 700; margin-bottom: 8px; color: #333; }
</style>
</head>
<body>
<div class="page">
<div class="cover">
<h1>🏙️ Smart App City</h1>
<h2>UI/UX Design System v2 — Blue Ocean Palette</h2>
<div class="cover-tagline">Martinique Digital Twin · React Native · DPI/OTN</div>
<div class="cover-feats">
<div class="cover-feat"><div class="cover-feat-icon">🗺️</div><span>Carte Live</span></div>
<div class="cover-feat"><div class="cover-feat-icon">🏛️</div><span>Services Ville</span></div>
<div class="cover-feat"><div class="cover-feat-icon">💳</div><span>Wallet DPI</span></div>
<div class="cover-feat"><div class="cover-feat-icon">🚌</div><span>Transport</span></div>
<div class="cover-feat"><div class="cover-feat-icon"></div><span>Énergie</span></div>
<div class="cover-feat"><div class="cover-feat-icon">🏥</div><span>Santé</span></div>
<div class="cover-feat"><div class="cover-feat-icon">🤖</div><span>AI Chat</span></div>
<div class="cover-feat"><div class="cover-feat-icon">📸</div><span>Signalements</span></div>
</div>
<div class="cover-meta">v2.0 Blue · 16 écrans · FR/EN/ES/DE · OpenSource</div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">🎨 Charte Graphique v2 — Blue Ocean</div>
<div style="margin-top:12px;font-size:11px;color:#555;margin-bottom:10px;">Palette principale: bleu océan (#1565C0) indigo (#3949AB) cyan (#00ACC1) — inspirée de la mer et du ciel de Martinique.</div>
<div style="font-weight:700;font-size:12px;margin-bottom:8px;color:#1565C0;">Primary (Blue Ocean)</div>
<div class="palette-grid">
<div class="palette-item"><div class="palette-swatch" style="background:#E3F2FD;"></div><div class="palette-label">50</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#BBDEFB;"></div><div class="palette-label">100</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#90CAF9;"></div><div class="palette-label">200</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#64B5F6;"></div><div class="palette-label">300</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#42A5F5;"></div><div class="palette-label">400</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#1565C0;"></div><div class="palette-label">500</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#0D47A1;"></div><div class="palette-label">600</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#0A3470;"></div><div class="palette-label">700</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#082854;"></div><div class="palette-label">800</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#051C38;"></div><div class="palette-label">900</div></div>
</div>
<div style="font-weight:700;font-size:12px;margin-bottom:8px;color:#00ACC1;margin-top:12px;">Ocean / Cyan</div>
<div class="palette-grid">
<div class="palette-item"><div class="palette-swatch" style="background:#E0F7FA;"></div><div class="palette-label">50</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#B2EBF2;"></div><div class="palette-label">100</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#80DEEA;"></div><div class="palette-label">200</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#4DD0E1;"></div><div class="palette-label">300</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#26C6DA;"></div><div class="palette-label">400</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#00ACC1;"></div><div class="palette-label">500</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#00838F;"></div><div class="palette-label">600</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#006064;"></div><div class="palette-label">700</div></div>
</div>
<div style="font-weight:700;font-size:12px;margin-bottom:8px;color:#3949AB;margin-top:12px;">Indigo Accent</div>
<div class="palette-grid">
<div class="palette-item"><div class="palette-swatch" style="background:#E8EAF6;"></div><div class="palette-label">50</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#C5CAE9;"></div><div class="palette-label">100</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#9FA8DA;"></div><div class="palette-label">200</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#7986CB;"></div><div class="palette-label">300</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#5C6BC0;"></div><div class="palette-label">400</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#3949AB;"></div><div class="palette-label">500</div></div>
</div>
<div style="font-weight:700;font-size:12px;margin-bottom:8px;color:#D32F2F;margin-top:12px;">Alerts</div>
<div class="palette-grid">
<div class="palette-item"><div class="palette-swatch" style="background:#D32F2F;"></div><div class="palette-label">Danger</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#F57C00;"></div><div class="palette-label">Warning</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#2E7D32;"></div><div class="palette-label">Success</div></div>
<div class="palette-item"><div class="palette-swatch" style="background:#0288D1;"></div><div class="palette-label">Info</div></div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">📱 Écrans — Navigation principale</div>
<div class="screen-grid" style="margin-top:12px;">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/01-onboarding-v2.png" alt="01 Onboarding v2" />
</div>
<div class="screen-label">01 Onboarding</div>
<div class="screen-page-label">Splash / Langue</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/02-home-dashboard-v2.png" alt="02 Home Dashboard v2" />
</div>
<div class="screen-label">02 Home Dashboard</div>
<div class="screen-page-label">IoT + Services</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/09-services-hub-v2.png" alt="09 Services Hub v2" />
</div>
<div class="screen-label">09 Services Hub</div>
<div class="screen-page-label">8 services villes</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/06-profil-blue.png" alt="06 Profil Blue" />
</div>
<div class="screen-label">06 Profil</div>
<div class="screen-page-label">Compte · i18n · DID</div>
</div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">💳 Écrans — Wallet & Transport</div>
<div class="screen-grid" style="margin-top:12px;">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/10-wallet-v2.png" alt="10 Wallet v2" />
</div>
<div class="screen-label">10 Wallet DPI</div>
<div class="screen-page-label">DPI / OTN / DID</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/11-bus-tracker-v2.png" alt="11 Bus Tracker v2" />
</div>
<div class="screen-label">11 Bus Tracker</div>
<div class="screen-page-label">Temps réel / Lignes</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/12-energy-v2.png" alt="12 Énergie v2" />
</div>
<div class="screen-label">12 Énergie</div>
<div class="screen-page-label">Smart Grid / IoT</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/13-health-v2.png" alt="13 Santé v2" />
</div>
<div class="screen-label">13 Santé</div>
<div class="screen-page-label">Pharmacies / RDV</div>
</div>
</div>
</div>
<div class="page">
<div class="section-title-pfd">🗺️ Écrans — Carte, AI, Marché, Signalements</div>
<div class="screen-grid" style="margin-top:12px;">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/03-carte-interactive-blue.png" alt="03 Carte Blue" />
</div>
<div class="screen-label">03 Carte Interactive</div>
<div class="screen-page-label">IoT / Filtres</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/05-ai-chat-blue.png" alt="05 AI Chat Blue" />
</div>
<div class="screen-label">05 AI Chat</div>
<div class="screen-page-label">RAG Assistant</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/04-marketplace-blue.png" alt="04 Marketplace Blue" />
</div>
<div class="screen-label">04 Marketplace</div>
<div class="screen-page-label">DPI</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/08-signalements-blue.png" alt="08 Signalements Blue" />
</div>
<div class="screen-label">08 Signalements</div>
<div class="screen-page-label">ODK / Citoyen</div>
</div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">🌤️ Écrans — Météo, Notifications, Transport</div>
<div class="screen-grid" style="margin-top:12px;">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/09-meteo-blue.png" alt="09 Météo Blue" />
</div>
<div class="screen-label">09 Météo</div>
<div class="screen-page-label">Prévisions · Alertes</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/07-notifications-blue.png" alt="07 Notifications Blue" />
</div>
<div class="screen-label">07 Notifications</div>
<div class="screen-page-label">Alertes · IoT · Marché</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/10-transport-blue.png" alt="10 Transport Blue" />
</div>
<div class="screen-label">10 Transport</div>
<div class="screen-page-label">Réseau · Horaires</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/11-energie-blue.png" alt="11 Énergie Blue" />
</div>
<div class="screen-label">11 Énergie</div>
<div class="screen-page-label">Conso · Solaire</div>
</div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">🏥 Écrans — Santé & Événements</div>
<div class="screen-grid" style="margin-top:12px;">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/12-sante-blue.png" alt="12 Santé Blue" />
</div>
<div class="screen-label">12 Santé</div>
<div class="screen-page-label">Pharmacies · RDV</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/13-evenements-blue.png" alt="13 Événements Blue" />
</div>
<div class="screen-label">13 Événements</div>
<div class="screen-page-label">Agenda · Culture</div>
</div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">🧩 Bibliothèque de composants</div>
<div class="comp-grid" style="margin-top:12px;">
<div class="comp-card">
<div class="comp-title">Bottom Navigation</div>
<div style="height:50px;background:#fff;border-top:1px solid #eee;display:flex;justify-content:space-around;align-items:center;border-radius:8px;">
<div style="text-align:center;font-size:8px;color:#1565C0;">🏠<br>Accueil</div>
<div style="text-align:center;font-size:8px;color:#999;">🗺️<br>Carte</div>
<div style="text-align:center;font-size:8px;color:#999;">🤖<br>Chat</div>
<div style="text-align:center;font-size:8px;color:#999;">🏪<br>Marché</div>
<div style="text-align:center;font-size:8px;color:#999;">👤<br>Profil</div>
</div>
</div>
<div class="comp-card">
<div class="comp-title">Buttons</div>
<div style="display:flex;flex-direction:column;gap:6px;">
<div style="background:#1565C0;color:white;padding:8px 16px;border-radius:20px;text-align:center;font-size:11px;font-weight:600;">Primary</div>
<div style="background:#EEEEEE;color:#424242;padding:8px 16px;border-radius:20px;text-align:center;font-size:11px;font-weight:600;">Secondary</div>
<div style="background:transparent;color:#1565C0;padding:8px 16px;border-radius:20px;text-align:center;font-size:11px;font-weight:600;border:1px solid #1565C0;">Ghost</div>
</div>
</div>
<div class="comp-card">
<div class="comp-title">Chips / Badges</div>
<div style="display:flex;flex-wrap:wrap;gap:6px;">
<span style="background:#E3F2FD;color:#1565C0;padding:3px 10px;border-radius:12px;font-size:10px;font-weight:600;">Marché</span>
<span style="background:#E0F7FA;color:#00838F;padding:3px 10px;border-radius:12px;font-size:10px;font-weight:600;">DPI</span>
<span style="background:#E8EAF6;color:#3949AB;padding:3px 10px;border-radius:12px;font-size:10px;font-weight:600;">OTN</span>
<span style="background:#E8F5E9;color:#2E7D32;padding:3px 10px;border-radius:12px;font-size:10px;font-weight:600;">IoT</span>
<span style="background:#FFF3E0;color:#E65100;padding:3px 10px;border-radius:12px;font-size:10px;font-weight:600;">RAG</span>
</div>
</div>
<div class="comp-card">
<div class="comp-title">Metric Card</div>
<div style="background:#fff;border-radius:10px;padding:10px;text-align:center;border:1px solid #e0e0e0;">
<div style="font-size:22px;font-weight:700;color:#1565C0;">60</div>
<div style="font-size:9px;color:#999;">Capteurs actifs</div>
</div>
</div>
<div class="comp-card">
<div class="comp-title">Toggle Switch</div>
<div style="display:flex;align-items:center;gap:10px;">
<div style="width:36px;height:20px;border-radius:10px;background:#1565C0;position:relative;">
<div style="width:16px;height:16px;border-radius:50%;background:white;position:absolute;top:2px;right:2px;"></div>
</div>
<div style="width:36px;height:20px;border-radius:10px;background:#BDBDBD;position:relative;">
<div style="width:16px;height:16px;border-radius:50%;background:white;position:absolute;top:2px;left:2px;"></div>
</div>
</div>
</div>
<div class="comp-card">
<div class="comp-title">Avatar</div>
<div style="display:flex;gap:8px;align-items:center;">
<div style="width:36px;height:36px;border-radius:50%;background:#BBDEFB;display:flex;align-items:center;justify-content:center;font-size:16px;">👤</div>
<div style="width:28px;height:28px;border-radius:50%;background:#C5CAE9;display:flex;align-items:center;justify-content:center;font-size:13px;">🤖</div>
<div style="width:44px;height:44px;border-radius:50%;background:#E0F7FA;display:flex;align-items:center;justify-content:center;font-size:20px;">🏙️</div>
</div>
</div>
</div>
</div>
<div class="page">
<div class="section-title-pdf">🔄 Parcours utilisateur principal</div>
<div style="margin-top:16px;">
<div style="display:flex;align-items:center;gap:0;flex-wrap:nowrap;overflow-x:auto;">
<div style="flex-shrink:0;text-align:center;padding:8px 12px;">
<div style="width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#051C38,#1565C0);display:flex;align-items:center;justify-content:center;font-size:24px;margin:0 auto 6px;">📱</div>
<div style="font-size:10px;font-weight:600;">Onboarding</div>
<div style="font-size:9px;color:#999;">Langue / Login</div>
</div>
<div style="font-size:20px;color:#1565C0;flex-shrink:0;"></div>
<div style="flex-shrink:0;text-align:center;padding:8px 12px;">
<div style="width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#1565C0,#0D47A1);display:flex;align-items:center;justify-content:center;font-size:24px;margin:0 auto 6px;">🏠</div>
<div style="font-size:10px;font-weight:600;">Dashboard</div>
<div style="font-size:9px;color:#999;">IoT / Services</div>
</div>
<div style="font-size:20px;color:#1565C0;flex-shrink:0;"></div>
<div style="flex-shrink:0;text-align:center;padding:8px 12px;">
<div style="width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#00ACC1,#00838F);display:flex;align-items:center;justify-content:center;font-size:24px;margin:0 auto 6px;">🏛️</div>
<div style="font-size:10px;font-weight:600;">Services</div>
<div style="font-size:9px;color:#999;">Choix service</div>
</div>
<div style="font-size:20px;color:#1565C0;flex-shrink:0;"></div>
<div style="flex-shrink:0;text-align:center;padding:8px 12px;">
<div style="width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#3949AB,#1565C0);display:flex;align-items:center;justify-content:center;font-size:24px;margin:0 auto 6px;">🤖</div>
<div style="font-size:10px;font-weight:600;">AI Chat</div>
<div style="font-size:9px;color:#999;">RAG / Data</div>
</div>
<div style="font-size:20px;color:#1565C0;flex-shrink:0;"></div>
<div style="flex-shrink:0;text-align:center;padding:8px 12px;">
<div style="width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,#1565C0,#3949AB);display:flex;align-items:center;justify-content:center;font-size:24px;margin:0 auto 6px;">💳</div>
<div style="font-size:10px;font-weight:600;">Wallet</div>
<div style="font-size:9px;color:#999;">Paiement DPI</div>
</div>
</div>
</div>
<div style="margin-top:24px;padding:16px;background:#E3F2FD;border-radius:12px;border-left:4px solid #1565C0;">
<div style="font-weight:700;font-size:13px;color:#0D47A1;margin-bottom:6px;">📋 Spécifications techniques</div>
<div style="font-size:11px;color:#333;line-height:1.8;">
<strong>Platform:</strong> React Native (iOS + Android)<br>
<strong>Backend:</strong> NestJS + FastAPI + RAG (MindsDB/LocalAI)<br>
<strong>Protocol:</strong> DPI/OTN (paiements)<br>
<strong>IoT:</strong> MQTT (EMQX/Mosquitto) → Telegraf → InfluxDB → Grafana<br>
<strong>Identity:</strong> DID / Verifiable Credentials<br>
<strong>Data:</strong> NGSI-LD (Orion-LD/Stellio) + QuantumLeap + CrateDB<br>
<strong>Mobile Data:</strong> ODK Central<br>
<strong>i18n:</strong> FR / EN / ES / DE<br>
<strong>Design:</strong> Inter + SF Pro · 390×844pt · 16 screens v2
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,315 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Smart App City — UI/UX Maquettes</title>
<style>
@page { size: A4 landscape; margin: 8mm; }
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 11px; color: #212121; background: #fff; }
.page { page-break-after: always; padding: 12px; min-height: 100%; }
.page:last-child { page-break-after: auto; }
/* Cover */
.cover { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; text-align: center; background: linear-gradient(160deg, #1B5E20, #00838F, #00ACC1); color: white; border-radius: 12px; padding: 30px; }
.cover h1 { font-size: 36px; font-weight: 700; margin-bottom: 6px; }
.cover h2 { font-size: 16px; font-weight: 400; opacity: 0.85; margin-bottom: 24px; }
.cover-feats { display: flex; gap: 24px; margin-bottom: 24px; }
.cover-feat { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 11px; }
.cover-feat-icon { width: 48px; height: 48px; background: rgba(255,255,255,0.15); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 22px; }
.cover-meta { font-size: 11px; opacity: 0.6; }
/* Screen grid for PDF */
.screen-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.phone-canvas { width: 100%; }
.phone-frame-pdf {
width: 100%; aspect-ratio: 390/844;
border-radius: 20px; border: 2.5px solid #424242;
overflow: hidden; position: relative;
background: white; box-shadow: 0 3px 12px rgba(0,0,0,0.1);
}
.phone-notch-pdf {
width: 30%; height: 16px; background: #424242;
border-radius: 0 0 10px 10px;
position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 5;
}
.phone-label { font-size: 10px; font-weight: 600; color: #424242; text-align: center; margin-top: 6px; }
.phone-desc { font-size: 9px; color: #9E9E9E; text-align: center; max-width: 180px; margin: 2px auto 0; }
.phone-frame-pdf img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Inline phone screens - simplified for PDF */
.screen-onboard { background: linear-gradient(160deg, #1B5E20, #00838F, #00ACC1); display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; padding: 16px; text-align: center; color: white; }
.screen-onboard .logo { width: 50px; height: 50px; background: rgba(255,255,255,0.15); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 26px; margin-bottom: 12px; }
.screen-onboard .title { font-size: 18px; font-weight: 700; margin-bottom: 3px; }
.screen-onboard .subtitle { font-size: 10px; opacity: 0.7; margin-bottom: 14px; }
.screen-onboard .langs { display: flex; gap: 5px; margin-bottom: 14px; }
.screen-onboard .lang-pill { padding: 3px 10px; border-radius: 10px; background: rgba(255,255,255,0.2); font-size: 9px; font-weight: 600; }
.screen-onboard .lang-pill.active { background: white; color: #1B5E20; }
.screen-onboard .feats { display: flex; gap: 10px; margin-bottom: 18px; }
.screen-onboard .feat { display: flex; flex-direction: column; align-items: center; gap: 3px; font-size: 8px; opacity: 0.7; }
.screen-onboard .feat-icon { width: 30px; height: 30px; background: rgba(255,255,255,0.12); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 14px; }
.screen-onboard .btns { width: 100%; max-width: 180px; display: flex; flex-direction: column; gap: 6px; }
.screen-onboard .btn-main { background: white; color: #2B6B2E; padding: 8px; border-radius: 16px; font-weight: 700; font-size: 10px; }
.screen-onboard .btn-ghost { background: rgba(255,255,255,0.15); color: white; padding: 8px; border-radius: 16px; font-weight: 600; font-size: 10px; border: 1.5px solid rgba(255,255,255,0.3); }
.screen-home { background: linear-gradient(135deg,#2E7D32,#00ACC1); height: 100%; display: flex; flex-direction: column; }
.screen-home .header { padding: 10px 12px 8px; color: white; }
.screen-home .greet { font-size: 9px; opacity: 0.8; }
.screen-home .name { font-size: 12px; font-weight: 700; }
.screen-home .live { font-size: 8px; display: flex; align-items: center; gap: 3px; }
.screen-home .live-dot { width: 5px; height: 5px; background: #66BB6A; border-radius: 50%; }
.screen-home .search { background: rgba(255,255,255,0.2); border-radius: 16px; padding: 6px 10px; font-size: 9px; color: rgba(255,255,255,0.7); margin-top: 6px; }
.screen-home .body { flex: 1; background: #FAFAFA; border-radius: 12px 12px 0 0; padding: 8px; }
.screen-home .metrics { display: grid; grid-template-columns: repeat(3,1fr); gap: 4px; margin-bottom: 6px; }
.screen-home .metric { background: white; border-radius: 8px; padding: 7px; text-align: center; border: 1px solid #E0E0E0; }
.screen-home .metric-val { font-size: 13px; font-weight: 700; color: #2E7D32; }
.screen-home .metric-lbl { font-size: 7px; color: #9E9E9E; }
.screen-home .alert { background: rgba(211,47,47,0.08); border: 1px solid rgba(211,47,47,0.2); border-radius: 8px; padding: 6px 8px; margin-bottom: 6px; font-size: 8px; color: #D32F2F; font-weight: 600; }
.screen-home .qactions { display: grid; grid-template-columns: repeat(4,1fr); gap: 6px; margin-bottom: 8px; }
.screen-home .qa { text-align: center; }
.screen-home .qa-icon { width: 32px; height: 32px; border-radius: 8px; margin: 0 auto 3px; display: flex; align-items: center; justify-content: center; font-size: 14px; color: white; }
.screen-home .qa-lbl { font-size: 7px; color: #757575; }
.screen-home .section-title { font-size: 10px; font-weight: 700; margin-bottom: 5px; }
.screen-home .sensors { display: flex; gap: 6px; overflow: hidden; }
.screen-home .sensor { flex-shrink: 0; width: 90px; background: white; border-radius: 8px; padding: 7px; border: 1px solid #E0E0E0; }
.screen-home .sensor-icon { font-size: 14px; margin-bottom: 3px; }
.screen-home .sensor-val { font-size: 12px; font-weight: 700; }
.screen-home .sensor-name { font-size: 7px; color: #9E9E9E; }
.screen-home .nav { background: white; border-top: 1px solid #E0E0E0; display: flex; justify-content: space-around; padding: 5px 0 10px; }
.screen-home .nav-item { text-align: center; font-size: 8px; color: #9E9E9E; }
.screen-home .nav-item.active { color: #2E7D32; font-weight: 600; }
.screen-map { background: #D4EEF7; height: 100%; position: relative; }
.screen-map .island { position: absolute; bottom: 15%; left: 10%; width: 80%; height: 50%; }
.screen-map .toolbar { position: absolute; top: 6px; left: 6px; right: 6px; display: flex; gap: 4px; }
.screen-map .search-box { flex: 1; background: white; border-radius: 16px; padding: 6px 10px; font-size: 9px; color: #9E9E9E; box-shadow: 0 2px 6px rgba(0,0,0,0.1); }
.screen-map .fab { width: 28px; height: 28px; background: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); }
.screen-map .legend { position: absolute; top: 46px; right: 6px; background: white; border-radius: 8px; padding: 6px; font-size: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); }
.screen-map .legend-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; margin-right: 3px; }
.screen-map .bottom-card { position: absolute; bottom: 6px; left: 6px; right: 6px; background: white; border-radius: 10px; padding: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.12); }
.screen-map .bc-title { font-weight: 700; font-size: 10px; }
.screen-map .bc-sub { font-size: 8px; color: #9E9E9E; }
.screen-map .bc-val { font-size: 14px; font-weight: 700; color: #2E7D32; }
.screen-map .bc-meta { display: flex; gap: 4px; margin-top: 5px; }
.screen-map .bc-m { flex: 1; background: #F5F5F5; border-radius: 4px; padding: 4px; text-align: center; }
.screen-map .bc-m-val { font-size: 9px; font-weight: 700; }
.screen-map .bc-m-lbl { font-size: 6px; color: #9E9E9E; }
.screen-market { background: white; height: 100%; display: flex; flex-direction: column; }
.screen-market .header { padding: 8px 10px; border-bottom: 1px solid #E0E0E0; }
.screen-market .title { font-size: 12px; font-weight: 700; }
.screen-market .search { background: #F5F5F5; border-radius: 16px; padding: 5px 10px; font-size: 9px; color: #9E9E9E; margin: 5px 0; }
.screen-market .cats { display: flex; gap: 4px; }
.screen-market .cat { padding: 3px 8px; border-radius: 10px; font-size: 8px; font-weight: 600; background: #F5F5F5; color: #757575; }
.screen-market .cat.active { background: #2E7D32; color: white; }
.screen-market .body { flex: 1; overflow: hidden; padding: 8px; background: #FAFAFA; }
.screen-market .featured { background: linear-gradient(135deg,#1B5E20,#00838F); border-radius: 10px; padding: 10px; color: white; margin-bottom: 8px; }
.screen-market .ft-tag { background: rgba(255,255,255,0.2); border-radius: 8px; padding: 2px 6px; font-size: 7px; font-weight: 600; display: inline-block; margin-bottom: 4px; }
.screen-market .ft-title { font-weight: 700; font-size: 11px; }
.screen-market .ft-desc { font-size: 8px; opacity: 0.8; }
.screen-market .products { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.screen-market .product { background: white; border-radius: 8px; overflow: hidden; border: 1px solid #E0E0E0; }
.screen-market .p-img { height: 50px; display: flex; align-items: center; justify-content: center; font-size: 22px; }
.screen-market .p-info { padding: 6px; }
.screen-market .p-name { font-size: 9px; font-weight: 600; }
.screen-market .p-shop { font-size: 7px; color: #9E9E9E; }
.screen-market .p-price { font-size: 10px; font-weight: 700; color: #2E7D32; }
.screen-market .nav { background: white; border-top: 1px solid #E0E0E0; display: flex; justify-content: space-around; padding: 4px 0 8px; }
.screen-market .nav-item { text-align: center; font-size: 8px; color: #9E9E9E; }
.screen-market .nav-item.active { color: #2E7D32; font-weight: 600; }
.screen-chat { background: #FAFAFA; height: 100%; display: flex; flex-direction: column; }
.screen-chat .header { background: white; border-bottom: 1px solid #E0E0E0; padding: 8px 10px; display: flex; align-items: center; gap: 8px; }
.screen-chat .avatar { width: 26px; height: 26px; border-radius: 50%; background: linear-gradient(135deg,#7C4DFF,#B388FF); display: flex; align-items: center; justify-content: center; font-size: 13px; position: relative; }
.screen-chat .online { position: absolute; bottom: 0; right: 0; width: 7px; height: 7px; background: #2E7D32; border-radius: 50%; border: 1.5px solid white; }
.screen-chat .name { font-weight: 700; font-size: 10px; }
.screen-chat .status { font-size: 8px; color: #2E7D32; }
.screen-chat .msgs { flex: 1; padding: 8px; display: flex; flex-direction: column; gap: 6px; overflow: hidden; }
.screen-chat .msg { display: flex; gap: 5px; align-items: flex-end; }
.screen-chat .msg.user { flex-direction: row-reverse; }
.screen-chat .msg-avatar { width: 18px; height: 18px; border-radius: 50%; background: linear-gradient(135deg,#7C4DFF,#B388FF); display: flex; align-items: center; justify-content: center; font-size: 9px; flex-shrink: 0; }
.screen-chat .bubble { max-width: 78%; padding: 6px 8px; border-radius: 10px; font-size: 8px; line-height: 1.4; }
.screen-chat .msg:not(.user) .bubble { background: #F5F5F5; border-bottom-left-radius: 3px; }
.screen-chat .msg.user .bubble { background: linear-gradient(135deg,#2E7D32,#1B5E20); color: white; border-bottom-right-radius: 3px; }
.screen-chat .time { font-size: 7px; color: #BDBDBD; margin-top: 2px; }
.screen-chat .msg.user .time { text-align: right; }
.screen-chat .quick { display: flex; gap: 4px; padding: 0 8px 6px; }
.screen-chat .qr { padding: 4px 8px; border-radius: 10px; background: #E8F5E9; color: #2E7D32; font-size: 8px; font-weight: 600; }
.screen-chat .input { background: white; border-top: 1px solid #E0E0E0; padding: 6px 8px; display: flex; gap: 5px; align-items: center; }
.screen-chat .input-box { flex: 1; border: 1.5px solid #E0E0E0; border-radius: 16px; padding: 6px 10px; font-size: 9px; color: #9E9E9E; }
.screen-chat .send { width: 28px; height: 28px; border-radius: 50%; background: #2E7D32; display: flex; align-items: center; justify-content: center; color: white; font-size: 11px; }
.screen-chat .nav { background: white; border-top: 1px solid #E0E0E0; display: flex; justify-content: space-around; padding: 3px 0 6px; }
.screen-chat .nav-item { text-align: center; font-size: 8px; color: #9E9E9E; }
.screen-chat .nav-item.active { color: #2E7D32; font-weight: 600; }
.screen-profile { background: linear-gradient(135deg,#2E7D32,#00ACC1); height: 100%; display: flex; flex-direction: column; }
.screen-profile .header { padding: 14px; text-align: center; color: white; }
.screen-profile .avatar { width: 48px; height: 48px; border-radius: 50%; background: rgba(255,255,255,0.2); margin: 0 auto 8px; display: flex; align-items: center; justify-content: center; font-size: 22px; border: 2px solid rgba(255,255,255,0.3); }
.screen-profile .name { font-weight: 700; font-size: 12px; }
.screen-profile .email { font-size: 8px; opacity: 0.7; }
.screen-profile .badge { display: inline-block; background: rgba(255,255,255,0.2); border-radius: 8px; padding: 2px 8px; font-size: 7px; font-weight: 600; margin-top: 4px; }
.screen-profile .stats { display: flex; justify-content: center; gap: 20px; margin-top: 10px; }
.screen-profile .stat { text-align: center; }
.screen-profile .stat-val { font-weight: 700; font-size: 12px; }
.screen-profile .stat-lbl { font-size: 7px; opacity: 0.6; }
.screen-profile .body { flex: 1; background: #FAFAFA; border-radius: 12px 12px 0 0; padding: 8px; overflow: hidden; }
.screen-profile .section { font-size: 8px; font-weight: 700; color: #9E9E9E; text-transform: uppercase; margin-bottom: 4px; }
.screen-profile .menu-card { background: white; border-radius: 8px; overflow: hidden; border: 1px solid #E0E0E0; margin-bottom: 6px; }
.screen-profile .menu-item { padding: 7px 8px; display: flex; align-items: center; gap: 8px; border-bottom: 1px solid #F5F5F5; }
.screen-profile .menu-icon { width: 22px; height: 22px; border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 11px; }
.screen-profile .menu-label { font-size: 9px; font-weight: 500; flex: 1; }
.screen-profile .menu-val { font-size: 8px; color: #9E9E9E; }
.screen-profile .flags { display: flex; gap: 3px; }
.screen-profile .flag { width: 16px; height: 16px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 8px; opacity: 0.4; }
.screen-profile .flag.active { opacity: 1; box-shadow: 0 0 0 1.5px #2E7D32; }
.screen-profile .nav { background: white; border-top: 1px solid #E0E0E0; display: flex; justify-content: space-around; padding: 4px 0 8px; }
.screen-profile .nav-item { text-align: center; font-size: 8px; color: #9E9E9E; }
.screen-profile .nav-item.active { color: #2E7D32; font-weight: 600; }
.screen-notif { background: white; height: 100%; display: flex; flex-direction: column; }
.screen-notif .header { padding: 8px 10px; border-bottom: 1px solid #E0E0E0; }
.screen-notif .title { font-size: 12px; font-weight: 700; }
.screen-notif .sub { font-size: 8px; color: #9E9E9E; }
.screen-notif .tabs { display: flex; gap: 4px; padding: 6px 10px; border-bottom: 1px solid #E0E0E0; }
.screen-notif .tab { padding: 3px 8px; border-radius: 10px; font-size: 8px; font-weight: 600; background: #F5F5F5; color: #757575; }
.screen-notif .tab.active { background: #2E7D32; color: white; }
.screen-notif .body { flex: 1; overflow: hidden; background: #FAFAFA; }
.screen-notif .divider { padding: 5px 10px; font-size: 8px; font-weight: 700; color: #9E9E9E; text-transform: uppercase; background: #FAFAFA; }
.screen-notif .item { padding: 8px 10px; border-bottom: 1px solid #F5F5F5; display: flex; gap: 8px; }
.screen-notif .item.unread { background: rgba(2,136,209,0.03); }
.screen-notif .icon { width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; flex-shrink: 0; }
.screen-notif .text { flex: 1; font-size: 8px; line-height: 1.4; }
.screen-notif .time { font-size: 7px; color: #BDBDBD; margin-top: 2px; }
.screen-notif .dot { width: 5px; height: 5px; border-radius: 50%; background: #0288D1; margin-top: 3px; flex-shrink: 0; }
.screen-notif .nav { background: white; border-top: 1px solid #E0E0E0; display: flex; justify-content: space-around; padding: 4px 0 8px; }
.screen-notif .nav-item { text-align: center; font-size: 8px; color: #9E9E9E; }
.screen-notif .nav-item.active { color: #2E7D32; font-weight: 600; }
.screen-report { background: white; height: 100%; display: flex; flex-direction: column; }
.screen-report .header { padding: 8px 10px; border-bottom: 1px solid #E0E0E0; }
.screen-report .title { font-size: 12px; font-weight: 700; }
.screen-report .sub { font-size: 8px; color: #9E9E9E; }
.screen-report .body { flex: 1; overflow: hidden; background: #FAFAFA; padding: 8px; }
.screen-report .section { font-size: 10px; font-weight: 700; margin-bottom: 6px; }
.screen-report .cats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5px; margin-bottom: 10px; }
.screen-report .cat { background: white; border-radius: 8px; padding: 8px; text-align: center; border: 1px solid #E0E0E0; }
.screen-report .cat-icon { font-size: 16px; margin-bottom: 3px; }
.screen-report .cat-name { font-size: 8px; font-weight: 600; }
.screen-report .cat-count { font-size: 7px; color: #9E9E9E; }
.screen-report .item { background: white; border-radius: 8px; padding: 8px; margin-bottom: 5px; border: 1px solid #E0E0E0; display: flex; gap: 6px; }
.screen-report .item-icon { font-size: 14px; flex-shrink: 0; }
.screen-report .item-title { font-size: 9px; font-weight: 600; }
.screen-report .item-desc { font-size: 7px; color: #9E9E9E; }
.screen-report .status { font-size: 7px; font-weight: 700; padding: 1px 6px; border-radius: 6px; display: inline-block; margin-top: 3px; }
.screen-report .s-progress { background: rgba(2,136,209,0.1); color: #0288D1; }
.screen-report .s-done { background: rgba(46,125,50,0.1); color: #2E7D32; }
.screen-report .form-card { background: white; border-radius: 10px; padding: 8px; border: 1px solid #E0E0E0; margin-top: 6px; }
.screen-report .form-title { font-weight: 700; font-size: 9px; }
.screen-report .form-sub { font-size: 7px; color: #9E9E9E; }
.screen-report .form-btns { display: flex; gap: 4px; margin-top: 6px; }
.screen-report .form-btn { flex: 1; padding: 6px; border-radius: 12px; font-size: 8px; font-weight: 600; text-align: center; }
.screen-report .nav { background: white; border-top: 1px solid #E0E0E0; display: flex; justify-content: space-around; padding: 4px 0 8px; }
.screen-report .nav-item { text-align: center; font-size: 8px; color: #9E9E9E; }
.screen-report .nav-item.active { color: #2E7D32; font-weight: 600; }
</style>
</head>
<body>
<div class="page">
<div class="cover">
<div style="font-size:50px;margin-bottom:16px;">🏙️</div>
<h1>Smart App City</h1>
<h2>Martinique Digital Twin · Maquettes UI/UX</h2>
<div class="cover-feats">
<div class="cover-feat"><div class="cover-feat-icon">🏠</div>Dashboard</div>
<div class="cover-feat"><div class="cover-feat-icon">🗺️</div>Carte Live</div>
<div class="cover-feat"><div class="cover-feat-icon">🤖</div>AI Chat RAG</div>
<div class="cover-feat"><div class="cover-feat-icon">🏪</div>Marketplace</div>
<div class="cover-feat"><div class="cover-feat-icon">📸</div>Signalements</div>
</div>
<div class="cover-meta">React Native · NestJS · FastAI · RAG · Beckn/DPI/OTN · i18n FR/EN/ES/DE · 2026</div>
</div>
</div>
<div class="page">
<div class="screen-grid">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/01-onboarding.png" alt="01 Onboarding" />
</div>
<div class="phone-label">01 — Onboarding</div>
<div class="phone-desc">Splash + sélection langue i18n</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/02-home-dashboard.png" alt="02 Home" />
</div>
<div class="phone-label">02 — Home Dashboard</div>
<div class="phone-desc">Vue d'ensemble temps réel</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/03-carte-interactive.png" alt="03 Carte" />
</div>
<div class="phone-label">03 — Carte Interactive</div>
<div class="phone-desc">IoT géolocalisé · Martinique</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/04-marketplace.png" alt="04 Marketplace" />
</div>
<div class="phone-label">04 — Marketplace Beckn/DPI</div>
<div class="phone-desc">Commerce décentralisé local</div>
</div>
</div>
</div>
<div class="page">
<div class="screen-grid">
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/05-ai-chat.png" alt="05 AI Chat" />
</div>
<div class="phone-label">05 — AI Chat (RAG)</div>
<div class="phone-desc">Assistant IA · Données temps réel</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/06-profil.png" alt="06 Profil" />
</div>
<div class="phone-label">06 — Profil & Paramètres</div>
<div class="phone-desc">i18n · Beckn · DID · Préférences</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/07-notifications.png" alt="07 Notifications" />
</div>
<div class="phone-label">07 — Notifications</div>
<div class="phone-desc">Alertes IoT · Marché · ODK</div>
</div>
<div class="phone-canvas">
<div class="phone-frame-pdf">
<img src="screenshots/08-signalements.png" alt="08 Signalements" />
</div>
<div class="phone-label">08 — Signalements (ODK)</div>
<div class="phone-desc">Rapports citoyens · GPS · Photo</div>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -0,0 +1,450 @@
/* Smart App City — Design System v2 BLUE */
/* i18n: FR / EN / ES / DE */
/* Platform: React Native → mobile-first */
/* Palette: Blue Ocean / Indigo / Cyan — inspired by sea & sky of Martinique */
:root {
/* ── Primary Palette — Blue Ocean ── */
--primary-50: #E3F2FD;
--primary-100: #BBDEFB;
--primary-200: #90CAF9;
--primary-300: #64B5F6;
--primary-400: #42A5F5;
--primary-500: #1565C0;
--primary-600: #0D47A1;
--primary-700: #0A3470;
--primary-800: #082854;
--primary-900: #051C38;
/* ── Deep Ocean ── */
--ocean-50: #E0F7FA;
--ocean-100: #B2EBF2;
--ocean-200: #80DEEA;
--ocean-300: #4DD0E1;
--ocean-400: #26C6DA;
--ocean-500: #00ACC1;
--ocean-600: #00838F;
--ocean-700: #006064;
/* ── Indigo Accent ── */
--indigo-50: #E8EAF6;
--indigo-100: #C5CAE9;
--indigo-200: #9FA8DA;
--indigo-300: #7986CB;
--indigo-400: #5C6BC0;
--indigo-500: #3949AB;
--indigo-600: #283593;
--indigo-700: #1A237E;
/* ── Alert Colors ── */
--alert-danger: #D32F2F;
--alert-warning: #F57C00;
--alert-success: #2E7D32;
--alert-info: #0288D1;
/* ── Neutrals ── */
--neutral-0: #FFFFFF;
--neutral-50: #FAFAFA;
--neutral-100: #F5F5F5;
--neutral-200: #EEEEEE;
--neutral-300: #E0E0E0;
--neutral-400: #BDBDBD;
--neutral-500: #9E9E9E;
--neutral-600: #757575;
--neutral-700: #616161;
--neutral-800: #424242;
--neutral-900: #212121;
--neutral-1000: #1A1A1A;
/* ── Typography ── */
--font-family: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
--font-family-mono: 'JetBrains Mono', 'SF Mono', monospace;
--text-xs: 11px;
--text-sm: 13px;
--text-base: 15px;
--text-md: 17px;
--text-lg: 20px;
--text-xl: 24px;
--text-2xl: 28px;
--text-3xl: 34px;
--text-4xl: 40px;
--weight-regular: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
/* ── Spacing ── */
--space-2xs: 2px;
--space-xs: 4px;
--space-sm: 8px;
--space-md: 12px;
--space-base: 16px;
--space-lg: 20px;
--space-xl: 24px;
--space-2xl: 32px;
--space-3xl: 40px;
--space-4xl: 48px;
/* ── Border Radius ── */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 20px;
--radius-2xl: 24px;
--radius-full: 9999px;
/* ── Shadows ── */
--shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
--shadow-md: 0 4px 12px rgba(0,0,0,0.1), 0 2px 4px rgba(0,0,0,0.06);
--shadow-lg: 0 8px 24px rgba(0,0,0,0.12), 0 4px 8px rgba(0,0,0,0.06);
--shadow-xl: 0 16px 48px rgba(0,0,0,0.16);
/* ── Dark Mode ── */
--bg-primary-dark: #0D1B2A;
--bg-secondary-dark: #1B2838;
--bg-card-dark: #1E3350;
--text-primary-dark: #E8EAF6;
--text-secondary-dark: #9FA8DA;
--text-tertiary-dark: #5C6BC0;
}
/* ── Base Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font-family);
font-size: var(--text-base);
color: var(--neutral-900);
background: var(--neutral-50);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
body.dark {
background: var(--bg-primary-dark);
color: var(--text-primary-dark);
}
/* ── Utility Classes ── */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.gap-xs { gap: var(--space-xs); }
.gap-sm { gap: var(--space-sm); }
.gap-md { gap: var(--space-md); }
.gap-base { gap: var(--space-base); }
.gap-lg { gap: var(--space-lg); }
.text-center { text-align: center; }
.w-full { width: 100%; }
.h-full { height: 100%; }
.relative { position: relative; }
.absolute { position: absolute; }
.rounded-md { border-radius: var(--radius-md); }
.rounded-lg { border-radius: var(--radius-lg); }
.rounded-full { border-radius: var(--radius-full); }
.shadow-sm { box-shadow: var(--shadow-sm); }
.shadow-md { box-shadow: var(--shadow-md); }
.shadow-lg { box-shadow: var(--shadow-lg); }
/* ── Component: Mobile Frame ── */
.mobile-frame {
width: 390px;
height: 844px;
border-radius: 40px;
border: 3px solid var(--neutral-800);
overflow: hidden;
position: relative;
background: var(--neutral-0);
box-shadow: var(--shadow-xl), 0 0 0 1px rgba(0,0,0,0.04);
}
.dark .mobile-frame {
border-color: var(--neutral-600);
background: var(--bg-primary-dark);
}
/* ── Notch ── */
.notch {
width: 120px;
height: 30px;
background: var(--neutral-900);
border-radius: 0 0 20px 20px;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
z-index: 100;
}
.dark .notch { background: var(--bg-primary-dark); border: 2px solid var(--neutral-600); border-top: none; }
/* ── Status Bar ── */
.status-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px 4px;
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 50;
}
/* ── Bottom Nav ── */
.bottom-nav {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 80px;
background: var(--neutral-0);
border-top: 1px solid var(--neutral-200);
display: flex;
justify-content: space-around;
align-items: center;
padding-bottom: 20px;
z-index: 50;
}
.dark .bottom-nav {
background: var(--bg-secondary-dark);
border-color: var(--neutral-700);
}
.bottom-nav-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
font-size: var(--text-xs);
color: var(--neutral-500);
cursor: pointer;
transition: color 0.2s;
}
.bottom-nav-item.active { color: var(--primary-500); }
.bottom-nav-item svg { width: 24px; height: 24px; }
/* ── Content Area ── */
.content-area {
position: absolute;
top: 44px;
bottom: 80px;
left: 0;
right: 0;
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: none;
}
.content-area::-webkit-scrollbar { display: none; }
/* ── Cards ── */
.card {
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: var(--space-base);
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.dark .card {
background: var(--bg-card-dark);
border-color: var(--neutral-700);
}
/* ── Buttons ── */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-xs);
padding: 12px 24px;
border-radius: var(--radius-full);
font-weight: var(--weight-semibold);
font-size: var(--text-base);
cursor: pointer;
border: none;
transition: all 0.2s;
min-height: 48px;
}
.btn-primary {
background: var(--primary-500);
color: white;
}
.btn-primary:hover { background: var(--primary-600); }
.btn-secondary {
background: var(--neutral-200);
color: var(--neutral-800);
}
.btn-ghost {
background: transparent;
color: var(--primary-500);
}
.btn-block { width: 100%; }
/* ── Metric Cards ── */
.metric-card {
padding: var(--space-base);
border-radius: var(--radius-lg);
background: var(--neutral-0);
border: 1px solid var(--neutral-200);
text-align: center;
}
.dark .metric-card {
background: var(--bg-card-dark);
border-color: var(--neutral-700);
}
.metric-value {
font-size: var(--text-2xl);
font-weight: var(--weight-bold);
color: var(--primary-500);
}
.metric-label {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-top: 4px;
}
/* ── Label ── */
.label {
font-size: var(--text-sm);
font-weight: var(--weight-medium);
color: var(--neutral-600);
margin-bottom: var(--space-xs);
}
.dark .label { color: var(--text-secondary-dark); }
/* ── Page Title ── */
.page-title {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
color: var(--neutral-900);
}
.dark .page-title { color: var(--text-primary-dark); }
/* ── Section Header ── */
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-base);
}
.section-title {
font-size: var(--text-md);
font-weight: var(--weight-semibold);
}
/* ── Online Indicator ── */
.online-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--alert-success);
display: inline-block;
}
/* ── Badge ── */
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 20px;
height: 20px;
border-radius: var(--radius-full);
background: var(--alert-danger);
color: white;
font-size: var(--text-xs);
font-weight: var(--weight-bold);
padding: 0 6px;
}
/* ── Chip ── */
.chip {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 12px;
border-radius: var(--radius-full);
background: var(--primary-50);
color: var(--primary-600);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
}
.dark .chip { background: rgba(21,101,192,0.15); }
/* ── Gradient Overlays ── */
.gradient-blue {
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
}
.gradient-ocean {
background: linear-gradient(135deg, var(--ocean-400), var(--ocean-600));
}
.gradient-indigo {
background: linear-gradient(135deg, var(--indigo-500), var(--primary-500));
}
.gradient-deep {
background: linear-gradient(160deg, var(--primary-700) 0%, var(--ocean-600) 50%, var(--ocean-500) 100%);
}
/* ── SVG Icon Base ── */
.icon { width: 24px; height: 24px; stroke-width: 2; fill: none; stroke: currentColor; }
.icon-sm { width: 18px; height: 18px; }
.icon-lg { width: 32px; height: 32px; }
.icon-xl { width: 48px; height: 48px; }
/* ── Thumbnail / Avatar ── */
.avatar {
width: 40px;
height: 40px;
border-radius: var(--radius-full);
object-fit: cover;
background: var(--neutral-200);
}
.avatar-sm { width: 32px; height: 32px; }
.avatar-lg { width: 56px; height: 56px; }
/* ── Spacing Utilities ── */
.px-base { padding-left: var(--space-base); padding-right: var(--space-base); }
.py-sm { padding-top: var(--space-sm); padding-bottom: var(--space-sm); }
.py-base { padding-top: var(--space-base); padding-bottom: var(--space-base); }
.p-base { padding: var(--space-base); }
.p-lg { padding: var(--space-lg); }
.mt-sm { margin-top: var(--space-sm); }
.mt-base { margin-top: var(--space-base); }
.mt-lg { margin-top: var(--space-lg); }
.mb-sm { margin-bottom: var(--space-sm); }
.mb-base { margin-bottom: var(--space-base); }
/* ── Grid ── */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-sm); }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-md); }
/* ── Scrollable Row ── */
.scroll-row {
display: flex;
gap: var(--space-md);
overflow-x: auto;
padding: 0 var(--space-base) var(--space-base);
scrollbar-width: none;
}
.scroll-row::-webkit-scrollbar { display: none; }
/* ── Language Picker ── */
.lang-btn {
padding: 6px 12px;
border-radius: var(--radius-md);
border: 2px solid var(--neutral-300);
background: transparent;
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
cursor: pointer;
color: var(--neutral-700);
transition: all 0.2s;
}
.lang-btn.active {
border-color: var(--primary-500);
background: var(--primary-500);
color: white;
}

View File

@@ -0,0 +1,430 @@
/* Smart App City — Design System */
/* i18n: FR / EN / ES / DE */
/* Platform: React Native → mobile-first */
:root {
/* ── Primary Palette ── */
--primary-50: #E8F5E9;
--primary-100: #C8E6C9;
--primary-200: #A5D6A7;
--primary-300: #81C784;
--primary-400: #66BB6A;
--primary-500: #2E7D32;
--primary-600: #2B6B2E;
--primary-700: #1B5E20;
/* ── Ocean Accent (Martinique theme) ── */
--ocean-50: #E0F7FA;
--ocean-100: #B2EBF2;
--ocean-200: #80DEEA;
--ocean-300: #4DD0E1;
--ocean-400: #26C6DA;
--ocean-500: #00ACC1;
--ocean-600: #00838F;
/* ── Alert Colors ── */
--alert-danger: #D32F2F;
--alert-warning: #F57C00;
--alert-success: #2E7D32;
--alert-info: #0288D1;
/* ── Neutrals ── */
--neutral-0: #FFFFFF;
--neutral-50: #FAFAFA;
--neutral-100: #F5F5F5;
--neutral-200: #EEEEEE;
--neutral-300: #E0E0E0;
--neutral-400: #BDBDBD;
--neutral-500: #9E9E9E;
--neutral-600: #757575;
--neutral-700: #616161;
--neutral-800: #424242;
--neutral-900: #212121;
--neutral-1000: #1A1A1A;
/* ── Typography ── */
--font-family: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif;
--font-family-mono: 'JetBrains Mono', 'SF Mono', monospace;
--text-xs: 11px;
--text-sm: 13px;
--text-base: 15px;
--text-md: 17px;
--text-lg: 20px;
--text-xl: 24px;
--text-2xl: 28px;
--text-3xl: 34px;
--text-4xl: 40px;
--weight-regular: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
/* ── Spacing ── */
--space-2xs: 2px;
--space-xs: 4px;
--space-sm: 8px;
--space-md: 12px;
--space-base: 16px;
--space-lg: 20px;
--space-xl: 24px;
--space-2xl: 32px;
--space-3xl: 40px;
--space-4xl: 48px;
/* ── Border Radius ── */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 20px;
--radius-2xl: 24px;
--radius-full: 9999px;
/* ── Shadows ── */
--shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
--shadow-md: 0 4px 12px rgba(0,0,0,0.1), 0 2px 4px rgba(0,0,0,0.06);
--shadow-lg: 0 8px 24px rgba(0,0,0,0.12), 0 4px 8px rgba(0,0,0,0.06);
--shadow-xl: 0 16px 48px rgba(0,0,0,0.16);
/* ── Dark Mode ── */
--bg-primary-dark: #121212;
--bg-secondary-dark: #1E1E1E;
--bg-card-dark: #2A2A2A;
--text-primary-dark: #ECECEC;
--text-secondary-dark: #A0A0A0;
--text-tertiary-dark: #6A6A6A;
}
/* ── Base Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font-family);
font-size: var(--text-base);
color: var(--neutral-900);
background: var(--neutral-50);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
body.dark {
background: var(--bg-primary-dark);
color: var(--text-primary-dark);
}
/* ── Utility Classes ── */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.gap-xs { gap: var(--space-xs); }
.gap-sm { gap: var(--space-sm); }
.gap-md { gap: var(--space-md); }
.gap-base { gap: var(--space-base); }
.gap-lg { gap: var(--space-lg); }
.text-center { text-align: center; }
.w-full { width: 100%; }
.h-full { height: 100%; }
.relative { position: relative; }
.absolute { position: absolute; }
.rounded-md { border-radius: var(--radius-md); }
.rounded-lg { border-radius: var(--radius-lg); }
.rounded-full { border-radius: var(--radius-full); }
.shadow-sm { box-shadow: var(--shadow-sm); }
.shadow-md { box-shadow: var(--shadow-md); }
.shadow-lg { box-shadow: var(--shadow-lg); }
/* ── Component: Mobile Frame ── */
.mobile-frame {
width: 390px;
height: 844px;
border-radius: 40px;
border: 3px solid var(--neutral-800);
overflow: hidden;
position: relative;
background: var(--neutral-0);
box-shadow: var(--shadow-xl), 0 0 0 1px rgba(0,0,0,0.04);
}
.dark .mobile-frame {
border-color: var(--neutral-600);
background: var(--bg-primary-dark);
}
/* ── Notch ── */
.notch {
width: 120px;
height: 30px;
background: var(--neutral-900);
border-radius: 0 0 20px 20px;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
z-index: 100;
}
.dark .notch { background: var(--bg-primary-dark); border: 2px solid var(--neutral-600); border-top: none; }
/* ── Status Bar ── */
.status-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px 4px;
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 50;
}
/* ── Bottom Nav ── */
.bottom-nav {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 80px;
background: var(--neutral-0);
border-top: 1px solid var(--neutral-200);
display: flex;
justify-content: space-around;
align-items: center;
padding-bottom: 20px;
z-index: 50;
}
.dark .bottom-nav {
background: var(--bg-secondary-dark);
border-color: var(--neutral-700);
}
.bottom-nav-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
font-size: var(--text-xs);
color: var(--neutral-500);
cursor: pointer;
transition: color 0.2s;
}
.bottom-nav-item.active { color: var(--primary-500); }
.bottom-nav-item svg { width: 24px; height: 24px; }
/* ── Content Area ── */
.content-area {
position: absolute;
top: 44px;
bottom: 80px;
left: 0;
right: 0;
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: none;
}
.content-area::-webkit-scrollbar { display: none; }
/* ── Cards ── */
.card {
background: var(--neutral-0);
border-radius: var(--radius-lg);
padding: var(--space-base);
box-shadow: var(--shadow-sm);
border: 1px solid var(--neutral-100);
}
.dark .card {
background: var(--bg-card-dark);
border-color: var(--neutral-700);
}
/* ── Buttons ── */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--space-xs);
padding: 12px 24px;
border-radius: var(--radius-full);
font-weight: var(--weight-semibold);
font-size: var(--text-base);
cursor: pointer;
border: none;
transition: all 0.2s;
min-height: 48px;
}
.btn-primary {
background: var(--primary-500);
color: white;
}
.btn-primary:hover { background: var(--primary-600); }
.btn-secondary {
background: var(--neutral-200);
color: var(--neutral-800);
}
.btn-ghost {
background: transparent;
color: var(--primary-500);
}
.btn-block { width: 100%; }
/* ── Metric Cards ── */
.metric-card {
padding: var(--space-base);
border-radius: var(--radius-lg);
background: var(--neutral-0);
border: 1px solid var(--neutral-200);
text-align: center;
}
.dark .metric-card {
background: var(--bg-card-dark);
border-color: var(--neutral-700);
}
.metric-value {
font-size: var(--text-2xl);
font-weight: var(--weight-bold);
color: var(--primary-500);
}
.metric-label {
font-size: var(--text-xs);
color: var(--neutral-500);
margin-top: 4px;
}
/* ── Label ── */
.label {
font-size: var(--text-sm);
font-weight: var(--weight-medium);
color: var(--neutral-600);
margin-bottom: var(--space-xs);
}
.dark .label { color: var(--text-secondary-dark); }
/* ── Page Title ── */
.page-title {
font-size: var(--text-lg);
font-weight: var(--weight-bold);
color: var(--neutral-900);
}
.dark .page-title { color: var(--text-primary-dark); }
/* ── Section Header ── */
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-base);
}
.section-title {
font-size: var(--text-md);
font-weight: var(--weight-semibold);
}
/* ── Online Indicator ── */
.online-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--alert-success);
display: inline-block;
}
/* ── Badge ── */
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 20px;
height: 20px;
border-radius: var(--radius-full);
background: var(--alert-danger);
color: white;
font-size: var(--text-xs);
font-weight: var(--weight-bold);
padding: 0 6px;
}
/* ── Chip ── */
.chip {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 12px;
border-radius: var(--radius-full);
background: var(--primary-50);
color: var(--primary-600);
font-size: var(--text-sm);
font-weight: var(--weight-medium);
}
.dark .chip { background: rgba(46,125,50,0.15); }
/* ── Gradient Overlay ── */
.gradient-green {
background: linear-gradient(135deg, var(--primary-500), var(--ocean-500));
}
.gradient-ocean {
background: linear-gradient(135deg, var(--ocean-400), var(--ocean-600));
}
/* ── SVG Icon Base ── */
.icon { width: 24px; height: 24px; stroke-width: 2; fill: none; stroke: currentColor; }
.icon-sm { width: 18px; height: 18px; }
.icon-lg { width: 32px; height: 32px; }
.icon-xl { width: 48px; height: 48px; }
/* ── Thumbnail / Avatar ── */
.avatar {
width: 40px;
height: 40px;
border-radius: var(--radius-full);
object-fit: cover;
background: var(--neutral-200);
}
.avatar-sm { width: 32px; height: 32px; }
.avatar-lg { width: 56px; height: 56px; }
/* ── Spacing Utilities ── */
.px-base { padding-left: var(--space-base); padding-right: var(--space-base); }
.py-sm { padding-top: var(--space-sm); padding-bottom: var(--space-sm); }
.py-base { padding-top: var(--space-base); padding-bottom: var(--space-base); }
.p-base { padding: var(--space-base); }
.p-lg { padding: var(--space-lg); }
.mt-sm { margin-top: var(--space-sm); }
.mt-base { margin-top: var(--space-base); }
.mt-lg { margin-top: var(--space-lg); }
.mb-sm { margin-bottom: var(--space-sm); }
.mb-base { margin-bottom: var(--space-base); }
/* ── Grid ── */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-sm); }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-md); }
/* ── Scrollable Row ── */
.scroll-row {
display: flex;
gap: var(--space-md);
overflow-x: auto;
padding: 0 var(--space-base) var(--space-base);
scrollbar-width: none;
}
.scroll-row::-webkit-scrollbar { display: none; }
/* ── Language Picker ── */
.lang-btn {
padding: 6px 12px;
border-radius: var(--radius-md);
border: 2px solid var(--neutral-300);
background: transparent;
font-size: var(--text-sm);
font-weight: var(--weight-semibold);
cursor: pointer;
color: var(--neutral-700);
transition: all 0.2s;
}
.lang-btn.active {
border-color: var(--primary-500);
background: var(--primary-500);
color: white;
}

Binary file not shown.

View File

@@ -0,0 +1,56 @@
{
"document": {
"name": "Smart App City — UI/UX v2 Blue",
"type": "DOCUMENT",
"children": [
{
"name": "Cover",
"type": "PAGE",
"children": [
{
"name": "Cover Frame",
"type": "FRAME",
"x": 0,
"y": 0,
"width": 1440,
"height": 900,
"fills": [
{
"type": "GRADIENT_LINEAR",
"gradientStops": [
{"color": {"r": 0.051, "g": 0.278, "b": 0.631, "a": 1}, "position": 0},
{"color": {"r": 0, "g": 0.514, "b": 0.561, "a": 1}, "position": 1}
]
}
],
"children": [
{"name": "Logo", "type": "RECTANGLE", "x": 620, "y": 200, "width": 200, "height": 200, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 1, "g": 1, "b": 1, "a": 0.15}}]},
{"name": "Title", "type": "TEXT", "x": 320, "y": 440, "width": 800, "text": "Smart App City", "fontSize": 72, "fontWeight": 700, "fills": [{"type": "SOLID", "color": {"r": 1, "g": 1, "b": 1, "a": 1}}]},
{"name": "Subtitle", "type": "TEXT", "x": 420, "y": 530, "width": 600, "text": "Martinique Digital Twin — UI/UX v2 Blue", "fontSize": 24, "fills": [{"type": "SOLID", "color": {"r": 1, "g": 1, "b": 1, "a": 0.7}}]},
{"name": "Version", "type": "TEXT", "x": 590, "y": 600, "width": 260, "text": "13 ecrans · Palette Blue Ocean · React Native", "fontSize": 14, "fills": [{"type": "SOLID", "color": {"r": 1, "g": 1, "b": 1, "a": 0.5}}]}
]
}
]
},
{
"name": "Screens",
"type": "PAGE",
"children": [
{"name": "01 Onboarding", "type": "FRAME", "x": 50, "y": 50, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0.051, "g": 0.278, "b": 0.631, "a": 1}, "position": 0}, {"color": {"r": 0, "g": 0.514, "b": 0.561, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "02 Home Dashboard", "type": "FRAME", "x": 480, "y": 50, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 0.961, "g": 0.961, "b": 0.961, "a": 1}}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "03 Carte Interactive", "type": "FRAME", "x": 910, "y": 50, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 0.831, "g": 0.925, "b": 0.969, "a": 1}}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "04 Marketplace", "type": "FRAME", "x": 1340, "y": 50, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 0.082, "g": 0.396, "b": 0.753, "a": 1}}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "05 AI Chat", "type": "FRAME", "x": 1770, "y": 50, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 0.961, "g": 0.961, "b": 0.961, "a": 1}}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "06 Profil", "type": "FRAME", "x": 50, "y": 960, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0.051, "g": 0.278, "b": 0.631, "a": 1}, "position": 0}, {"color": {"r": 0, "g": 0.514, "b": 0.561, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "07 Notifications", "type": "FRAME", "x": 480, "y": 960, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 0.082, "g": 0.396, "b": 0.753, "a": 1}}], "strokes":[{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "08 Signalements", "type": "FRAME", "x": 910, "y": 960, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "SOLID", "color": {"r": 0.082, "g": 0.396, "b": 0.753, "a": 1}}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "09 Meteo", "type": "FRAME", "x": 1340, "y": 960, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0.051, "g": 0.278, "b": 0.631, "a": 1}, "position": 0}, {"color": {"r": 0.008, "g": 0.533, "b": 0.82, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "10 Transport", "type": "FRAME", "x": 1770, "y": 960, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0.082, "g": 0.396, "b": 0.753, "a": 1}, "position": 0}, {"color": {"r": 0.008, "g": 0.533, "b": 0.82, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "11 Energie", "type": "FRAME", "x": 50, "y": 1870, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0.082, "g": 0.396, "b": 0.753, "a": 1}, "position": 0}, {"color": {"r": 0, "g": 0.514, "b": 0.561, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "12 Sante", "type": "FRAME", "x": 480, "y": 1870, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0, "g": 0.514, "b": 0.561, "a": 1}, "position": 0}, {"color": {"r": 0, "g": 0.675, "b": 0.757, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]},
{"name": "13 Evenements", "type": "FRAME", "x": 910, "y": 1870, "width": 390, "height": 844, "cornerRadius": 40, "fills": [{"type": "GRADIENT_LINEAR", "gradientStops": [{"color": {"r": 0.224, "g": 0.286, "b": 0.671, "a": 1}, "position": 0}, {"color": {"r": 0.082, "g": 0.396, "b": 0.753, "a": 1}, "position": 1}]}], "strokes": [{"type": "SOLID", "color": {"r": 0.259, "g": 0.259, "b": 0.259, "a": 1}, "thickness": 3}]}
]
}
]
}
}

Binary file not shown.

View File

@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2400" height="3600" viewBox="0 0 2400 3600">
<defs>
<linearGradient id="deepBlue" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#051C38"/>
<stop offset="40%" style="stop-color:#0D47A1"/>
<stop offset="100%" style="stop-color:#00838F"/>
</linearGradient>
<linearGradient id="blueHeader" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#0D47A1"/>
<stop offset="100%" style="stop-color:#00ACC1"/>
</linearGradient>
<linearGradient id="indigoGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#3949AB"/>
<stop offset="100%" style="stop-color:#1565C0"/>
</linearGradient>
<linearGradient id="oceanGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#00838F"/>
<stop offset="100%" style="stop-color:#00ACC1"/>
</linearGradient>
<linearGradient id="darkMode" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#0D1B2A"/>
<stop offset="100%" style="stop-color:#1B2838"/>
</linearGradient>
</defs>
<rect width="2400" height="3600" fill="#F5F7FA"/>
<rect x="0" y="0" width="2400" height="80" fill="url(#deepBlue)"/>
<text x="40" y="52" font-family="Inter, sans-serif" font-size="28" font-weight="700" fill="white">Smart App City — UI/UX v2 Blue · Penpot Design System</text>
<text x="40" y="130" font-family="Inter, sans-serif" font-size="18" font-weight="700" fill="#212121">Color Palette — Blue Ocean</text>
<rect x="40" y="150" width="120" height="80" rx="8" fill="#E3F2FD" stroke="#BBDEFB"/>
<rect x="40" y="150" width="120" height="40" rx="8" fill="#1565C0"/>
<text x="52" y="250" font-family="monospace" font-size="11" fill="#666">primary-500</text>
<text x="52" y="266" font-family="monospace" font-size="10" fill="#999">#1565C0</text>
<rect x="180" y="150" width="120" height="80" rx="8" fill="#0D47A1" stroke="#1565C0"/>
<text x="192" y="250" font-family="monospace" font-size="11" fill="#666">primary-600</text>
<text x="192" y="266" font-family="monospace" font-size="10" fill="#999">#0D47A1</text>
<rect x="320" y="150" width="120" height="80" rx="8" fill="#00ACC1" stroke="#26C6DA"/>
<text x="332" y="250" font-family="monospace" font-size="11" fill="#666">ocean-500</text>
<text x="332" y="266" font-family="monospace" font-size="10" fill="#999">#00ACC1</text>
<rect x="460" y="150" width="120" height="80" rx="8" fill="#3949AB" stroke="#5C6BC0"/>
<text x="472" y="250" font-family="monospace" font-size="11" fill="#666">indigo-500</text>
<text x="472" y="266" font-family="monospace" font-size="10" fill="#999">#3949AB</text>
<rect x="620" y="150" width="100" height="60" rx="8" fill="#D32F2F"/>
<text x="630" y="230" font-family="monospace" font-size="10" fill="#666">Danger</text>
<rect x="740" y="150" width="100" height="60" rx="8" fill="#F57C00"/>
<text x="750" y="230" font-family="monospace" font-size="10" fill="#666">Warning</text>
<rect x="860" y="150" width="100" height="60" rx="8" fill="#2E7D32"/>
<text x="875" y="230" font-family="monospace" font-size="10" fill="#666">Success</text>
<rect x="980" y="150" width="100" height="60" rx="8" fill="#0288D1"/>
<text x="1000" y="230" font-family="monospace" font-size="10" fill="#666">Info</text>
<text x="40" y="310" font-family="Inter, sans-serif" font-size="18" font-weight="700" fill="#212121">Dark Mode</text>
<rect x="40" y="330" width="120" height="60" rx="8" fill="#0D1B2A"/>
<text x="52" y="410" font-family="monospace" font-size="11" fill="#666">bg-primary</text>
<rect x="180" y="330" width="120" height="60" rx="8" fill="#1B2838"/>
<text x="192" y="410" font-family="monospace" font-size="11" fill="#666">bg-secondary</text>
<rect x="320" y="330" width="120" height="60" rx="8" fill="#1E3350"/>
<text x="332" y="410" font-family="monospace" font-size="11" fill="#666">bg-card</text>
<text x="40" y="470" font-family="Inter, sans-serif" font-size="18" font-weight="700" fill="#212121">Screen Wireframes — 13 ecrans</text>
<g transform="translate(40, 490)">
<g transform="translate(0,0)">
<rect width="170" height="360" rx="16" fill="url(#deepBlue)" stroke="#424242" stroke-width="2"/>
<rect x="55" y="120" width="60" height="60" rx="12" fill="rgba(255,255,255,0.15)"/>
<text x="85" y="220" text-anchor="middle" font-size="14" font-weight="700" fill="white">Smart App City</text>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">01 Onboarding</text>
</g>
<g transform="translate(190,0)">
<rect width="170" height="360" rx="16" fill="white" stroke="#424242" stroke-width="2"/>
<rect width="170" height="60" rx="16" fill="url(#blueHeader)"/>
<rect x="10" y="80" width="46" height="50" rx="8" fill="white" stroke="#E0E0E0"/>
<rect x="62" y="80" width="46" height="50" rx="8" fill="white" stroke="#E0E0E0"/>
<rect x="114" y="80" width="46" height="50" rx="8" fill="white" stroke="#E0E0E0"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">02 Home Dashboard</text>
</g>
<g transform="translate(380,0)">
<rect width="170" height="360" rx="16" fill="#D4EEF7" stroke="#424242" stroke-width="2"/>
<ellipse cx="85" cy="180" rx="60" ry="100" fill="#BBDEFB" stroke="#64B5F6"/>
<circle cx="70" cy="140" r="5" fill="#1565C0"/>
<circle cx="110" cy="160" r="5" fill="#00ACC1"/>
<circle cx="60" cy="200" r="4" fill="#D32F2F"/>
<circle cx="85" cy="175" r="8" fill="#1565C0" stroke="white" stroke-width="2"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">03 Carte Interactive</text>
</g>
<g transform="translate(570,0)">
<rect width="170" height="360" rx="16" fill="#1565C0" stroke="#424242" stroke-width="2"/>
<rect x="10" y="60" width="150" height="80" rx="12" fill="url(#oceanGrad)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">04 Marketplace</text>
</g>
<g transform="translate(760,0)">
<rect width="170" height="360" rx="16" fill="white" stroke="#424242" stroke-width="2"/>
<rect x="10" y="10" width="30" height="30" rx="15" fill="url(#indigoGrad)"/>
<rect x="50" y="60" width="100" height="40" rx="12" fill="#F5F5F5"/>
<rect x="30" y="110" width="100" height="40" rx="12" fill="url(#blueHeader)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">05 AI Chat</text>
</g>
<g transform="translate(950,0)">
<rect width="170" height="360" rx="16" fill="url(#deepBlue)" stroke="#424242" stroke-width="2"/>
<circle cx="85" cy="80" r="30" fill="rgba(255,255,255,0.2)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">06 Profil</text>
</g>
<g transform="translate(1140,0)">
<rect width="170" height="360" rx="16" fill="#1565C0" stroke="#424242" stroke-width="2"/>
<rect x="10" y="60" width="150" height="50" rx="8" fill="rgba(255,255,255,0.1)"/>
<rect x="10" y="120" width="150" height="50" rx="8" fill="rgba(255,255,255,0.05)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">07 Notifications</text>
</g>
<g transform="translate(1330,0)">
<rect width="170" height="360" rx="16" fill="#1565C0" stroke="#424242" stroke-width="2"/>
<rect x="10" y="60" width="70" height="60" rx="8" fill="rgba(255,255,255,0.1)"/>
<rect x="90" y="60" width="70" height="60" rx="8" fill="rgba(255,255,255,0.1)"/>
<circle cx="140" cy="330" r="20" fill="url(#blueHeader)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">08 Signalements</text>
</g>
</g>
<g transform="translate(40, 900)">
<g transform="translate(0,0)">
<rect width="170" height="360" rx="16" fill="url(#deepBlue)" stroke="#424242" stroke-width="2"/>
<text x="85" y="100" text-anchor="middle" font-size="36" font-weight="200" fill="white">28°</text>
<text x="85" y="160" text-anchor="middle" font-size="12" fill="rgba(255,255,255,0.7)">Partiellement nuageux</text>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">09 Meteo</text>
</g>
<g transform="translate(190,0)">
<rect width="170" height="360" rx="16" fill="url(#blueHeader)" stroke="#424242" stroke-width="2"/>
<rect x="10" y="60" width="150" height="70" rx="12" fill="white" stroke="#E0E0E0"/>
<rect x="20" y="70" width="30" height="30" rx="8" fill="#1565C0"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">10 Transport</text>
</g>
<g transform="translate(380,0)">
<rect width="170" height="360" rx="16" fill="url(#blueHeader)" stroke="#424242" stroke-width="2"/>
<rect x="10" y="60" width="70" height="60" rx="8" fill="white" stroke="#E0E0E0"/>
<rect x="90" y="60" width="70" height="60" rx="8" fill="white" stroke="#E0E0E0"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">11 Energie</text>
</g>
<g transform="translate(570,0)">
<rect width="170" height="360" rx="16" fill="url(#oceanGrad)" stroke="#424242" stroke-width="2"/>
<circle cx="85" cy="100" r="35" fill="rgba(255,255,255,0.15)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">12 Sante</text>
</g>
<g transform="translate(760,0)">
<rect width="170" height="360" rx="16" fill="url(#indigoGrad)" stroke="#424242" stroke-width="2"/>
<rect x="10" y="60" width="150" height="70" rx="12" fill="rgba(255,255,255,0.1)"/>
<text x="85" y="400" text-anchor="middle" font-size="8" fill="#999">13 Evenements</text>
</g>
</g>
<text x="40" y="1350" font-family="Inter, sans-serif" font-size="12" fill="#999">Smart App City v2 Blue — Design System for Figma &amp; Penpot · 13 screens · React Native · Martinique Digital Twin</text>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

1
smart-app-city/frontend/node_modules/.bin/acorn generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../acorn/bin/acorn

View File

@@ -0,0 +1 @@
../baseline-browser-mapping/dist/cli.cjs

1
smart-app-city/frontend/node_modules/.bin/browserslist generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../browserslist/cli.js

1
smart-app-city/frontend/node_modules/.bin/detect-libc generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../detect-libc/bin/detect-libc.js

1
smart-app-city/frontend/node_modules/.bin/envinfo generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../envinfo/dist/cli.js

1
smart-app-city/frontend/node_modules/.bin/esparse generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../esprima/bin/esparse.js

1
smart-app-city/frontend/node_modules/.bin/esvalidate generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../esprima/bin/esvalidate.js

1
smart-app-city/frontend/node_modules/.bin/excpretty generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../@expo/xcpretty/build/cli.js

1
smart-app-city/frontend/node_modules/.bin/expo generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../expo/bin/cli

1
smart-app-city/frontend/node_modules/.bin/expo-internal generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../@expo/cli/build/bin/cli

View File

@@ -0,0 +1 @@
../expo-modules-autolinking/bin/expo-modules-autolinking.js

1
smart-app-city/frontend/node_modules/.bin/fxparser generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../fast-xml-parser/src/cli/cli.js

1
smart-app-city/frontend/node_modules/.bin/image-size generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../image-size/bin/image-size.js

1
smart-app-city/frontend/node_modules/.bin/is-docker generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../is-docker/cli.js

1
smart-app-city/frontend/node_modules/.bin/js-yaml generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../js-yaml/bin/js-yaml.js

1
smart-app-city/frontend/node_modules/.bin/jscodeshift generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../jscodeshift/bin/jscodeshift.js

1
smart-app-city/frontend/node_modules/.bin/jsesc generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../jsesc/bin/jsesc

1
smart-app-city/frontend/node_modules/.bin/json5 generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../json5/lib/cli.js

1
smart-app-city/frontend/node_modules/.bin/logkitty generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../logkitty/bin/logkitty.js

1
smart-app-city/frontend/node_modules/.bin/loose-envify generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../loose-envify/cli.js

1
smart-app-city/frontend/node_modules/.bin/md5-file generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../md5-file/cli.js

1
smart-app-city/frontend/node_modules/.bin/metro generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../metro/src/cli.js

View File

@@ -0,0 +1 @@
../metro-symbolicate/src/index.js

1
smart-app-city/frontend/node_modules/.bin/mime generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../mime/cli.js

1
smart-app-city/frontend/node_modules/.bin/mkdirp generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../mkdirp/bin/cmd.js

1
smart-app-city/frontend/node_modules/.bin/nanoid generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../nanoid/bin/nanoid.cjs

1
smart-app-city/frontend/node_modules/.bin/node-which generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../which/bin/node-which

1
smart-app-city/frontend/node_modules/.bin/parser generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../@babel/parser/bin/babel-parser.js

View File

@@ -0,0 +1 @@
../chrome-launcher/bin/print-chrome-path.js

View File

@@ -0,0 +1 @@
../qrcode-terminal/bin/qrcode-terminal.js

1
smart-app-city/frontend/node_modules/.bin/rc generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../rc/cli.js

1
smart-app-city/frontend/node_modules/.bin/react-native generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../@react-native-community/cli/build/bin.js

1
smart-app-city/frontend/node_modules/.bin/regjsparser generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../regjsparser/bin/parser

1
smart-app-city/frontend/node_modules/.bin/resolve generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../resolve/bin/resolve

Some files were not shown because too many files have changed in this diff Show More