Files
kolaytercih/src/app/globals.css
bilalgursen 52f565ea4a feat(ui): 11 Ekim gece işi — program ayrıntıda açılan gösterge kareleri, veri akışı sahnesi, haritada kenar eritme
- program-ayrinti: kontenjan türleri, netler ve mezun istihdamı kapalıyken
  gösterge karesi; dokununca kare panele dönüşüp bölümün tamamını açar.
  Kontenjan türü satırlarına "kime açık" alt satırı (KONTENJAN_TURU_KIME).
- veri-akisi: üstte öğrencinin üç seçimi, altta YÖK Atlas'ın üç verisi,
  ortada DanışmanlaKonuş çekirdeği; kayıtlar kıvrımlı yollardan çekirdeğe
  akar (kt-akis-* kuralları globals.css'te).
- tercih-haritasi: il'e yakınlaşınca kenarlar iki katlı mask'la erir; tam
  görünümde mask yok, ülke uçları solmaz.
- DESIGN.md: ilgili bölümler güncellendi (§4.19, §4.28).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:30:59 +03:00

1024 lines
29 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-clarity-city);
--font-mono: var(--font-geist-mono);
--font-heading: var(--font-cal-sans);
--font-bricolage: var(--font-bricolage-grotesque);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--radius-sm: calc(var(--radius) * 0.6);
--radius-md: calc(var(--radius) * 0.8);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.4);
--radius-2xl: calc(var(--radius) * 1.8);
--radius-3xl: calc(var(--radius) * 2.2);
--radius-4xl: calc(var(--radius) * 2.6);
}
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.623 0.188 259.8);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.623 0.188 259.8 / 60%);
--chart-1: oklch(0.87 0 0);
--chart-2: oklch(0.556 0 0);
--chart-3: oklch(0.439 0 0);
--chart-4: oklch(0.371 0 0);
--chart-5: oklch(0.269 0 0);
--radius: 0.625rem;
/* Hareket eğrileri (DESIGN.md §6); JS karşılığı src/lib/hareket.ts EGRI */
--egri-giris: cubic-bezier(0.16, 1, 0.3, 1);
--egri-standart: cubic-bezier(0.22, 1, 0.36, 1);
--egri-guclu-cikis: cubic-bezier(0.23, 1, 0.32, 1);
--egri-yerlesme: cubic-bezier(0.32, 0.72, 0, 1);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
/* Harita il zeminleri (tercih-haritasi, yurtdisi-haritalar) */
--kt-harita-secili: oklch(0.97 0.014 254.6); /* blue-50 */
--kt-harita-dolu: oklch(0.882 0.059 254.1); /* blue-200 */
}
/* Karanlık mod (DESIGN.md §2.3). Bileşenlere `dark:` sınıfı yazılmaz; tema
palet token'larını çevirerek çalışır: slate ölçeği ters döner (50 = sayfa
zemini, 900 = başlık metni), yüzeyler `bg-card`'dan gelir, renkli açık
zeminler (orange-50, amber-50…) koyu tona, koyu renkli metinler (amber-900,
emerald-800…) açık tona iner. `text-white` ve dolu marka zeminleri
(orange-500, primary, emerald-500…) iki temada aynıdır.
`@media screen`: yazdırma çıktısı tema ne olursa olsun açık kalır. */
@media screen {
.dark {
--background: oklch(0.21 0.03 262);
--foreground: oklch(0.95 0.008 250);
--card: oklch(0.21 0.03 262);
--card-foreground: oklch(0.95 0.008 250);
--popover: oklch(0.21 0.03 262);
--popover-foreground: oklch(0.95 0.008 250);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.26 0.03 262);
--secondary-foreground: oklch(0.95 0.008 250);
--muted: oklch(0.26 0.03 262);
--muted-foreground: oklch(0.68 0.04 257);
--accent: oklch(0.26 0.03 262);
--accent-foreground: oklch(0.95 0.008 250);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(0.31 0.03 260);
--input: oklch(0.31 0.03 260);
--sidebar: oklch(0.21 0.03 262);
--sidebar-foreground: oklch(0.95 0.008 250);
--sidebar-primary: oklch(0.623 0.188 259.8);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.26 0.03 262);
--sidebar-accent-foreground: oklch(0.95 0.008 250);
--sidebar-border: oklch(0.31 0.03 260);
--sidebar-ring: oklch(0.556 0 0);
/* Nötr ölçek: ters çevrilmiş slate. 950 çevrilmez — koyu vurgu
yüzeyinin (kt-koyu-yuzey) zeminidir, iki temada koyu kalır. */
--color-slate-50: oklch(0.165 0.025 262);
--color-slate-100: oklch(0.26 0.03 262);
--color-slate-200: oklch(0.31 0.03 260);
--color-slate-300: oklch(0.4 0.035 258);
--color-slate-400: oklch(0.6 0.04 257);
--color-slate-500: oklch(0.68 0.04 257);
--color-slate-600: oklch(0.76 0.035 256);
--color-slate-700: oklch(0.83 0.025 255);
--color-slate-800: oklch(0.89 0.015 255);
--color-slate-900: oklch(0.95 0.008 250);
/* Renkli açık zeminler ve kenarlıklar → koyu ton */
--color-orange-50: oklch(0.27 0.05 50);
--color-orange-100: oklch(0.32 0.07 50);
--color-orange-200: oklch(0.45 0.1 48);
--color-amber-50: oklch(0.27 0.045 80);
--color-amber-100: oklch(0.32 0.06 80);
--color-amber-200: oklch(0.45 0.09 78);
--color-emerald-50: oklch(0.26 0.04 165);
--color-emerald-100: oklch(0.31 0.055 165);
--color-emerald-200: oklch(0.42 0.08 165);
--color-red-50: oklch(0.26 0.05 25);
--color-red-100: oklch(0.31 0.07 25);
--color-red-200: oklch(0.42 0.1 25);
--color-rose-50: oklch(0.26 0.05 12);
--color-rose-100: oklch(0.31 0.07 12);
--color-sky-50: oklch(0.26 0.04 235);
--color-sky-100: oklch(0.31 0.055 235);
--color-sky-200: oklch(0.42 0.07 235);
--color-violet-50: oklch(0.27 0.05 293);
/* Koyu renkli metinler → açık ton (koyu zeminde okunsun) */
--color-orange-700: oklch(0.8 0.13 55);
--color-amber-700: oklch(0.84 0.13 85);
--color-amber-800: oklch(0.88 0.11 88);
--color-amber-900: oklch(0.92 0.08 90);
--color-emerald-600: oklch(0.74 0.15 163);
--color-emerald-700: oklch(0.8 0.13 163);
--color-emerald-800: oklch(0.86 0.11 164);
--color-emerald-900: oklch(0.91 0.08 165);
--color-red-600: oklch(0.7 0.19 24);
--color-red-700: oklch(0.77 0.15 22);
--color-red-800: oklch(0.84 0.11 20);
--color-red-900: oklch(0.9 0.07 18);
--color-rose-700: oklch(0.8 0.12 12);
--color-rose-800: oklch(0.86 0.09 10);
--color-sky-600: oklch(0.74 0.13 235);
--kt-harita-secili: oklch(0.27 0.05 258);
--kt-harita-dolu: oklch(0.42 0.1 258);
}
/* Koyu vurgu yüzeyi (CTA bandı, arama funnel kartı): zemini slate-950,
içindeki açık slate metinler iki temada aynı kalsın diye ölçek burada
açık temadaki değerlerine geri döner. */
.dark .kt-koyu-yuzey {
--color-slate-50: oklch(0.984 0.003 247.858);
--color-slate-100: oklch(0.968 0.007 247.896);
--color-slate-200: oklch(0.929 0.013 255.508);
--color-slate-300: oklch(0.869 0.022 252.894);
--color-slate-400: oklch(0.704 0.04 256.788);
--color-slate-500: oklch(0.554 0.046 257.417);
--color-slate-600: oklch(0.446 0.043 257.281);
--color-slate-700: oklch(0.372 0.044 257.287);
--color-slate-800: oklch(0.279 0.041 260.031);
--color-slate-900: oklch(0.208 0.042 265.755);
}
/* El çizimi şemalar (mermaid) açık kâğıt için çizilir: düğüm renkleri
tanımın içinde sabit. Koyu temada şema beyaz bir kâğıdın üstünde durur. */
.dark .kt-sema-kagit {
padding: 0.75rem;
border-radius: 1rem;
background: #fff;
}
/* Tek renk koyu logolar (URAP): koyu temada açığa çevrilir; yerleşim
oynamaz. Çok renkli marka logolarında kullanılmaz (renk bozulur). */
.dark .kt-koyu-cevir {
filter: invert(1) hue-rotate(180deg);
}
/* Çok renkli, koyu metinli logo görselleri (iyzico bandı: kart markaları)
beyaz hap üstünde durur. */
.dark .kt-acik-logo {
box-sizing: content-box;
padding: 0.5rem 0.875rem;
border-radius: 0.75rem;
background: #fff;
}
}
/* TypingAnimation imleci (animate-blink-cursor utility'si) */
@theme {
--animate-blink-cursor: blink-cursor 1s step-end infinite;
@keyframes blink-cursor {
50% {
opacity: 0;
}
}
}
/* Rozet (PixelMark) pikselleri: sırayla turuncuya ısınır, iz gibi yavaşça söner.
Zamanlama ısı fırçasıyla aynı dili konuşur: ani ısınma (%8), uzun soğuma (%66). */
@theme {
--animate-pixel-isi: pixel-isi 2.4s ease-in-out infinite;
--animate-pixel-isi-accent: pixel-isi-accent 2.4s ease-in-out infinite;
@keyframes pixel-isi {
0%,
66%,
100% {
fill: currentColor;
fill-opacity: var(--px-op, 0.3);
}
8% {
fill: var(--color-orange-500);
fill-opacity: 0.85;
}
}
@keyframes pixel-isi-accent {
0%,
66%,
100% {
fill-opacity: 0.55;
}
8% {
fill-opacity: 1;
}
}
}
/* Ödeme dönüşünde kilidi açılan listenin blur çözülme animasyonu */
@keyframes kt-unblur {
from {
filter: blur(12px);
opacity: 0.4;
}
to {
filter: blur(0);
opacity: 1;
}
}
.kt-unblur {
animation: kt-unblur 0.9s ease-out both;
}
/* Hareket azaltılmışsa blur çözülmesi yerine kısa, yumuşak bir belirme:
kavramayı sağlayan geri bildirim kalır, gösterişli efekt düşer. */
@media (prefers-reduced-motion: reduce) {
.kt-unblur {
animation: kt-unblur-sade 0.25s ease-out both;
}
}
@keyframes kt-unblur-sade {
from {
opacity: 0.6;
}
to {
opacity: 1;
}
}
/* Landing bölümlerinin görünüme girerken belirmesi (bkz. landing/reveal.tsx).
İçerik SSR'da GÖRÜNÜR; gizleme yalnızca script çalışan tarayıcılarda ve
IO sınıfı ekleyene kadar geçerli — JS'siz istemcide sayfa asla boş kalmaz. */
@media (scripting: enabled) {
.kt-reveal {
opacity: 0;
translate: 0 var(--reveal-y, 28px);
transition:
opacity 0.55s cubic-bezier(0.21, 0.47, 0.32, 0.98),
translate 0.55s cubic-bezier(0.21, 0.47, 0.32, 0.98);
/* Emniyet: hydration hiç gelmezse 3 sn sonra içerik yine de belirir */
animation: kt-reveal-emniyet 0.5s ease-out 3s forwards;
}
.kt-reveal.kt-reveal-in {
opacity: 1;
translate: 0 0;
}
@media (prefers-reduced-motion: reduce) {
.kt-reveal {
translate: 0 0;
transition: opacity 0.25s ease-out;
}
}
}
@keyframes kt-reveal-emniyet {
to {
opacity: 1;
translate: 0 0;
}
}
/* Uzun tablo satırları: viewport dışı satırların layout/paint'i atlanır
(rendering-content-visibility). contain-intrinsic-size satır yüksekliği
tahminidir — scrollbar zıplamasını önler. Sorun çıkarsa satır bazında
class kaldırılarak geri alınabilir. */
@utility kt-cv-satir {
content-visibility: auto;
contain-intrinsic-size: auto 57px;
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
/* Chrome autofill'in soluk mavi dolgusu inputun kendi arka planını
ezmesin; dolgu metne kırpılır, renkler temadan gelir. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
-webkit-background-clip: text;
-webkit-text-fill-color: var(--foreground);
caret-color: var(--foreground);
}
html {
@apply font-sans;
}
}
/* Site geneli üst/alt progressive blur katmanları (root layout).
Kendi CSS'iyle yazılır çünkü bu iki katman `position: fixed` + `backdrop-filter`
birleşimini taşıyan tek yer: iOS/iPadOS WebKit bu birleşimde bulanıklığı ayrı
bir kompozit katmana alıp kaydırma sırasında bayat scroll konumuyla çiziyor,
katman ekranın ortasında bir şerit gibi görünüyor (22 Eyl 2026, iPad + Chrome
raporu — Chrome iOS da WebKit'tir, hata Safari'yle aynı). Aşağıdaki @supports
bloğu yalnızca iOS/iPadOS'ta eşleşir (`-webkit-touch-callout` başka hiçbir
tarayıcıda desteklenmez; masaüstü Safari dahil) ve orada bulanıklık + maske
düşer, degrade fade kalır. Katalogdaki ProgressiveBlur kullanımları `absolute`
olduğu için bu hatadan etkilenmiyor; onlar bileşende kalır. */
.kt-sayfa-blur {
position: fixed;
inset-inline: 0;
z-index: 40;
height: 7rem;
pointer-events: none;
user-select: none;
-webkit-user-select: none;
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
}
/* Degrade: ekran kenarında gövde zemini (bg-slate-50), içeriye doğru şeffaf.
Maske bulanıklığı aynı yönde söndürür — sert kenar kalmaz. */
.kt-sayfa-blur-ust {
top: 0;
background: linear-gradient(to top, transparent, var(--color-slate-50));
-webkit-mask-image: linear-gradient(to bottom, #000 50%, transparent);
mask-image: linear-gradient(to bottom, #000 50%, transparent);
}
.kt-sayfa-blur-alt {
bottom: 0;
background: linear-gradient(to bottom, transparent, var(--color-slate-50));
-webkit-mask-image: linear-gradient(to top, #000 50%, transparent);
mask-image: linear-gradient(to top, #000 50%, transparent);
}
@supports (-webkit-touch-callout: none) {
.kt-sayfa-blur {
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
.kt-sayfa-blur-ust,
.kt-sayfa-blur-alt {
-webkit-mask-image: none;
mask-image: none;
}
}
/* 24'lük piksel listede dokunma nabzı (bkz. components/piksel-liste.tsx):
basılan kare ve komşuları kısa bir büyüyüp söner. Tek seferlik, 420 ms. */
@keyframes kt-piksel-nabiz {
0% {
transform: scale(1);
}
35% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
.kt-piksel-nabiz {
animation: kt-piksel-nabiz 0.42s cubic-bezier(0.23, 1, 0.32, 1);
}
/* Şehir haritasında (sehir-piksel-haritasi.tsx) ilin kareleri sırayla
belirir; her karenin gecikmesi inline (35 ms × sıra). DESIGN.md §4.17. */
@keyframes kt-piksel-belir {
from {
opacity: 0;
transform: scale(0.6);
}
to {
opacity: 1;
transform: scale(1);
}
}
.kt-piksel-belir {
transform-box: fill-box;
transform-origin: center;
animation: kt-piksel-belir 0.42s cubic-bezier(0.23, 1, 0.32, 1) both;
}
/* Harita görünüme girene kadar bekler (PikselSvg data-gorundu yazar). */
.kt-piksel-harita:not([data-gorundu]) .kt-piksel-belir {
animation-play-state: paused;
}
@media (prefers-reduced-motion: reduce) {
.kt-piksel-belir {
animation: none;
}
}
/* Veri akışı (veri-akisi.tsx, DESIGN.md §4.28). Üstte üç kutu, ortada
çekirdek, altta üç kutu; yollar SVG, kayıtlar HTML (yalnız translate /
scale / opacity oynar).
Geometri: yatay eksen kabın eninin yüzdesi (kap `@container`, x'ler cqw),
dikey eksen rem: kutular 5rem, çekirdek 10,5–14,5rem arası, sahne 25rem.
Kaydın iki ucu satır içi gelir (--x0/--y0 port, --x1/--y1 çekirdek kenarı).
Eğri: yol, iki ucu dikey çıkan S kıvrımıdır — C(x0 ym, x1 ym), ym orta
yükseklik. Bu eğride parametre zamanla doğrusal ilerlerken x tam olarak
cubic-bezier(1/3, 0, 2/3, 1), y tam olarak cubic-bezier(1/3, .5, 2/3, .5)
izler. Kayıt bu yüzden iç içe iki öğedir: dıştaki yatay, içteki dikey
kayar; ikisi birlikte çizginin tam üstünde yürür, ölçüm ya da JS gerekmez.
Bu iki eğri hareket zevki değil yolun geometrisidir (--akis-x / --akis-y);
yol değişirse onlar da değişir. İz, aynı iki kaymayı --ek kadar gecikmeyle
yapan iki küçük noktadır; böylece o da çizginin üstünde kalır.
Döngü 6 sn, altı kayıt 1 sn arayla (--g satır içi gecikme). Bir kaydın ömrü:
0 → 20 % yol (1,2 sn)
0 → 4 % kalkış: porttan küçük ve soluk çıkar (ölçek 0,6 → 1)
13 → 17 % işlenir: içi boş nokta şişer (1 → 1,2), dolar ve piksel kareye döner
15 → 19 % iz çekirdek kenarına varmadan söner
20 → 23 % kayıt kenarda sönerek içeri alınır
20 → 32 % çekirdek nabzı: çerçeve kaydın renginde yanar, genişleyip söner
0 → 10 % kaynak vurgusu: kutunun çerçevesi ve port kısa bir an yanar
Eğri öğenin `animation` kısayolundadır, keyframe'in içinde değil: tarayıcı
`@keyframes` içindeki `animation-timing-function: var(--…)` değerini çözmez
(doğrusala düşer). Kısayoldaki eğri her durak aralığına ayrı ayrı uygulanır.
Yalnız ekrandayken oynar (data-oynuyor). Hareketi azalt'ta her yolda bir
ham kayıt durağan durur. */
.kt-akis-sahne {
height: 25rem;
--akis-x: cubic-bezier(0.3333, 0, 0.6667, 1);
--akis-y: cubic-bezier(0.3333, 0.5, 0.6667, 0.5);
}
.kt-akis-kayit-kap {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
pointer-events: none;
}
/* Port: yolun kutudan çıktığı nokta; kayıt buradan doğar. */
.kt-akis-port {
position: absolute;
top: -3.5px;
left: -3.5px;
width: 7px;
height: 7px;
border: 1px solid var(--color-slate-300);
border-radius: 9999px;
background: var(--card);
translate: var(--x0) var(--y0);
}
.kt-akis-port > .kt-akis-vurgu {
position: absolute;
inset: 1px;
border-radius: inherit;
background: var(--renk);
}
.kt-akis-x,
.kt-akis-y {
position: absolute;
top: 0;
left: 0;
}
.kt-akis-x {
translate: var(--x0) 0;
animation: kt-akis-x 6s var(--akis-x) calc(var(--g, 0s) + var(--ek, 0s)) infinite;
}
.kt-akis-y {
translate: 0 var(--y0);
animation: kt-akis-y 6s var(--akis-y) calc(var(--g, 0s) + var(--ek, 0s)) infinite;
}
/* İz noktası: kayıttan küçük, dolu ve soluk. */
.kt-akis-iz {
position: absolute;
top: -2px;
left: -2px;
width: 4px;
height: 4px;
border-radius: 9999px;
background: var(--renk);
opacity: 0;
animation: kt-akis-iz 6s var(--egri-standart) calc(var(--g, 0s) + var(--ek, 0s)) infinite;
}
/* Ham kayıt: içi boş nokta. */
.kt-akis-kare {
position: absolute;
top: -5px;
left: -5px;
box-sizing: border-box;
width: 10px;
height: 10px;
border: 1.5px solid var(--renk);
border-radius: 50%;
background: var(--card);
opacity: 0;
scale: 0.6;
animation: kt-akis-kare 6s var(--egri-standart) var(--g, 0s) infinite;
}
/* İşlenmiş kayıt: aynı kutunun dolusu, üstüne solarak gelir. */
.kt-akis-dolgu {
position: absolute;
inset: 0;
border-radius: inherit;
background: var(--renk);
opacity: 0;
animation: kt-akis-dolgu 6s var(--egri-standart) var(--g, 0s) infinite;
}
.kt-akis-nabiz,
.kt-akis-vurgu {
border-color: var(--renk);
opacity: 0;
}
.kt-akis-nabiz {
animation: kt-akis-nabiz 6s var(--egri-guclu-cikis) var(--g, 0s) infinite;
}
.kt-akis-vurgu {
animation: kt-akis-vurgu 6s var(--egri-standart) var(--g, 0s) infinite;
}
@keyframes kt-akis-x {
0% {
translate: var(--x0) 0;
}
20%,
100% {
translate: var(--x1) 0;
}
}
@keyframes kt-akis-y {
0% {
translate: 0 var(--y0);
}
20%,
100% {
translate: 0 var(--y1);
}
}
@keyframes kt-akis-iz {
0%,
3% {
opacity: 0;
}
7%,
15% {
opacity: 0.4;
}
19%,
100% {
opacity: 0;
}
}
@keyframes kt-akis-kare {
0% {
scale: 0.6;
opacity: 0;
border-radius: 50%;
}
4%,
13% {
scale: 1;
opacity: 1;
border-radius: 50%;
}
17% {
scale: 1.2;
opacity: 1;
border-radius: 25%;
}
20% {
scale: 1;
opacity: 1;
border-radius: 25%;
}
23%,
100% {
scale: 0.8;
opacity: 0;
border-radius: 25%;
}
}
@keyframes kt-akis-dolgu {
0%,
13% {
opacity: 0;
}
17%,
100% {
opacity: 1;
}
}
/* Çekirdek geniş bir dikdörtgen: yatayda az, dikeyde çok büyür ki halka her
yanda aynı kadar (≈6 px) açılsın. */
@keyframes kt-akis-nabiz {
0%,
19.9% {
scale: 1;
opacity: 0;
}
20% {
scale: 1;
opacity: 0.5;
}
32%,
100% {
scale: 1.06 1.2;
opacity: 0;
}
}
@keyframes kt-akis-vurgu {
0% {
opacity: 0;
}
2% {
opacity: 0.5;
}
10%,
100% {
opacity: 0;
}
}
/* Oynatma durumu `animation` kısayolundan sonra gelmeli (kısayol sıfırlar). */
:is(.kt-akis-x, .kt-akis-y, .kt-akis-iz, .kt-akis-kare, .kt-akis-dolgu, .kt-akis-nabiz, .kt-akis-vurgu) {
animation-play-state: paused;
}
[data-oynuyor]
:is(.kt-akis-x, .kt-akis-y, .kt-akis-iz, .kt-akis-kare, .kt-akis-dolgu, .kt-akis-nabiz, .kt-akis-vurgu) {
animation-play-state: running;
}
@media (prefers-reduced-motion: reduce) {
:is(.kt-akis-x, .kt-akis-y, .kt-akis-iz, .kt-akis-kare, .kt-akis-dolgu, .kt-akis-nabiz, .kt-akis-vurgu) {
animation: none;
}
/* Durağan kare: yolun ortasında ham kayıt — bilgi eksilmez. */
.kt-akis-x {
translate: calc((var(--x0) + var(--x1)) / 2) 0;
}
.kt-akis-y {
translate: 0 calc((var(--y0) + var(--y1)) / 2);
}
.kt-akis-kare {
opacity: 1;
scale: 1;
}
}
/* Tema geçişi (DESIGN.md §2.3, lib/tema-gecisi.ts): yeni tema header'daki
logodan yumuşak bir halka gibi açılır. Eski görüntü yerinde durur; yeni
görüntü radyal degrade maskesiyle üstünde belirir. Maskenin kenarı keskin
değil: yarıçapın %55'ine kadar tam opak, oradan kenara doğru tüy gibi
söner (--kt-tema-cekirdek; JS'teki CEKIRDEK ile aynı olmalı) — ışık
yayılır gibi, sert çizgi yok. Yarıçap (--kt-tema-r) 0 → --kt-tema-son
yumuşak kalkıp yumuşak durur; kısa ve hafif (600 ms) — asıl gösteri,
geçiş bitince oynayan logo dönüşümüdür. Merkez ve son yarıçap JS'ten gelir.
Hareket azaltılmışsa JS geçişi hiç başlatmaz, tema düz değişir. */
@property --kt-tema-r {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
.kt-tema-gecis {
view-transition-name: root;
--kt-tema-cekirdek: 0.55;
}
.kt-tema-gecis::view-transition-old(root),
.kt-tema-gecis::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
.kt-tema-gecis::view-transition-old(root) {
z-index: 1;
}
.kt-tema-gecis::view-transition-new(root) {
z-index: 2;
mask-image: radial-gradient(
circle at var(--kt-tema-x) var(--kt-tema-y),
#000 calc(var(--kt-tema-r) * var(--kt-tema-cekirdek)),
transparent var(--kt-tema-r)
);
animation: kt-tema-halka 600ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
@keyframes kt-tema-halka {
from {
--kt-tema-r: 0px;
}
to {
--kt-tema-r: var(--kt-tema-son);
}
}
/* Sayfa geçişi (DESIGN.md §6, components/sayfa-gecisi.tsx): rota değişince
eski içerik hızla söner, yenisi hafifçe yükselerek belirir — çıkış girişten
hızlı. Üst çubuk kendi grubunda ve animasyonsuz: içerik değişir, çubuk
yerinde kalır (uygulama hissi, §11.4). Tema geçişinde (`.kt-tema-gecis`)
çubuk adını bırakır ki halka onu da kaplasın. */
.kt-ust-cubuk {
view-transition-name: kt-ust-cubuk;
}
.kt-tema-gecis .kt-ust-cubuk {
view-transition-name: none;
}
::view-transition-group(kt-ust-cubuk) {
animation: none;
z-index: 100;
}
::view-transition-old(kt-ust-cubuk) {
display: none;
}
::view-transition-new(kt-ust-cubuk) {
animation: none;
}
::view-transition-old(.kt-sayfa-cik) {
animation: 120ms var(--egri-standart) both kt-sayfa-sol reverse;
}
::view-transition-new(.kt-sayfa-gir) {
animation:
200ms var(--egri-standart) 80ms both kt-sayfa-sol,
280ms var(--egri-giris) both kt-sayfa-yuksel;
}
@keyframes kt-sayfa-sol {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes kt-sayfa-yuksel {
from {
translate: 0 8px;
}
to {
translate: 0 0;
}
}
@media (prefers-reduced-motion: reduce) {
::view-transition-old(.kt-sayfa-cik),
::view-transition-new(.kt-sayfa-gir) {
animation: none;
}
}
/* Ana sayfa ilk ekranının girişi (DESIGN.md §6 "sayfa başına tek orkestre
giriş", §11.2): önce harita belirir, sonra başlık, sonra form netleşerek
gelir — sırayla, üst üste binmeden. `--sira` ile kademelenir. Başlık LCP
öğesi olduğundan hiçbir kare tam saydam başlamaz (opaklık 0,35'ten). */
.kt-hero-gir {
animation: kt-hero-gir 0.7s var(--egri-giris) both;
animation-delay: calc(var(--sira, 0) * 110ms + 80ms);
}
.kt-hero-harita {
animation: kt-hero-harita 1.1s var(--egri-standart) both;
}
@keyframes kt-hero-gir {
from {
opacity: 0.35;
filter: blur(10px);
translate: 0 12px;
}
to {
opacity: 1;
filter: blur(0);
translate: 0 0;
}
}
@keyframes kt-hero-harita {
from {
opacity: 0;
scale: 0.985;
}
to {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.kt-hero-gir,
.kt-hero-harita {
animation: kt-unblur-sade 0.25s ease-out both;
}
}
/* "Nasıl çalışır" adımları arasındaki çizgi (DESIGN.md §4.32): adımın rakamı
biçimine dönüşüp geri toplanınca (adim-akisi.tsx `data-dolu` yazar) soldan
maviyle dolar. JS'siz istemcide dolu durur. */
@media (scripting: enabled) {
.kt-cizgi-dol {
transform: scaleX(0);
transform-origin: left;
transition: transform 0.6s var(--egri-guclu-cikis);
}
.kt-cizgi-dol[data-dolu] {
transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
.kt-cizgi-dol {
transform: none;
transition: none;
}
}
}
/* Piksel morf (components/piksel-morf.tsx, DESIGN.md §4.38): her piksel bir
<g>; yeri `translate` ile verilir ve kare değişince yeni hücresine süzülür.
`gizli` küçülüp söner. Turuncu vurgu, doku karesinin üstündeki ikinci
karedir: çabuk ısınır, yavaş soğur (ısı fırçasıyla aynı asimetri).
Sekme yok (§6); kayma süresi sahneye göre `--morf-sure` ile ayarlanır. */
.kt-morf-px {
transform-box: fill-box;
transform-origin: center;
transition:
translate var(--morf-sure, 0.55s) var(--egri-standart) var(--g, 0ms),
opacity 0.3s var(--egri-standart) var(--g, 0ms),
scale 0.3s var(--egri-standart) var(--g, 0ms);
}
.kt-morf-px[data-ton="gizli"] {
opacity: 0;
scale: 0.6;
}
.kt-morf-vurgu {
opacity: 0;
fill-opacity: 0.7;
transition: opacity 1.2s var(--egri-standart);
}
.kt-morf-taban {
transition: opacity 0.6s var(--egri-standart);
}
.kt-morf-px[data-ton="vurgu"] > .kt-morf-taban {
opacity: 0;
transition: opacity 0.25s var(--egri-standart) var(--g, 0ms);
}
.kt-morf-px[data-ton="vurgu"] > .kt-morf-vurgu {
opacity: 1;
animation:
kt-morf-isin 0.25s var(--egri-standart) var(--g, 0ms) backwards,
kt-morf-nabiz 3.6s ease-in-out var(--n, 0s) infinite;
}
@keyframes kt-morf-isin {
from {
opacity: 0;
}
}
@keyframes kt-morf-nabiz {
50% {
fill-opacity: 0.35;
}
}
@media (prefers-reduced-motion: reduce) {
.kt-morf-px,
.kt-morf-taban,
.kt-morf-vurgu {
transition: none;
}
.kt-morf-px[data-ton="vurgu"] > .kt-morf-vurgu {
animation: none;
}
}
/* Kendini çizen tik (landing-parcalari.tsx, DESIGN.md §5.2.3): karşılaştırma
tablosu ekrana girince (Reveal → .kt-reveal-in) önce halka, sonra işaret
çizilir; satır gecikmesi `--tik-g` ile gelir. `pathLength="1"` bekler. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
.kt-reveal .kt-tik-ciz {
stroke-dasharray: 1;
stroke-dashoffset: 1;
opacity: 0;
transition:
stroke-dashoffset 0.5s var(--egri-standart) calc(var(--tik-g, 0ms) + 250ms),
opacity 0.01s linear calc(var(--tik-g, 0ms) + 250ms);
}
.kt-reveal .kt-tik-isaret {
transition-duration: 0.3s, 0.01s;
transition-delay:
calc(var(--tik-g, 0ms) + 600ms),
calc(var(--tik-g, 0ms) + 600ms);
}
.kt-reveal.kt-reveal-in .kt-tik-ciz {
stroke-dashoffset: 0;
opacity: 1;
}
}
/* Hero haritasının serpintisi (turkey-pixel-map.tsx, DESIGN.md §11.1 V2):
piksel bir süre yerinde durur, kopup `--d` birim (10 = bir hücre) düşerken
söner, sonra yerinde yeniden belirir. Süre ve faz satır içi. */
@keyframes kt-serpinti {
0%,
42% {
translate: 0 0;
opacity: 1;
animation-timing-function: ease-in;
}
76% {
translate: 0 calc(var(--d, 20) * 1px);
opacity: 0;
animation-timing-function: step-end;
}
80% {
translate: 0 0;
opacity: 0;
animation-timing-function: ease-out;
}
100% {
translate: 0 0;
opacity: 1;
}
}
.kt-serpinti {
animation: kt-serpinti 6s infinite;
}
@media (prefers-reduced-motion: reduce) {
.kt-serpinti {
animation: none;
}
}
/* Piksel şeridi (components/piksel-serit.tsx, DESIGN.md §4.38): kaydırmaya
bağlı sütun. Okuma çizgisini geçen piksel `data-yandi` alır ve turuncuya
ısınır; geri kaydırınca yavaş soğur. Şeridin ucu (`data-uc`) tam turuncu. */
.kt-serit-px {
fill: currentColor;
fill-opacity: var(--op, 0.2);
transition:
fill 0.9s var(--egri-standart),
fill-opacity 0.9s var(--egri-standart);
}
.kt-serit-px[data-yandi] {
fill: var(--color-orange-500);
fill-opacity: 0.62;
transition-duration: 0.16s;
}
.kt-serit-px[data-uc] {
fill-opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
.kt-serit-px {
transition: none;
}
}