Files
2026-09-18 00:01:42 +02:00

391 lines
18 KiB
HTML

<!DOCTYPE html><html lang="en" style=""><head><meta charset="utf-8"><meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" name="viewport"><link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" rel="stylesheet"><link href="https://fonts.googleapis.com" rel="preconnect"><link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"><link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,200..800;1,6..72,200..800&amp;family=Plus+Jakarta+Sans:ital,wght@0,300..800;1,300..800&amp;display=swap" rel="stylesheet"><script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script><script id="tailwind-config">tailwind.config = {
darkMode: "class",
theme: {
extend: {
colors: {
"inverse-on-surface": "#f4f0e9",
"on-error": "#ffffff",
"on-tertiary": "#ffffff",
"primary-fixed": "#f6dfc7",
"secondary-fixed-dim": "#ffb691",
"inverse-primary": "#d9c3ac",
"error": "#ba1a1a",
"on-tertiary-fixed-variant": "#374c36",
"error-container": "#ffdad6",
"secondary": "#8e4d2a",
"on-primary-fixed": "#25190b",
"on-background": "#1c1c18",
"on-secondary-container": "#783d1a",
"surface-dim": "#dddad3",
"primary": "#635341",
"on-surface": "#1c1c18",
"background": "#fdf9f2",
"surface-container-high": "#ece8e1",
"on-surface-variant": "#4d453e",
"on-primary-container": "#ffefe1",
"surface-container": "#f1ede6",
"on-tertiary-fixed": "#0d200d",
"outline": "#7f756d",
"tertiary-container": "#5e745c",
"surface": "#fdf9f2",
"on-error-container": "#93000a",
"on-primary-fixed-variant": "#544433",
"primary-container": "#7d6b58",
"on-secondary-fixed": "#341100",
"outline-variant": "#d0c4ba",
"on-tertiary-container": "#e1f9db",
"surface-container-highest": "#e6e2db",
"secondary-container": "#feaa7f",
"surface-container-lowest": "#ffffff",
"on-primary": "#ffffff",
"surface-container-low": "#f7f3ec",
"on-secondary": "#ffffff",
"surface-variant": "#e6e2db",
"tertiary": "#465b44",
"on-secondary-fixed-variant": "#713714",
"tertiary-fixed-dim": "#b5cdb0",
"surface-tint": "#6c5b49",
"primary-fixed-dim": "#d9c3ac",
"tertiary-fixed": "#d1e9cc",
"secondary-fixed": "#ffdbcb",
"inverse-surface": "#31302c",
"surface-bright": "#fdf9f2"
},
borderRadius: {
"DEFAULT": "1rem",
"lg": "1.75rem",
"xl": "2.25rem",
"full": "9999px"
},
spacing: {
"margin-mobile": "1.25rem",
"space-lg": "1.5rem",
"space-md": "1rem",
"space-xl": "2.5rem",
"gutter-mobile": "0.75rem",
"space-xs": "0.25rem",
"gutter": "1rem",
"space-sm": "0.5rem",
"margin": "1.5rem"
},
fontFamily: {
"body-sm": ["Plus Jakarta Sans", "sans-serif"],
"headline-md": ["Newsreader", "serif"],
"headline-xl": ["Newsreader", "serif"],
"label-md": ["Plus Jakarta Sans", "sans-serif"],
"headline-lg-mobile": ["Newsreader", "serif"],
"headline-lg": ["Newsreader", "serif"],
"label-sm": ["Plus Jakarta Sans", "sans-serif"],
"body-lg": ["Plus Jakarta Sans", "sans-serif"],
"body-md": ["Plus Jakarta Sans", "sans-serif"],
"headline-xl-mobile": ["Newsreader", "serif"],
"label-lg": ["Plus Jakarta Sans", "sans-serif"]
},
fontSize: {
"body-sm": ["14px", { lineHeight: "20px", fontWeight: "400" }],
"headline-md": ["22px", { lineHeight: "30px", fontWeight: "400" }],
"headline-xl": ["40px", { lineHeight: "48px", letterSpacing: "-0.02em", fontWeight: "400" }],
"label-md": ["13px", { lineHeight: "18px", letterSpacing: "0.02em", fontWeight: "500" }],
"headline-lg-mobile": ["26px", { lineHeight: "34px", letterSpacing: "0em", fontWeight: "400" }],
"headline-lg": ["30px", { lineHeight: "38px", letterSpacing: "-0.01em", fontWeight: "400" }],
"label-sm": ["11px", { lineHeight: "16px", letterSpacing: "0.04em", fontWeight: "600" }],
"body-lg": ["18px", { lineHeight: "28px", fontWeight: "400" }],
"body-md": ["16px", { lineHeight: "24px", fontWeight: "400" }],
"headline-xl-mobile": ["32px", { lineHeight: "40px", letterSpacing: "-0.01em", fontWeight: "400" }],
"label-lg": ["15px", { lineHeight: "20px", letterSpacing: "0.01em", fontWeight: "600" }]
}
}
}
};</script><style>
@layer base {
html, body {
width: 100vw;
margin: 0;
padding: 0;
background-color: #fdf9f2;
}
body {
overscroll-behavior: none;
}
.pb-safe {
padding-bottom: env(safe-area-inset-bottom, 16px);
}
.pt-safe {
padding-top: env(safe-area-inset-top, 16px);
}
}
::-webkit-scrollbar {
display: none;
}
.card-enter {
animation: gentleFadeUp 0.32s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.card-exit {
animation: gentleFadeOut 0.22s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes gentleFadeUp {
0% {
opacity: 0;
transform: translateY(14px) scale(0.985);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes gentleFadeOut {
0% {
opacity: 1;
transform: translateY(0) scale(1);
}
100% {
opacity: 0;
transform: translateY(-10px) scale(0.98);
}
}
</style></head><body class="bg-surface font-body-md text-body-md text-on-surface min-h-screen flex flex-col justify-between pt-safe pb-safe selection:bg-secondary/15"><main class="flex-1 flex flex-col w-full max-w-md mx-auto px-margin-mobile justify-between"><header class="pt-2 pb-1 flex flex-col gap-2">
<div class="flex items-center justify-between">
<button aria-label="Undo previous value" class="inline-flex items-center gap-1.5 py-1.5 px-3 rounded-full bg-surface-container text-on-surface-variant font-label-md text-label-md transition-all active:scale-95 disabled:opacity-40 disabled:pointer-events-none hover:bg-surface-container-high" id="undo-btn" onclick="undoLastSort()">
<span class="material-symbols-outlined text-[17px]">undo</span>
<span class="">Previous</span>
</button>
<div class="flex items-center gap-1.5 px-3 py-1 rounded-full bg-surface-container-low border border-outline-variant/40">
<span class="w-1.5 h-1.5 rounded-full bg-tertiary"></span>
<span class="font-label-sm text-label-sm text-primary uppercase tracking-wider">Stage 1 · Initial Sort</span>
</div>
<button aria-label="Save and exit" class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-surface-container text-on-surface-variant transition-colors hover:bg-surface-container-high active:scale-95" onclick="saveAndExit()" title="Save &amp; pause">
<span class="material-symbols-outlined text-[18px]">bookmark_border</span>
</button>
</div>
<!-- Progress indicator -->
<div class="mt-1.5 flex flex-col gap-1.5">
<div class="flex items-baseline justify-between text-on-surface-variant">
<span class="font-label-md text-label-md tracking-tight text-on-surface font-medium" id="counter-label">104 of 100 values sorted</span>
<span class="font-label-sm text-label-sm text-outline" id="percent-label">100%</span>
</div>
<div class="w-full h-1 bg-surface-container-high rounded-full overflow-hidden">
<div class="h-full bg-primary-container rounded-full transition-all duration-300 ease-out" id="progress-bar" style="width: 100%;"></div>
</div>
</div>
</header>
<!-- Center Hero: Single Focused Value Card -->
<section class="my-auto py-2 flex flex-col items-center">
<div class="w-full relative card-enter" id="card-container">
<!-- Shadow stack aesthetic cue underneath -->
<div class="absolute inset-x-3 -bottom-1.5 h-6 rounded-xl bg-surface-container-high/60 -z-10 transform scale-[0.98]"></div>
<div class="absolute inset-x-6 -bottom-3 h-5 rounded-xl bg-surface-container-highest/40 -z-20 transform scale-[0.95]"></div>
<article class="relative bg-surface-container-lowest border border-outline-variant/50 rounded-xl p-6 shadow-sm flex flex-col transition-all duration-200">
<!-- Card Category Tag -->
<div class="flex items-center justify-between mb-4">
</div>
<!-- Value Title -->
<h2 class="font-headline-xl text-3xl sm:text-headline-xl text-on-surface tracking-normal leading-tight mb-3" id="card-title">Compassion</h2>
<!-- Definition Essence -->
<p class="font-body-md text-body-md text-on-surface-variant leading-relaxed mb-6 font-normal" id="card-definition">Meeting human vulnerability, struggle, and limitation with open warmth and kindness.</p>
<!-- Contemplative Question -->
</article>
</div>
</section>
<!-- Bottom: 5 Reflective Piles Rating Scale & Pile Distribution -->
<footer class="pb-1 pt-1 flex flex-col gap-3">
<!-- Prompt guidance text -->
<div class="flex items-center justify-between px-1">
<span class="font-label-sm text-label-sm text-on-surface-variant tracking-wide uppercase flex items-center gap-1">
<span class="material-symbols-outlined text-[15px] text-primary">layers</span>
Assign to reflective pile
</span>
<span class="font-label-sm text-label-sm text-outline" id="pile-helper">Tap to sort</span>
</div>
<!-- 5 Rating Buttons / Tier Rows -->
<div aria-label="Sort into piles 1 through 5" class="flex flex-col gap-1.5" role="group">
<!-- Pile 5 -->
<button class="group relative flex items-center justify-between w-full py-2.5 px-3.5 rounded-lg bg-surface-container hover:bg-surface-container-high active:scale-[0.98] border border-outline-variant/40 transition-all text-left" onclick="sortCurrentCard(5)" type="button">
<div class="flex items-center gap-3">
<span class="w-6 h-6 rounded-full bg-tertiary text-on-tertiary flex items-center justify-center font-label-md text-label-md font-semibold shrink-0">5</span>
<span class="font-label-lg text-label-lg text-on-surface font-semibold group-hover:text-primary transition-colors">Most Important</span>
</div>
<span class="font-label-sm text-label-sm text-on-surface-variant/80">Non-negotiable core</span>
</button>
<!-- Pile 4 -->
<button class="group relative flex items-center justify-between w-full py-2.5 px-3.5 rounded-lg bg-surface-container hover:bg-surface-container-high active:scale-[0.98] border border-outline-variant/40 transition-all text-left" onclick="sortCurrentCard(4)" type="button">
<div class="flex items-center gap-3">
<span class="w-6 h-6 rounded-full bg-surface-container-highest text-on-surface flex items-center justify-center font-label-md text-label-md font-semibold shrink-0">4</span>
<span class="font-label-lg text-label-lg text-on-surface font-medium group-hover:text-primary transition-colors">Very Important</span>
</div>
<span class="font-label-sm text-label-sm text-on-surface-variant/80">Deeply held guide</span>
</button>
<!-- Pile 3 -->
<button class="group relative flex items-center justify-between w-full py-2.5 px-3.5 rounded-lg bg-surface-container hover:bg-surface-container-high active:scale-[0.98] border border-outline-variant/40 transition-all text-left" onclick="sortCurrentCard(3)" type="button">
<div class="flex items-center gap-3">
<span class="w-6 h-6 rounded-full bg-surface-container-highest text-on-surface flex items-center justify-center font-label-md text-label-md font-semibold shrink-0">3</span>
<span class="font-label-lg text-label-lg text-on-surface font-medium group-hover:text-primary transition-colors">Important</span>
</div>
<span class="font-label-sm text-label-sm text-on-surface-variant/80">Valued aspect</span>
</button>
<!-- Pile 2 -->
<button class="group relative flex items-center justify-between w-full py-2.5 px-3.5 rounded-lg bg-surface-container-low hover:bg-surface-container active:scale-[0.98] border border-outline-variant/30 transition-all text-left" onclick="sortCurrentCard(2)" type="button">
<div class="flex items-center gap-3">
<span class="w-6 h-6 rounded-full bg-surface-container-high text-on-surface-variant flex items-center justify-center font-label-md text-label-md shrink-0">2</span>
<span class="font-label-md text-label-md text-on-surface font-medium">Somewhat Important</span>
</div>
<span class="font-label-sm text-label-sm text-outline">Contextual</span>
</button>
<!-- Pile 1 -->
<button class="group relative flex items-center justify-between w-full py-2.5 px-3.5 rounded-lg bg-surface-container-low hover:bg-surface-container active:scale-[0.98] border border-outline-variant/30 transition-all text-left" onclick="sortCurrentCard(1)" type="button">
<div class="flex items-center gap-3">
<span class="w-6 h-6 rounded-full bg-surface-container-high text-on-surface-variant flex items-center justify-center font-label-md text-label-md shrink-0">1</span>
<span class="font-label-md text-label-md text-on-surface font-medium">Not Important</span>
</div>
<span class="font-label-sm text-label-sm text-outline">Not a current compass</span>
</button>
</div>
<!-- Live Pile Distribution Strip -->
</footer>
</main>
<script>
// Contemplative Values Deck Data
const valuesDeck = [
{
title: "Courage",
domain: "Core Ground",
icon: "nature",
definition: "Moving forward in fidelity to truth and conviction despite fear, doubt, or external friction.",
prompt: "How essential is this fidelity to who you choose to be each day?"
},
{
title: "Authenticity",
domain: "Inward Presence",
icon: "self_improvement",
definition: "Living in honest congruence with who you genuinely are, without defensive performance.",
prompt: "Where does being fully yourself create peace and power in your life?"
},
{
title: "Compassion",
domain: "Relational",
icon: "favorite",
definition: "Meeting human vulnerability, struggle, and limitation with open warmth and kindness.",
prompt: "How central is gentle empathy when things are difficult?"
},
{
title: "Wisdom",
domain: "Inquiry",
icon: "menu_book",
definition: "Discerning what is enduring, balanced, and essential through patient observation.",
prompt: "Do you look to patient discernment to steer your major choices?"
},
{
title: "Freedom",
domain: "Sovereignty",
icon: "all_inclusive",
definition: "Spaciousness to author your own rhythm, personal boundaries, and inner cadence.",
prompt: "How much do autonomy and breathing room shape your daily vitality?"
},
{
title: "Integrity",
domain: "Core Ground",
icon: "shield",
definition: "Honoring your word, ethical compass, and silent internal agreements without compromise.",
prompt: "Does living in harmony with your conscience anchor your peace of mind?"
},
{
title: "Creativity",
domain: "Expression",
icon: "palette",
definition: "Generative synthesis, playfulness, and bringing novel perspective or art into form.",
prompt: "Is making, imagining, or expressing vital to your well-being?"
},
{
title: "Peace",
domain: "Inward Presence",
icon: "spa",
definition: "Cultivating unshakeable interior stillness, gentle calm, and non-reactivity.",
prompt: "How essential is quiet inner tranquility amidst worldly commotion?"
}
];
let currentIndex = 0;
let sortedCount = 14;
const totalCards = 100;
const pileCounts = { 1: 2, 2: 3, 3: 5, 4: 3, 5: 1 };
const historyStack = [];
function updateDisplay() {
const cardData = valuesDeck[currentIndex % valuesDeck.length];
const container = document.getElementById('card-container');
// Retain animation smoothness
container.classList.remove('card-enter');
void container.offsetWidth; // trigger reflow
container.classList.add('card-enter');
document.getElementById('card-title').textContent = cardData.title;
document.getElementById('card-domain').textContent = cardData.domain;
document.getElementById('card-icon').textContent = cardData.icon;
document.getElementById('card-definition').textContent = cardData.definition;
document.getElementById('card-prompt').textContent = cardData.prompt;
document.getElementById('counter-label').textContent = `${sortedCount} of ${totalCards} values sorted`;
const percentage = Math.min(100, Math.round((sortedCount / totalCards) * 100));
document.getElementById('percent-label').textContent = `${percentage}%`;
document.getElementById('progress-bar').style.width = `${percentage}%`;
// Update pile pill numbers
for (let i = 1; i <= 5; i++) {
const el = document.getElementById(`count-${i}`);
if (el) el.textContent = pileCounts[i];
}
// Undo button state
document.getElementById('undo-btn').disabled = historyStack.length === 0;
}
function sortCurrentCard(pileNumber) {
// Record to history for smooth undo
historyStack.push({
cardIndex: currentIndex,
assignedPile: pileNumber
});
pileCounts[pileNumber] = (pileCounts[pileNumber] || 0) + 1;
sortedCount++;
currentIndex = (currentIndex + 1) % valuesDeck.length;
const container = document.getElementById('card-container');
container.classList.add('card-exit');
setTimeout(() => {
container.classList.remove('card-exit');
updateDisplay();
}, 120);
}
function undoLastSort() {
if (historyStack.length === 0) return;
const lastAction = historyStack.pop();
if (pileCounts[lastAction.assignedPile] > 0) {
pileCounts[lastAction.assignedPile]--;
}
sortedCount = Math.max(0, sortedCount - 1);
currentIndex = lastAction.cardIndex;
updateDisplay();
}
function saveAndExit() {
const btn = document.getElementById('pile-helper');
btn.textContent = "Progress saved";
btn.classList.add('text-tertiary', 'font-semibold');
setTimeout(() => {
btn.textContent = "Tap to sort";
btn.classList.remove('text-tertiary', 'font-semibold');
}, 2000);
}
document.addEventListener('DOMContentLoaded', () => {
updateDisplay();
});
</script>
</body></html>