Teemavalitsin: painike kiertää gecko/forge/serpent, oletus forge

- Teemapainike (emoji) oikeaan yläkulmaan kuten kipina.tech:ssä
- Oletus forge (syaani), tallennetaan localStorage:iin
- Hero-kuva vaihtuu teeman mukaan fade-efektillä
- Kolme hero-kuvaa: gecko_hero, forge_hero (hämähäkki), serpent_hero
This commit is contained in:
2026-04-13 14:29:14 +03:00
parent 3a00de9b8e
commit 66b4435362
4 changed files with 49 additions and 4 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -32,6 +32,7 @@ import Settings from "../components/Settings.astro";
<div class="bg-mesh"></div> <div class="bg-mesh"></div>
<header class="landing-nav"> <header class="landing-nav">
<a href="/" class="landing-logo"><span class="logo-accent">KIPINÄ</span> <span class="logo-sub">/ agentic studio</span></a> <a href="/" class="landing-logo"><span class="logo-accent">KIPINÄ</span> <span class="logo-sub">/ agentic studio</span></a>
<button id="theme-cycle-btn" class="theme-cycle-btn" title="Vaihda teemaa"></button>
</header> </header>
<section class="hero"> <section class="hero">
@@ -136,11 +137,18 @@ import Settings from "../components/Settings.astro";
</div> </div>
<script is:inline> <script is:inline>
// === Teeman satunnaisvalinta (gecko/forge/serpent) === // === Teemajärjestelmä (gecko/forge/serpent) — oletus forge ===
const KS_THEMES = [
{ id: 'gecko', icon: '\u{1F98E}' },
{ id: 'forge', icon: '\u{2699}\u{FE0F}' },
{ id: 'serpent', icon: '\u{1F40D}' }
];
const KS_DEFAULT = 'forge';
(function() { (function() {
const themes = ['gecko', 'forge', 'serpent']; let saved = KS_DEFAULT;
const theme = themes[Math.floor(Math.random() * themes.length)]; try { saved = localStorage.getItem('kipina-studio-theme') || KS_DEFAULT; } catch(_){}
document.documentElement.setAttribute('data-theme', theme); if (!KS_THEMES.find(t => t.id === saved)) saved = KS_DEFAULT;
document.documentElement.setAttribute('data-theme', saved);
})(); })();
// === Helpers === // === Helpers ===
@@ -149,6 +157,32 @@ import Settings from "../components/Settings.astro";
d.style.display = d.style.display === 'none' ? 'block' : 'none'; d.style.display = d.style.display === 'none' ? 'block' : 'none';
}; };
// === Teemapainike: kierrätys + hero-kuvan vaihto ===
(function() {
const btn = document.getElementById('theme-cycle-btn');
const heroImg = document.querySelector('.hero-orb-img');
function currentTheme() { return document.documentElement.getAttribute('data-theme') || KS_DEFAULT; }
function applyTheme(themeId) {
document.documentElement.setAttribute('data-theme', themeId);
const t = KS_THEMES.find(x => x.id === themeId) || KS_THEMES[1];
if (btn) btn.textContent = t.icon;
if (heroImg) {
heroImg.style.opacity = '0';
setTimeout(() => { heroImg.src = '/' + themeId + '_hero.webp'; heroImg.style.opacity = '1'; }, 200);
}
try { localStorage.setItem('kipina-studio-theme', themeId); } catch(_){}
}
// Alkuasetus
applyTheme(currentTheme());
// Klikkaus kiertää seuraavaan
if (btn) btn.addEventListener('click', () => {
const cur = currentTheme();
const idx = KS_THEMES.findIndex(t => t.id === cur);
const next = KS_THEMES[(idx + 1) % KS_THEMES.length];
applyTheme(next.id);
});
})();
function esc(str) { function esc(str) {
if (!str) return ''; if (!str) return '';
return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');

View File

@@ -290,10 +290,20 @@ body {
.landing-nav { .landing-nav {
padding: 20px 40px; padding: 20px 40px;
display: flex; align-items: center; justify-content: space-between;
} }
.landing-logo { text-decoration: none; font-size: 18px; font-weight: 700; } .landing-logo { text-decoration: none; font-size: 18px; font-weight: 700; }
.logo-accent { color: var(--hero-accent); } .logo-accent { color: var(--hero-accent); }
.logo-sub { color: #8b949e; font-weight: 400; } .logo-sub { color: #8b949e; font-weight: 400; }
.theme-cycle-btn {
background: none; border: 1px solid var(--border); border-radius: 8px;
width: 38px; height: 38px; font-size: 20px; cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: border-color 0.2s, transform 0.15s;
}
.theme-cycle-btn:hover {
border-color: var(--hero-accent); transform: scale(1.1);
}
/* Hero */ /* Hero */
.hero { .hero {
@@ -380,6 +390,7 @@ body {
.hero-orb-img { .hero-orb-img {
width: 100%; height: 100%; object-fit: contain; width: 100%; height: 100%; object-fit: contain;
filter: drop-shadow(0 0 40px var(--hero-glow)); filter: drop-shadow(0 0 40px var(--hero-glow));
transition: opacity 0.2s ease;
} }
@keyframes orb-float { @keyframes orb-float {
0%, 100% { transform: translateY(0); } 0%, 100% { transform: translateY(0); }