Something went wrong. Try again.
A warm, tech-dystopian color scheme inspired by corrupted hardware and failing systems. digitalrust.katsuricata.com
theme color-scheme color-theme warm color
Something went wrong. Try again.
5.7 kB · 258 lines
Svelte
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259<script lang="ts"> const images = [ { thumb: '/digitalrustt.webp', full: '/digitalrust.webp', alt: 'VS Code window using Digital Rust theme with Rust sample code open' }, { thumb: '/digitalrust2t.webp', full: '/digitalrust2.webp', alt: 'Linux desktop with Digital Rust wallpaper and terminal window running theme audit' }, { thumb: '/digitalrust3t.webp', full: '/digitalrust3.webp', alt: 'KDE color scheme editor window displaying the Digital Rust theme palette with preview swatches for UI elements' }, { thumb: '/digitalrust4t.webp', full: '/digitalrust4.webp', alt: 'Linux desktop terminal using the Digital Rust, showing a fastfetch system overview with hardware specs and ASCII logo' } ];
let lightbox: HTMLDialogElement; let current = $state(0);
function show(index: number) { current = (index + images.length) % images.length; }
function open(index: number) { show(index); lightbox.showModal(); }</script>
<section aria-labelledby="preview-heading" class="preview-section"> <h2 id="preview-heading" class="section-title">Theme Preview</h2> <div class="preview-grid"> {#each images as image, i (image.full)} <button type="button" class="preview-button" onclick={() => open(i)}> <img src={image.thumb} alt={image.alt} class="preview-img" loading="lazy" decoding="async" /> </button> {/each} </div></section>
<dialog bind:this={lightbox} class="lightbox" aria-label="Image lightbox" onclick={(event) => event.target === lightbox && lightbox.close()} onkeydown={(event) => { if (event.key === 'ArrowLeft') show(current - 1); if (event.key === 'ArrowRight') show(current + 1); }}> <button class="lightbox-close" aria-label="Close lightbox" onclick={() => lightbox.close()}> CLOSE </button> <button class="lightbox-nav lightbox-prev" aria-label="Previous image" onclick={() => show(current - 1)}>PREV</button > <button class="lightbox-nav lightbox-next" aria-label="Next image" onclick={() => show(current + 1)}>NEXT</button > <img src={images[current].full} alt={images[current].alt} class="lightbox-img" /></dialog>
<style> .preview-section { margin-top: var(--dr-space-2xl); }
.preview-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: var(--dr-space-lg); }
.preview-button { display: block; width: 100%; padding: 0; border: none; background: none; cursor: pointer; }
.preview-img { width: 100%; height: auto; aspect-ratio: 16/10; object-fit: cover; border-radius: var(--dr-radius); border: var(--dr-border); box-shadow: var(--dr-shadow-offset-md), var(--dr-shadow-inner-highlight); transition: transform var(--dr-transition-fast), box-shadow var(--dr-transition-fast), border-color var(--dr-transition-fast); cursor: pointer; background: var(--dr-surface-base); }
.preview-img:hover { transform: translate(-2px, -2px); border-color: var(--dr-accent); box-shadow: var(--dr-shadow-hover-md), var(--dr-shadow-glow-sm); }
.preview-img:active { transform: translate(2px, 2px); box-shadow: var(--dr-shadow-active); }
.lightbox { background: var(--event-horizon-95); border: none; padding: 0; max-width: 100vw; max-height: 100vh; overflow: hidden; }
.lightbox::backdrop { background: var(--event-horizon-95); }
.lightbox[open] { display: flex; align-items: center; justify-content: center; width: 100vw; height: 100vh; }
.lightbox-img { max-width: 85vw; max-height: 85vh; object-fit: contain; background-color: var(--dr-surface-base); border: var(--dr-border); box-shadow: var(--dr-shadow-offset-lg), var(--dr-shadow-glow-md); }
.lightbox-close, .lightbox-nav { position: fixed; font-family: var(--dr-font-heading); font-size: var(--dr-text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; border: var(--dr-border); background: var(--dr-surface-elevated); color: var(--dr-text-primary); cursor: pointer; box-shadow: var(--dr-shadow-offset-sm); transition: transform var(--dr-transition-fast), box-shadow var(--dr-transition-fast), background var(--dr-transition-fast); z-index: 1001; }
.lightbox-close:hover, .lightbox-nav:hover { box-shadow: var(--dr-shadow-hover-md); background: var(--dr-surface-highlight); }
.lightbox-close:active, .lightbox-nav:active { box-shadow: var(--dr-shadow-active); }
.lightbox-close { top: 1rem; right: 1rem; padding: var(--dr-space-sm) var(--dr-space-md); border-radius: var(--dr-radius); }
.lightbox-close:hover { transform: translate(-2px, -2px); }
.lightbox-close:active { transform: translate(2px, 2px); }
.lightbox-prev { left: 1rem; top: 50%; transform: translateY(-50%); padding: var(--dr-space-md) var(--dr-space-sm); border-radius: var(--dr-radius); }
.lightbox-prev:hover { transform: translate(-2px, calc(-50% - 2px)); }
.lightbox-prev:active { transform: translate(2px, calc(-50% + 2px)); }
.lightbox-next { right: 1rem; top: 50%; transform: translateY(-50%); padding: var(--dr-space-md) var(--dr-space-sm); border-radius: var(--dr-radius); }
.lightbox-next:hover { transform: translate(-2px, calc(-50% - 2px)); }
.lightbox-next:active { transform: translate(2px, calc(-50% + 2px)); }
@media (max-width: 768px) { .lightbox { padding: 0; }
.lightbox-img { max-height: 80vh; max-width: 90vw; padding: 0; }
.lightbox-prev, .lightbox-next { display: none; } }
@media (prefers-reduced-motion: reduce) { .lightbox { animation: none; } }</style>