writinginprogress

Preparing for a theme revamp

Post last updated 2 months ago

The itch hits once again and I'm looking to revamp the theme of this blog. I'll leave all the code for my current theme at the end of the post for posterity. Firstly, some reflections on what I like and don't like about my current theme.

The good

The bad

The future

I want my next theme to be simpler and more coherent. Some nice blogs that inspired me with this are:

So besides simplicity I might have a slight pink obsession.

While the vision is mine, the code is in some parts generated with AI

Home

<h1 style="
  font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;
  font-size: 1.5em;
  line-height: 1.2;
">
hi<br>
buna<br>
willkommen<br>
bienvenue<br>
こんにちは
</h1>

<p>
everyone, you've stumbled upon my refuge on the internet. Here I'm sharing my thoughts, <i>more or less coherently</i> about various topics, from tech to politics and random daily stuff. In my life I've been warned more than once about being insensitive when expressing my thoughts, consider yourself warned. These being said, I do have good intentions. <br>
Have a nice stay! (´• ω •`)
</p>
<div class="theme-controls" role="group" aria-label="Theme settings">
<span aria-hidden="true">◆◆</span>
<button type="button" id="preferdark" class="theme-toggle" data-action="switch-light">ʕ -ᴥ-ʔ</button>
<button type="button" id="preferlight" class="theme-toggle" data-action="switch-dark">ʕ •ᴥ•ʔ</button>
<span class="palette-dropdown" id="light-palette-dropdown">
<button type="button" class="theme-icon" data-action="toggle-palette"></button>
<div class="palette-menu">
<button class="palette-option" data-palette="first">Rose</button>
<button class="palette-option" data-palette="second">Forest</button>
<button class="palette-option" data-palette="third">Ocean</button>
<button class="palette-option" data-palette="fourth">Warmth</button>
<button class="palette-option" data-palette="fifth">Cool</button>
</div>
</span>
<span class="palette-dropdown" id="dark-palette-dropdown">
<button type="button" class="theme-icon" data-action="toggle-palette"></button>
<div class="palette-menu">
<button class="palette-option" data-palette="first">Deep Teal</button>
<button class="palette-option" data-palette="second">Plum Garden</button>
<button class="palette-option" data-palette="third">Ember</button>
<button class="palette-option" data-palette="fourth">Moss</button>
<button class="palette-option" data-palette="fifth">Midnight</button>
<button class="palette-option" data-palette="sixth">Charcoal</button>
</div>
</span>
<span aria-hidden="true">◆◆</span>
</div>

<p class="intro">Read a few words <a href="/about">about myself</a>, my views on <a href="/ai">AI</a>, what I <a href="/use">use</a> or check <a href="/blog">all posts</a><br>You can subscribe to my <a href="/feed">RSS</a> or <a href="mailto:george.bals25@gmail.com">contact me</a></p>
<script>
(function() {
    const html = document.documentElement;
    const getStored = (key, fallback) => localStorage.getItem(key) || fallback;
    
    // Default logic: Force 'dark' and 'sixth' (Charcoal) for new users
    const theme = getStored('theme', 'dark'); 
    html.setAttribute('data-theme', theme);
    
    const defaultPal = (theme === 'dark') ? 'sixth' : 'first';
    html.setAttribute('data-palette', getStored('pal-' + theme, defaultPal));

    function updateUI() {
        const currentPal = html.getAttribute('data-palette');
        document.querySelectorAll('.palette-option').forEach(btn => {
            btn.classList.toggle('active', btn.getAttribute('data-palette') === currentPal);
        });
    }

    document.addEventListener('click', (e) => {
        const target = e.target;
        const action = target.closest('[data-action]')?.getAttribute('data-action');
        const palBtn = target.closest('.palette-option');

        if (action?.startsWith('switch-')) {
            const newMode = action.replace('switch-', '');
            html.setAttribute('data-theme', newMode);
            localStorage.setItem('theme', newMode);
            const savedPal = getStored('pal-' + newMode, (newMode === 'dark' ? 'sixth' : 'first'));
            html.setAttribute('data-palette', savedPal);
            updateUI();
        }

        if (action === 'toggle-palette') {
            e.stopPropagation();
            const menu = target.closest('.palette-dropdown').querySelector('.palette-menu');
            const isShow = menu.classList.contains('show');
            document.querySelectorAll('.palette-menu').forEach(m => m.classList.remove('show'));
            if (!isShow) menu.classList.add('show');
        }

        if (palBtn) {
            const newPal = palBtn.getAttribute('data-palette');
            html.setAttribute('data-palette', newPal);
            localStorage.setItem('pal-' + html.getAttribute('data-theme'), newPal);
            updateUI();
        }

        if (!target.closest('.palette-dropdown')) {
            document.querySelectorAll('.palette-menu').forEach(m => m.classList.remove('show'));
        }
    });

    window.addEventListener('DOMContentLoaded', updateUI);
})();
</script>
<a href="https://www.goeuropean.org/"><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/balssh/buyfromeu.gif" alt="Buy from EU"></a>

CSS

/* 1. FONT & CORE VARIABLES */
 @font-face {
     font-family: 'tt2020';
     src: url('https://bear-images.sfo2.cdn.digitaloceanspaces.com/balssh/tt2020base-regular.woff2') format('woff2');
     font-weight: normal;
     font-style: normal;
     font-display: swap;
}
 :root {
     --font-mono: 'tt2020', monospace;
     --width: 65ch;
     color-scheme: dark;
    /* Default: Charcoal */
     --bg: oklch(17.5% 0.02 339.24);
     --text: oklch(82% 0.04 98);
     --text-dim: oklch(68% 0.03 98);
     --accent: oklch(72% 0.11 34.37);
     --link: oklch(78% 0.10 145);
     --code-bg: oklch(21% 0.02 339);
     --border: oklch(27% 0.02 339);
}
/* --- Light Palettes --- */
html[data-theme="light"][data-palette="first"] {
    --bg: oklch(94% 0.025 290);
    --text: oklch(25% 0.04 290);
    --text-dim: oklch(50% 0.035 290);
    --accent: oklch(68% 0.18 30);      /* Coral sunset against lavender */
    --link: oklch(50% 0.12 140);      /* Fresh lime contrast */
    --code-bg: oklch(90% 0.035 290);
    --border: oklch(86% 0.045 290);
}

html[data-theme="light"][data-palette="second"] {
     --bg: oklch(95% 0.02 145);
     --text: oklch(22% 0.03 145);
  	 --text-dim: oklch(48% 0.03 145); 
     --accent: oklch(55% 0.14 145);
     --link: oklch(42% 0.1 145);
     --code-bg: oklch(91% 0.025 145);
     --border: oklch(87% 0.03 145);
}

html[data-theme="light"][data-palette="third"] {
    --bg: oklch(96% 0.025 195);       /* Shifted toward seafoam/cyan */
    --text: oklch(22% 0.04 195);
    --text-dim: oklch(48% 0.03 195);  /* Added depth */
    --accent: oklch(65% 0.16 20);     /* Salmon/coral - ocean sunset */
    --link: oklch(45% 0.1 265);       /* Deep water blue */
    --code-bg: oklch(92% 0.03 195);
    --border: oklch(88% 0.035 195);
}

html[data-theme="light"][data-palette="fourth"] {
    --bg: oklch(94% 0.025 55);        /* Warm sand */
    --text: oklch(25% 0.04 55);
    --text-dim: oklch(50% 0.035 55);  /* Added depth */
    --accent: oklch(62% 0.18 30);     /* Terracotta/rust */
    --link: oklch(48% 0.1 245);       /* Shadow blue */
    --code-bg: oklch(90% 0.03 55);
    --border: oklch(86% 0.04 55);
}

html[data-theme="light"][data-palette="fifth"] {
    --bg: oklch(94% 0.02 255);        /* Storm slate */
    --text: oklch(20% 0.03 255);
    --text-dim: oklch(45% 0.025 255); /* Added depth */
    --accent: oklch(68% 0.16 55);     /* Lightning amber */
    --link: oklch(50% 0.1 345);       /* Soft magenta */
    --code-bg: oklch(90% 0.02 255);
    --border: oklch(85% 0.03 255);
}
/* --- Dark Palettes --- */
 html[data-theme="dark"][data-palette="first"] {
     --bg: oklch(17% 0.025 215);
     --text: oklch(82% 0.04 210);
     --accent: oklch(70% 0.12 205);
     --link: oklch(76% 0.11 140);
     --code-bg: oklch(21% 0.02 215);
     --border: oklch(27% 0.025 215);
}
 html[data-theme="dark"][data-palette="second"] {
     --bg: oklch(17% 0.02 270);
     --text: oklch(82% 0.04 285);
     --accent: oklch(73% 0.15 300);
     --link: oklch(75% 0.10 80);
     --code-bg: oklch(21% 0.02 270);
     --border: oklch(27% 0.02 270);
}
 html[data-theme="dark"][data-palette="third"] {
     --bg: oklch(17.5% 0.02 15);
     --text: oklch(82% 0.04 50);
     --accent: oklch(74% 0.16 40);
     --link: oklch(74% 0.10 155);
     --code-bg: oklch(21% 0.02 20);
     --border: oklch(27% 0.02 20);
}
 html[data-theme="dark"][data-palette="fourth"] {
     --bg: oklch(17% 0.02 140);
     --text: oklch(82% 0.04 135);
     --accent: oklch(72% 0.14 80);
     --link: oklch(76% 0.10 30);
     --code-bg: oklch(21% 0.02 140);
     --border: oklch(27% 0.02 140);
}
 html[data-theme="dark"][data-palette="fifth"] {
     --bg: oklch(14% 0.015 250);
     --text: oklch(85% 0.05 55);
     --accent: oklch(75% 0.18 315);
     --link: oklch(78% 0.12 185);
     --code-bg: oklch(19% 0.015 250);
     --border: oklch(25% 0.015 250);
}
 html[data-theme="dark"][data-palette="sixth"] {
     --bg: oklch(17.5% 0.02 339.24);
     --text: oklch(82% 0.04 98);
     --accent: oklch(72% 0.11 34.37);
     --link: oklch(78% 0.10 145);
     --code-bg: oklch(21% 0.02 339);
     --border: oklch(27% 0.02 339);
}
/* 2. GLOBAL LAYOUT & MOBILE FIXES */
 *, *::before, *::after {
     transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
     box-sizing: border-box;
}
 html {
     background-color: var(--bg);
     height: 100%;
     scrollbar-gutter: stable;
}
 body {
     font-family: var(--font-mono);
   	 font-weight: 600;
     font-size: 1.3rem;
     line-height: 1.5;
     margin: 0;
     padding: 20px;
     min-height: 100vh;
     background-color: var(--bg);
     color: var(--text);
     text-align: justify;
}
/* Images & Directive Gif */
 img {
     max-width: 100%;
     height: auto;
     display: block;
     margin: 1.5rem auto;
     border-radius: 4px;
}
 #footer-directive img {
     display: inline-block;
     margin: 0 auto;
     max-width: 180px;
     height: auto;
     border: 1px solid var(--border);
     padding: 4px;
     background: var(--code-bg);
}
/* Desktop Grid */
 @media screen and (min-width: 992px) {
     body {
         display: grid;
         margin: 0 auto;
         max-width: 1400px;
         grid-template-columns: 1fr var(--width) 25ch 0.5fr;
         grid-template-rows: auto auto 1fr;
         grid-template-areas: 
           ". main header ." 
           ". main footer ." 
           ". main . .";
         justify-items: start;
         column-gap: 40px;
         padding: 60px 40px;
    }
     header {
         grid-area: header;
         border-left: 5px solid color-mix(in oklch, var(--accent), transparent 50%);
         padding: 0 0 5px 1.2rem;
         align-self: start;
    }
     footer {
         grid-area: footer;
         padding: 0 1.2rem !important;
    }
     #footer-directive img {
         margin: 0;
    }
     main {
         grid-area: main;
         width: 100%;
         max-width: var(--width);
         margin: 0 auto;
    }
}
/* 3. TYPOGRAPHY & IFRAMES */
 h1, h2, h3 {
     color: var(--accent);
     font-weight: 700;
     margin-top: 0;
}
 a {
     color: var(--link);
     text-decoration: none;
}
 a:hover {
     color: var(--accent);
     text-decoration: underline;
}
 hr {
     border: 0;
     border-top: 1px dashed var(--border);
     margin: 2rem 0;
}
 code {
     font-family: monospace;
     padding: 2px 5px;
     background-color: var(--code-bg);
     border-radius: 3px;
     color: var(--link);
}
 blockquote {
     border-left: 2px solid var(--accent);
     color: var(--text-dim);
     padding-left: 20px;
     font-style: italic;
     margin: 1.5rem 0;
}
 .embed-container {
     width: 100%;
     margin: 1.5rem 0;
}
 iframe {
     border: 1px solid var(--border);
     border-radius: 8px;
     filter: grayscale(0.2) contrast(0.9);
     transition: all 0.3s ease;
}
 iframe:hover {
     filter: grayscale(0) contrast(1);
     border-color: var(--accent);
}
/* 4. POST LIST (Fixed Mobile Spacing) */
 ul.blog-posts {
     list-style: none;
     padding: 0;
}
 ul.blog-posts > li {
     display: flex;
     flex-direction: row-reverse;
     justify-content: space-between;
     align-items: baseline;
     padding: 0.6em 0;
     border-bottom: 1px solid var(--border);
     gap: 1rem;
}
 ul.blog-posts a {
     color: var(--text);
}
 ul.blog-posts a:hover {
     color: var(--link);
     padding-left: 4px;
}
 @media screen and (max-width: 600px) {
     ul.blog-posts > li {
         flex-direction: column;
         align-items: flex-start;
         gap: 0.2rem;
    }
}
/* 5. YOUR CUSTOM UPVOTE BUTTONS (Restored) */
 .upvote-button svg {
     display: none;
}
 .upvote-button {
     flex-direction: row !important;
     gap: .75em;
     cursor: pointer;
     background: transparent;
     border: none;
     padding: 0;
     display: flex;
}
 .upvote-button::before {
     content: 'ʕ ꈍᴥꈍʔ';
     font-family: var(--font-mono);
     font-size: 0.9rem;
     border: 1px solid var(--border);
     border-radius: .5em;
     padding: 0.3em 0.8em;
     background-color: var(--code-bg);
     color: var(--text);
     transition: all 0.2s ease;
}
 .upvote-button:hover::before {
     content: 'ʕ•ᴥ•ʔノ♡';
     background-color: var(--link);
     color: var(--bg);
     border-color: var(--link);
}
 .upvote-button[disabled]::before {
     content: 'ʕ≧ᴥ≦ʔ';
     background-color: transparent;
     border: 1px dashed var(--border);
     color: var(--text-dim);
}
 .upvote-count {
     margin: 0;
     color: var(--text-dim);
     font-size: 0.9rem;
}
 .upvote-count::after {
     content: ' ♡';
}
/* 6. UI CONTROLS */
 .theme-controls {
     display: flex;
     align-items: center;
     gap: 12px;
     margin: 1rem 0;
     font-size: 0.95rem;
     color: var(--text-dim);
     position: relative;
}
 #preferlight, #preferdark, .palette-dropdown {
     display: none;
}
 html[data-theme="light"] #preferlight, html[data-theme="light"] #light-palette-dropdown {
     display: inline-flex;
}
 html[data-theme="dark"] #preferdark, html[data-theme="dark"] #dark-palette-dropdown {
     display: inline-flex;
}
 .theme-toggle {
     cursor: pointer;
     font-size: 1.2rem;
     padding: 0.2rem;
     background: none;
     border: 1px solid transparent;
     border-radius: 4px;
     color: var(--text-dim);
}
 .theme-toggle:hover {
     color: var(--accent);
     background: var(--code-bg);
     border-color: var(--border);
}
 .theme-icon {
     cursor: pointer;
     font-size: 1.4rem;
     padding: 0.2rem;
     background: none;
     border: 1px solid transparent;
     border-radius: 4px;
     color: var(--text-dim);
}
 .theme-icon:hover {
     color: var(--accent);
     background: var(--code-bg);
     border-color: var(--border);
}
 .palette-menu {
     display: none;
     position: absolute;
     top: 100%;
     left: 50%;
     transform: translateX(-50%);
     background-color: var(--code-bg);
     border: 1px solid var(--border);
     border-radius: 4px;
     box-shadow: 0 4px 12px rgba(0,0,0,0.4);
     z-index: 100;
     min-width: 150px;
}
 .palette-menu.show {
     display: flex;
     flex-direction: column;
}
 .palette-option {
     padding: 0.5rem;
     font-family: var(--font-mono);
     color: var(--text);
     background: none;
     border: none;
     cursor: pointer;
     text-align: center;
}
 .palette-option:hover {
     background-color: var(--accent);
     color: var(--bg);
}
 .palette-option.active {
     background-color: var(--link);
     color: var(--bg);
}
/* 7. CODE BLOCKS */
.highlight {
     background-color: var(--code-bg);
     border: 1px solid var(--border);
     border-radius: 8px;
     margin: 1.5rem 0;
     padding: 1.2rem;
     overflow-x: auto; /* Keeps long code lines from breaking the layout */
     font-family: var(--font-mono);
     font-size: 0.85em; /* Scales nicely against your 1.3rem body size */
     color: var(--text);
     box-shadow: inset 0 2px 4px rgb(0 0 0 / 5%);
     scrollbar-color: var(--border) transparent; /* For Firefox */
}

/* Reset the `<pre>` tag often generated by markdown parsers */
.highlight pre {
     margin: 0;
     padding: 0;
     background: transparent;
     border: none;
}

/* Override your inline `code` rule so the whole block isn't your --link color */
.highlight code {
     background-color: transparent;
     padding: 0;
     color: inherit;
     border-radius: 0;
     font-family: inherit;
     font-size: inherit;
     white-space: pre; /* Preserves formatting */
}

/* Custom Webkit scrollbars so the scrollable code blocks match the theme */
.highlight::-webkit-scrollbar {
     height: 8px;
}
.highlight::-webkit-scrollbar-track {
     background: transparent;
     border-radius: 0 0 8px 8px;
}
.highlight::-webkit-scrollbar-thumb {
     background-color: var(--border);
     border-radius: 4px;
}
.highlight::-webkit-scrollbar-thumb:hover {
     background-color: var(--accent);
}

You can reach out by sending me an email.


  1. The color combinations were chosen based on my very vague ramblings about what colors I think I'd like to use and her actual good eyes.

#blog #tinkering