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

1436 lines
47 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; }
}
/* QUIXZOOM STANDARD — Dark Theme */
:root {
--qz-bg: #0a0a0a;
--qz-surface: #111111;
--qz-surface-2: #1a1a1a;
--qz-border: rgba(255,255,255,0.08);
--qz-text: #e8e8e8;
--qz-text-dim: #a0a0a0;
--qz-text-muted: #6b6b6b;
--qz-blue: #007AFF;
--qz-blue-dark: #0056CC;
--qz-radius: 10px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Inter', sans-serif;
background: var(--qz-bg);
color: var(--qz-text);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
/* Navigation */
.qz-nav {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
display: flex; align-items: center; justify-content: space-between;
padding: 0 24px; height: 56px;
background: rgba(255,255,255,0.92);
backdrop-filter: blur(16px);
border-bottom: 1px solid var(--qz-border);
}
.qz-nav-logo { font-size: 18px; font-weight: 700; color: #fff; text-decoration: none; }
.qz-nav-links { display: flex; gap: 24px; list-style: none; }
.qz-nav-links a { font-size: 14px; color: var(--qz-text-dim); text-decoration: none; transition: color 0.2s; }
.qz-nav-links a:hover { color: #fff; }
/* Buttons */
.qz-btn {
display: inline-flex; align-items: center; gap: 6px;
padding: 12px 24px; border-radius: var(--qz-radius);
font-size: 15px; font-weight: 600; text-decoration: none;
transition: all 0.2s; cursor: pointer; border: none;
}
.qz-btn-primary {
background: var(--qz-blue); color: #fff;
}
.qz-btn-primary:hover {
background: var(--qz-blue-dark); transform: translateY(-1px);
}
.qz-btn-ghost {
background: transparent; color: var(--qz-text);
border: 1px solid var(--qz-border);
}
.qz-btn-ghost:hover {
border-color: var(--qz-blue); color: var(--qz-blue);
}
/* Cards */
.qz-card {
background: var(--qz-surface);
border: 1px solid var(--qz-border);
border-radius: var(--qz-radius);
padding: 24px;
transition: transform 0.2s, border-color 0.2s;
}
.qz-card:hover {
transform: translateY(-2px);
border-color: rgba(0,122,255,0.3);
}
/* Footer */
.qz-footer {
border-top: 1px solid var(--qz-border);
padding: 40px 24px;
text-align: center;
color: var(--qz-text-dim);
font-size: 14px;
}
/* Banner */
.qz-banner {
background: #001E50;
color: rgba(255,255,255,0.55);
text-align: center;
padding: 10px;
font-size: 12px;
}
.qz-banner a { color: rgba(255,255,255,0.8); text-decoration: none; }
@media (max-width: 768px) {
.qz-nav-links { display: none; }
}
</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; }
}
/* QUIXZOOM STANDARD — Dark Theme */
:root {
--qz-bg: #0a0a0a;
--qz-surface: #111111;
--qz-surface-2: #1a1a1a;
--qz-border: rgba(255,255,255,0.08);
--qz-text: #e8e8e8;
--qz-text-dim: #a0a0a0;
--qz-text-muted: #6b6b6b;
--qz-blue: #007AFF;
--qz-blue-dark: #0056CC;
--qz-radius: 10px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Inter', sans-serif;
background: var(--qz-bg);
color: var(--qz-text);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
/* Navigation */
.qz-nav {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
display: flex; align-items: center; justify-content: space-between;
padding: 0 24px; height: 56px;
background: rgba(255,255,255,0.92);
backdrop-filter: blur(16px);
border-bottom: 1px solid var(--qz-border);
}
.qz-nav-logo { font-size: 18px; font-weight: 700; color: #fff; text-decoration: none; }
.qz-nav-links { display: flex; gap: 24px; list-style: none; }
.qz-nav-links a { font-size: 14px; color: var(--qz-text-dim); text-decoration: none; transition: color 0.2s; }
.qz-nav-links a:hover { color: #fff; }
/* Buttons */
.qz-btn {
display: inline-flex; align-items: center; gap: 6px;
padding: 12px 24px; border-radius: var(--qz-radius);
font-size: 15px; font-weight: 600; text-decoration: none;
transition: all 0.2s; cursor: pointer; border: none;
}
.qz-btn-primary {
background: var(--qz-blue); color: #fff;
}
.qz-btn-primary:hover {
background: var(--qz-blue-dark); transform: translateY(-1px);
}
.qz-btn-ghost {
background: transparent; color: var(--qz-text);
border: 1px solid var(--qz-border);
}
.qz-btn-ghost:hover {
border-color: var(--qz-blue); color: var(--qz-blue);
}
/* Cards */
.qz-card {
background: var(--qz-surface);
border: 1px solid var(--qz-border);
border-radius: var(--qz-radius);
padding: 24px;
transition: transform 0.2s, border-color 0.2s;
}
.qz-card:hover {
transform: translateY(-2px);
border-color: rgba(0,122,255,0.3);
}
/* Footer */
.qz-footer {
border-top: 1px solid var(--qz-border);
padding: 40px 24px;
text-align: center;
color: var(--qz-text-dim);
font-size: 14px;
}
/* Banner */
.qz-banner {
background: #001E50;
color: rgba(255,255,255,0.55);
text-align: center;
padding: 10px;
font-size: 12px;
}
.qz-banner a { color: rgba(255,255,255,0.8); text-decoration: none; }
@media (max-width: 768px) {
.qz-nav-links { display: none; }
}
</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">
<script type="module" src="https://auth.quixzoom.com/site-auth-snippet.js"></script>
</head>
<body>
<!-- Nav Bar -->
<nav class="qz-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>
<!-- quiXzoom Mina Sidor - Universal Header Component -->
<!-- Injicera detta i <head> på alla quiXzoom-sajter -->
<style>
.qz-auth-bar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 48px;
background: #0A0A0A;
border-bottom: 1px solid rgba(255,255,255,0.1);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
z-index: 9999;
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
}
.qz-auth-bar .qz-logo {
font-size: 18px;
font-weight: 700;
color: #fff;
text-decoration: none;
letter-spacing: -0.5px;
}
.qz-auth-bar .qz-logo span {
color: #007AFF;
}
.qz-auth-bar .qz-nav {
display: flex;
gap: 8px;
align-items: center;
}
.qz-auth-bar .qz-btn {
padding: 8px 16px;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
border: none;
text-decoration: none;
}
.qz-auth-bar .qz-btn-primary {
background: #007AFF;
color: white;
}
.qz-auth-bar .qz-btn-primary:hover {
background: #0056CC;
}
.qz-auth-bar .qz-btn-ghost {
background: transparent;
color: rgba(255,255,255,0.8);
}
.qz-auth-bar .qz-btn-ghost:hover {
background: rgba(255,255,255,0.1);
color: white;
}
.qz-auth-bar .qz-user {
display: flex;
align-items: center;
gap: 8px;
color: white;
font-size: 14px;
}
.qz-auth-bar .qz-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: #007AFF;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
}
.qz-auth-bar .qz-dropdown {
position: relative;
}
.qz-auth-bar .qz-dropdown-menu {
position: absolute;
top: 40px;
right: 0;
background: #1C1C1E;
border: 1px solid rgba(255,255,255,0.1);
border-radius: 12px;
padding: 8px;
min-width: 200px;
display: none;
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
}
.qz-auth-bar .qz-dropdown-menu.active {
display: block;
}
.qz-auth-bar .qz-dropdown-item {
padding: 10px 12px;
border-radius: 8px;
color: white;
text-decoration: none;
display: flex;
align-items: center;
gap: 10px;
font-size: 14px;
transition: background 0.2s;
}
.qz-auth-bar .qz-dropdown-item:hover {
background: rgba(255,255,255,0.1);
}
.qz-auth-bar .qz-dropdown-divider {
height: 1px;
background: rgba(255,255,255,0.1);
margin: 8px 0;
}
.qz-auth-bar .qz-balance {
background: rgba(0,122,255,0.15);
color: #007AFF;
padding: 4px 10px;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
}
@media (max-width: 640px) {
.qz-auth-bar .qz-nav .qz-btn-ghost:not(.qz-user) {
display: none;
}
}
/* QUIXZOOM STANDARD — Dark Theme */
:root {
--qz-bg: #0a0a0a;
--qz-surface: #111111;
--qz-surface-2: #1a1a1a;
--qz-border: rgba(255,255,255,0.08);
--qz-text: #e8e8e8;
--qz-text-dim: #a0a0a0;
--qz-text-muted: #6b6b6b;
--qz-blue: #007AFF;
--qz-blue-dark: #0056CC;
--qz-radius: 10px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Inter', sans-serif;
background: var(--qz-bg);
color: var(--qz-text);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
/* Navigation */
.qz-nav {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
display: flex; align-items: center; justify-content: space-between;
padding: 0 24px; height: 56px;
background: rgba(255,255,255,0.92);
backdrop-filter: blur(16px);
border-bottom: 1px solid var(--qz-border);
}
.qz-nav-logo { font-size: 18px; font-weight: 700; color: #fff; text-decoration: none; }
.qz-nav-links { display: flex; gap: 24px; list-style: none; }
.qz-nav-links a { font-size: 14px; color: var(--qz-text-dim); text-decoration: none; transition: color 0.2s; }
.qz-nav-links a:hover { color: #fff; }
/* Buttons */
.qz-btn {
display: inline-flex; align-items: center; gap: 6px;
padding: 12px 24px; border-radius: var(--qz-radius);
font-size: 15px; font-weight: 600; text-decoration: none;
transition: all 0.2s; cursor: pointer; border: none;
}
.qz-btn-primary {
background: var(--qz-blue); color: #fff;
}
.qz-btn-primary:hover {
background: var(--qz-blue-dark); transform: translateY(-1px);
}
.qz-btn-ghost {
background: transparent; color: var(--qz-text);
border: 1px solid var(--qz-border);
}
.qz-btn-ghost:hover {
border-color: var(--qz-blue); color: var(--qz-blue);
}
/* Cards */
.qz-card {
background: var(--qz-surface);
border: 1px solid var(--qz-border);
border-radius: var(--qz-radius);
padding: 24px;
transition: transform 0.2s, border-color 0.2s;
}
.qz-card:hover {
transform: translateY(-2px);
border-color: rgba(0,122,255,0.3);
}
/* Footer */
.qz-footer {
border-top: 1px solid var(--qz-border);
padding: 40px 24px;
text-align: center;
color: var(--qz-text-dim);
font-size: 14px;
}
/* Banner */
.qz-banner {
background: #001E50;
color: rgba(255,255,255,0.55);
text-align: center;
padding: 10px;
font-size: 12px;
}
.qz-banner a { color: rgba(255,255,255,0.8); text-decoration: none; }
@media (max-width: 768px) {
.qz-nav-links { display: none; }
}
</style>
<div id="qz-auth-bar" class="qz-auth-bar">
<a href="https://quixzoom.com" class="qz-logo">qui<span>X</span>zoom</a>
<div class="qz-nav">
<div id="qz-auth-guest">
<a href="https://app.quixzoom.com/login" class="qz-btn qz-btn-ghost">Logga in</a>
<a href="https://app.quixzoom.com/register" class="qz-btn qz-btn-primary">Bli Zoomer</a>
</div>
<div id="qz-auth-user" style="display:none;">
<span class="qz-balance" id="qz-balance">$0.00</span>
<div class="qz-dropdown">
<button class="qz-btn qz-btn-ghost qz-user" onclick="qzToggleDropdown()">
<div class="qz-avatar" id="qz-avatar">E</div>
<span id="qz-user-name">Erik</span>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2.5 4.5L6 8L9.5 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<div class="qz-dropdown-menu" id="qz-dropdown-menu">
<a href="https://app.quixzoom.com/dashboard" class="qz-dropdown-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/></svg>
Dashboard
</a>
<a href="https://app.quixzoom.com/wallet" class="qz-dropdown-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/><path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/><path d="M18 12a2 2 0 0 0 0 4h4v-4h-4z"/></svg>
Plånbok
</a>
<a href="https://app.quixzoom.com/missions" class="qz-dropdown-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
Mina uppdrag
</a>
<div class="qz-dropdown-divider"></div>
<a href="https://app.quixzoom.com/settings" class="qz-dropdown-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.67 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.67 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.67a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
Inställningar
</a>
<a href="#" onclick="qzLogout(); return false;" class="qz-dropdown-item">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
Logga ut
</a>
</div>
</div>
</div>
</div>
</div>
<script>
(function() {
const SSO_BASE = 'https://auth.quixzoom.com';
const APP_BASE = 'https://app.quixzoom.com';
// Check auth status
async function qzCheckAuth() {
try {
const res = await fetch(SSO_BASE + '/auth/check', {
credentials: 'include',
});
if (res.ok) {
const data = await res.json();
if (data.authenticated) {
document.getElementById('qz-auth-guest').style.display = 'none';
document.getElementById('qz-auth-user').style.display = 'flex';
document.getElementById('qz-user-name').textContent = data.user.name || data.user.email;
document.getElementById('qz-avatar').textContent = (data.user.name || data.user.email)[0].toUpperCase();
if (data.user.balance !== undefined) {
document.getElementById('qz-balance').textContent = '$' + data.user.balance.toFixed(2);
}
}
}
} catch (e) {
// Silent fail - show guest state
}
}
// Toggle dropdown
window.qzToggleDropdown = function() {
document.getElementById('qz-dropdown-menu').classList.toggle('active');
};
// Close dropdown on outside click
document.addEventListener('click', function(e) {
if (!e.target.closest('.qz-dropdown')) {
document.getElementById('qz-dropdown-menu').classList.remove('active');
}
});
// Logout
window.qzLogout = async function() {
try {
await fetch(SSO_BASE + '/auth/logout', {
method: 'POST',
credentials: 'include',
});
} catch (e) {}
document.cookie = 'qz_access_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=.quixzoom.com; path=/;';
document.cookie = 'qz_refresh_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=.quixzoom.com; path=/;';
window.location.reload();
};
// Init
qzCheckAuth();
})();
</script>
</body>
</html>