testing dark/light mode

This commit is contained in:
2026-08-13 12:21:37 -05:00
parent 1aad2224e2
commit d7d60dc0f6
5 changed files with 277 additions and 316 deletions

View File

@@ -3,16 +3,37 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hex Studios</title> <title>Hex Studios</title>
<script>
(function() {
var stored = localStorage.getItem('theme');
if (stored === 'light') document.documentElement.setAttribute('data-theme', 'light');
})();
function toggleTheme() {
var isLight = document.documentElement.getAttribute('data-theme') === 'light';
if (isLight) {
document.documentElement.removeAttribute('data-theme');
localStorage.setItem('theme', 'dark');
} else {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem('theme', 'light');
}
}
</script>
<link rel="stylesheet" href="styles/main.css"> <link rel="stylesheet" href="styles/main.css">
</head> </head>
<body> <body>
<button id="theme-toggle" onclick="toggleTheme()">toggle theme</button>
<h1>// Hex Studios</h1> <h1>// Hex Studios</h1>
<i>Developer, biker, musician, engineer, and an unapologetic centrist in the deep red south. The real @hexstudios.</i> <i>Developer, biker, musician, engineer, and an unapologetic centrist in the deep red south. The real @hexstudios.</i>
<div id="stick-posts-section"> <div id="stick-posts-section">
<h2>Pinned posts</h2> <h2>Pinned posts</h2>
<ul> <ul>
<li><a href="posts/about.html">About Hex Studios</a></li> <li><a href="posts/about.html">About</a></li>
</ul> </ul>
</div> </div>

371
post.html
View File

