Files
boc/quixzoom-landing-fixed/launch.html
T

915 lines
32 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="sv" data-theme="dark">
<head>
<meta charset="UTF-8">
<link rel="canonical" href="https://www.quixzoom.com/launch.html">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<title>quiXzoom Launch — Sverige 2026</title>
<meta name="description" content="quiXzoom launches in Sweden 2026. Join the revolution — earn money taking photos, flexible missions, instant payouts.">
<link rel="stylesheet" >
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--ios-bg-primary: #000000;
--ios-bg-secondary: #1C1C1E;
--ios-bg-tertiary: #2C2C2E;
--ios-bg-elevated: #3A3A3C;
--ios-separator: rgba(84,84,88,0.65);
--ios-label: #FFFFFF;
--ios-label-secondary: rgba(235,235,245,0.6);
--ios-label-tertiary: rgba(235,235,245,0.3);
--ios-blue: #0A84FF;
--ios-green: #30D158;
--ios-orange: #FF9F0A;
--ios-red: #FF453A;
--ios-purple: #BF5AF2;
--ios-teal: #64D2FF;
--ios-yellow: #FFD60A;
--ios-indigo: #5E5CE6;
--ios-pink: #FF375F;
--ios-mint: #63E6E2;
--radius-card: 16px;
--radius-sm: 10px;
--font-display: -apple-system, BlinkMacSystemFont, 'SF Pro Display', system-ui, sans-serif;
--font-text: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
--spring: cubic-bezier(0.34,1.56,0.64,1);
}
body {
background: var(--ios-bg-primary);
color: var(--ios-label);
font-family: var(--font-text);
-webkit-font-smoothing: antialiased;
min-height: 100dvh;
padding-bottom: calc(40px + env(safe-area-inset-bottom, 0));
overflow-x: hidden;
}
/* Nav Bar */
.nav-bar {
position: sticky;
top: 0;
z-index: 100;
background: rgba(242,242,247,0.85);
backdrop-filter: saturate(180%) blur(24px);
-webkit-backdrop-filter: saturate(180%) blur(24px);
border-bottom: 0.5px solid var(--ios-separator);
display: flex;
align-items: center;
justify-content: space-between;
padding: calc(env(safe-area-inset-top, 0px) + 10px) 20px 10px;
min-height: 52px;
}
.nav-back {
color: var(--ios-blue);
font-size: 17px;
text-decoration: none;
display: flex;
align-items: center;
gap: 4px;
}
.nav-title {
font-size: 17px;
font-weight: 600;
font-family: var(--font-display);
letter-spacing: -0.3px;
}
.nav-pill {
font-size: 13px;
font-weight: 600;
padding: 4px 10px;
border-radius: var(--radius-xl);
background: var(--ios-bg-tertiary);
color: var(--ios-label-secondary);
}
.nav-pill.critical { background: rgba(255,69,58,0.2); color: var(--ios-red); }
.nav-pill.warning { background: rgba(255,159,10,0.2); color: var(--ios-orange); }
.nav-pill.ok { background: rgba(48,209,88,0.2); color: var(--ios-green); }
/* Hero Countdown */
.hero {
display: flex;
flex-direction: column;
align-items: center;
padding: 32px 20px 20px;
text-align: center;
background: linear-gradient(180deg, rgba(10,132,255,0.08) 0%, transparent 100%);
border-bottom: 0.5px solid var(--ios-separator);
}
.hero-eyebrow {
font-size: 13px;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: uppercase;
color: var(--ios-blue);
margin-bottom: 8px;
}
.hero-title {
font-size: 28px;
font-weight: 700;
font-family: var(--font-display);
letter-spacing: -0.5px;
margin-bottom: 24px;
}
.countdown-ring {
position: relative;
width: 160px;
height: 160px;
margin-bottom: 16px;
}
.countdown-ring svg {
width: 160px;
height: 160px;
transform: rotate(-90deg);
}
.countdown-ring circle {
fill: none;
stroke-width: 6;
stroke-linecap: round;
}
.countdown-ring .track { stroke: var(--ios-bg-tertiary); }
.countdown-ring .progress { stroke: var(--ios-blue); transition: stroke-dashoffset 1s ease; }
.countdown-inner {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.countdown-days {
font-size: 52px;
font-weight: 800;
font-family: var(--font-display);
line-height: 1;
letter-spacing: -2px;
}
.countdown-label {
font-size: 13px;
color: var(--ios-label-secondary);
font-weight: 500;
margin-top: 2px;
}
.hero-date {
font-size: 15px;
color: var(--ios-label-secondary);
margin-bottom: 4px;
}
.hero-date strong { color: var(--ios-label); font-weight: 600; }
/* Stat Row */
.stat-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--ios-separator);
border-top: 1px solid var(--ios-separator);
border-bottom: 1px solid var(--ios-separator);
margin-top: 0;
}
.stat-cell {
background: var(--ios-bg-primary);
padding: 14px 12px;
text-align: center;
}
.stat-num {
font-size: 24px;
font-weight: 700;
font-family: var(--font-display);
letter-spacing: -0.5px;
}
.stat-desc {
font-size: 11px;
color: var(--ios-label-secondary);
margin-top: 2px;
}
/* Content */
.content { padding: 0 0 20px; }
/* Section header */
.section-header {
padding: 24px 20px 8px;
display: flex;
align-items: center;
justify-content: space-between;
}
.section-title {
font-size: 20px;
font-weight: 700;
font-family: var(--font-display);
letter-spacing: -0.3px;
}
.section-badge {
font-size: 13px;
font-weight: 600;
color: var(--ios-label-secondary);
}
.section-badge.ok { color: var(--ios-green); }
.section-badge.warn { color: var(--ios-orange); }
.section-badge.crit { color: var(--ios-red); }
/* Card list */
.card-list {
margin: 0 16px;
background: var(--ios-bg-secondary);
border-radius: var(--radius-card);
overflow: hidden;
}
/* Milestone row */
.milestone-row {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-bottom: 0.5px solid var(--ios-separator);
cursor: pointer;
transition: background 0.15s;
-webkit-tap-highlight-color: transparent;
}
.milestone-row:last-child { border-bottom: none; }
.milestone-row:active { background: var(--ios-bg-tertiary); }
.checkbox {
width: 24px;
height: 24px;
border-radius: var(--radius-full);
border: 2px solid var(--ios-bg-elevated);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all 0.2s var(--spring);
background: var(--ios-bg-secondary);
}
.checkbox.checked {
background: var(--ios-green);
border-color: var(--ios-green);
}
.checkbox.checked::after {
content: '';
width: 6px;
height: 10px;
border: 2px solid white;
border-top: none;
border-left: none;
transform: rotate(45deg) translate(-1px, -1px);
display: block;
}
.checkbox.critical { border-color: var(--ios-red); }
.milestone-text { flex: 1; min-width: 0; }
.milestone-label {
font-size: 15px;
font-weight: 500;
color: var(--ios-label);
line-height: 1.3;
}
.milestone-meta {
font-size: 12px;
color: var(--ios-label-secondary);
margin-top: 2px;
}
.milestone-row.done .milestone-label {
color: var(--ios-label-secondary);
text-decoration: line-through;
}
.blocker-tag {
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: var(--radius-sm);
background: rgba(255,69,58,0.15);
color: var(--ios-red);
flex-shrink: 0;
}
.warn-tag {
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: var(--radius-sm);
background: rgba(255,159,10,0.15);
color: var(--ios-orange);
flex-shrink: 0;
}
.ok-tag {
font-size: 11px;
font-weight: 600;
padding: 3px 8px;
border-radius: var(--radius-sm);
background: rgba(48,209,88,0.15);
color: var(--ios-green);
flex-shrink: 0;
}
/* Revenue / Tech status rows */
.status-row {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-bottom: 0.5px solid var(--ios-separator);
}
.status-row:last-child { border-bottom: none; }
.status-icon {
width: 36px;
height: 36px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.status-icon.blue { background: rgba(10,132,255,0.15); }
.status-icon.green { background: rgba(48,209,88,0.15); }
.status-icon.orange { background: rgba(255,159,10,0.15); }
.status-icon.red { background: rgba(255,69,58,0.15); }
.status-icon.purple { background: rgba(191,90,242,0.15); }
.status-text { flex: 1; min-width: 0; }
.status-label {
font-size: 15px;
font-weight: 500;
}
.status-desc {
font-size: 12px;
color: var(--ios-label-secondary);
margin-top: 2px;
}
.status-dot {
width: 10px;
height: 10px;
border-radius: var(--radius-full);
flex-shrink: 0;
}
.status-dot.red { background: var(--ios-red); }
.status-dot.orange { background: var(--ios-orange); }
.status-dot.green { background: var(--ios-green); }
.status-dot.grey { background: var(--ios-label-secondary); }
/* Team action rows */
.action-row {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 14px 16px;
border-bottom: 0.5px solid var(--ios-separator);
}
.action-row:last-child { border-bottom: none; }
.action-avatar {
width: 36px;
height: 36px;
border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 700;
flex-shrink: 0;
}
.action-text { flex: 1; min-width: 0; }
.action-who {
font-size: 15px;
font-weight: 600;
}
.action-task {
font-size: 14px;
color: var(--ios-label-secondary);
margin-top: 2px;
line-height: 1.4;
}
.action-time {
font-size: 12px;
color: var(--ios-label-tertiary);
flex-shrink: 0;
margin-top: 2px;
}
/* Progress bar */
.progress-bar-wrap {
padding: 0 16px 16px;
margin: 0 16px;
background: var(--ios-bg-secondary);
border-radius: 0 0 var(--radius-card) var(--radius-card);
}
.progress-bar-label {
display: flex;
justify-content: space-between;
font-size: 13px;
color: var(--ios-label-secondary);
margin-bottom: 8px;
padding-top: 4px;
}
.progress-bar-track {
height: 6px;
background: var(--ios-bg-elevated);
border-radius: var(--radius-sm);
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
border-radius: var(--radius-sm);
background: var(--ios-green);
transition: width 0.8s var(--spring);
}
/* Info card */
.info-card {
margin: 16px 16px 0;
background: rgba(10,132,255,0.08);
border: 1px solid rgba(10,132,255,0.2);
border-radius: var(--radius-card);
padding: 14px 16px;
display: flex;
gap: 10px;
align-items: flex-start;
}
.info-card-icon { font-size: 20px; flex-shrink: 0; }
.info-card-text { font-size: 14px; color: var(--ios-label-secondary); line-height: 1.5; }
.info-card-text strong { color: var(--ios-blue); }
/* Last updated */
.last-updated {
text-align: center;
font-size: 12px;
color: var(--ios-label-tertiary);
padding: 20px 20px 4px;
}
/* Spinner */
.spin {
display: inline-block;
width: 14px;
height: 14px;
border: 2px solid var(--ios-label-tertiary);
border-top-color: var(--ios-blue);
border-radius: var(--radius-full);
animation: spin 0.8s linear infinite;
vertical-align: middle;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* Responsive */
@media (min-width: 600px) {
.hero, .stat-row, .content { max-width: 480px; margin-left: auto; margin-right: auto; }
.nav-bar { max-width: none; }
}
@media (max-width: 640px) {
.hero h1 { font-size: 2rem !important; }
.hero p { font-size: 1rem !important; }
.card { padding: 1.5rem !important; }
.grid { grid-template-columns: 1fr !important; }
.btn { padding: 0.75rem 1.5rem !important; font-size: 1rem !important; }
}
</style>
<style id="wcag-contrast-enforcement">
/* AAMOS GLOBAL CONTRAST ENFORCEMENT — WCAG AA (4.5:1 minimum) */
/* Regel: Ingen text under 70% opacity. Aldrig. */
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
/* Fix common low-contrast patterns */
[style*="rgba(60,60,67,0.4)"] { color: rgba(60,60,67,0.65) !important; }
[style*="rgba(60,60,67,0.3)"] { color: rgba(60,60,67,0.65) !important; }
[style*="rgba(255,255,255,0.4)"] { color: rgba(255,255,255,0.72) !important; }
[style*="rgba(255,255,255,0.3)"] { color: rgba(255,255,255,0.72) !important; }
[style*="opacity: 0.4"] { opacity: 0.72 !important; }
[style*="opacity: 0.3"] { opacity: 0.72 !important; }
@media (max-width: 640px) {
.hero h1 { font-size: 2rem !important; }
.hero p { font-size: 1rem !important; }
.card { padding: 1.5rem !important; }
.grid { grid-template-columns: 1fr !important; }
.btn { padding: 0.75rem 1.5rem !important; font-size: 1rem !important; }
}
</style>
<meta property="og:type" content="website">
<meta property="og:title" content="quiXzoom Launch — Sverige 2026">
<meta property="og:description" content="quiXzoom — Earn per Mission. No Platform Fee.">
<meta property="og:url" content="https://www.quixzoom.com/launch.html">
<meta property="og:image" content="https://www.quixzoom.com/images/sweden-launch.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="quiXzoom launch August 2026 — earn per mission">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://www.quixzoom.com/images/sweden-launch.jpg">
<meta name="twitter:title" content="quiXzoom Launch — Sverige 2026">
</head>
<body>
<!-- Nav Bar -->
<nav class="nav-bar">
<a class="nav-back" href="aamos-hub/index.html">
<svg width="10" height="17" viewBox="0 0 10 17" fill="none"><path d="M9 1L1 8.5L9 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
Hub
</a>
<span class="nav-title">quiXzoom Launch</span>
<span class="nav-pill critical" id="nav-pill"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2L10 8L14 9L8 14L6 8L2 7L8 2Z" fill="#666"/></svg> <span id="nav-days"></span>d</span>
</nav>
<!-- Hero -->
<section class="hero">
<div class="hero-eyebrow"><span class="flag-se">SE</span> Sverige-lansering</div>
<h1 class="hero-title">quiXzoom Launch Tracker</h1>
<div class="countdown-ring">
<svg viewBox="0 0 160 160">
<circle class="track" cx="80" cy="80" r="70" />
<circle class="progress" cx="80" cy="80" r="70"
stroke-dasharray="439.8"
id="progress-arc"
stroke-dashoffset="0" />
</svg>
<div class="countdown-inner">
<span class="countdown-days" id="countdown-days"></span>
<span class="countdown-label">dagar kvar</span>
</div>
</div>
<p class="hero-date">Lanseringsdatum: <strong>1 augusti 2026</strong></p>
</section>
<!-- Stats -->
<div class="stat-row">
<div class="stat-cell">
<div class="stat-num" id="stat-done" style="color:var(--ios-green)">0</div>
<div class="stat-desc">Klara</div>
</div>
<div class="stat-cell">
<div class="stat-num" id="stat-remaining" style="color:var(--ios-orange)">9</div>
<div class="stat-desc">Återstår</div>
</div>
<div class="stat-cell">
<div class="stat-num" id="stat-blockers" style="color:var(--ios-red)">2</div>
<div class="stat-desc">Blockers</div>
</div>
</div>
<!-- Content -->
<div class="content">
<!-- Section 1: Kritiska Milstolpar -->
<div class="section-header">
<h2 class="section-title">Kritiska Milstolpar</h2>
<span class="section-badge crit" id="milestone-badge">0 / 9</span>
</div>
<div class="card-list" id="milestone-list">
<!-- Stripe KYC -->
<div class="milestone-row" data-id="stripe-kyc" data-blocker="true" onclick="toggleMilestone(this)">
<div class="checkbox critical" id="chk-stripe-kyc"></div>
<div class="milestone-text">
<div class="milestone-label">Stripe KYC aktiverat</div>
<div class="milestone-meta">Blockar alla betalningar · Prioritet #1</div>
</div>
<span class="blocker-tag">BLOCKER</span>
</div>
<!-- TED EU -->
<div class="milestone-row" data-id="ted-api" data-blocker="true" onclick="toggleMilestone(this)">
<div class="checkbox critical" id="chk-ted-api"></div>
<div class="milestone-text">
<div class="milestone-label">TED EU API-nyckel konfigurerad</div>
<div class="milestone-meta">5 min · gratis · Erik fixar</div>
</div>
<span class="blocker-tag">BLOCKER</span>
</div>
<!-- EIN -->
<div class="milestone-row" data-id="ein" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-ein"></div>
<div class="milestone-text">
<div class="milestone-label">EIN QuiXzoom Inc (Delaware) mottaget</div>
<div class="milestone-meta">Winston follow-up pågår</div>
</div>
<span class="warn-tag">VÄNTAR</span>
</div>
<!-- Zoomer rekrytering -->
<div class="milestone-row" data-id="zoomer-rekrytering" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-zoomer-rekrytering"></div>
<div class="milestone-text">
<div class="milestone-label">Zoomer rekryteringskampanj aktiv</div>
<div class="milestone-meta">Mål: 20+ zoomers inför soft launch</div>
</div>
<span class="warn-tag">EJ STARTAD</span>
</div>
<!-- App Store -->
<div class="milestone-row" data-id="app-store" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-app-store"></div>
<div class="milestone-text">
<div class="milestone-label">App Store-ansökan (iOS + Android)</div>
<div class="milestone-meta">Johan ansvarig · Review tar 13 dagar</div>
</div>
<span class="warn-tag">EJ STARTAT</span>
</div>
<!-- Stripe Connect -->
<div class="milestone-row" data-id="stripe-connect" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-stripe-connect"></div>
<div class="milestone-text">
<div class="milestone-label">Stripe Connect för zoomer-utbetalningar</div>
<div class="milestone-meta">Beror på Stripe KYC</div>
</div>
<span class="warn-tag">BLOCKERAS</span>
</div>
<!-- PR -->
<div class="milestone-row" data-id="pr" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-pr"></div>
<div class="milestone-text">
<div class="milestone-label">PR / pressrelease klar</div>
<div class="milestone-meta">Deadline: 25 maj 2026</div>
</div>
<span class="warn-tag">EJ KLAR</span>
</div>
<!-- Beta-test -->
<div class="milestone-row" data-id="beta" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-beta"></div>
<div class="milestone-text">
<div class="milestone-label">Beta-test genomfört (min. 10 zoomers)</div>
<div class="milestone-meta">Soft launch: 1 augusti 2026</div>
</div>
<span class="warn-tag">EJ STARTAD</span>
</div>
<!-- Legal -->
<div class="milestone-row" data-id="legal" onclick="toggleMilestone(this)">
<div class="checkbox" id="chk-legal"></div>
<div class="milestone-text">
<div class="milestone-label">Legal (terms, privacy policy) godkänt</div>
<div class="milestone-meta">GDPR Art. 13, Art. 30 + zoomer-avtal</div>
</div>
<span class="warn-tag">EJ KLART</span>
</div>
</div>
<!-- Progress bar (continuation of card) -->
<div class="progress-bar-wrap" style="margin: 0 16px; border-radius: 0 0 16px 16px; padding: 12px 16px 16px;">
<div class="progress-bar-label">
<span>Framsteg</span>
<span id="pct-label">0%</span>
</div>
<div class="progress-bar-track">
<div class="progress-bar-fill" id="progress-fill" style="width:0%"></div>
</div>
</div>
<!-- Section 2: Revenue Readiness -->
<div class="section-header">
<h2 class="section-title">Revenue Readiness</h2>
<span class="section-badge crit" id="revenue-badge"><svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M10 3L17 17H3L10 3Z" stroke="#f59e0b" stroke-width="2"/><path d="M10 8V12M10 14V14.5" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/></svg> Ej redo</span>
</div>
<div class="card-list">
<div class="status-row">
<div class="status-icon red"></div>
<div class="status-text">
<div class="status-label">Stripe KYC</div>
<div class="status-desc">Blockar alla live-betalningar — aktivera omedelbart</div>
</div>
<div class="status-dot red"></div>
</div>
<div class="status-row">
<div class="status-icon orange"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M2 8C2 11.3 4.7 14 8 14C10.5 14 12.7 12.5 13.7 10.3" stroke="#666" stroke-width="1.5" stroke-linecap="round"/><path d="M14 8C14 4.7 11.3 2 8 2C5.5 2 3.3 3.5 2.3 5.7" stroke="#666" stroke-width="1.5" stroke-linecap="round"/><path d="M13.5 7.5L14 10L11.5 9.5" stroke="#666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M2.5 8.5L2 6L4.5 6.5" stroke="#666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
<div class="status-text">
<div class="status-label">Payment flow</div>
<div class="status-desc">Ej testbar utan Stripe KYC · Implementerat i kod</div>
</div>
<div class="status-dot orange"></div>
</div>
<div class="status-row">
<div class="status-icon green"></div>
<div class="status-text">
<div class="status-label">Pricing konfigurerat</div>
<div class="status-desc">quiXzoom-priser satt i systemet</div>
</div>
<div class="status-dot green"></div>
</div>
<div class="status-row">
<div class="status-icon red"></div>
<div class="status-text">
<div class="status-label">Stripe Connect (zoomer-utbetalningar)</div>
<div class="status-desc">Väntar på KYC-godkännande</div>
</div>
<div class="status-dot red"></div>
</div>
</div>
<!-- Section 3: Tech Readiness -->
<div class="section-header">
<h2 class="section-title">Tech Readiness</h2>
<span class="section-badge warn" id="tech-badge">Delvis redo</span>
</div>
<div class="card-list">
<div class="status-row">
<div class="status-icon green"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" stroke="#666" stroke-width="1.5"/><path d="M8 2V4M8 12V14M2 8H4M12 8H14M4.3 4.3L5.7 5.7M10.3 10.3L11.7 11.7M4.3 11.7L5.7 10.3M10.3 5.7L11.7 4.3" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg></div>
<div class="status-text">
<div class="status-label">AAMOS backend</div>
<div class="status-desc">Live · amos.wavult.com operationell</div>
</div>
<div class="status-dot green"></div>
</div>
<div class="status-row">
<div class="status-icon green"></div>
<div class="status-text">
<div class="status-label">quixzoom.com</div>
<div class="status-desc">Landing page live</div>
</div>
<div class="status-dot green"></div>
</div>
<div class="status-row">
<div class="status-icon orange"></div>
<div class="status-text">
<div class="status-label">iOS / Android app</div>
<div class="status-desc">Under utveckling · App Store-submission ej genomförd</div>
</div>
<div class="status-dot orange"></div>
</div>
<div class="status-row">
<div class="status-icon orange"></div>
<div class="status-text">
<div class="status-label">TED EU API</div>
<div class="status-desc">API-nyckel saknas · 5 min att fixa</div>
</div>
<div class="status-dot orange"></div>
</div>
<div class="status-row">
<div class="status-icon red"></div>
<div class="status-text">
<div class="status-label">Load-test + rollback-plan</div>
<div class="status-desc">Ej genomfört · Kritisk inför launch</div>
</div>
<div class="status-dot red"></div>
</div>
<div class="status-row">
<div class="status-icon red"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="7" width="10" height="7" rx="1" stroke="#666" stroke-width="1.5"/><path d="M5 7V5C5 3.3 6.3 2 8 2C9.7 2 11 3.3 11 5V7" stroke="#666" stroke-width="1.5"/><circle cx="8" cy="10.5" r="1" fill="#666"/></svg></div>
<div class="status-text">
<div class="status-label">Pentest / säkerhetsgranskning</div>
<div class="status-desc">Ej genomförd · Måste göras inför launch</div>
</div>
<div class="status-dot red"></div>
</div>
</div>
<!-- Section 4: Team Actions Needed -->
<div class="section-header">
<h2 class="section-title">Team Actions Needed</h2>
<span class="section-badge crit">Åtgärd krävs</span>
</div>
<div class="card-list">
<div class="action-row">
<div class="action-avatar" style="background:rgba(10,132,255,0.15);color:var(--ios-blue)">ES</div>
<div class="action-text">
<div class="action-who">Erik</div>
<div class="action-task">Stripe KYC — logga in på Stripe Dashboard, slutför verifiering<br><strong style="color:var(--ios-red)">BLOCKER</strong> · Tar 3060 min</div>
</div>
<div class="action-time">Idag</div>
</div>
<div class="action-row">
<div class="action-avatar" style="background:rgba(10,132,255,0.15);color:var(--ios-blue)">ES</div>
<div class="action-text">
<div class="action-who">Erik</div>
<div class="action-task">TED EU API-nyckel — skaffa och konfigurera<br><em style="color:var(--ios-label-secondary)">Gratis · 5 min</em></div>
</div>
<div class="action-time">Idag</div>
</div>
<div class="action-row">
<div class="action-avatar" style="background:rgba(48,209,88,0.15);color:var(--ios-green)">JN</div>
<div class="action-text">
<div class="action-who">Johan</div>
<div class="action-task">App Store submission — iOS + Android<br><em style="color:var(--ios-label-secondary)">Review tar 13 dagar efter submission</em></div>
</div>
<div class="action-time">Denna vecka</div>
</div>
<div class="action-row">
<div class="action-avatar" style="background:rgba(191,90,242,0.15);color:var(--ios-purple)">WK</div>
<div class="action-text">
<div class="action-who">Winston</div>
<div class="action-task">EIN follow-up — QuiXzoom Inc Delaware<br><em style="color:var(--ios-label-secondary)">Kontakta IRS / formation-agent</em></div>
</div>
<div class="action-time">Denna vecka</div>
</div>
</div>
<div class="info-card">
<div class="info-card-icon"></div>
<div class="info-card-text">
<strong>Nästa kritiska deadline:</strong> PR/pressrelease måste vara klar senast <strong>25 maj</strong> (3 veckor innan launch). Zoomer-rekrytering bör starta omedelbart — mål: 20+ zoomers till soft launch <strong>1 augusti</strong>.
</div>
</div>
<div class="last-updated" id="last-updated">Uppdaterad <span id="updated-time"></span></div>
</div><!-- /content -->
<script>
// Launch date
const LAUNCH_DATE = new Date('2026-06-15T00:00:00+02:00');
// We assume campaign started ~90 days before launch for the ring
const CAMPAIGN_START = new Date('2026-03-17T00:00:00+02:00');
function daysUntilLaunch() {
const now = new Date();
return Math.max(0, Math.ceil((LAUNCH_DATE - now) / 86400000));
}
function updateHero() {
const days = daysUntilLaunch();
document.getElementById('countdown-days').textContent = days;
document.getElementById('nav-days').textContent = days;
// Ring: 0 = no time left, full = 100% remaining
const total = (LAUNCH_DATE - CAMPAIGN_START) / 86400000;
const remaining = (LAUNCH_DATE - new Date()) / 86400000;
const pct = Math.max(0, Math.min(1, remaining / total));
const circumference = 2 * Math.PI * 70; // r=70
const offset = circumference * (1 - pct);
document.getElementById('progress-arc').style.strokeDasharray = circumference;
document.getElementById('progress-arc').style.strokeDashoffset = offset;
// Color
const arc = document.getElementById('progress-arc');
arc.style.stroke = days <= 7 ? 'var(--ios-red)' : days <= 21 ? 'var(--ios-orange)' : 'var(--ios-blue)';
const pill = document.getElementById('nav-pill');
pill.className = 'nav-pill ' + (days <= 7 ? 'critical' : days <= 21 ? 'warning' : 'critical');
document.getElementById('updated-time').textContent = new Date().toLocaleString('sv-SE', {
day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit'
});
}
// Milestone state (persisted in localStorage)
const STORAGE_KEY = 'qx_launch_milestones_v2';
function loadState() {
try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } catch { return {}; }
}
function saveState(state) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
}
function applyState() {
const state = loadState();
let done = 0, blockers = 0;
const rows = document.querySelectorAll('.milestone-row[data-id]');
rows.forEach(row => {
const id = row.dataset.id;
const chk = document.getElementById('chk-' + id);
if (state[id]) {
chk.classList.add('checked');
row.classList.add('done');
done++;
// Remove tags when done
const tag = row.querySelector('.blocker-tag, .warn-tag, .ok-tag');
if (tag) tag.style.display = 'none';
} else {
chk.classList.remove('checked');
row.classList.remove('done');
if (row.dataset.blocker === 'true' && !state[id]) blockers++;
}
});
const remaining = rows.length - done;
document.getElementById('stat-done').textContent = done;
document.getElementById('stat-remaining').textContent = remaining;
document.getElementById('stat-blockers').textContent = blockers;
document.getElementById('milestone-badge').textContent = done + ' / ' + rows.length;
const pct = Math.round((done / rows.length) * 100);
document.getElementById('progress-fill').style.width = pct + '%';
document.getElementById('pct-label').textContent = pct + '%';
const badge = document.getElementById('milestone-badge');
badge.className = 'section-badge ' + (done === rows.length ? 'ok' : done > rows.length / 2 ? 'warn' : 'crit');
}
function toggleMilestone(row) {
const id = row.dataset.id;
const state = loadState();
state[id] = !state[id];
saveState(state);
applyState();
}
// Init
updateHero();
applyState();
setInterval(updateHero, 60000);
</script>
</body>
</html>