00c3343b1d
- Hugo site for openbureau.ch (Deutsch, i18n-ready for EN/IT) - Theme themes/openbureau/ = local copy of shibui, customized via site-level layouts and assets to keep the theme reference clean - Editorial typography stack: Newsreader serif body, Space Grotesk display, Inter for listings, IBM Plex Mono for technical meta - Content structure: library/ (Theorie, Büroführung, Software) with manifest and colophon at root; software is a library category, not a separate top-level - Three views over one source: Journal (chronological home), Library (atlas grouped by section + tag cloud), single articles Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
61 lines
1.6 KiB
JavaScript
Executable File
61 lines
1.6 KiB
JavaScript
Executable File
(function() {
|
|
if (!window.matchMedia('(pointer: fine)').matches) return;
|
|
|
|
const canvas = document.createElement('canvas');
|
|
canvas.style.cssText = 'position:fixed;pointer-events:none;z-index:9999;image-rendering:pixelated;left:-200px;top:-200px;';
|
|
document.body.appendChild(canvas);
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
const P = 2;
|
|
|
|
const grid = [
|
|
'_BB_______',
|
|
'BRRB______',
|
|
'BRRRB_____',
|
|
'BRRRRB____',
|
|
'BRRRRRB___',
|
|
'BRRRRRRB__',
|
|
'BRRRRRRB__',
|
|
'BRRRRSB___',
|
|
'BRRSRRB___',
|
|
'_BBBRRB___',
|
|
'____BBB___',
|
|
];
|
|
|
|
const rows = grid.length;
|
|
const cols = Math.max(...grid.map(r => r.length));
|
|
canvas.width = cols * P;
|
|
canvas.height = rows * P;
|
|
canvas.style.width = cols * P + 'px';
|
|
canvas.style.height = rows * P + 'px';
|
|
|
|
grid.forEach((row, y) => {
|
|
for (let x = 0; x < row.length; x++) {
|
|
const c = row[x];
|
|
if (c === 'B') { ctx.fillStyle = '#1a1a1a'; ctx.fillRect(x*P, y*P, P, P); }
|
|
else if (c === 'R') { ctx.fillStyle = '#ffffff'; ctx.fillRect(x*P, y*P, P, P); }
|
|
else if (c === 'S') { ctx.fillStyle = '#b0b0b0'; ctx.fillRect(x*P, y*P, P, P); }
|
|
}
|
|
});
|
|
|
|
function setPos(x, y) {
|
|
canvas.style.left = x + 'px';
|
|
canvas.style.top = y + 'px';
|
|
}
|
|
|
|
try {
|
|
const saved = sessionStorage.getItem('cursorPos');
|
|
if (saved) {
|
|
const pos = JSON.parse(saved);
|
|
setPos(pos.x, pos.y);
|
|
}
|
|
} catch(e) {}
|
|
|
|
document.addEventListener('mousemove', e => {
|
|
setPos(e.clientX, e.clientY);
|
|
try {
|
|
sessionStorage.setItem('cursorPos', JSON.stringify({ x: e.clientX, y: e.clientY }));
|
|
} catch(e) {}
|
|
}, { passive: true });
|
|
})();
|