new sesctions and hidden pages and effects
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
1. Current work/job if
|
||||||
|
|
||||||
|
-. Game list
|
||||||
|
- tech tools and eq research sections.
|
||||||
|
-
|
||||||
@@ -48,6 +48,9 @@ func main() {
|
|||||||
staticPage("/finance", "finance.html")
|
staticPage("/finance", "finance.html")
|
||||||
staticPage("/cinema", "cinema.html")
|
staticPage("/cinema", "cinema.html")
|
||||||
staticPage("/engine", "engine.html")
|
staticPage("/engine", "engine.html")
|
||||||
|
staticPage("/42", "42.html")
|
||||||
|
staticPage("/secret", "secret.html")
|
||||||
|
|
||||||
//http.HandleFunc("/portfolio", Portfolio)
|
//http.HandleFunc("/portfolio", Portfolio)
|
||||||
http.HandleFunc("/git", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/git", func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, "https://git.samantha42.xyz", http.StatusFound)
|
http.Redirect(w, r, "https://git.samantha42.xyz", http.StatusFound)
|
||||||
|
|||||||
+153
@@ -0,0 +1,153 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>42</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;1,400&family=DM+Mono:wght@300&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--ink: #1a1a18;
|
||||||
|
--ink-light: #9a9890;
|
||||||
|
--paper: #fafaf7;
|
||||||
|
--accent: #1a1a18;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
background: var(--paper);
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 480px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number {
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: clamp(5rem, 20vw, 9rem);
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
color: var(--ink);
|
||||||
|
line-height: 1;
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(12px);
|
||||||
|
animation: rise 1s cubic-bezier(0.16, 1, 0.3, 1) 0.1s forwards;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 48px;
|
||||||
|
background: var(--ink-light);
|
||||||
|
margin: 2.5rem auto;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0);
|
||||||
|
transform-origin: top;
|
||||||
|
animation: grow 0.8s cubic-bezier(0.16, 1, 0.3, 1) 0.6s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote {
|
||||||
|
font-family: 'EB Garamond', Georgia, serif;
|
||||||
|
font-size: clamp(1.15rem, 3.5vw, 1.4rem);
|
||||||
|
font-style: italic;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: var(--ink);
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
opacity: 0;
|
||||||
|
animation: rise 1s cubic-bezier(0.16, 1, 0.3, 1) 0.9s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attribution {
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
color: var(--ink-light);
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
opacity: 0;
|
||||||
|
animation: rise 1s cubic-bezier(0.16, 1, 0.3, 1) 1.2s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secret-hint {
|
||||||
|
margin-top: 4rem;
|
||||||
|
opacity: 0;
|
||||||
|
animation: rise 1s cubic-bezier(0.16, 1, 0.3, 1) 2s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secret-hint p {
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: var(--ink-light);
|
||||||
|
cursor: default;
|
||||||
|
transition: color 0.4s;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secret-hint p:hover {
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
.secret-hint a {
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: transparent;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.6s, letter-spacing 0.4s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secret-hint:hover a {
|
||||||
|
color: var(--ink-light);
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secret-hint a:hover {
|
||||||
|
color: var(--ink) !important;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rise {
|
||||||
|
to { opacity: 1; transform: translateY(0) scaleY(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes grow {
|
||||||
|
to { opacity: 1; transform: scaleY(1); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="number">42</div>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<p class="quote">So long, and thanks for all the fish.</p>
|
||||||
|
<p class="attribution">Douglas Adams · The Hitchhiker's Guide to the Galaxy</p>
|
||||||
|
|
||||||
|
<div class="secret-hint">
|
||||||
|
<p>shhh. i have a secret to share — <a href="/secret">follow me</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+202
-12
@@ -32,6 +32,10 @@
|
|||||||
<a href="#experience">experience</a>
|
<a href="#experience">experience</a>
|
||||||
<a href="#education">education</a>
|
<a href="#education">education</a>
|
||||||
<a href="#opinion">opinion</a>
|
<a href="#opinion">opinion</a>
|
||||||
|
<a href="#automation">automation</a>
|
||||||
|
<a href="#interest">interest</a>
|
||||||
|
<a class="hidden" href="/42">42</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -46,14 +50,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<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</div>
|
<div style="font-family:var(--ff-mono);font-size:0.75rem;color:var(--muted);">Denmark<br>Aalborg Øst, 9220</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main id="about">
|
<main id="about">
|
||||||
|
|
||||||
<div class="hero">
|
<div class="hero">
|
||||||
<p class="hero-eyebrow">portfolio · 2026</p>
|
<p class="hero-eyebrow">About Me · 2026</p>
|
||||||
<h1>Samantha<br><span>Vero Friis</span></h1>
|
<h1>Samantha<br><span>Vero Friis</span></h1>
|
||||||
<p class="hero-bio">Bachelor's student in Business Administration seeking an entry-level analyst or finance-related role while studying. Strong numerical skills, advanced Excel, and experience in company, risk, and financial analysis. Analytical, detail-oriented, and efficiency-focused.</p>
|
<p class="hero-bio">Bachelor's student in Business Administration seeking an entry-level analyst or finance-related role while studying. Strong numerical skills, advanced Excel, and experience in company, risk, and financial analysis. Analytical, detail-oriented, and efficiency-focused.</p>
|
||||||
<div class="hero-meta">
|
<div class="hero-meta">
|
||||||
@@ -79,6 +83,7 @@
|
|||||||
<span class="exp-tag">engineering</span>
|
<span class="exp-tag">engineering</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="exp-body">Build lightweight backend tools to automate repetitive analytical and operational tasks. Python for data processing, validation, and workflow automation. Lightweight online services in Go, focusing on speed and reliability.</p>
|
<p class="exp-body">Build lightweight backend tools to automate repetitive analytical and operational tasks. Python for data processing, validation, and workflow automation. Lightweight online services in Go, focusing on speed and reliability.</p>
|
||||||
|
<a class="navigate" href="#automation">// Go to Tools</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -96,7 +101,7 @@
|
|||||||
<div class="edu-card">
|
<div class="edu-card">
|
||||||
<div class="edu-year">2024 — 2025</div>
|
<div class="edu-year">2024 — 2025</div>
|
||||||
<div class="edu-body">
|
<div class="edu-body">
|
||||||
<div class="edu-degree">Mathematics-Technology & Computer Science (BSc)</div>
|
<div class="edu-degree">Mathematics-Technology (BSc)</div>
|
||||||
<div class="edu-inst">Aalborg University · 1 semester</div>
|
<div class="edu-inst">Aalborg University · 1 semester</div>
|
||||||
<span class="edu-tag tag-dropped">discontinued</span>
|
<span class="edu-tag tag-dropped">discontinued</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -146,13 +151,51 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="section-head"><h2>Movie/Show Top list</h2></div>
|
|
||||||
|
|
||||||
|
<section id="automation">
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 class="page-title">Technical Tools & Automation</h2>
|
||||||
|
<span class="page-sub">engineering/programing</span>
|
||||||
|
</div>
|
||||||
|
<div class="exp-grid">
|
||||||
|
<div class="exp-card">
|
||||||
|
<div class="exp-header">
|
||||||
|
<span class="exp-title">Portfolio Engine</span>
|
||||||
|
</div>
|
||||||
|
<p class="exp-body">A lightweight portfolio and financial data backend written in Go. Tracks companies, currencies, revenue reports, and trades across configurable time periods — replacing spreadsheets with a proper database, REST API, and interactive shell.</p>
|
||||||
|
<span class="exp-title">Roadmap</span>
|
||||||
|
<ul style="padding: 20px;">
|
||||||
|
<li class="exp-body">Price update endpoint</li>
|
||||||
|
<li class="exp-body">Multi-currency conversion</li>
|
||||||
|
<li class="exp-body">Frontend dashboard</li>
|
||||||
|
<li class="exp-body">Shares outstanding history database table</li>
|
||||||
|
<li class="exp-body">Earnings per share (EPS) based on shares owned</li>
|
||||||
|
<li class="exp-body">First-In, First-Out (FIFO) realized gains</li>
|
||||||
|
<li class="exp-body">Dividends earned and related taxes</li>
|
||||||
|
<li class="exp-body">Total tax obligations</li>
|
||||||
|
</ul>
|
||||||
|
<a class="outlink" href="https://git.samantha42.xyz/samantha/Portfolio-Engine" >Git repo</a>
|
||||||
|
</div>
|
||||||
|
<div class="exp-card">
|
||||||
|
<div class="exp-header">
|
||||||
|
<span class="exp-title">Accounting Management</span>
|
||||||
|
</div>
|
||||||
|
<p class="exp-body"> A lightweight, SQL-backed, web-based CLI system designed to track assets and liabilities. The goal is to provide a simple, fast, and scalable financial tracking tool that can grow from personal use to more advanced scenarios.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 class="page-title" id="interest">interests</h2>
|
||||||
|
<span class="page-sub">Fav lists</span>
|
||||||
|
</div>
|
||||||
|
<div class="section-head"><h2>Movie/Show Top list</h2></div>
|
||||||
<div class="toplist-group">
|
<div class="toplist-group">
|
||||||
<h3>Top 5 Movies</h3>
|
<h3>Top 5 Movies</h3>
|
||||||
<div class="toplist-body">
|
<div class="toplist-body" >
|
||||||
<div class="poster-grid">
|
<div class="poster-grid">
|
||||||
<div class="poster-item">
|
<div class="poster-item posterhover" onclick="bladerunnerClick()">
|
||||||
<img src="/static/posters/bladerunner2049.jpg" alt="Blade Runner 2049">
|
<img src="/static/posters/bladerunner2049.jpg" alt="Blade Runner 2049">
|
||||||
<p>Blade Runner 2049</p>
|
<p>Blade Runner 2049</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -164,11 +207,11 @@
|
|||||||
<img src="/static/posters/Fightclub.jpg" alt="Fight Club">
|
<img src="/static/posters/Fightclub.jpg" alt="Fight Club">
|
||||||
<p>Fight Club</p>
|
<p>Fight Club</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="poster-item">
|
<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">
|
||||||
<p>Dracula: A Love Tale</p>
|
<p>Dracula: A Love Tale</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="poster-item">
|
<div class="poster-item posterhover" onclick="dragonClick()">
|
||||||
<img src="/static/posters/TheGirlwiththeDragonTattoo.webp" alt="Girl with a Dragon Tattoos">
|
<img src="/static/posters/TheGirlwiththeDragonTattoo.webp" alt="Girl with a Dragon Tattoos">
|
||||||
<p>Girl with a Dragon Tattoo</p>
|
<p>Girl with a Dragon Tattoo</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -179,14 +222,14 @@
|
|||||||
<h3>Top 5 Shows</h3>
|
<h3>Top 5 Shows</h3>
|
||||||
<div class="toplist-body">
|
<div class="toplist-body">
|
||||||
<div class="poster-grid">
|
<div class="poster-grid">
|
||||||
<div class="poster-item">
|
|
||||||
<img src="/static/posters/Chernobyl.webp" alt="Chernobyl">
|
|
||||||
<p>Chernobyl</p>
|
|
||||||
</div>
|
|
||||||
<div class="poster-item">
|
<div class="poster-item">
|
||||||
<img src="/static/posters/Succession.webp" alt="Succession">
|
<img src="/static/posters/Succession.webp" alt="Succession">
|
||||||
<p>Succession</p>
|
<p>Succession</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="poster-item">
|
||||||
|
<img src="/static/posters/Chernobyl.webp" alt="Chernobyl">
|
||||||
|
<p>Chernobyl</p>
|
||||||
|
</div>
|
||||||
<div class="poster-item">
|
<div class="poster-item">
|
||||||
<img src="/static/posters/Breaking Bad.webp" alt="Breaking Bad">
|
<img src="/static/posters/Breaking Bad.webp" alt="Breaking Bad">
|
||||||
<p>Breaking Bad</p>
|
<p>Breaking Bad</p>
|
||||||
@@ -202,6 +245,42 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="section-head"><h2>Lunix rice</h2></div>
|
||||||
|
<div class="rice-wrap">
|
||||||
|
<img src="/static/images/rice.png" width="500px">
|
||||||
|
<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 that’s hard to go back from.</p>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div class="section-head"><h2>Games</h2></div>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
@@ -211,5 +290,116 @@
|
|||||||
<div class="footer-copy">© 2026 — all rights reserved</div>
|
<div class="footer-copy">© 2026 — all rights reserved</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<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>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 544 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 533 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 798 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,236 @@
|
|||||||
|
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
#matrix-wrap {
|
||||||
|
background: #000;
|
||||||
|
min-height: 1200px;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: var(--border-radius-lg);
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
canvas#rain {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
}
|
||||||
|
#terminal {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 2rem 2.5rem;
|
||||||
|
min-height: 600px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
#boot-lines {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.boot-line {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #00ff41;
|
||||||
|
line-height: 1.8;
|
||||||
|
opacity: 0;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
.boot-line.dim { color: #00aa2b; }
|
||||||
|
.boot-line.bright { color: #a3ffb4; font-weight: 500; }
|
||||||
|
.boot-line.warn { color: #ffcc00; }
|
||||||
|
#prompt-area {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
#prompt-area.visible { opacity: 1; }
|
||||||
|
#input-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
#prompt-label {
|
||||||
|
color: #00ff41;
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
#cmd-input {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #00ff4166;
|
||||||
|
border-radius: 0;
|
||||||
|
color: #00ff41;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 14px;
|
||||||
|
outline: none;
|
||||||
|
flex: 1;
|
||||||
|
padding: 2px 4px;
|
||||||
|
caret-color: #00ff41;
|
||||||
|
}
|
||||||
|
#cmd-input:focus { border-bottom-color: #00ff41; }
|
||||||
|
#output {
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #00ff41;
|
||||||
|
line-height: 1.9;
|
||||||
|
min-height: 60px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.o-dim { color: #00aa2b; }
|
||||||
|
.o-bright { color: #a3ffb4; }
|
||||||
|
.o-warn { color: #ffcc00; }
|
||||||
|
.o-pink { color: #ff79c6; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="matrix-wrap">
|
||||||
|
<canvas id="rain"></canvas>
|
||||||
|
<div id="terminal">
|
||||||
|
<div id="boot-lines"></div>
|
||||||
|
<div id="prompt-area">
|
||||||
|
<div id="input-row">
|
||||||
|
<span id="prompt-label">samantha42@secret:~$</span>
|
||||||
|
<input id="cmd-input" type="text" autocomplete="off" spellcheck="false" placeholder="type 'help'" aria-label="Terminal input" />
|
||||||
|
</div>
|
||||||
|
<div id="output"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const canvas = document.getElementById('rain');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const wrap = document.getElementById('matrix-wrap');
|
||||||
|
|
||||||
|
function resizeCanvas() {
|
||||||
|
canvas.width = wrap.offsetWidth;
|
||||||
|
canvas.height = wrap.offsetHeight;
|
||||||
|
}
|
||||||
|
resizeCanvas();
|
||||||
|
|
||||||
|
const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン0123456789ABCDEF@#$%&*';
|
||||||
|
const fontSize = 14;
|
||||||
|
let cols, drops;
|
||||||
|
|
||||||
|
function initDrops() {
|
||||||
|
cols = Math.floor(canvas.width / fontSize);
|
||||||
|
drops = Array(cols).fill(1);
|
||||||
|
}
|
||||||
|
initDrops();
|
||||||
|
|
||||||
|
function drawRain() {
|
||||||
|
ctx.fillStyle = 'rgba(0,0,0,0.05)';
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.font = fontSize + 'px monospace';
|
||||||
|
for (let i = 0; i < drops.length; i++) {
|
||||||
|
const bright = Math.random() > 0.95;
|
||||||
|
ctx.fillStyle = bright ? '#a3ffb4' : '#00ff41';
|
||||||
|
ctx.globalAlpha = bright ? 1 : 0.7;
|
||||||
|
const ch = chars[Math.floor(Math.random() * chars.length)];
|
||||||
|
ctx.fillText(ch, i * fontSize, drops[i] * fontSize);
|
||||||
|
ctx.globalAlpha = 1;
|
||||||
|
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
|
||||||
|
drops[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterval(drawRain, 50);
|
||||||
|
|
||||||
|
const bootSequence = [
|
||||||
|
{ text: 'SAMANTHA42 OS v4.2.0 — initializing...', cls: 'dim', delay: 200 },
|
||||||
|
{ text: 'Loading kernel modules... [OK]', cls: 'dim', delay: 400 },
|
||||||
|
{ text: 'Mounting secret filesystem... [OK]', cls: 'dim', delay: 600 },
|
||||||
|
{ text: 'Verifying identity... [OK]', cls: 'dim', delay: 900 },
|
||||||
|
{ text: '> ACCESS GRANTED ', cls: 'bright', delay: 1200 },
|
||||||
|
{ text: '', cls: '', delay: 1350 },
|
||||||
|
{ text: 'Welcome back, curious one. ', cls: 'warn', delay: 1500 },
|
||||||
|
{ text: 'You found the secret page. Nice work. ', cls: '', delay: 1700 },
|
||||||
|
{ text: '', cls: '', delay: 1850 },
|
||||||
|
{ text: "Type 'help' to see what's hidden here.", cls: 'dim', delay: 2000 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const bootEl = document.getElementById('boot-lines');
|
||||||
|
const promptArea = document.getElementById('prompt-area');
|
||||||
|
|
||||||
|
bootSequence.forEach(({ text, cls, delay }) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const line = document.createElement('div');
|
||||||
|
line.className = 'boot-line' + (cls ? ' ' + cls : '');
|
||||||
|
line.textContent = text;
|
||||||
|
bootEl.appendChild(line);
|
||||||
|
requestAnimationFrame(() => { line.style.opacity = '1'; });
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => { promptArea.classList.add('visible'); }, 2200);
|
||||||
|
|
||||||
|
const commands = {
|
||||||
|
help: () => `<span class="o-bright">available commands:</span>
|
||||||
|
<span class="o-dim"> whoami </span>— the real story
|
||||||
|
<span class="o-dim"> skills </span>— the unofficial skill list
|
||||||
|
<span class="o-dim"> facts </span>— things my CV won't tell you
|
||||||
|
<span class="o-dim"> crush </span>— current hyperfixations
|
||||||
|
<span class="o-dim"> 42 </span>— the answer
|
||||||
|
<span class="o-dim"> clear </span>— clear the terminal`,
|
||||||
|
|
||||||
|
whoami: () => `<span class="o-bright">samantha</span> — numberphile, programmer, overthinker.
|
||||||
|
loves: movies, pixel-perfect layouts or fun design, staying up too late debugging.
|
||||||
|
hates: Comic Sans and broken padding.
|
||||||
|
found here by: <span class="o-pink">being curious</span> (good trait btw)`,
|
||||||
|
|
||||||
|
skills: () => `<span class="o-bright">UNOFFICIAL SKILL TREE</span>
|
||||||
|
<span class="o-dim"> ████████████████████</span> pretending to understand the error
|
||||||
|
<span class="o-dim"> █████████████████░░░</span> googling things I definitely know
|
||||||
|
<span class="o-dim"> ████████████████████</span> making things pretty at 2am
|
||||||
|
<span class="o-dim"> █████████░░░░░░░░░░░</span> replying to emails promptly
|
||||||
|
<span class="o-dim"> ████████████████████</span> convincing clients the bug is a feature`,
|
||||||
|
|
||||||
|
facts: () => `<span class="o-bright">fun facts not on
|
||||||
|
→ 42 is my favourite number (obviously)
|
||||||
|
→ I debug best when listening to lo-fi`,
|
||||||
|
|
||||||
|
crush: () => `<span class="o-bright">current hyperfixations:</span>
|
||||||
|
<span class="o-pink"> ♡</span> linux ricing
|
||||||
|
<span class="o-pink"> ♡</span> Japanese Katakana typography
|
||||||
|
<span class="o-pink"> ♡</span> number go up. But Fuck btc, lol
|
||||||
|
<span class="o-pink"> ♡</span> praying yto loard gaben. If you know, you know
|
||||||
|
<span class="o-pink"> ♡</span> building useless website pages, clearly`,
|
||||||
|
|
||||||
|
42: () => `<span class="o-bright">"The Answer to the Ultimate Question of Life,
|
||||||
|
the Universe, and Everything."</span>
|
||||||
|
— Deep Thought, after 7.5 million years
|
||||||
|
|
||||||
|
also: my lucky number. also: this website's name.
|
||||||
|
<span class="o-dim">don't ask what the question is. nobody knows.</span>`,
|
||||||
|
|
||||||
|
clear: () => '__clear__',
|
||||||
|
};
|
||||||
|
|
||||||
|
const input = document.getElementById('cmd-input');
|
||||||
|
const output = document.getElementById('output');
|
||||||
|
|
||||||
|
input.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key !== 'Enter') return;
|
||||||
|
const cmd = input.value.trim().toLowerCase();
|
||||||
|
input.value = '';
|
||||||
|
if (!cmd) return;
|
||||||
|
|
||||||
|
if (commands[cmd]) {
|
||||||
|
const result = commands[cmd]();
|
||||||
|
if (result === '__clear__') {
|
||||||
|
output.innerHTML = '';
|
||||||
|
} else {
|
||||||
|
output.innerHTML = `<span class="o-dim">$ ${cmd}</span>\n` + result + '\n\n';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.innerHTML = `<span class="o-dim">$ ${cmd}</span>\n<span class="o-warn">command not found: ${cmd}</span>\ntype <span class="o-bright">help</span> to see available commands\n\n`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
input.addEventListener('focus', () => {});
|
||||||
|
setTimeout(() => { input.focus(); }, 2300);
|
||||||
|
</script>
|
||||||
@@ -70,6 +70,15 @@ nav{
|
|||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sidebar-links a.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-links:hover a.hidden {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
aside{
|
aside{
|
||||||
border-right:1px solid var(--border);
|
border-right:1px solid var(--border);
|
||||||
padding:2.5rem 1.5rem;
|
padding:2.5rem 1.5rem;
|
||||||
@@ -309,3 +318,98 @@ footer{
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-grid {
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
font-family: var(--ff-mono);
|
||||||
|
font-size: clamp(1rem, 4vw, 2rem);
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title::before {
|
||||||
|
content: '> ';
|
||||||
|
color: var(--green);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-sub {
|
||||||
|
font-family: var(--ff-mono);
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--muted);
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
padding-left: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.posterhover:hover img {
|
||||||
|
transform: scale(1.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#rain-canvas {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 999;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.8s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dragon-grid {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 999;
|
||||||
|
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:hover{text-decoration:underline;}
|
||||||
|
|
||||||
|
a{
|
||||||
|
font-family:var(--ff-mono);font-size:0.78rem;color:var(--muted);
|
||||||
|
text-decoration:none;padding:0.3rem 0.6rem;border-radius:4px;
|
||||||
|
transition:color 0.15s,background 0.15s;
|
||||||
|
display:flex;align-items:center;gap:6px;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user