Test
@@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
.htaccess
|
||||
/.idea
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
$title = 'About';
|
||||
include $_SERVER['DOCUMENT_ROOT'] . '/includes/head.php';
|
||||
?>
|
||||
<body class="bg-[#0a0a0a] text-white min-h-screen">
|
||||
<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/nav.php'; ?>
|
||||
|
||||
<main class="pt-16">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6 py-12">
|
||||
<h1 class="text-2xl font-semibold mb-12">About</h1>
|
||||
<div class="space-y-5 text-neutral-300 leading-relaxed text-sm">
|
||||
<p><!-- Who you are --></p>
|
||||
<p><!-- What you do / what you're into --></p>
|
||||
<p><!-- Anything else --></p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"categories": [
|
||||
{
|
||||
"name": "Interesting",
|
||||
"links": [
|
||||
{ "title": "Example", "url": "https://example.com", "note": "optional description" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Tools",
|
||||
"links": [
|
||||
{ "title": "Example", "url": "https://example.com" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Reading",
|
||||
"links": [
|
||||
{ "title": "Example", "url": "https://example.com" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"title": "Entry title",
|
||||
"date": "2026-02-19",
|
||||
"listening": "",
|
||||
"watching": "",
|
||||
"reading": "",
|
||||
"working on": "",
|
||||
"thinking": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 542 KiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 6.2 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 5.2 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 4.1 MiB |
|
After Width: | Height: | Size: 8.5 MiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 231 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 6.5 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 12 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 7.1 MiB |
|
After Width: | Height: | Size: 7.8 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
$title = 'Contact';
|
||||
include $_SERVER['DOCUMENT_ROOT'] . '/includes/head.php';
|
||||
?>
|
||||
<body class="bg-[#0a0a0a] text-white min-h-screen">
|
||||
<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/nav.php'; ?>
|
||||
|
||||
<main class="pt-16">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6 py-12">
|
||||
<h1 class="text-2xl mb-3">Contact</h1>
|
||||
<p class="text-neutral-400 text-sm mb-12">Get in touch.</p>
|
||||
<a href="mailto:admin@sistav.com" class="text-neutral-300 hover:text-white transition-colors text-sm">
|
||||
admin@sistav.com
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
<footer class="border-t border-[#1c1c1c] mt-20">
|
||||
<div class="max-w-5xl mx-auto px-4 sm:px-6 py-8 text-neutral-700 text-xs">
|
||||
sistav.com
|
||||
</div>
|
||||
</footer>
|
||||
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= isset($title) ? htmlspecialchars($title) . ' — sistav.com' : 'sistav.com' ?></title>
|
||||
<link rel="icon" href="/favicon.ico" sizes="any">
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&display=swap" rel="stylesheet">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: { cream: '#e0d5c0' }
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
/* Global text softening */
|
||||
body { color: #e6dfd8 !important; }
|
||||
|
||||
/* Headings */
|
||||
h1 {
|
||||
font-family: 'DM Serif Display', Georgia, serif !important;
|
||||
font-weight: 400 !important;
|
||||
font-size: 2.25rem !important;
|
||||
color: #e6dfd8;
|
||||
letter-spacing: -0.01em;
|
||||
text-align: center;
|
||||
}
|
||||
article h2 {
|
||||
font-family: inherit !important;
|
||||
font-weight: 400 !important;
|
||||
font-size: 0.75rem !important;
|
||||
color: #d4d4d4 !important;
|
||||
letter-spacing: 0.1em !important;
|
||||
text-transform: uppercase !important;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* Gif frame */
|
||||
#gif-frame {
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
border: 2px solid #6b6b6b;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255,0.05),
|
||||
0 4px 8px rgba(0,0,0,0.55),
|
||||
0 16px 40px rgba(0,0,0,0.75),
|
||||
0 40px 90px rgba(0,0,0,0.35);
|
||||
}
|
||||
|
||||
/* Grain overlay */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9998;
|
||||
pointer-events: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E");
|
||||
opacity: 0.04;
|
||||
}
|
||||
|
||||
/* Custom cursor */
|
||||
* { cursor: none !important; }
|
||||
#site-cursor {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: 99999;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: width .2s ease, height .2s ease, opacity .2s ease;
|
||||
opacity: 0;
|
||||
}
|
||||
#site-cursor.visible { opacity: 1; }
|
||||
#site-cursor.expanded { width: 22px; height: 22px; opacity: 0.3; }
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var cursor = document.getElementById('site-cursor');
|
||||
if (!cursor || !window.matchMedia('(hover: hover)').matches) return;
|
||||
|
||||
document.addEventListener('mousemove', function (e) {
|
||||
cursor.style.left = e.clientX + 'px';
|
||||
cursor.style.top = e.clientY + 'px';
|
||||
cursor.classList.add('visible');
|
||||
});
|
||||
|
||||
document.addEventListener('mouseleave', function () {
|
||||
cursor.classList.remove('visible');
|
||||
});
|
||||
|
||||
document.addEventListener('mouseover', function (e) {
|
||||
if (e.target.closest('a, button, [role="button"]'))
|
||||
cursor.classList.add('expanded');
|
||||
else
|
||||
cursor.classList.remove('expanded');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
$_nav_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
|
||||
function _nav_active(string $href): bool {
|
||||
global $_nav_path;
|
||||
return $href === '/'
|
||||
? ($_nav_path === '/' || $_nav_path === '/index.php')
|
||||
: strpos($_nav_path, $href) === 0;
|
||||
}
|
||||
|
||||
$_nav_pages = [
|
||||
'/about/' => 'About',
|
||||
'/log/' => 'Log',
|
||||
'/links/' => 'Links',
|
||||
'/contact/' => 'Contact',
|
||||
];
|
||||
?>
|
||||
<nav class="fixed top-0 left-0 right-0 z-50 bg-[#0a0a0a] border-b border-[#1c1c1c]">
|
||||
<div class="max-w-5xl mx-auto px-4 sm:px-6 flex items-center justify-between h-16">
|
||||
<a href="/" class="text-base font-semibold tracking-wide">sistav.com</a>
|
||||
|
||||
<div class="hidden md:flex items-center gap-8 text-base">
|
||||
<?php foreach ($_nav_pages as $href => $label): ?>
|
||||
<a href="<?= $href ?>" class="<?= _nav_active($href) ? '' : 'text-neutral-400 hover:text-[#e6dfd8]' ?> transition-colors duration-150"><?= $label ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<button id="nav-toggle" class="md:hidden text-neutral-400 hover:text-white p-1" aria-label="Toggle menu" aria-expanded="false">
|
||||
<svg id="nav-icon-open" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
<svg id="nav-icon-close" class="w-5 h-5 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="nav-mobile" class="hidden border-t border-[#1c1c1c] bg-[#0a0a0a]">
|
||||
<div class="max-w-5xl mx-auto px-4 py-5 flex flex-col gap-5 text-sm">
|
||||
<?php foreach ($_nav_pages as $href => $label): ?>
|
||||
<a href="<?= $href ?>" class="<?= _nav_active($href) ? '' : 'text-neutral-300 hover:text-[#e6dfd8]' ?> transition-colors text-base"><?= $label ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="site-cursor"></div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var toggle = document.getElementById('nav-toggle');
|
||||
var mobile = document.getElementById('nav-mobile');
|
||||
var iconOpen = document.getElementById('nav-icon-open');
|
||||
var iconClose = document.getElementById('nav-icon-close');
|
||||
toggle.addEventListener('click', function () {
|
||||
var justHid = mobile.classList.toggle('hidden');
|
||||
iconOpen.classList.toggle('hidden', !justHid);
|
||||
iconClose.classList.toggle('hidden', justHid);
|
||||
toggle.setAttribute('aria-expanded', String(!justHid));
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>sistav.com</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #000;
|
||||
}
|
||||
img {
|
||||
max-width: 90vw;
|
||||
max-height: 90vh;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="gif.gif" alt="gif">
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
$gif_files = glob($_SERVER['DOCUMENT_ROOT'] . '/assets/gifs/*.gif');
|
||||
$gifs = array_map(fn($f) => '/assets/gifs/' . basename($f), $gif_files);
|
||||
$default = !empty($gifs) ? $gifs[0] : '';
|
||||
include $_SERVER['DOCUMENT_ROOT'] . '/includes/head.php';
|
||||
?>
|
||||
<body class="bg-[#0a0a0a] text-white min-h-screen">
|
||||
<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/nav.php'; ?>
|
||||
|
||||
<main class="h-screen flex items-center justify-center pt-16">
|
||||
<div id="gif-frame">
|
||||
<img id="main-gif" src="<?= htmlspecialchars($default) ?>" alt="" style="display:block;opacity:0;transition:opacity 0.4s ease">
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
var gifs = <?= json_encode($gifs) ?>;
|
||||
var img = document.getElementById('main-gif');
|
||||
|
||||
function sizeGif() {
|
||||
if (!img.naturalWidth) return;
|
||||
var maxPx = Math.min(window.innerWidth, window.innerHeight) * 0.65;
|
||||
var scale = Math.min(maxPx / img.naturalWidth, maxPx / img.naturalHeight);
|
||||
img.style.width = Math.round(img.naturalWidth * scale) + 'px';
|
||||
img.style.height = Math.round(img.naturalHeight * scale) + 'px';
|
||||
img.style.opacity = '1';
|
||||
}
|
||||
|
||||
img.src = gifs[Math.floor(Math.random() * gifs.length)];
|
||||
img.addEventListener('load', sizeGif);
|
||||
if (img.complete && img.naturalWidth) sizeGif();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
$title = 'Links';
|
||||
include $_SERVER['DOCUMENT_ROOT'] . '/includes/head.php';
|
||||
|
||||
$data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/assets/data/links.json'), true);
|
||||
$categories = $data['categories'] ?? [];
|
||||
?>
|
||||
<body class="bg-[#0a0a0a] text-white min-h-screen">
|
||||
<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/nav.php'; ?>
|
||||
|
||||
<main class="pt-16">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6 py-12">
|
||||
<h1 class="text-2xl font-semibold mb-3">Links</h1>
|
||||
<p class="text-neutral-400 text-sm mb-16">Things worth sharing.</p>
|
||||
|
||||
<div class="space-y-12">
|
||||
<?php foreach ($categories as $cat): ?>
|
||||
<section>
|
||||
<h2 class="text-xs text-neutral-300 uppercase tracking-widest mb-5"><?= htmlspecialchars($cat['name']) ?></h2>
|
||||
<ul class="space-y-4">
|
||||
<?php foreach ($cat['links'] as $link):
|
||||
$domain = preg_replace('/^www\./', '', parse_url($link['url'], PHP_URL_HOST));
|
||||
?>
|
||||
<li>
|
||||
<a href="<?= htmlspecialchars($link['url']) ?>" target="_blank" rel="noopener" class="group">
|
||||
<span class="flex items-baseline gap-2">
|
||||
<span class="text-neutral-300 text-sm group-hover:text-white transition-colors"><?= htmlspecialchars($link['title']) ?></span>
|
||||
<span class="text-neutral-500 text-xs"><?= $domain ?></span>
|
||||
</span>
|
||||
<?php if (!empty($link['note'])): ?>
|
||||
<span class="block text-neutral-500 text-xs mt-0.5"><?= htmlspecialchars($link['note']) ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</section>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
$title = 'Log';
|
||||
include $_SERVER['DOCUMENT_ROOT'] . '/includes/head.php';
|
||||
|
||||
$data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/assets/data/log.json'), true);
|
||||
$entries = $data['entries'] ?? [];
|
||||
$fields = ['listening', 'watching', 'reading', 'working on', 'thinking'];
|
||||
?>
|
||||
<body class="bg-[#0a0a0a] text-white min-h-screen">
|
||||
<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/nav.php'; ?>
|
||||
|
||||
<main class="pt-16">
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6 py-12">
|
||||
<h1 class="text-2xl font-semibold mb-3">Log</h1>
|
||||
<p class="text-neutral-300 text-sm mb-16">What I'm into lately. Updated whenever.</p>
|
||||
|
||||
<div class="space-y-12">
|
||||
<?php if (empty($entries)): ?>
|
||||
<p class="text-neutral-700 text-sm">Nothing yet.</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach ($entries as $entry): ?>
|
||||
<article>
|
||||
<h2 class="mb-5"><?= htmlspecialchars($entry['title']) ?></h2>
|
||||
<p class="text-[#a3a3a3] text-xs font-mono mb-6"><?= date('F j, Y', strtotime($entry['date'])) ?></p>
|
||||
<dl class="space-y-3">
|
||||
<?php foreach ($fields as $field): ?>
|
||||
<?php if (!empty($entry[$field])): ?>
|
||||
<div class="grid grid-cols-[90px_1fr] gap-4">
|
||||
<dt class="text-neutral-500 text-xs"><?= $field ?></dt>
|
||||
<dd class="text-neutral-200 text-sm"><?= htmlspecialchars($entry[$field]) ?></dd>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</dl>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||