- fallbacks composants + directus.ts passes a Mostuki Photo / Cannes - corrige Contact.astro (PARIS -> CANNES) - seed/token scripts : defauts Mostuki + email corentin.jog@gmail.com - docker-compose dev : conteneurs mostuki-*, email admin, secrets dev - backup.sh : conteneurs par defaut mostuki-* - package.json : name mostuki-photo + description vitrine - .env.example : email admin - DEPLOY.md : retrait des references obsoletes a l ancien branding Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
106 lines
3.5 KiB
JavaScript
106 lines
3.5 KiB
JavaScript
// ===== Dark mode toggle =====
|
|
(function () {
|
|
const KEY = 'lv-theme';
|
|
const root = document.documentElement;
|
|
function apply(theme) {
|
|
if (theme === 'dark') root.setAttribute('data-theme', 'dark');
|
|
else root.removeAttribute('data-theme');
|
|
document.querySelectorAll('.theme-toggle').forEach(b => b.setAttribute('aria-pressed', theme === 'dark'));
|
|
}
|
|
const saved = localStorage.getItem(KEY);
|
|
if (saved) apply(saved);
|
|
document.addEventListener('click', (e) => {
|
|
const btn = e.target.closest('.theme-toggle');
|
|
if (!btn) return;
|
|
const next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
|
|
localStorage.setItem(KEY, next);
|
|
apply(next);
|
|
});
|
|
})();
|
|
|
|
// ===== Boot screen =====
|
|
(function () {
|
|
const boot = document.getElementById('boot');
|
|
if (!boot) return;
|
|
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
if (reduce || sessionStorage.getItem('lv-boot-seen')) {
|
|
boot.remove();
|
|
return;
|
|
}
|
|
const safety = setTimeout(() => { try { boot.remove(); } catch {} }, 6000);
|
|
const target = boot.querySelector('.boot__text');
|
|
const lines = [
|
|
'> initializing mostuki photo studio . . .',
|
|
'> loading typography: JetBrainsMono v2.304 . . . OK',
|
|
'> loading palette: ink #0a0a0a / paper #f4f1eb / accent #5e2ca5 . . . OK',
|
|
'> resolving photographer.heart . . . OK',
|
|
'> serving since 2018 . . . OK',
|
|
'> ready.',
|
|
];
|
|
let i = 0, j = 0, buf = '';
|
|
function step() {
|
|
if (i >= lines.length) {
|
|
setTimeout(() => {
|
|
boot.classList.add('is-done');
|
|
setTimeout(() => { boot.remove(); clearTimeout(safety); }, 600);
|
|
sessionStorage.setItem('lv-boot-seen', '1');
|
|
}, 250);
|
|
return;
|
|
}
|
|
const line = lines[i];
|
|
if (j <= line.length) {
|
|
target.textContent = buf + line.slice(0, j);
|
|
j++;
|
|
setTimeout(step, 12);
|
|
} else {
|
|
buf += line + '\n';
|
|
i++; j = 0;
|
|
setTimeout(step, 90);
|
|
}
|
|
}
|
|
boot.classList.add('is-active');
|
|
step();
|
|
})();
|
|
|
|
// ===== Konami code -> VHS mode toggle =====
|
|
(function () {
|
|
const SEQ = ['ArrowUp','ArrowUp','ArrowDown','ArrowDown','ArrowLeft','ArrowRight','ArrowLeft','ArrowRight','b','a'];
|
|
let i = 0;
|
|
function showBanner(active) {
|
|
let b = document.getElementById('vhs-banner');
|
|
if (!b) {
|
|
b = document.createElement('div');
|
|
b.id = 'vhs-banner';
|
|
b.className = 'vhs-banner';
|
|
b.setAttribute('role', 'status');
|
|
b.setAttribute('aria-live', 'polite');
|
|
document.body.appendChild(b);
|
|
}
|
|
b.textContent = active ? '> VHS MODE ENABLED. PRESS KONAMI AGAIN TO DISABLE.' : '> VHS MODE DISABLED.';
|
|
b.classList.add('is-visible');
|
|
setTimeout(() => b.classList.remove('is-visible'), 3500);
|
|
}
|
|
function toggleVHS() {
|
|
const active = document.body.classList.toggle('vhs-mode');
|
|
const logo = document.querySelector('.logo');
|
|
if (logo) {
|
|
if (active) {
|
|
logo.dataset.original = logo.dataset.original || logo.innerHTML;
|
|
logo.innerHTML = '[ MOSTUKI_v1.4.2-rc.1<span class="cursor" aria-hidden="true">▌</span> ]';
|
|
} else if (logo.dataset.original) {
|
|
logo.innerHTML = logo.dataset.original;
|
|
}
|
|
}
|
|
showBanner(active);
|
|
}
|
|
window.addEventListener('keydown', (e) => {
|
|
const want = SEQ[i];
|
|
const got = e.key.length === 1 ? e.key.toLowerCase() : e.key;
|
|
if (got === want.toLowerCase()) {
|
|
i++;
|
|
if (i === SEQ.length) { toggleVHS(); i = 0; }
|
|
} else {
|
|
i = (got === SEQ[0].toLowerCase()) ? 1 : 0;
|
|
}
|
|
});
|
|
})();
|