new darkmode, disbales/hidden min games

This commit is contained in:
samantha42
2026-05-23 11:52:02 +02:00
parent 4cb5ea8724
commit 0f0c72e705
16 changed files with 771 additions and 1347 deletions
+184
View File
@@ -0,0 +1,184 @@
<style>
.theme-root {
--bg: #1a1a3e;
--surface: #12122a;
--surface2: #1e1e40;
--border: #2e2e5e;
--border2: #3a3a6e;
--text: #e8e8ff;
--muted: #9090c0;
--dim: #5050a0;
}
.theme-root.day {
--bg: #f7f6f3;
--surface: #ffffff;
--surface2: #f0eeea;
--border: #e2ddd6;
--border2: #ccc7be;
--text: #1a1917;
--muted: #6b6560;
--dim: #b0aa9f;
}
.scene {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem 1rem;
gap: 1rem;
font-family: var(--font-sans);
background: var(--bg);
border-radius: var(--border-radius-lg);
transition: background 0.4s ease;
}
.demo-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--border-radius-lg);
padding: 1rem 1.5rem;
width: 100%;
max-width: 280px;
transition: background 0.4s ease, border-color 0.4s ease;
}
.demo-card p { margin: 0 0 4px; font-size: 14px; color: var(--text); transition: color 0.4s ease; }
.demo-card span { font-size: 12px; color: var(--muted); transition: color 0.4s ease; }
.demo-tag {
display: inline-block;
margin-top: 8px;
font-size: 11px;
padding: 2px 8px;
border-radius: 20px;
background: var(--surface2);
color: var(--dim);
border: 1px solid var(--border2);
transition: background 0.4s ease, color 0.4s ease, border-color 0.4s ease;
}
.toggle-wrap {
position: relative;
width: 50px;
height: 25px;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.track {
position: absolute;
inset: 0;
border-radius: 12.5px;
transition: background 0.5s ease;
overflow: hidden;
}
.track.day { background: #87CEEB; }
.track.night { background: #1a1a3e; }
.stars { position: absolute; inset: 0; opacity: 0; transition: opacity 0.4s ease; }
.night .stars { opacity: 1; }
.star { position: absolute; background: white; border-radius: 50%; animation: twinkle 2s infinite; }
.star:nth-child(1) { width:2px; height:2px; top:4px; left:6px; animation-delay:0s; }
.star:nth-child(2) { width:1px; height:1px; top:10px; left:14px; animation-delay:0.4s; }
.star:nth-child(3) { width:1px; height:1px; top:5px; left:22px; animation-delay:0.8s; }
.star:nth-child(4) { width:2px; height:2px; top:14px; left:10px; animation-delay:1.2s; }
.star:nth-child(5) { width:1px; height:1px; top:8px; left:30px; animation-delay:0.2s; }
@keyframes twinkle { 0%,100% { opacity:1; } 50% { opacity:0.3; } }
.knob {
position: absolute;
top: 3px;
width: 19px;
height: 19px;
border-radius: 50%;
transition: left 0.45s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.4s ease;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.knob.night {
left: 3px;
background: radial-gradient(circle at 35% 35%, #e8e8ff, #c8c8f8);
box-shadow: 0 0 0 2px rgba(180,180,255,0.18), 0 0 7px 4px rgba(140,140,255,0.35), 0 0 14px 6px rgba(100,100,220,0.18);
}
.knob.day {
left: 28px;
background: radial-gradient(circle at 40% 40%, #fff8c5, #FFD700);
box-shadow: 0 0 0 3px rgba(255,220,0,0.25), 0 0 8px 4px rgba(255,200,0,0.45), 0 0 16px 6px rgba(255,160,0,0.2);
}
.sun-rays { position: absolute; inset: -7px; opacity: 0; transition: opacity 0.3s ease 0.15s; pointer-events: none; }
.knob.day .sun-rays { opacity: 1; }
.ray { position: absolute; width: 1.5px; height: 4px; background: rgba(255,220,0,0.9); border-radius: 1px; left: 50%; transform-origin: 50% 16px; margin-left: -0.75px; }
.moon-crater { position: absolute; border-radius: 50%; background: rgba(140,140,200,0.4); transition: opacity 0.3s ease; }
.knob.day .moon-crater { opacity: 0; }
.knob.night .moon-crater { opacity: 1; }
.label { font-size: 13px; font-weight: 500; user-select: none; color: var(--muted); transition: color 0.4s ease; }
.state-label { font-size: 11px; color: var(--muted); letter-spacing: 0.05em; text-transform: uppercase; transition: color 0.4s ease; }
.row { display: flex; align-items: center; gap: 12px; }
</style>
<div class="theme-root day" id="themeRoot">
<div class="scene">
<h2 class="sr-only">Day and night toggle with scoped theme tokens</h2>
<div class="demo-card">
<p>Sample card</p>
<span>Tokens update on toggle</span><br>
<span class="demo-tag">surface2 · dim · border2</span>
</div>
<div class="row">
<span class="label">Night</span>
<div class="toggle-wrap" role="switch" aria-checked="true" tabindex="0" id="toggle" aria-label="Toggle day/night mode">
<div class="track day" id="track">
<div class="stars">
<div class="star"></div><div class="star"></div><div class="star"></div>
<div class="star"></div><div class="star"></div>
</div>
</div>
<div class="knob day" id="knob">
<div class="sun-rays" id="rays"></div>
<div class="moon-crater" style="width:4px;height:4px;top:3px;left:5px;"></div>
<div class="moon-crater" style="width:3px;height:3px;top:9px;left:9px;"></div>
<div class="moon-crater" style="width:2px;height:2px;top:4px;left:11px;"></div>
</div>
</div>
<span class="label">Day</span>
</div>
<span class="state-label" id="stateLabel">Day mode</span>
</div>
</div>
<script>
const toggle = document.getElementById('toggle');
const track = document.getElementById('track');
const knob = document.getElementById('knob');
const rays = document.getElementById('rays');
const stateLabel = document.getElementById('stateLabel');
const themeRoot = document.getElementById('themeRoot');
let isDay = true;
for (let i = 0; i < 8; i++) {
const r = document.createElement('div');
r.className = 'ray';
r.style.transform = `rotate(${i * 45}deg)`;
rays.appendChild(r);
}
function applyState() {
if (isDay) {
track.className = 'track day';
knob.className = 'knob day';
stateLabel.textContent = 'Day mode';
toggle.setAttribute('aria-checked', 'true');
themeRoot.classList.add('day');
} else {
track.className = 'track night';
knob.className = 'knob night';
stateLabel.textContent = 'Night mode';
toggle.setAttribute('aria-checked', 'false');
themeRoot.classList.remove('day');
}
}
toggle.addEventListener('click', () => { isDay = !isDay; applyState(); });
toggle.addEventListener('keydown', e => {
if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); isDay = !isDay; applyState(); }
});
</script>
+62 -154
View File
@@ -6,9 +6,10 @@
<title>Samantha Vero Friis</title> <title>Samantha Vero Friis</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/> <link rel="preconnect" href="https://fonts.googleapis.com"/>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap" rel="stylesheet"/> <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500&family=IBM+Plex+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="/static/styles2.css" /> <link rel="stylesheet" href="/static/style/styles2.css" />
<link rel="stylesheet" href="/static/style/game.css" />
</head> </head>
<body> <body class="theme-root day " id="themeRoot">
<nav> <nav>
<a class="nav-logo" href="#">samantha_vero_friis</a> <a class="nav-logo" href="#">samantha_vero_friis</a>
@@ -20,11 +21,28 @@
<a href="/infra">infrastructure</a> <a href="/infra">infrastructure</a>
<a href="/git">git</a> <a href="/git">git</a>
<a class="cta" href="mailto:me@samantha42.xyz">contact</a> <a class="cta" href="mailto:me@samantha42.xyz">contact</a>
</div> </div>
</nav> </nav>
<div class="shell"> <div class="shell">
<aside> <aside>
<div class="row">
<div class="toggle-wrap" role="switch" aria-checked="true" tabindex="0" id="toggle" aria-label="Toggle day/night mode">
<div class="track day" id="track">
<div class="stars">
<div class="star"></div><div class="star"></div><div class="star"></div>
<div class="star"></div><div class="star"></div>
</div>
</div>
<div class="knob day" id="knob">
<div class="sun-rays" id="rays"></div>
<div class="moon-crater" style="width:4px;height:4px;top:3px;left:5px;"></div>
<div class="moon-crater" style="width:3px;height:3px;top:9px;left:9px;"></div>
<div class="moon-crater" style="width:2px;height:2px;top:4px;left:11px;"></div>
</div>
</div>
</div>
<div> <div>
<p class="sidebar-label">navigate</p> <p class="sidebar-label">navigate</p>
<div class="sidebar-links"> <div class="sidebar-links">
@@ -52,6 +70,24 @@
<p class="sidebar-label">location</p> <p class="sidebar-label">location</p>
<div style="font-family:var(--ff-mono);font-size:0.75rem;color:var(--muted);">Denmark<br>Aalborg Øst, 9220</div> <div style="font-family:var(--ff-mono);font-size:0.75rem;color:var(--muted);">Denmark<br>Aalborg Øst, 9220</div>
</div> </div>
<div>
<p class="sidebar-label">languages</p>
<div class="lang-row">
<span class="lang-badge">Danish</span>
<span class="lang-badge">English</span>
</div>
</div>
<div style="flex: 1;"></div>
<!--
<div class="sidebar-links">
<p class="sidebar-label">mini games</p>
<a href="#alice" onclick="unhideGame()"> Follow the rabbit</a>
<a href="#tetris" onclick="unhideTetris()" >Alexey Pajitnov</a>
</div>
-->
</aside> </aside>
<main id="about"> <main id="about">
@@ -127,14 +163,6 @@
</div> </div>
</section> </section>
<section>
<div class="section-head"><h2>languages</h2></div>
<div class="lang-row">
<span class="lang-badge">Danish</span>
<span class="lang-badge">English</span>
</div>
</section>
<section> <section>
<div class="section-head"><h2>interests</h2></div> <div class="section-head"><h2>interests</h2></div>
<div class="interests-row"> <div class="interests-row">
@@ -188,7 +216,7 @@
<div class="page-header"> <div class="page-header">
<h2 class="page-title" id="interest">interests</h2> <h2 class="page-title" id="interest">interests</h2>
<span class="page-sub">Fav lists</span> <span class="page-sub" id="interest-sub">Fav lists</span>
</div> </div>
<div class="section-head"><h2>Movie/Show Top list</h2></div> <div class="section-head"><h2>Movie/Show Top list</h2></div>
<div class="toplist-group"> <div class="toplist-group">
@@ -203,9 +231,9 @@
<img src="/static/posters/AcureForWellness.jpg" alt="A Cure of Wellness"> <img src="/static/posters/AcureForWellness.jpg" alt="A Cure of Wellness">
<p>A Cure of Wellness</p> <p>A Cure of Wellness</p>
</div> </div>
<div class="poster-item"> <div class="poster-item posterhover" onclick="matrixClick()">
<img src="/static/posters/Fightclub.jpg" alt="Fight Club"> <img src="/static/posters/matrix.jpg" alt="matrix">
<p>Fight Club</p> <p>The Matrix</p>
</div> </div>
<div class="poster-item posterhover" onclick="draculaClick()"> <div class="poster-item posterhover" onclick="draculaClick()">
<img src="/static/posters/Dracula.webp" alt="Dracula: A Love Tale"> <img src="/static/posters/Dracula.webp" alt="Dracula: A Love Tale">
@@ -246,38 +274,28 @@
</div> </div>
</div> </div>
<div class="section-head"><h2>Lunix rice</h2></div> <div class="section-head"><h2>Lunix rice</h2></div>
<div class="rice-wrap"> <div>
<img src="/static/images/rice.png" width="500px"> <div style="padding-left: 10%;"><img src="/static/images/rice.png" width="80%" style="align-self: center;"></div>
<p class="exp-body">I love my custom Linux setup. I use Hyprland, which automatically arranges app windows on my screen so everything stays organized without dragging things around. I also use Quickshell, which lets me customize menus, shortcuts, and system controls to work exactly how I want. <p class="exp-body">I love my custom Linux setup. I use Hyprland, which automatically arranges app windows on my screen so everything stays organized without dragging things around. I also use Quickshell, which lets me customize menus, shortcuts, and system controls to work exactly how I want.
My system is based on Arch Linux or Manjaro Linux, which are versions of Linux that give you more control and customization than a typical computer setup. The result is a clean, fast, and super efficient desktop thats hard to go back from.</p> My system is based on Arch Linux or Manjaro Linux, which are versions of Linux that give you more control and customization than a typical computer setup. The result is a clean, fast, and super efficient desktop thats hard to go back from.
<a class="outlink" href="https://git.samantha42.xyz/samantha/dotfiles" >Git repo</a>
</p>
</div> </div>
<!-- <section style="display: none;" id="alice" class="play" >
<div class="section-head"><h2>Games</h2></div> <br>
<div class="section-head"><h2>Want to play a game Alice?!</h2></div>
<div class="story-text" id="story-text"></div>
<div class="choices" id="choices"></div>
</section>
<script src="/static/scripts/game.js"></script>
<section style="display: none;" id="tetris" >
<h2>This game is</h2>
</section>
<script src="/static/scripts/tetris.js"></script>
<div class="toplist-group">
<div class="toplist-body">
<div class="game-grid">
<div class="poster-item">
<img src="/static/posters/Chernobyl.webp" alt="Chernobyl">
<p>Chernobyl</p>
</div>
<div class="poster-item">
<p>Balders Gate</p>
</div>
<div class="poster-item">
<p>Factorio</p>
</div>
<div class="poster-item">
<p>Slay the spire 2</p>
</div>
<div class="game-item">
<img src="/static/posters/risetr-banner.png" alt="Rise of the Tomb Raider">
<p>Rise of the Tomb Raider</p>
</div>
</div>
</div>-->
</div> </div>
@@ -290,116 +308,6 @@ My system is based on Arch Linux or Manjaro Linux, which are versions of Linux t
<div class="footer-copy">© 2026 — all rights reserved</div> <div class="footer-copy">© 2026 — all rights reserved</div>
</footer> </footer>
<script> <script src="/static/about.js" ></script>
// just some fun.
console.log("%c👀 hi there!", "font-size:20px")
function draculaClick() {
const el = document.getElementById('interest');
if (!el) return; // el is a DOM node, never a string
el.textContent = '🦇 interest 🦇';
setTimeout(() => {
el.textContent = "interest";
}, 5000);
}
function bladerunnerClick() {
if (document.getElementById('rain-canvas')) return; // already running, do nothing
const el = document.getElementById('interest');
el.textContent = 'tears in rain';
startRain();
setTimeout(() => {
el.textContent = "interest";
stopRain();
}, 10000);
}
let rainCanvas, rainCtx, rainInterval;
function startRain() {
rainCanvas = document.createElement('canvas');
rainCanvas.id = 'rain-canvas';
rainCanvas.width = window.innerWidth;
rainCanvas.height = window.innerHeight;
document.body.appendChild(rainCanvas);
rainCtx = rainCanvas.getContext('2d');
requestAnimationFrame(() => { rainCanvas.style.opacity = '1'; });
const drops = Array.from({ length: 120 }, () => ({
x: Math.random() * rainCanvas.width,
y: Math.random() * rainCanvas.height,
speed: 8 + Math.random() * 7,
length: 12 + Math.random() * 20,
opacity: 0.2 + Math.random() * 0.4
}));
rainInterval = setInterval(() => {
rainCtx.clearRect(0, 0, rainCanvas.width, rainCanvas.height);
drops.forEach(drop => {
rainCtx.beginPath();
rainCtx.moveTo(drop.x, drop.y);
rainCtx.lineTo(drop.x - 2, drop.y + drop.length);
rainCtx.strokeStyle = `rgba(174, 214, 241, ${drop.opacity})`;
rainCtx.lineWidth = 3;
rainCtx.stroke();
drop.y += drop.speed;
if (drop.y > rainCanvas.height) {
drop.y = -drop.length;
drop.x = Math.random() * rainCanvas.width;
}
});
}, 30);
}
function stopRain() {
if (!rainCanvas) return;
rainCanvas.style.opacity = '0';
setTimeout(() => {
clearInterval(rainInterval);
rainCanvas.remove();
rainCanvas = null;
}, 800);
}
function dragonClick() {
const existing = document.getElementById('dragon-grid');
if (existing) { existing.remove(); return; }
const grid = document.createElement('canvas');
grid.id = 'dragon-grid';
grid.width = window.innerWidth;
grid.height = window.innerHeight;
grid.style.transition = 'opacity 1s ease';
document.body.appendChild(grid);
const ctx = grid.getContext('2d');
const img = new Image();
img.src = '/static/images/dragon.png';
img.onload = () => {
const size = 250;
const cols = Math.ceil(grid.width / size);
const rows = Math.ceil(grid.height / size);
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
ctx.drawImage(img, c * size, r * size, size, size);
}
}
setTimeout(() => {
grid.style.opacity = '0';
setTimeout(() => grid.remove(), 1000);
}, 300);
};
}
</script>
</body> </body>
</html> </html>
+184
View File
@@ -0,0 +1,184 @@
const toggle = document.getElementById('toggle');
const track = document.getElementById('track');
const knob = document.getElementById('knob');
const rays = document.getElementById('rays');
const stateLabel = document.getElementById('state-label');
const themeRoot = document.getElementById('themeRoot');
let isDay = true;
const RAY_COUNT = 8;
for (let i = 0; i < RAY_COUNT; i++) {
const r = document.createElement('div');
r.className = 'ray';
r.style.transform = `rotate(${i * (360/RAY_COUNT)}deg)`;
rays.appendChild(r);
}
function applyState() {
if (isDay) {
track.className = 'track day';
knob.className = 'knob day';
toggle.setAttribute('aria-checked', 'true');
themeRoot.classList.remove('night');
} else {
track.className = 'track night';
knob.className = 'knob night';
toggle.setAttribute('aria-checked', 'false');
themeRoot.classList.add('night');
}
}
toggle.addEventListener('click', () => { isDay = !isDay; applyState(); });
toggle.addEventListener('keydown', e => {
if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); isDay = !isDay; applyState(); }
});
function copyClass() {
navigator.clipboard.writeText(classOut.textContent).catch(() => {});
}
// just some fun.
console.log("%c👀 hi there!", "font-size:20px")
function draculaClick() {
const el = document.getElementById('interest');
if (!el) return; // el is a DOM node, never a string
el.textContent = '🦇 interest 🦇';
setTimeout(() => {
el.textContent = "interest";
}, 5000);
}
function matrixClick() {
const sub = document.getElementById('interest-sub');
const col = sub.color
sub.textContent = `Do not try and bend the spoon. That's impossible. Instead... only try to realize the truth.`
sub.style.color = "green"
setTimeout(() => {
sub.textContent = "Fav lists"
sub.style.color = "#6b6560"
}, 15000);
}
function bladerunnerClick() {
if (document.getElementById('rain-canvas')) return; // already running, do nothing
const el = document.getElementById('interest');
el.textContent = 'tears in rain';
startRain();
setTimeout(() => {
el.textContent = "interest";
stopRain();
}, 10000);
}
let rainCanvas, rainCtx, rainInterval;
function startRain() {
rainCanvas = document.createElement('canvas');
rainCanvas.id = 'rain-canvas';
rainCanvas.width = window.innerWidth;
rainCanvas.height = window.innerHeight;
document.body.appendChild(rainCanvas);
rainCtx = rainCanvas.getContext('2d');
requestAnimationFrame(() => { rainCanvas.style.opacity = '1'; });
const drops = Array.from({ length: 120 }, () => ({
x: Math.random() * rainCanvas.width,
y: Math.random() * rainCanvas.height,
speed: 8 + Math.random() * 7,
length: 12 + Math.random() * 20,
opacity: 0.2 + Math.random() * 0.4
}));
rainInterval = setInterval(() => {
rainCtx.clearRect(0, 0, rainCanvas.width, rainCanvas.height);
drops.forEach(drop => {
rainCtx.beginPath();
rainCtx.moveTo(drop.x, drop.y);
rainCtx.lineTo(drop.x - 2, drop.y + drop.length);
rainCtx.strokeStyle = `rgba(174, 214, 241, ${drop.opacity})`;
rainCtx.lineWidth = 3;
rainCtx.stroke();
drop.y += drop.speed;
if (drop.y > rainCanvas.height) {
drop.y = -drop.length;
drop.x = Math.random() * rainCanvas.width;
}
});
}, 30);
}
function stopRain() {
if (!rainCanvas) return;
rainCanvas.style.opacity = '0';
setTimeout(() => {
clearInterval(rainInterval);
rainCanvas.remove();
rainCanvas = null;
}, 800);
}
function unhideGame() {
const alicegameSection = document.getElementById('alice');
const gameSection = document.getElementById('tetris');
if (alicegameSection.style.display == 'none') {
alicegameSection.style.display = 'block';
} else {
alicegameSection.style.display = 'none';
}
gameSection.style.display = 'none';
}
function unhideTetris() {
const alicegameSection = document.getElementById('alice');
const gameSection = document.getElementById('tetris');
if (gameSection.style.display == 'none') {
gameSection.style.display = 'block';
} else {
gameSection.style.display = 'none';
}
alicegameSection.style.display = 'none';
}
function dragonClick() {
const existing = document.getElementById('dragon-grid');
if (existing) { existing.remove(); return; }
const grid = document.createElement('canvas');
grid.id = 'dragon-grid';
grid.width = window.innerWidth;
grid.height = window.innerHeight;
grid.style.transition = 'opacity 1s ease';
document.body.appendChild(grid);
const ctx = grid.getContext('2d');
const img = new Image();
img.src = '/static/images/dragon.png';
img.onload = () => {
const size = 250;
const cols = Math.ceil(grid.width / size);
const rows = Math.ceil(grid.height / size);
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
ctx.drawImage(img, c * size, r * size, size, size);
}
}
setTimeout(() => {
grid.style.opacity = '0';
setTimeout(() => grid.remove(), 1000);
}, 300);
};
}
+1 -1
View File
@@ -8,7 +8,7 @@
href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap" href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap"
rel="stylesheet" rel="stylesheet"
/> />
<link rel="stylesheet" href="/static/styles.css" /> <link rel="stylesheet" href="/static/style/styles.css" />
</head> </head>
<body> <body>
<div class="container--narrow"> <div class="container--narrow">
+1 -1
View File
@@ -8,7 +8,7 @@
href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap" href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap"
rel="stylesheet" rel="stylesheet"
/> />
<link rel="stylesheet" href="/static/styles.css" /> <link rel="stylesheet" href="/static/style/styles.css" />
</head> </head>
<body> <body>
<div class="container--narrow"> <div class="container--narrow">
+1 -1
View File
@@ -6,7 +6,7 @@
<title>FP&amp;A Budgeting Engine — Samantha Vero Friis</title> <title>FP&amp;A Budgeting Engine — Samantha Vero Friis</title>
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Libre+Caslon+Text:wght@400;700;800&family=Syne:wght@400;700;800&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Libre+Caslon+Text:wght@400;700;800&family=Syne:wght@400;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="/static/styles.css" /> <link rel="stylesheet" href="/static/style/styles.css" />
<style> <style>
/* ── Page-specific layout ── */ /* ── Page-specific layout ── */
header { padding: 2.4rem 0 2rem; } header { padding: 2.4rem 0 2rem; }
+1 -1
View File
@@ -8,7 +8,7 @@
href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap" href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap"
rel="stylesheet" rel="stylesheet"
/> />
<link rel="stylesheet" href="/static/styles.css" /> <link rel="stylesheet" href="/static/style/styles.css" />
</head> </head>
<body> <body>
<div class="container--narrow"> <div class="container--narrow">
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.0 KiB

