feat(tema): tema geçişi logodan piksel piksel yayılır

Sitenin piksel imzasının hareketli hâli: yeni tema header'daki logodan
başlar, kare ızgarası hâlinde dağınık bir ön yüzle ekrana yayılır; her kare
sırası gelince yumuşakça belirir (900 ms, --kt-tema-sure). View Transitions
+ küçük tuvalden üretilen, önbelleklenen maske kareleri; pixelated ile keskin.
Reduced-motion ve desteksiz tarayıcıda düz geçiş. DESIGN §2.3 güncel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-09 00:22:42 +03:00
parent a51724fdcc
commit 83dca068f8
6 changed files with 174 additions and 43 deletions

View File

@@ -477,47 +477,43 @@
background: var(--color-slate-700);
}
/* Tema geçişi (DESIGN.md §2.3, lib/tema-gecisi.ts): tema değişirken tüm
sayfa tek parça crossfade yapar — eski görüntü solar, yeni belirir.
mursela-nextjs'teki tema geçişiyle aynı: 640 ms, ease-in-out. Sınıf
(`kt-tema-gecis`) geçiş süresince <html>'de durur; stil yalnız tema
değişimine uygulanır. Hareket azaltılmışsa JS geçişi hiç başlatmaz,
tema düz değişir. */
/* Tema geçişi (DESIGN.md §2.3, lib/tema-gecisi.ts): yeni tema header'daki
logodan başlar ve ekrana piksel piksel yayılır — sitenin piksel imzasının
hareketli hâli. Eski görüntü yerinde durur; yeni görüntü, JS'in kare kare
bastığı kare ızgarası maskesiyle (--kt-tema-maske, küçük bir tuvalden
üretilir; --kt-tema-en/boy ızgaranın ekrandaki ölçüsü) üstünde açılır.
`pixelated`: küçük maske büyütülürken kareler bulanmaz, keskin kalır.
Sürenin tek kaynağı --kt-tema-sure (JS buradan okur). kt-tema-omur değeri
değişmeyen ama gerçek bir animasyondur: view transition, üzerindeki
animasyon bitene kadar kalkmaz; maskeyi JS sürerken ömrü bu tutar.
Hareket azaltılmışsa JS geçişi hiç başlatmaz, tema düz değişir. */
:root {
--kt-tema-sure: 900ms;
}
.kt-tema-gecis {
view-transition-name: root;
--kt-tema-sure: 640ms;
--kt-tema-egri: cubic-bezier(0.6, 0, 0.2, 1);
}
.kt-tema-gecis::view-transition-old(root),
.kt-tema-gecis::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
will-change: opacity;
backface-visibility: hidden;
}
.kt-tema-gecis::view-transition-group(root) {
animation-duration: var(--kt-tema-sure);
animation-timing-function: var(--kt-tema-egri);
}
.kt-tema-gecis::view-transition-old(root) {
z-index: 1;
animation: kt-tema-cikis var(--kt-tema-sure) var(--kt-tema-egri) both;
}
.kt-tema-gecis::view-transition-new(root) {
z-index: 0;
animation: kt-tema-giris var(--kt-tema-sure) var(--kt-tema-egri) both;
z-index: 2;
mask-image: var(--kt-tema-maske);
mask-repeat: no-repeat;
mask-position: 0 0;
mask-size: var(--kt-tema-en) var(--kt-tema-boy);
image-rendering: pixelated;
animation: kt-tema-omur calc(var(--kt-tema-sure) + 80ms) linear both;
}
@keyframes kt-tema-cikis {
@keyframes kt-tema-omur {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes kt-tema-giris {
from {
opacity: 0;
}
to {
opacity: 1;
}