@@ -1,279 +1,144 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Post</title> <title>Post</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js/styles/github.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js/styles/github.min.css">
<script src="https://cdn.jsdelivr.net/npm/highlight.js/lib/common.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/highlight.js/lib/common.min.js"></script>
<style> <script>
:root { (function() {
--ink: #26241f; var stored = localStorage.getItem('theme');
--ink-soft: #6b6a63; if (stored === 'light') document.documentElement.setAttribute('data-theme', 'light');
--paper: #fbfaf7; })();
--rule: #e4e1d8;
--accent: #3a5a40;
--code-bg: #f1efe8;
}
* { box-sizing: border-box; } function toggleTheme() {
var isLight = document.documentElement.getAttribute('data-theme') === 'light';
if (isLight) {
document.documentElement.removeAttribute('data-theme');
localStorage.setItem('theme', 'dark');
} else {
document.documentElement.setAttribute('data-theme', 'light');
localStorage.setItem('theme', 'light');
}
}
</script>
html { -webkit-text-size-adjust: 100%; } <link rel="stylesheet" href="styles/main.css">
body { </head>
margin: 0; <body>
background: var(--paper);
color: var(--ink);
font-family: Georgia, 'Iowan Old Style', 'Palatino Linotype', serif;
line-height: 1.7;
}
.wrap { <div class="wrap">
max-width: 680px; <button id="theme-toggle" onclick="toggleTheme()">toggle theme</button>
margin: 0 auto; <a class="back-link" href="index.html">&larr; Return home</a>
padding: 4rem 1.5rem 6rem; <p class="meta" id="meta" hidden></p>
} <div id="content"><p class="state">Loading post&hellip;</p></div>
</div>
.back-link { <script>
display: inline-flex; function parseFrontMatter(raw) {
align-items: center; const match = raw.match(/^---\r?\n([\s\S]+?)\r?\n---\r?\n([\s\S]*)$/);
gap: 0.4rem; if (!match) return { meta: {}, body: raw };
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
font-size: 0.85rem;
letter-spacing: 0.02em;
text-transform: uppercase;
color: var(--ink-soft);
text-decoration: none;
margin-bottom: 3rem;
border-bottom: 1px solid transparent;
transition: border-color 0.15s ease, color 0.15s ease;
}
.back-link:hover {
color: var(--accent);
border-color: var(--accent);
}
.meta { const meta = {};
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; match[1].split(/\r?\n/).forEach(line => {
font-size: 0.85rem; const idx = line.indexOf(':');
color: var(--ink-soft); if (idx === -1) return;
margin: 0 0 0.5rem; const key = line.slice(0, idx).trim();
text-transform: uppercase; let value = line.slice(idx + 1).trim();
letter-spacing: 0.04em; // strip optional surrounding quotes: title: "My Post"
} value = value.replace(/^["'](.*)["']$/, '$1');
meta[key] = value;
});
#content h1:first-child { return { meta, body: match[2] };
font-size: 2.1rem; }
line-height: 1.25;
margin: 0 0 0.75rem;
letter-spacing: -0.01em;
}
#content h1, #content h2, #content h3 { function formatDate(dateStr) {
font-family: Georgia, serif; if (!dateStr) return '';
color: var(--ink); const d = new Date(dateStr);
margin-top: 2.2em; if (isNaN(d)) return dateStr; // fall back to raw string if unparseable
margin-bottom: 0.6em; return d.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' });
} }
#content h2 { font-size: 1.5rem; border-bottom: 1px solid var(--rule); padding-bottom: 0.3em; } function showError(message) {
#content h3 { font-size: 1.2rem; } document.getElementById('content').innerHTML =
`<p class="state error">${message}</p>`;
}
#content p { margin: 1.1em 0; } // ---- main ------------------------------------------------------------
#content a { color: var(--accent); text-decoration-color: rgba(58,90,64,0.35); } marked.setOptions({
#content a:hover { text-decoration-color: var(--accent); } highlight: (code, lang) => {
try {
return lang
? hljs.highlight(code, { language: lang }).value
: hljs.highlightAuto(code).value;
} catch (e) {
return code;
}
}
});
#content img { async function loadPost() {
max-width: 100%; const params = new URLSearchParams(window.location.search);
height: auto; const file = params.get('file');
border-radius: 4px;
margin: 1.5em 0;
}
#content blockquote { if (!file) {
margin: 1.5em 0; showError('No post specified. Link to this page as <code>post.html?file=your-post.md</code>.');
padding: 0.2em 1.2em; return;
border-left: 3px solid var(--accent); }
color: var(--ink-soft);
font-style: italic;
}
#content ul, #content ol { // Guard against path traversal — keep the fetch confined to posts/
padding-left: 1.4em; if (file.includes('..') || file.startsWith('/')) {
} showError('Invalid post path.');
#content li { margin: 0.4em 0; } return;
}
#content hr { try {
border: none; const res = await fetch('posts/' + file);
border-top: 1px solid var(--rule); if (!res.ok) throw new Error('HTTP ' + res.status);
margin: 2.5em 0; const raw = await res.text();
}
#content code { const { meta, body } = parseFrontMatter(raw);
font-family: 'SF Mono', Menlo, Consolas, monospace; const html = marked.parse(body);
font-size: 0.85em;
background: var(--code-bg);
padding: 0.15em 0.4em;
border-radius: 3px;
}
#content pre { document.getElementById('content').innerHTML = html;
background: var(--code-bg);
padding: 1em 1.2em;
border-radius: 6px;
overflow-x: auto;
line-height: 1.5;
}
#content pre code {
background: none;
padding: 0;
font-size: 0.85em;
}
#content table { // Title: front matter > first H1 in the doc > filename
width: 100%; let title = meta.title;
border-collapse: collapse; if (!title) {
margin: 1.5em 0; const h1 = document.querySelector('#content h1');
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; title = h1 ? h1.textContent : file.replace(/\.md$/, '');
font-size: 0.9rem; }
} document.title = title;
#content th, #content td {
text-align: left;
padding: 0.5em 0.8em;
border-bottom: 1px solid var(--rule);
}
#content th { color: var(--ink-soft); font-weight: 600; }
.state { // Inject an H1 if front matter supplied a title but the body didn't have one
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; if (meta.title && !document.querySelector('#content h1:first-child')) {
color: var(--ink-soft); const h1 = document.createElement('h1');
font-size: 0.95rem; h1.textContent = meta.title;
} document.getElementById('content').prepend(h1);
}
.state.error { color: #a3413a; } // Meta line: date (and tags, if present)
const metaEl = document.getElementById('meta');
const parts = [];
if (meta.date) parts.push(formatDate(meta.date));
if (meta.tags) parts.push(meta.tags.split(',').map(t => t.trim()).join(' &middot; '));
if (parts.length) {
metaEl.innerHTML = parts.join(' &nbsp;/&nbsp; ');
metaEl.hidden = false;
}
} catch (err) {
showError('Could not load this post. It may have been moved or deleted.');
}
}
@media (prefers-reduced-motion: no-preference) { document.addEventListener('DOMContentLoaded', loadPost);
.wrap { animation: rise 0.35s ease-out both; } </script>
@keyframes rise { </body>
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
}
</style>
</head>
<body>
<div class="wrap">
<a class="back-link" href="index.html">&larr; All posts</a>
<p class="meta" id="meta" hidden></p>
<div id="content"><p class="state">Loading post&hellip;</p></div>
</div>
<script>
function parseFrontMatter(raw) {
const match = raw.match(/^---\r?\n([\s\S]+?)\r?\n---\r?\n([\s\S]*)$/);
if (!match) return { meta: {}, body: raw };
const meta = {};
match[1].split(/\r?\n/).forEach(line => {
const idx = line.indexOf(':');
if (idx === -1) return;
const key = line.slice(0, idx).trim();
let value = line.slice(idx + 1).trim();
// strip optional surrounding quotes: title: "My Post"
value = value.replace(/^["'](.*)["']$/, '$1');
meta[key] = value;
});
return { meta, body: match[2] };
}
function formatDate(dateStr) {
if (!dateStr) return '';
const d = new Date(dateStr);
if (isNaN(d)) return dateStr; // fall back to raw string if unparseable
return d.toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' });
}
function showError(message) {
document.getElementById('content').innerHTML =
`<p class="state error">${message}</p>`;
}
// ---- main ------------------------------------------------------------
marked.setOptions({
highlight: (code, lang) => {
try {
return lang
? hljs.highlight(code, { language: lang }).value
: hljs.highlightAuto(code).value;
} catch (e) {
return code;
}
}
});
async function loadPost() {
const params = new URLSearchParams(window.location.search);
const file = params.get('file');
if (!file) {
showError('No post specified. Link to this page as <code>post.html?file=your-post.md</code>.');
return;
}
// Guard against path traversal — keep the fetch confined to posts/
if (file.includes('..') || file.startsWith('/')) {
showError('Invalid post path.');
return;
}
try {
const res = await fetch('posts/' + file);
if (!res.ok) throw new Error('HTTP ' + res.status);
const raw = await res.text();
const { meta, body } = parseFrontMatter(raw);
const html = marked.parse(body);
document.getElementById('content').innerHTML = html;
// Title: front matter > first H1 in the doc > filename
let title = meta.title;
if (!title) {
const h1 = document.querySelector('#content h1');
title = h1 ? h1.textContent : file.replace(/\.md$/, '');
}
document.title = title;
// Inject an H1 if front matter supplied a title but the body didn't have one
if (meta.title && !document.querySelector('#content h1:first-child')) {
const h1 = document.createElement('h1');
h1.textContent = meta.title;
document.getElementById('content').prepend(h1);
}
// Meta line: date (and tags, if present)
const metaEl = document.getElementById('meta');
const parts = [];
if (meta.date) parts.push(formatDate(meta.date));
if (meta.tags) parts.push(meta.tags.split(',').map(t => t.trim()).join(' &middot; '));
if (parts.length) {
metaEl.innerHTML = parts.join(' &nbsp;/&nbsp; ');
metaEl.hidden = false;
}
} catch (err) {
showError('Could not load this post. It may have been moved or deleted.');
}
}
document.addEventListener('DOMContentLoaded', loadPost);
</script>
</body>
</html> </html>

View File

@@ -1,52 +0,0 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hex Studios</title>
<link rel="stylesheet" href="styles/main.css">
</head>
<body>
<div id="page-header">
<h1>// Hex Studios</h1>
<i>Developer, biker, musician, engineer, and an unapologetic centrist in the deep red south. The real @hexstudios.</i>
</div>
<div id="post-body">
<a href="../index.html">&lt;-- Back to home</a>
<h1>// ABout Hex Studios</h1>
<h2>// What is this?</h2>
<p>Good question. It <i>was</i> my personal portfolio site, used for listing on applications to corporate slop jobs, but over time I just grew into wanting this place to be a space where I can be unapologetically <i><b>me</b></i>. You can still visit the old site <a href="old2/index.html">here</a> if you want. It's pretty cool.</p>
<p>So thats what this is. I'll still list my credentials and who I am, but I won't shy away from being me.</p>
<h2>// Well then, who are you?</h2>
<p>My name is Chris. I make stuff, sometimes. By day I'm a software engineer working with C# and unity. I love programming and old technology, I spend my time outside of work learning the ins-and-outs of computers and electronics in general, using C and C++ to mess with native applications and embedded firmware, hoping to one day reclaim the magic of technology from the souless corporate sphere it currently lives in.</p>
<p>Some of my hobbies include: Making and enjoying music, motorcycles, game development, light gaming (mostly indie games and older titles), homelabbing, poking at old technology</p>
<p>Oh yeah I also run a small company with my wife called Bellsworne. You should <a href="https://bellsworne.com">check us out.</a></p>
<h2>// My creds</h2>
<h3>Education:</h3>
<ul>
<li>B.S. Software Engineering</li>
<li>A.S. Computer Science</li>
<li>CompTIA Project Managment+ Certification</li>
</ul>
<h3>Professional:</h3>
<ul>
<li>5+ years of software engineering, primarily in C#/.NET</li>
<li>~2 years of electronics repair (phones, laptops, etc)</li>
</ul>
<i>I was also a barista for two years, who'uld've thunk it</i>
<h3>Personal:</h3>
<ul>
<li>13+ years of linux experience (I use NixOS, btw)</li>
<li>10+ years of C/C++</li>
<li>10+ years of HTML/CSS</li>
<li>Other languages, experience varies: Odin, Python, JS, Java</li>
</ul>
</div>
</body>
</html>

View File

@@ -11,7 +11,7 @@ Good question. It *was* my personal portfolio site, used for listing on applicat
So thats what this is. I'll still list my credentials and who I am, but I won't shy away from being me. So thats what this is. I'll still list my credentials and who I am, but I won't shy away from being me.
## // Well than, who are you? ## // Well then, who are you?
My name is Chris. I make stuff, sometimes. By day I'm a software engineer working with C# and unity. I love programming and old technology, I spend my time outside of work learning the ins-and-outs of computers and electronics in general, using C and C++ to mess with native applications and embedded firmware, hoping to one day reclaim the magic of technology from the souless corporate sphere it currently lives in. My name is Chris. I make stuff, sometimes. By day I'm a software engineer working with C# and unity. I love programming and old technology, I spend my time outside of work learning the ins-and-outs of computers and electronics in general, using C and C++ to mess with native applications and embedded firmware, hoping to one day reclaim the magic of technology from the souless corporate sphere it currently lives in.
Some of my hobbies include: Making and enjoying music, motorcycles, game development, light gaming (mostly indie games and older titles), homelabbing, poking at old technology. Some of my hobbies include: Making and enjoying music, motorcycles, game development, light gaming (mostly indie games and older titles), homelabbing, poking at old technology.
@@ -27,6 +27,7 @@ Oh yeah I also run a small company with my wife called Bellsworne. You should [c
### Professional: ### Professional:
- 5+ years of software engineering, primarily in C#/.NET - 5+ years of software engineering, primarily in C#/.NET
- ~2 years of electronics repair (phones, laptops, etc) - ~2 years of electronics repair (phones, laptops, etc)
*I was also a barista for two years, who'uld've thunk it lol* *I was also a barista for two years, who'uld've thunk it lol*
### Personal: ### Personal:

View File

@@ -1,17 +1,143 @@
:root { :root {
--background-color: #1a1a1a; --background-color: #1a1a1a;
--foreground-color: #f5f5f5; --foreground-color: #f0f0ea;
--soft-color: #8a8a82;
--accent-color: #a5453a;
--rule-color: #333330;
--code-bg: #242422;
}
[data-theme="light"] {
--background-color: #f2f0ea;
--foreground-color: #1a1a1a;
--soft-color: #6b6a63;
--accent-color: #8c2e24;
--rule-color: #d8d5cb;
--code-bg: #e8e5da;
} }
* { * {
font-family: 'Times New Roman', Times, serif; font-family: 'Times New Roman', Times, serif;
color: var(--foreground-color); color: var(--foreground-color);
box-sizing: border-box;
} }
body { body {
background-color: var(--background-color); background-color: var(--background-color);
width: 80%; width: 80%;
margin: auto; max-width: 700px;
padding-top: 4%; margin: auto;
font-size: 12pt; padding-top: 4%;
padding-bottom: 6%;
font-size: 12pt;
line-height: 1.6;
}
a {
color: var(--accent-color);
}
a:hover {
text-decoration: none;
}
hr {
border: none;
border-top: 1px solid var(--rule-color);
margin: 2em 0;
}
/* theme toggle */
#theme-toggle {
background: none;
border: 1px solid var(--rule-color);
color: var(--soft-color);
font-size: 10pt;
padding: 0.2em 0.6em;
cursor: pointer;
}
#theme-toggle:hover {
color: var(--accent-color);
border-color: var(--accent-color);
}
/* post lists on the main page */
#posts-section ul,
#sticky-posts-section ul {
list-style: none;
padding: 0;
}
#posts-section li,
#sticky-posts-section li {
margin: 0.5em 0;
}
/* post.html */
.back-link {
display: inline-block;
font-size: 10pt;
color: var(--soft-color);
text-decoration: none;
margin-bottom: 2em;
}
.back-link:hover {
color: var(--accent-color);
}
.meta {
font-size: 10pt;
color: var(--soft-color);
margin: 0 0 1em;
}
#content h1:first-child {
font-size: 1.8em;
margin: 0 0 0.4em;
}
#content h1,
#content h2,
#content h3 {
margin-top: 1.6em;
margin-bottom: 0.5em;
}
#content h2 {
border-bottom: 1px solid var(--rule-color);
padding-bottom: 0.2em;
}
#content p {
margin: 1em 0;
}
#content blockquote {
margin: 1.2em 0;
padding-left: 1em;
border-left: 2px solid var(--accent-color);
color: var(--soft-color);
font-style: italic;
}
#content code {
font-family: Consolas, Menlo, monospace;
font-size: 0.9em;
background: var(--code-bg);
padding: 0.1em 0.35em;
}
#content pre {
background: var(--code-bg);
padding: 1em;
overflow-x: auto;
line-height: 1.5;
}
#content pre code {
background: none;
padding: 0;
}
.state {
color: var(--soft-color);
font-size: 10pt;
}
.state.error {
color: var(--accent-color);
} }