403 lines
9.9 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>stratumiops — Ontology + Reflection System</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #0f172a;
--surface: #1e293b;
--surface-deep: #0f172a;
--border: #334155;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--text-muted: #475569;
--accent-blue: #3b82f6;
--accent-amber: #fbbf24;
--accent-green: #34d399;
--accent-purple: #a78bfa;
--font: ui-monospace, 'JetBrains Mono', 'Fira Code', monospace;
}
body {
background: var(--bg);
color: var(--text-primary);
font-family: var(--font);
min-height: 100vh;
}
/* ── PRESENTATION MODE ── */
#presentation {
display: none;
position: fixed;
inset: 0;
background: #000;
z-index: 100;
flex-direction: column;
align-items: center;
justify-content: center;
}
#presentation.active {
display: flex;
}
#slide-container {
width: 100%;
max-width: min(100vw, calc(100vh * 16 / 9));
aspect-ratio: 16 / 9;
position: relative;
}
#slide-container img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
}
#presentation-controls {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 52px;
background: rgba(15, 23, 42, 0.92);
border-top: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
gap: 24px;
backdrop-filter: blur(8px);
}
#presentation-controls button {
background: var(--surface);
border: 1px solid var(--border);
color: var(--text-primary);
font-family: var(--font);
font-size: 12px;
padding: 6px 16px;
border-radius: 4px;
cursor: pointer;
letter-spacing: 1px;
transition: background 0.15s, border-color 0.15s;
}
#presentation-controls button:hover {
background: #334155;
border-color: var(--accent-blue);
}
#presentation-controls button:disabled {
opacity: 0.3;
cursor: not-allowed;
}
#slide-counter {
font-size: 12px;
color: var(--text-muted);
min-width: 60px;
text-align: center;
}
#exit-presentation {
position: fixed;
top: 16px;
right: 16px;
background: rgba(15, 23, 42, 0.8);
border: 1px solid var(--border);
color: var(--text-secondary);
font-family: var(--font);
font-size: 11px;
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
z-index: 200;
letter-spacing: 1px;
}
#exit-presentation:hover {
color: var(--text-primary);
border-color: var(--accent-blue);
}
/* ── GALLERY MODE ── */
#gallery {
min-height: 100vh;
}
header {
padding: 32px 48px 24px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: baseline;
gap: 24px;
}
header h1 {
font-size: 18px;
font-weight: 700;
color: var(--text-primary);
letter-spacing: -0.5px;
}
header span {
font-size: 12px;
color: var(--text-muted);
letter-spacing: 2px;
}
.start-btn {
margin-left: auto;
background: var(--accent-blue);
border: none;
color: #fff;
font-family: var(--font);
font-size: 12px;
padding: 8px 20px;
border-radius: 4px;
cursor: pointer;
letter-spacing: 1px;
font-weight: 600;
}
.start-btn:hover {
background: #2563eb;
}
.slides-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
gap: 24px;
padding: 32px 48px;
}
.slide-card {
cursor: pointer;
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
background: var(--surface);
transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.slide-card:hover {
border-color: var(--accent-blue);
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.15);
}
.slide-card img {
width: 100%;
aspect-ratio: 16 / 9;
display: block;
object-fit: cover;
}
.slide-card-meta {
padding: 10px 14px;
display: flex;
align-items: center;
justify-content: space-between;
border-top: 1px solid var(--border);
}
.slide-number {
font-size: 11px;
color: var(--text-muted);
letter-spacing: 1px;
}
.slide-status {
font-size: 10px;
letter-spacing: 1px;
padding: 2px 8px;
border-radius: 3px;
}
.slide-status.full {
background: rgba(52, 211, 153, 0.12);
color: var(--accent-green);
border: 1px solid rgba(52, 211, 153, 0.3);
}
.slide-status.stub {
background: rgba(71, 85, 105, 0.2);
color: var(--text-muted);
border: 1px solid var(--border);
}
footer {
padding: 24px 48px;
border-top: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
}
footer span {
font-size: 11px;
color: var(--text-muted);
letter-spacing: 2px;
}
.key-hint {
font-size: 11px;
color: var(--text-muted);
}
.key-hint kbd {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 3px;
padding: 1px 6px;
font-family: var(--font);
font-size: 10px;
}
</style>
</head>
<body>
<!-- PRESENTATION MODE -->
<div id="presentation">
<button id="exit-presentation" onclick="exitPresentation()">ESC · EXIT</button>
<div id="slide-container">
<img id="current-slide" src="" alt="Slide">
</div>
<div id="presentation-controls">
<button id="btn-prev" onclick="prevSlide()">← PREV</button>
<span id="slide-counter">01 / 14</span>
<button id="btn-next" onclick="nextSlide()">NEXT →</button>
</div>
</div>
<!-- GALLERY MODE -->
<div id="gallery">
<header>
<h1>stratumiops</h1>
<span>ONTOLOGY + REFLECTION SYSTEM</span>
<button class="start-btn" onclick="startPresentation(1)">PRESENT →</button>
</header>
<div class="slides-grid" id="slides-grid"></div>
<footer>
<span>STRATUMIOPS · 14 SLIDES</span>
<span class="key-hint">
<kbd></kbd> <kbd></kbd> navigate &nbsp;·&nbsp; <kbd>Esc</kbd> exit &nbsp;·&nbsp; click to open
</span>
</footer>
</div>
<script>
const TOTAL = 14;
const FULL_SLIDES = [1, 2, 3, 4, 5];
const TITLES = [
"Problems We Are Solving",
"Yin / Yang — Truth and Coexistence",
"Ingredient List — The Stack",
"Nickel — What and Why",
"Nushell — What and Why",
"DAGs and FSMs — Acyclic Graphs",
"Operational Ontology — Why and How",
"Reflection — Definitions",
"ADRs — Making Decisions Alive",
"Implementation — Parts and Definitions",
"Mechanics and Workflow — Use Cases",
"Integration in Projects",
"Integration with Claude Code",
"Concurrent Use",
];
let currentSlide = 1;
function padNum(n) {
return String(n).padStart(2, '0');
}
function slideSrc(n) {
return `slide-${padNum(n)}.svg`;
}
// Build gallery
const grid = document.getElementById('slides-grid');
for (let i = 1; i <= TOTAL; i++) {
const isFull = FULL_SLIDES.includes(i);
const card = document.createElement('div');
card.className = 'slide-card';
card.dataset.slide = i;
card.onclick = () => startPresentation(i);
card.innerHTML = `
<img src="${slideSrc(i)}" alt="Slide ${padNum(i)}" loading="lazy">
<div class="slide-card-meta">
<span class="slide-number">${padNum(i)} / ${padNum(TOTAL)} · ${TITLES[i - 1]}</span>
<span class="slide-status ${isFull ? 'full' : 'stub'}">${isFull ? 'FULL' : 'STUB'}</span>
</div>
`;
grid.appendChild(card);
}
function startPresentation(n) {
currentSlide = n || 1;
document.getElementById('presentation').classList.add('active');
document.getElementById('gallery').style.display = 'none';
updateSlide();
document.addEventListener('keydown', handleKey);
}
function exitPresentation() {
document.getElementById('presentation').classList.remove('active');
document.getElementById('gallery').style.display = '';
document.removeEventListener('keydown', handleKey);
}
function updateSlide() {
const img = document.getElementById('current-slide');
img.src = slideSrc(currentSlide);
img.alt = `Slide ${currentSlide}: ${TITLES[currentSlide - 1]}`;
document.getElementById('slide-counter').textContent = `${padNum(currentSlide)} / ${padNum(TOTAL)}`;
document.getElementById('btn-prev').disabled = currentSlide <= 1;
document.getElementById('btn-next').disabled = currentSlide >= TOTAL;
}
function prevSlide() {
if (currentSlide > 1) { currentSlide--; updateSlide(); }
}
function nextSlide() {
if (currentSlide < TOTAL) { currentSlide++; updateSlide(); }
}
function handleKey(e) {
switch (e.key) {
case 'ArrowRight':
case 'ArrowDown':
case ' ':
e.preventDefault();
nextSlide();
break;
case 'ArrowLeft':
case 'ArrowUp':
e.preventDefault();
prevSlide();
break;
case 'Escape':
exitPresentation();
break;
case 'Home':
currentSlide = 1; updateSlide();
break;
case 'End':
currentSlide = TOTAL; updateSlide();
break;
}
}
</script>
</body>
</html>