+1 -1
View File
@@ -8,7 +8,7 @@
href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap" href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Syne:wght@400;700;800&display=swap"
rel="stylesheet" rel="stylesheet"
/> />
<link rel="stylesheet" href="/static/styles.css"/> <link rel="stylesheet" href="/static/style/styles.css"/>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

+77
View File
@@ -0,0 +1,77 @@
const nodes = {
start: {
text: `Voice: Wake up alice! they are coming. you need to find your way out NOW please...
You find yourself on a little cute bed, you see out of the window into the fog, you turn to see whom is speaking to only find a door.`,
choices: [
{ idx: 'A', text: 'You silently walk up to the door.', next: 'door' },
{ idx: 'B', text: 'Poke your head out of the window to see what\'s there.', next: 'window' },
{ idx: 'C', text: 'In a panic you hide under the bed', next: 'bed' },
]
},
door: {
text: `You press your ear against the wood. Silence. Then — footsteps, slow and deliberate, getting closer from the other side.`,
choices: [
{ idx: 'A', text: 'Open the door.', next: 'door' },
{ idx: 'B', text: 'Step back and hide under the bed.', next: 'bed' },
{ idx: 'C', text: 'Go to the window now', next: 'highrise' },
]
},
window: {
text: `The fog shifts. Below you, shapes move through it — too tall, too still. One of them looks up.`,
choices: [
{ idx: 'A', text: 'Duck back inside immediately.', next: 'start' },
{ idx: 'B', text: 'Keep watching. You need to know what they are.', next: 'highrise' },
]
},
bed: {
text: `you feel silent and place your ear against the floor listen to noice below. A deep voice you seem to reconise talk, you cant make it out. You turn your head to use the other ear, you see a old book in the corner.`,
choices: [
{ idx: 'A', text: 'Pickup the book', next: 'book'},
{ idx: 'B', text: 'wait, consentrait to listend closely to the words.', next: 'start' },
{ idx: 'C', text: 'go to the window and see ', next: 'window' },
{ idx: 'D', text: 'leave to walk to the door', next: 'door' },
]
},
book: {
text: `The book is old and dusty as one may expect, but underneath that. A rare bueaty you have never seen before.`,
choices: [
{ idx: 'A', text: 'go to the window and see ', next: 'window' },
{ idx: 'B', text: 'leave to walk to the door', next: 'door' },
]
},
wait: {
text: `You hear the man say: "she is mine to keep" unsure of the meaning of this. You quickly find yourself exposed to the room to choice a path. `,
choices: [
{ idx: 'A', text: 'go to the window and see ', next: 'window' },
{ idx: 'B', text: 'leave to walk to the door', next: 'door' },
]
},
highrise: {
text: `your eyes get in focus and see stears below, you find yourself on a highrise building. two people a talking on the ground below.`,
choices: [
{idx: 'A', text: 'walk out to small staers balcany', next: 'window'},
{idx: 'B', text: 'Go back to the door', next: 'window'}
]
}
};
function goTo(nodeId) {
const node = nodes[nodeId];
if (!node) return;
document.getElementById('story-text').innerText = node.text;
const choicesEl = document.getElementById('choices');
choicesEl.innerHTML = '';
node.choices.forEach(c => {
const btn = document.createElement('button');
btn.className = 'choice-btn';
btn.innerHTML = `<span class="idx">${c.idx}</span><span>${c.text}</span>`;
btn.onclick = () => goTo(c.next);
choicesEl.appendChild(btn);
});
}
goTo('start');
View File
+57
View File
@@ -0,0 +1,57 @@
.play {
padding: 2rem 0;
}
.play .section-head h2 {
font-family: var(--ff-mono);
font-size: 1rem;
font-weight: 400;
letter-spacing: 0.08em;
color: var(--muted);
margin-bottom: 1.5rem;
}
.play .story-text {
font-family: var(--ff-mono);
font-size: 0.85rem;
line-height: 1.9;
color: var(--fg);
max-width: 560px;
margin-bottom: 2rem;
white-space: pre-wrap;
border: 1px solid rgb(167, 205, 250);
border-radius: 10px;
padding: 1rem 1.25rem;
}
.play .choices {
display: flex;
flex-direction: column;
gap: 0.6rem;
max-width: 560px;
}
.play .choices a,
.play .choices button {
font-family: var(--ff-mono);
font-size: 0.8rem;
color: var(--muted);
background: none;
border: none;
border-left: 1px solid var(--muted);
padding: 0.3rem 0.75rem;
cursor: pointer;
text-align: left;
text-decoration: none;
transition: color 0.15s, border-color 0.15s;
}
.play .choices a:hover,
.play .choices button:hover {
color: var(--fg);
border-color: var(--fg);
}
.idx {
color: blueviolet;
padding: 10px;
}
+198 -35
View File
@@ -1,19 +1,37 @@
:root{ .theme-root.night {
--bg:#f7f6f3; --bg: #2d2d2d;
--surface:#ffffff; --surface: #363636;
--surface2:#f0eeea; --surface2: #2a2a2a;
--border:#e2ddd6; --border: #555555;
--border2:#ccc7be; --border2: #ccc7be;
--text:#1a1917; --text: #ffffff;
--muted:#6b6560; --muted: #d9d9d9;
--dim:#b0aa9f; --dim: #b0aa9f;
--accent:#1a56db; --navback: rgb(63, 63, 63, 0.95);
--accent: #5389ff;
--accent2:#1447b8; --accent2:#1447b8;
--green:#0a7c52; --green:#0eaf74;
--amber:#92620a; --amber:#ffd78e;
--ff-mono:'IBM Plex Mono',monospace;
--ff-sans:'IBM Plex Sans',sans-serif;
} }
.theme-root {
--bg:#f7f6f3;
--surface:#ffffff;
--surface2:#f0eeea;
--border:#e2ddd6;
--border2:#ccc7be;
--text:#1a1917;
--muted:#6b6560;
--dim:#b0aa9f;
--accent:#1a56db;
--accent2:#1447b8;
--green:#0a7c52;
--amber:#92620a;
--navback: rgba(247,246,243,0.95)
--ff-mono:'IBM Plex Mono',monospace;
--ff-sans:'IBM Plex Sans',sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0;} *{box-sizing:border-box;margin:0;padding:0;}
html{font-size:15px;scroll-behavior:smooth;} html{font-size:15px;scroll-behavior:smooth;}
body{ body{
@@ -37,7 +55,7 @@ body::before{
nav{ nav{
position:sticky;top:0;z-index:100; position:sticky;top:0;z-index:100;
background:rgba(247,246,243,0.94); background: var(--navback);
backdrop-filter:blur(10px); backdrop-filter:blur(10px);
border-bottom:1px solid var(--border); border-bottom:1px solid var(--border);
padding:0 clamp(1rem,5vw,3rem); padding:0 clamp(1rem,5vw,3rem);
@@ -58,7 +76,7 @@ nav{
transition:color 0.15s,background 0.15s; transition:color 0.15s,background 0.15s;
} }
.nav-links a:hover{color:var(--text);background:var(--surface2);} .nav-links a:hover{color:var(--text);background:var(--surface2);}
.nav-links .cta{color:var(--accent);border:1px solid var(--accent2);margin-left:0.4rem;} .nav-links .cta{color:var(--accent);border:1px solid var(--accent);margin-left:0.4rem;}
.nav-links .cta:hover{background:var(--accent2);color:#fff;} .nav-links .cta:hover{background:var(--accent2);color:#fff;}
.shell{ .shell{
@@ -72,17 +90,18 @@ nav{
.sidebar-links a.hidden { .sidebar-links a.hidden {
display: none; opacity: 0;
transition: opacity 0.4s linear;
} }
.sidebar-links:hover a.hidden { .sidebar-links:hover a.hidden {
display: block; opacity: 1;
} }
aside{ aside{
border-right:1px solid var(--border); border-right:1px solid var(--border);
padding:2.5rem 1.5rem; padding:2.5rem 1.5rem;
display:flex;flex-direction:column;gap:2.5rem; display:flex;flex-direction:column;gap:1rem;
position:sticky;top:52px;height:calc(100vh - 52px); position:sticky;top:52px;height:calc(100vh - 52px);
overflow-y:auto; overflow-y:auto;
background:var(--surface); background:var(--surface);
@@ -251,8 +270,8 @@ footer{
} }
.tag-dropped { .tag-dropped {
background: #F0EBE4; background: var(--surface2);
color: #8A5C2E; color: var(--amber);
} }
@@ -389,20 +408,6 @@ footer{
opacity: 0.15; opacity: 0.15;
} }
.rice-wrap {
display: flex;
align-items: flex-start;
gap: 1.5rem;
}
.rice-wrap img {
flex-shrink: 0;
}
.rice-wrap .exp-body {
flex: 1;
}
.outlink {font-family:var(--ff-mono);font-size:0.78rem;color:var(--accent);text-decoration:none;} .outlink {font-family:var(--ff-mono);font-size:0.78rem;color:var(--accent);text-decoration:none;}
.outlink:hover{text-decoration:underline;} .outlink:hover{text-decoration:underline;}
@@ -413,3 +418,161 @@ a{
transition:color 0.15s,background 0.15s; transition:color 0.15s,background 0.15s;
display:flex;align-items:center;gap:6px; display:flex;align-items:center;gap:6px;
} }
.rabbit-svg path { fill: gray; transition: fill 0.3s ease; }
.rabbit-svg:hover path { fill: #7F77DD; }
.scene {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem 1rem;
gap: 1rem;
font-family: var(--font-sans);
}
.toggle-wrap {
position: relative;
width: 50px;
height: 25px;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.track {
position: absolute;
inset: 0;
width: 50px;
height: 25px;
border-radius: 12.5px;
transition: background 0.5s ease;
overflow: hidden;
}
.track.day { background: #87CEEB; }
.track.night { background: #1a1a3e; }
.stars {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.4s ease;
}
.night .stars { opacity: 1; }
.star {
position: absolute;
background: white;
border-radius: 50%;
animation: twinkle 2s infinite;
}
.star:nth-child(1) { width:2px; height:2px; top:4px; left:6px; animation-delay:0s; }
.star:nth-child(2) { width:1px; height:1px; top:10px; left:14px; animation-delay:0.4s; }
.star:nth-child(3) { width:1px; height:1px; top:5px; left:22px; animation-delay:0.8s; }
.star:nth-child(4) { width:2px; height:2px; top:14px; left:10px; animation-delay:1.2s; }
.star:nth-child(5) { width:1px; height:1px; top:8px; left:30px; animation-delay:0.2s; }
@keyframes twinkle {
0%,100% { opacity:1; } 50% { opacity:0.3; }
}
.knob {
position: absolute;
top: 3px;
width: 19px;
height: 19px;
border-radius: 50%;
transition: left 0.45s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.4s ease;
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.knob.night {
left: 3px;
background: radial-gradient(circle at 35% 35%, #e8e8ff, #c8c8f8);
box-shadow:
0 0 0 2px rgba(180,180,255,0.18),
0 0 7px 4px rgba(140,140,255,0.35),
0 0 14px 6px rgba(100,100,220,0.18);
}
.knob.day {
left: 28px;
background: radial-gradient(circle at 40% 40%, #fff8c5, #FFD700);
box-shadow:
0 0 0 3px rgba(255,220,0,0.25),
0 0 8px 4px rgba(255,200,0,0.45),
0 0 16px 6px rgba(255,160,0,0.2);
}
.sun-rays {
position: absolute;
inset: -7px;
opacity: 0;
transition: opacity 0.3s ease 0.15s;
pointer-events: none;
}
.knob.day .sun-rays { opacity: 1; }
.ray {
position: absolute;
width: 1.5px;
height: 4px;
background: rgba(255,220,0,0.9);
border-radius: 1px;
left: 50%;
transform-origin: 50% 16px;
margin-left: -0.75px;
}
.moon-crater {
position: absolute;
border-radius: 50%;
background: rgba(140,140,200,0.4);
transition: opacity 0.3s ease;
}
.knob.day .moon-crater { opacity: 0; }
.knob.night .moon-crater { opacity: 1; }
.label {
font-size: 13px;
font-weight: 500;
letter-spacing: 0.03em;
transition: color 0.4s ease;
user-select: none;
}
.label.day-label { color: #B8860B; }
.label.night-label { color: #9090d0; }
.state-label {
font-size: 11px;
color: var(--color-text-secondary);
letter-spacing: 0.05em;
text-transform: uppercase;
}
.row {
display: flex;
align-items: center;
gap: 12px;
}
.copy-block {
background: var(--color-background-secondary);
border: 0.5px solid var(--color-border-tertiary);
border-radius: var(--border-radius-lg);
padding: 1rem 1.25rem;
width: 100%;
max-width: 420px;
}
.copy-block p { margin: 0 0 8px; font-size: 13px; color: var(--color-text-secondary); }
.copy-block code {
font-family: var(--font-mono);
font-size: 12px;
color: var(--color-text-primary);
display: block;
white-space: nowrap;
overflow-x: auto;
}
.copy-btn {
margin-top: 10px;
font-size: 12px;
padding: 4px 10px;
border-radius: var(--border-radius-md);
cursor: pointer;
border: 0.5px solid var(--color-border-secondary);
background: transparent;
color: var(--color-text-secondary);
}
.copy-btn:hover { background: var(--color-background-secondary); }
File diff suppressed because it is too large Load Diff