// Shared tokens, placeholders, and bits used across all three variations. const SN_PALETTE = { dirt: '#7B5A3A', dirtDark: '#5A4229', dirtLight: '#A07A4F', grass: '#6B8E3D', grassDark: '#4E6B28', grassLight: '#8FB05A', stone: '#8A8A8A', stoneDark: '#5F5F5F', stoneLight: '#B5B5B5', parchment: '#F3ECDC', parchmentDark: '#E4D9BD', ink: '#1F1A14', linkBlue: '#0000EE', linkVisited: '#551A8B', }; // Tiled block background as an SVG data URI — 32x32 tile. // Slight per-cell variation to avoid grid pattern readability. function tiledBlockBg(top, mid, dark, size = 32) { const svg = ` `; return `url("data:image/svg+xml;utf8,${encodeURIComponent(svg)}")`; } // A "grass top" strip bg — darker dirt below a lighter grass cap. function grassTopBg() { const svg = ` `; return `url("data:image/svg+xml;utf8,${encodeURIComponent(svg)}")`; } // Diagonal-stripe placeholder SVG w/ a mono label centered. function StripedPlaceholder({ w = 320, h = 180, label = 'screenshot', tone = 'dirt' }) { const stroke = tone === 'stone' ? '#6a6a6a' : tone === 'grass' ? '#4E6B28' : '#5A4229'; const fill = tone === 'stone' ? '#c5c5c2' : tone === 'grass' ? '#a8c073' : '#cdb48a'; const fg = tone === 'stone' ? '#2a2a2a' : '#2a1f12'; const svg = ( {label} ); return svg; } // Tiny pixel logo: spells "SN" in blocks. Uses a grid of colored pixels. function PixelLogoSN({ scale = 6, top = SN_PALETTE.grass, side = SN_PALETTE.grassDark, base = SN_PALETTE.dirt, shadow = SN_PALETTE.dirtDark }) { // 2-color block lettering on a 15x7 grid. S then N. const S = [ '.###.', '#....', '#....', '.##..', '...#.', '....#', '###..', ]; const N = [ '#...#', '##..#', '#.#.#', '#..##', '#...#', '#...#', '#...#', ]; const rows = 7, cols = 11; // 5 + 1 gap + 5 const grid = []; for (let r = 0; r < rows; r++) { let line = ''; for (let c = 0; c < 5; c++) line += S[r][c]; line += '.'; for (let c = 0; c < 5; c++) line += N[r][c]; grid.push(line); } return (
{grid.map((row, r) => (
{row.split('').map((ch, c) => { const on = ch === '#'; const bg = on ? (r === 0 ? top : r === rows - 1 ? shadow : side) : 'transparent'; return
; })}
))}
); } // A rendered 3D-ish isometric "grass block" drawn with CSS/SVG pixels. function PixelGrassBlock({ size = 64 }) { const p = size / 16; const svg = ` `; return grass block; } // A simple day/night toggle — pixel sun/moon with 2 states. function DayNightToggle({ night, onToggle, scale = 3 }) { // 12x12 pixel sun/moon const sun = [ '....####....', '...#....#...', '..#......#..', '.#........#.', '#..........#', '#..........#', '#..........#', '#..........#', '.#........#.', '..#......#..', '...#....#...', '....####....', ]; const moon = [ '....####....', '...#....#...', '..#..##...#.', '.#..####..#.', '#..####....#', '#..####....#', '#..####....#', '#..####....#', '.#..####..#.', '..#..##...#.', '...#....#...', '....####....', ]; const art = night ? moon : sun; const fill = night ? '#e6e2c7' : '#e8c24a'; const stroke = night ? '#7a7560' : '#8a6a1e'; return ( ); } // Pixel cursor trail — spawns small colored squares that fade. // Activated inside a container via onMouseMove. function useCursorTrail(containerRef, { enabled = true, color = '#6B8E3D' } = {}) { React.useEffect(() => { if (!enabled) return; const el = containerRef.current; if (!el) return; let last = 0; const onMove = (e) => { const now = performance.now(); if (now - last < 28) return; last = now; const r = el.getBoundingClientRect(); const x = e.clientX - r.left; const y = e.clientY - r.top; const dot = document.createElement('div'); dot.style.position = 'absolute'; dot.style.left = (x - 3) + 'px'; dot.style.top = (y - 3) + 'px'; dot.style.width = '6px'; dot.style.height = '6px'; dot.style.background = color; dot.style.pointerEvents = 'none'; dot.style.opacity = '1'; dot.style.transition = 'opacity 600ms linear, transform 600ms linear'; dot.style.zIndex = '999'; el.appendChild(dot); requestAnimationFrame(() => { dot.style.opacity = '0'; dot.style.transform = `translate(${(Math.random()-0.5)*6}px, ${6 + Math.random()*8}px)`; }); setTimeout(() => { dot.remove(); }, 650); }; el.addEventListener('mousemove', onMove); return () => el.removeEventListener('mousemove', onMove); }, [containerRef, enabled, color]); } Object.assign(window, { SN_PALETTE, tiledBlockBg, grassTopBg, StripedPlaceholder, PixelLogoSN, PixelGrassBlock, DayNightToggle, useCursorTrail, });