feat: Passwordless cross-device authentication

- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
This commit is contained in:
Bernt
2026-07-07 07:11:50 +00:00
parent 4aa984ad74
commit 6989a98d75
61843 changed files with 5491611 additions and 872231 deletions
+24 -22
View File
@@ -182,7 +182,7 @@ h1 em{font-style:normal;color:var(--qx-blue)}
.btn-secondary:hover{background:rgba(255,255,255,.15);transform:translateY(-2px)}
.trust-strip{display:flex;align-items:center;justify-content:center;gap:16px;flex-wrap:wrap;margin-top:16px;color:rgba(255,255,255,.5);font-size:.8125rem;font-weight:500}
.trust-strip span{display:flex;align-items:center;gap:6px}
.trust-strip span::before{content:'';color:var(--qx-green);font-weight:700}
.trust-strip span::before{content:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';color:var(--qx-green);font-weight:700}
/* =========================================
STATS BAR
@@ -254,8 +254,8 @@ section{padding:88px 24px}
.payment-details{margin-top:36px}
.payment-details summary{cursor:pointer;font-size:1rem;font-weight:700;color:var(--qx-black);padding:18px 24px;background:var(--qx-gray);border-radius:var(--qx-radius);list-style:none;display:flex;align-items:center;justify-content:space-between;transition:background .15s}
.payment-details summary:hover{background:#eaeaec}
.payment-details summary::after{content:'';font-size:1.25rem;color:var(--qx-blue);transition:transform .25s}
.payment-details[open] summary::after{content:''}
.payment-details summary::after{content:'';font-size:1.25rem;color:var(--qx-blue);transition:transform .25s}
.payment-details[open] summary::after{content:''}
.payment-details-body{padding:24px;background:var(--qx-gray);border-radius:0 0 var(--qx-radius) var(--qx-radius);margin-top:-4px}
.payment-details-body ul{list-style:none;display:flex;flex-direction:column;gap:12px}
.payment-details-body li{display:flex;gap:10px;color:var(--qx-gray-dark);font-size:.9375rem;line-height:1.5}
@@ -292,7 +292,7 @@ section{padding:88px 24px}
.client-card:hover .client-extra,.client-card:focus-within .client-extra{max-height:180px;padding:0 28px 24px}
.client-extra ul{list-style:none;display:flex;flex-direction:column;gap:8px;margin-top:12px;border-top:1px solid var(--qx-border);padding-top:14px}
.client-extra li{display:flex;gap:8px;color:var(--qx-gray-dark);font-size:.875rem;line-height:1.5}
.client-extra li::before{content:'';color:var(--qx-green);font-weight:700;flex-shrink:0}
.client-extra li::before{content:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';color:var(--qx-green);font-weight:700;flex-shrink:0}
.client-extra a{display:inline-flex;align-items:center;gap:4px;color:var(--qx-blue);font-size:.875rem;font-weight:600;margin-top:12px;transition:gap .15s}
.client-extra a:hover{gap:8px}
.client-ctas{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
@@ -553,17 +553,18 @@ footer{background:var(--qx-footer);color:rgba(255,255,255,.6);padding:60px 24px
</ul>
<div class="nav-right">
<div class="lang-dropdown" tabindex="0" role="navigation" aria-label="Välj språk">
<button class="lang-toggle" aria-haspopup="true" aria-label="Välj språk — Svenska aktiv">🇸🇪 SV </button>
<button class="lang-toggle" aria-haspopup="true" aria-label="Välj språk — Svenska aktiv"><span class="flag-se">SE</span> SV </button>
<ul class="lang-menu" role="menu">
<li><a href="https://quixzoom.se/" hreflang="sv" class="active" role="menuitem">🇸🇪 Svenska</a></li>
<li><a href="https://quixzoom.de/" hreflang="de" role="menuitem">🇩🇪 Deutsch</a></li>
<li><a href="https://quixzoom.fr/" hreflang="fr" role="menuitem">🇫🇷 Français</a></li>
<li><a href="https://quixzoom.nl/" hreflang="nl" role="menuitem">🇳🇱 Nederlands</a></li>
<li><a href="https://quixzoom.co.uk/" hreflang="en-gb" role="menuitem">🇬🇧 English</a></li>
<li><a href="https://quixzoom.it/" hreflang="it" role="menuitem">🇮🇹 Italiano</a></li>
<li><a href="https://quixzoom.es/" hreflang="es" role="menuitem">🇪🇸 Español</a></li>
<li><a href="https://quixzoom.se/" hreflang="sv" class="active" role="menuitem"><span class="flag-se">SE</span> Svenska</a></li>
<li><a href="https://quixzoom.de/" hreflang="de" role="menuitem"> Deutsch</a></li>
<li><a href="https://quixzoom.fr/" hreflang="fr" role="menuitem"> Français</a></li>
<li><a href="https://quixzoom.nl/" hreflang="nl" role="menuitem"> Nederlands</a></li>
<li><a href="https://quixzoom.co.uk/" hreflang="en-gb" role="menuitem"> English</a></li>
<li><a href="https://quixzoom.it/" hreflang="it" role="menuitem"> Italiano</a></li>
<li><a href="https://quixzoom.es/" hreflang="es" role="menuitem"> Español</a></li>
</ul>
</div>
<a href="/login/" style="color:rgba(255,255,255,.7);font-size:.875rem;font-weight:600;padding:8px 12px;border-radius:8px;transition:color .15s,background .15s;text-decoration:none;white-space:nowrap">Logga in</a>
<a class="nav-cta" href="https://app.quixzoom.com/join">Bli Zoomer →</a>
<label class="hamburger" for="nav-toggle" aria-label="Öppna meny" role="button">
<span></span><span></span><span></span>
@@ -576,6 +577,7 @@ footer{background:var(--qx-footer);color:rgba(255,255,255,.6);padding:60px 24px
<a href="#tjäna-pengar">Tjäna pengar</a>
<a href="#uppdragsgivare">Uppdragsgivare</a>
<a href="#faq">FAQ</a>
<a href="/login/" style="color:rgba(255,255,255,.85);font-size:1rem;font-weight:500;padding:10px 14px;border-radius:10px;transition:background .15s;text-decoration:none;display:block">Logga in</a>
<a class="m-cta" href="https://app.quixzoom.com/join">Bli Zoomer gratis →</a>
</nav>
</nav>
@@ -587,7 +589,7 @@ footer{background:var(--qx-footer);color:rgba(255,255,255,.6);padding:60px 24px
==================================================== -->
<section id="hero" aria-labelledby="hero-h1">
<div class="container">
<div class="hero-badge">🇸🇪 Sverige · Lanseras 1 augusti 2026 · Skärgårdsregionen</div>
<div class="hero-badge"><span class="flag-se">SE</span> Sverige · Lanseras 1 augusti 2026 · Skärgårdsregionen</div>
<h1 id="hero-h1">Välj ett uppdrag.<br>Gå dit. Fotografera.<br><em>Tjäna.</em></h1>
<p class="hero-sub">quiXzoom betalar dig f
<p class="hero-diff">Nordens enda plattform för on-demand fältinspektion — det drönare och satelliter inte ser.</p>ör att fotografera infrastruktur, natur och stadsmiljöer nära dig. Välj dina egna tider. Betalt varje måndag.</p>
@@ -1003,14 +1005,14 @@ footer{background:var(--qx-footer);color:rgba(255,255,255,.6);padding:60px 24px
<p class="app-sub">Registrera dig gratis. Välj ditt första uppdrag. Tjäna pengar den här veckan.</p>
<div class="app-buttons">
<a class="app-btn" href="https://app.quixzoom.com/join" aria-label="Registrera dig — App Store kommer snart">
<div class="app-btn-icon">🍎</div>
<div class="app-btn-icon"></div>
<div class="app-btn-text">
<small>Ladda ner på</small>
App Store
</div>
</a>
<a class="app-btn" href="https://app.quixzoom.com/join" aria-label="Registrera dig — Google Play kommer snart">
<div class="app-btn-icon"></div>
<div class="app-btn-icon"></div>
<div class="app-btn-text">
<small>Hämta på</small>
Google Play
@@ -1039,13 +1041,13 @@ footer{background:var(--qx-footer);color:rgba(255,255,255,.6);padding:60px 24px
<div class="brand-logo">quiX<span class="x">zoom</span></div>
<div class="tagline">The World's Camera Network</div>
<nav class="footer-lang" aria-label="Välj språk">
<a href="https://quixzoom.se/" hreflang="sv" class="active" aria-label="Svenska">🇸🇪 SV</a>
<a href="https://quixzoom.de/" hreflang="de" aria-label="Deutsch">🇩🇪 DE</a>
<a href="https://quixzoom.fr/" hreflang="fr" aria-label="Français">🇫🇷 FR</a>
<a href="https://quixzoom.nl/" hreflang="nl" aria-label="Nederlands">🇳🇱 NL</a>
<a href="https://quixzoom.co.uk/" hreflang="en-gb" aria-label="English">🇬🇧 EN</a>
<a href="https://quixzoom.it/" hreflang="it" aria-label="Italiano">🇮🇹 IT</a>
<a href="https://quixzoom.es/" hreflang="es" aria-label="Español">🇪🇸 ES</a>
<a href="https://quixzoom.se/" hreflang="sv" class="active" aria-label="Svenska"><span class="flag-se">SE</span> SV</a>
<a href="https://quixzoom.de/" hreflang="de" aria-label="Deutsch"> DE</a>
<a href="https://quixzoom.fr/" hreflang="fr" aria-label="Français"> FR</a>
<a href="https://quixzoom.nl/" hreflang="nl" aria-label="Nederlands"> NL</a>
<a href="https://quixzoom.co.uk/" hreflang="en-gb" aria-label="English"> EN</a>
<a href="https://quixzoom.it/" hreflang="it" aria-label="Italiano"> IT</a>
<a href="https://quixzoom.es/" hreflang="es" aria-label="Español"> ES</a>
</nav>
</div>