311 lines
13 KiB
HTML
311 lines
13 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=390, initial-scale=1">
|
||
|
|
<title>Kalei — Ritual Complete</title>
|
||
|
|
<link rel="stylesheet" href="../../assets/design-system.css">
|
||
|
|
<style>
|
||
|
|
.celebration-burst {
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translate(-50%, -50%);
|
||
|
|
width: 300px;
|
||
|
|
height: 300px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: radial-gradient(circle, rgba(139,92,246,0.11) 0%, rgba(59,130,246,0.07) 30%, rgba(16,185,129,0.05) 60%, transparent 80%);
|
||
|
|
filter: blur(30px);
|
||
|
|
animation: breathing 6s ease-in-out infinite;
|
||
|
|
pointer-events: none;
|
||
|
|
}
|
||
|
|
@keyframes successBurst {
|
||
|
|
0% { transform: scale(0) rotate(-30deg); opacity: 0; }
|
||
|
|
60% { transform: scale(1.15) rotate(5deg); opacity: 1; }
|
||
|
|
80% { transform: scale(0.95) rotate(-2deg); opacity: 1; }
|
||
|
|
100% { transform: scale(1) rotate(0deg); opacity: 1; }
|
||
|
|
}
|
||
|
|
.complete-hero {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
padding: var(--space-8) var(--space-4) var(--space-5);
|
||
|
|
text-align: center;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
.burst-icon {
|
||
|
|
width: 120px;
|
||
|
|
height: 120px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
margin-bottom: var(--space-5);
|
||
|
|
animation: successBurst 0.8s ease forwards;
|
||
|
|
}
|
||
|
|
.complete-heading {
|
||
|
|
font-family: var(--font-display);
|
||
|
|
font-size: 30px;
|
||
|
|
font-weight: 700;
|
||
|
|
background: var(--prismatic);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
margin-bottom: var(--space-2);
|
||
|
|
}
|
||
|
|
.complete-sub {
|
||
|
|
font-size: 14px;
|
||
|
|
color: var(--dim-light);
|
||
|
|
margin-bottom: var(--space-5);
|
||
|
|
line-height: 1.6;
|
||
|
|
max-width: 280px;
|
||
|
|
}
|
||
|
|
.stats-row {
|
||
|
|
display: flex;
|
||
|
|
gap: var(--space-3);
|
||
|
|
width: 100%;
|
||
|
|
margin-bottom: var(--space-5);
|
||
|
|
}
|
||
|
|
.stat-pill {
|
||
|
|
flex: 1;
|
||
|
|
background: var(--deep-glass);
|
||
|
|
border: 1px solid var(--twilight);
|
||
|
|
border-radius: var(--radius-xl);
|
||
|
|
padding: var(--space-3);
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
.stat-pill .val {
|
||
|
|
font-size: 22px;
|
||
|
|
font-weight: 700;
|
||
|
|
color: var(--pure-light);
|
||
|
|
}
|
||
|
|
.stat-pill .lbl {
|
||
|
|
font-size: 10px;
|
||
|
|
color: var(--dim-light);
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.05em;
|
||
|
|
margin-top: 2px;
|
||
|
|
}
|
||
|
|
.tile-earned-card {
|
||
|
|
background: var(--deep-glass);
|
||
|
|
border: 1px solid rgba(139,92,246,0.35);
|
||
|
|
border-radius: var(--radius-xl);
|
||
|
|
padding: var(--space-4);
|
||
|
|
width: 100%;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--space-3);
|
||
|
|
margin-bottom: var(--space-5);
|
||
|
|
box-shadow: 0 0 20px rgba(139,92,246,0.12);
|
||
|
|
}
|
||
|
|
.tile-preview-icon {
|
||
|
|
width: 52px;
|
||
|
|
height: 52px;
|
||
|
|
border-radius: 12px;
|
||
|
|
background: rgba(59,130,246,0.12);
|
||
|
|
border: 1px solid var(--sapphire);
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
box-shadow: 0 0 14px rgba(59,130,246,0.2);
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.btn-done {
|
||
|
|
width: 100%;
|
||
|
|
height: 52px;
|
||
|
|
background: var(--amethyst);
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
font-size: 16px;
|
||
|
|
font-weight: 600;
|
||
|
|
color: var(--pure-light);
|
||
|
|
text-decoration: none;
|
||
|
|
box-shadow: var(--glow-amethyst);
|
||
|
|
margin-bottom: var(--space-3);
|
||
|
|
transition: background 0.2s ease-out;
|
||
|
|
}
|
||
|
|
.btn-done:hover { background: var(--amethyst-light); }
|
||
|
|
.streak-indicator {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
gap: var(--space-2);
|
||
|
|
margin-bottom: var(--space-5);
|
||
|
|
}
|
||
|
|
.streak-flame-dots {
|
||
|
|
display: flex;
|
||
|
|
gap: 3px;
|
||
|
|
}
|
||
|
|
.flame-dot {
|
||
|
|
width: 8px;
|
||
|
|
height: 8px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: var(--amber);
|
||
|
|
box-shadow: 0 0 5px rgba(245,158,11,0.4);
|
||
|
|
}
|
||
|
|
.flame-dot.active { animation: pulse 2s ease-in-out infinite; }
|
||
|
|
.flame-dot.new {
|
||
|
|
background: var(--amber-light);
|
||
|
|
box-shadow: 0 0 8px rgba(245,158,11,0.7);
|
||
|
|
animation: pulse 1.5s ease-in-out infinite;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="device-frame">
|
||
|
|
|
||
|
|
<!-- STATUS BAR -->
|
||
|
|
<div class="status-bar" style="position: relative; z-index: 2;">
|
||
|
|
<span class="time">8:52</span>
|
||
|
|
<div class="icons">
|
||
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="1" y="7" width="2.5" height="5" rx="0.5" fill="#E2E8F0" opacity="0.4"/><rect x="4.5" y="5" width="2.5" height="7" rx="0.5" fill="#E2E8F0" opacity="0.6"/><rect x="8" y="3" width="2.5" height="9" rx="0.5" fill="#E2E8F0" opacity="0.8"/><rect x="11.5" y="1" width="2.5" height="11" rx="0.5" fill="#E2E8F0"/></svg>
|
||
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M 2,8 C 4,4 12,4 14,8" stroke="#E2E8F0" stroke-width="1.2" fill="none" stroke-linecap="round"/><path d="M 4,10 C 6,7 10,7 12,10" stroke="#E2E8F0" stroke-width="1" fill="none" opacity="0.8" stroke-linecap="round"/><circle cx="8" cy="12" r="1.2" fill="#E2E8F0"/></svg>
|
||
|
|
<svg width="24" height="12" viewBox="0 0 24 12" fill="none"><rect x="0.5" y="0.5" width="21" height="11" rx="2.5" stroke="#E2E8F0" stroke-width="1" opacity="0.5"/><rect x="22" y="3" width="2" height="6" rx="1" fill="#E2E8F0" opacity="0.3"/><rect x="2" y="2" width="16" height="8" rx="1.5" fill="#10B981" opacity="0.9"/></svg>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Celebration background -->
|
||
|
|
<div class="celebration-burst"></div>
|
||
|
|
|
||
|
|
<!-- SCREEN CONTENT -->
|
||
|
|
<div class="screen-content centered" style="position: relative; z-index: 2;">
|
||
|
|
|
||
|
|
<div class="burst-icon">
|
||
|
|
<svg width="120" height="120" viewBox="-60 -60 120 120">
|
||
|
|
<defs>
|
||
|
|
<linearGradient id="rc48-grEm" x1="0" y1="0" x2="0" y2="1">
|
||
|
|
<stop offset="0%" stop-color="#6EE7B7"><animate attributeName="stop-color" values="#6EE7B7;#A7F3D0;#6EE7B7" dur="5s" repeatCount="indefinite"/></stop>
|
||
|
|
<stop offset="100%" stop-color="#059669"/>
|
||
|
|
</linearGradient>
|
||
|
|
<radialGradient id="rc48-successGlow" cx="50%" cy="50%" r="50%">
|
||
|
|
<stop offset="0%" stop-color="#10B981" stop-opacity="0.4"/>
|
||
|
|
<stop offset="100%" stop-color="#10B981" stop-opacity="0"/>
|
||
|
|
</radialGradient>
|
||
|
|
<filter id="rc48-glowLg" x="-80%" y="-80%" width="260%" height="260%">
|
||
|
|
<feGaussianBlur stdDeviation="6" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||
|
|
</filter>
|
||
|
|
<filter id="rc48-glowMd" x="-50%" y="-50%" width="200%" height="200%">
|
||
|
|
<feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||
|
|
</filter>
|
||
|
|
<filter id="rc48-glowSm" x="-50%" y="-50%" width="200%" height="200%">
|
||
|
|
<feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||
|
|
</filter>
|
||
|
|
<clipPath id="rc48-clip"><circle r="56"/></clipPath>
|
||
|
|
</defs>
|
||
|
|
|
||
|
|
<g clip-path="url(#rc48-clip)" filter="url(#rc48-glowMd)">
|
||
|
|
<circle r="45" fill="none" stroke="#10B981" stroke-width="0.8" opacity="0.2" stroke-dasharray="6 8"/>
|
||
|
|
<circle r="30" fill="none" stroke="#10B981" stroke-width="0.6" opacity="0.25" stroke-dasharray="4 6"/>
|
||
|
|
<g>
|
||
|
|
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="45s" repeatCount="indefinite"/>
|
||
|
|
<path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#rc48-grEm)" opacity="0.6"/>
|
||
|
|
<g transform="rotate(60)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#rc48-grEm)" opacity="0.5"/></g>
|
||
|
|
<g transform="rotate(120)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#rc48-grEm)" opacity="0.55"/></g>
|
||
|
|
<g transform="rotate(180)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#rc48-grEm)" opacity="0.5"/></g>
|
||
|
|
<g transform="rotate(240)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#rc48-grEm)" opacity="0.6"/></g>
|
||
|
|
<g transform="rotate(300)"><path d="M 0,-45 L 3,-42 L 0,-39 L -3,-42 Z" fill="url(#rc48-grEm)" opacity="0.5"/></g>
|
||
|
|
</g>
|
||
|
|
</g>
|
||
|
|
|
||
|
|
<g filter="url(#rc48-glowLg)">
|
||
|
|
<circle r="30" fill="none" stroke="#10B981" stroke-width="2" opacity="0">
|
||
|
|
<animate attributeName="r" values="10;35;40" dur="1.5s" repeatCount="indefinite"/>
|
||
|
|
<animate attributeName="opacity" values="0.6;0.3;0" dur="1.5s" repeatCount="indefinite"/>
|
||
|
|
</circle>
|
||
|
|
<circle r="20" fill="none" stroke="#6EE7B7" stroke-width="1" opacity="0">
|
||
|
|
<animate attributeName="r" values="8;25;30" dur="1.5s" begin="0.2s" repeatCount="indefinite"/>
|
||
|
|
<animate attributeName="opacity" values="0.4;0.2;0" dur="1.5s" begin="0.2s" repeatCount="indefinite"/>
|
||
|
|
</circle>
|
||
|
|
<circle r="16" fill="url(#rc48-successGlow)" opacity="0.6">
|
||
|
|
<animate attributeName="opacity" values="0.4;0.8;0.4" dur="2s" repeatCount="indefinite"/>
|
||
|
|
</circle>
|
||
|
|
<path d="M 0,-10 L 10,0 L 0,10 L -10,0 Z" fill="url(#rc48-grEm)" opacity="0.9"/>
|
||
|
|
<path d="M 0,-10 L 10,0 L 0,0 Z" fill="#fff" opacity="0.2"/>
|
||
|
|
<path d="M -4,0 L -1,4 L 5,-3" fill="none" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/>
|
||
|
|
</g>
|
||
|
|
|
||
|
|
<circle r="4" fill="#6EE7B7" opacity="0.5" filter="url(#rc48-glowSm)">
|
||
|
|
<animate attributeName="r" values="3;5;3" dur="2s" repeatCount="indefinite"/>
|
||
|
|
</circle>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="complete-heading">Day 14. Done.</div>
|
||
|
|
<div class="complete-sub">You showed up again. That's the whole thing — fourteen mornings in a row, building something that lasts.</div>
|
||
|
|
|
||
|
|
<!-- Streak — 14 dots, last one highlighted as new -->
|
||
|
|
<div class="streak-indicator">
|
||
|
|
<div class="streak-flame-dots">
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot"></div>
|
||
|
|
<div class="flame-dot new"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<span class="body-sm" style="color: var(--amber-light); font-weight: 600; margin-bottom: var(--space-5); display:block;">14-day streak — your longest yet</span>
|
||
|
|
|
||
|
|
<!-- Stats -->
|
||
|
|
<div class="stats-row">
|
||
|
|
<div class="stat-pill">
|
||
|
|
<div class="val">15</div>
|
||
|
|
<div class="lbl">Minutes</div>
|
||
|
|
</div>
|
||
|
|
<div class="stat-pill">
|
||
|
|
<div class="val">4</div>
|
||
|
|
<div class="lbl">Steps</div>
|
||
|
|
</div>
|
||
|
|
<div class="stat-pill">
|
||
|
|
<div class="val" style="color: var(--amber-light);">14</div>
|
||
|
|
<div class="lbl">Day Streak</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- New tile earned -->
|
||
|
|
<div class="tile-earned-card">
|
||
|
|
<div class="tile-preview-icon">
|
||
|
|
<svg width="34" height="26" viewBox="-18 -12 36 24">
|
||
|
|
<defs>
|
||
|
|
<linearGradient id="rc48-grSap" x1="0" y1="0" x2="0" y2="1">
|
||
|
|
<stop offset="0%" stop-color="#93C5FD"><animate attributeName="stop-color" values="#93C5FD;#BFDBFE;#93C5FD" dur="4.5s" repeatCount="indefinite"/></stop>
|
||
|
|
<stop offset="100%" stop-color="#2563EB"/>
|
||
|
|
</linearGradient>
|
||
|
|
<filter id="rc48-glowSap" x="-50%" y="-50%" width="200%" height="200%">
|
||
|
|
<feGaussianBlur stdDeviation="2" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||
|
|
</filter>
|
||
|
|
</defs>
|
||
|
|
<rect x="-15" y="-9" width="30" height="18" rx="3" fill="#121628" stroke="#3B82F6" stroke-width="0.8"/>
|
||
|
|
<g filter="url(#rc48-glowSap)">
|
||
|
|
<path d="M 0,-5 L 5,0 L 0,5 L -5,0 Z" fill="url(#rc48-grSap)" opacity="0.5"/>
|
||
|
|
</g>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
<div style="flex:1;">
|
||
|
|
<div class="subheading" style="color: var(--sapphire-light); margin-bottom: 2px;">Evidence tile added</div>
|
||
|
|
<div class="body-sm text-dim">Ritual Completion · Feb 22 · Day 14</div>
|
||
|
|
</div>
|
||
|
|
<a href="../you/42-evidence-wall-full.html" style="text-decoration:none;">
|
||
|
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M8 4L14 10L8 16" stroke="var(--sapphire-light)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- CTA -->
|
||
|
|
<a href="../turn/10-turn-home.html" class="btn-done">Back to home</a>
|
||
|
|
<a href="49-ritual-streak.html" style="text-decoration: none; font-size: 14px; color: var(--dim-light);">View full streak history</a>
|
||
|
|
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</body>
|
||
|
|
</html>
|