Files
kolaytercih/docs/tasarim/DESIGN.md
bilalgursen 17606902bd feat(header): Beta sürüm rozeti main'den alındı; v2 dalı 2.0.0
main'deki b2bab50 ile aynı içerik (surum.ts, surum-rozeti.tsx, header, AGENTS.md
sürümleme kuralı, DESIGN.md §2.2/§4.14); bu dal 2.0.0 geliştirme sürümü.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 23:04:59 +03:00

100 KiB
Raw Blame History

KolayTercih görsel dili (DESIGN.md)

Bu dosya sitenin görsel dilinin tek yazılı kaynağıdır. Yeni ekran, bileşen, modal, kart ya da buton çizmeden önce okunur; mevcut arayüz değiştirilirken buna bakılır. Değerler koddan çıkarılmıştır (src/app/globals.css, src/app/layout.tsx, src/components/pixel-decor.tsx, src/components/ui/*, src/app/page.tsx, src/features/katalog/components/universite-icerik.tsx); kodla çelişirse kod değil, bu dosya düzeltilir ve çelişki raporlanır. Kural ihlallerini pnpm tasarim:denetim yakalar.

Biçim: Google Stitch'in DESIGN.md düzeni (9 bölüm). Sabit değerler Tailwind sınıfı olarak verilir; kodda da sınıf kullanılır, hex/oklch elle yazılmaz.

Canlı referans ekran: /universite/ankara-universitesi (23 Eyl 2026'da Bilal'le birlikte bu belgedeki "şişko ve sade" dile göre baştan tasarlandı). Bir kural belirsiz kalırsa o sayfanın kodu (universite-icerik.tsx, universite-program-tablosu.tsx, akademik-ayrinti.tsx, nav-baslik.tsx) ölçüdür. Site genelinde dönüşüm bu ekranı örnek alır.


1. Görsel tema ve atmosfer

Bir cümle: Beyaz, bol nefesli, şişko ve sade — kullanıcıya "basit bir şey kullanıyorum" hissi veren, Apple uygulamaları kadar kolay anlaşılır bir arayüz; mavi bilgi + turuncu aksiyon; her yüzeyde küçük bir piksel imzası (hero'daki dot-matrix Türkiye haritasının ve logodaki üç karenin dili) dolaşır.

1.1 Temel his: şişko ve sade

Referans: header (src/components/site-header.tsx ve içindeki arama/kullanıcı hapları), hero ve üniversite sayfası. Bu hissi veren şeyler, ekrandan bağımsız:

  • İri dokunma alanı. Butonlar ve haplar 44–48 px (h-11/h-12), tam yuvarlak.
  • İri yazı, az eleman. Bir ekranda az şey var ve her biri büyük. Küçük gri yazı yığını yok.
  • Sayı kahramandır. Bir veri gösteriliyorsa sayı kartın en büyük öğesidir; etiket ve açıklama onun altında ikinci planda.
  • Sık bakılan önde, ayrıntı bir dokunuş derinde (Apple'ın "önce ortak yol, gelişmiş seçenekler bir seviye aşağıda" ilkesi). Sayfada en çok dört özet sayı; fazlası ayrıntı satırının açtığı alt sayfaya (§4.10).
  • Nefes alanı korunur. Harita gibi görsel dinlenme alanları küçültülmez, sıkıştırılmaz, bilgiyle doldurulmaz. Sadeleştirmek = bu alanları silmek değil, etraflarındaki kalabalığı azaltmaktır.
  • Verimli ama havadar. Alt sayfa ve paneller dikine uzamaz; ilişkili öğeler yan yana dizilir, aralarında boşluk kalır (§5.3).
  • Doğal duruş. Eşit, hizalı ızgaralar yerine logodaki üç kare gibi hafif kaymış yerleşim (§4.11). Her şey birbirine cetvelle hizalıysa ekran "tablo" gibi durur.
  • Basınca tepki. Her tıklanabilir öğe basınca hafifçe küçülür (active:scale-[0.97], geniş satırlarda [0.99]), üzerine gelince turuncuya döner (§2.1).

1.2 Genel kurallar

  • Açık temada zemin beyaz (koyu temada karşılığı, §2.3); koyu zemin yalnızca CTA bandı ve çekmece başlığı gibi tek bir vurgu yüzeyinde (PixelMasonry ile: büyüklü küçüklü, hafif kaymış kareler).
  • İmza dekoratiftir ama rastgele değildir: deterministik ızgara (hücre 10, nokta 7.4, rx 2), imleç yaklaşınca turuncuya ısınan pikseller (usePixelHeat), uzaklaşınca yavaş soğuma. Piksel veri taşıyorsa (ör. PixelSira) kalır; iki bölüm arasına süs olarak konmuş piksel ayraç alt sayfalarda ve kompakt panellerde kullanılmaz.
  • Ton: öğrenciye "sen" diyen, sakin, vaatsiz. Süs yok, gösteriş yok; hareket yalnızca bir şey söylüyorsa var.
  • Karanlık mod token'la çalışır, dark: sınıfı yazılmaz (§2.3). Bileşen tek bir sınıf dizisiyle yazılır; iki temada doğru görünmesi palet token'larının işidir.

2. Renk paleti ve rolleri

Rol Sınıf Nerede
Bilgi/vurgu mavisi (primary) text-primary, bg-primary/10, border-primary/30 Rozet metni, ikon kutusu, hero'daki italik vurgu, linklerin durağan rengi
Aksiyon turuncusu bg-orange-500 hover:bg-orange-600 text-white Funnel CTA butonları. Bir ekranda tek turuncu buton
Hover turuncusu hover:text-orange-500, hover:border-orange-500, hover:bg-orange-50/60, group-hover:text-orange-500 Link, kart, satır ve ikincil butonların üzerine gelme hâli (§2.1); liste satırı adı hariç (mavi kalır)
Piksel vurgusu fill-orange-500 (opaklık 0.55–0.85) Yalnızca piksel süslerinin "sıcak" noktaları
Başlık metni text-slate-900 h1–h3, kart başlıkları, iri sayılar
Gövde metni text-slate-600 Paragraf, açıklama
İkincil metin text-slate-500 Meta bilgi, yardımcı satır, kart açıklaması
Silik metin text-slate-400 İpucu, devre dışı, placeholder, sayının yanındaki birim (/ 198)
Kenarlık border-slate-200 (landing kartlarında border-slate-200/70) Kart, rozet, çarpı, giriş alanı
İç zemin bg-slate-50 Kartın içindeki ikincil kutu, tablo başlığı
Nötr hover zemini hover:bg-slate-100 Yalnız kapatma çarpısı ve ghost buton
Risk: güvenli emerald-500 / text-emerald-600 Her zaman "Güvenli" metniyle
Risk: az riskli amber-500 / text-amber-600 Her zaman "Az riskli" metniyle
Risk: riskli red-500 / text-red-600 Her zaman "Riskli" metniyle
Uyarı kutusu border-amber-200 bg-amber-50 text-amber-900 Bilgilendirme notu
Gösterge karesi Dolu zemin + beyaz yazı: bg-orange-500, bg-primary, bg-indigo-500, bg-green-600; rounded-3xl Yalnız sayı gösterge kareleri (§4.11). Renk sempati katar, anlam taşımaz: etiket her karede yazılı
Hata text-destructive, text-red-600 Form hatası

2.1 Hover: tek turuncu

Bilal'in kararı (23 Eyl 2026): üzerine gelme hâlinde sitenin turuncusu kullanılır ve bu turuncu tek tondur: orange-500 — CTA butonunun turuncusuyla birebir aynı değer.

  • Link / metin: transition-colors hover:text-orange-500 (altı çizili linklerde hover:underline kalır).
  • Tıklanabilir kart / satır: hover:border-orange-500 hover:bg-orange-50/60; içindeki iri sayı ya da başlık group-hover:text-orange-500; sağdaki ok group-hover:translate-x-0.5 group-hover:text-orange-500.
  • İkincil (outline) buton: hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500.
  • İstisna — liste satırındaki adlar mavi kalır: program/üniversite listelerinde satırın adı (bölüm ya da üniversite sayfasına giden link) hover:text-primary hover:underline. Bilal'in kararı (23 Eyl 2026): uzun bir listede imleç satırdan satıra geçerken yanıp sönen turuncu adlar yorucu; mavi sakin kalır. Satırın butonları ve listedeki diğer linkler §2.1'e uyar.
  • Yapılmaz: hover'da text-primary/border-primary (eski mavi hover — yukarıdaki istisna dışında), orange-600 yazı, orange-300 kenarlık — aynı ekranda iki turuncu tonu göze "farklı turuncu" diye batar. Tek istisna: turuncu CTA'nın kendi zemininin hover'ı (hover:bg-orange-600), kanonik.
  • Geçiş notu: kodda hâlâ hover:text-primary / hover:border-primary/30 kullanan yerler var (landing kartı dahil); tarama sırasında bu kurala çevrilir. Denetim bunları mavi-hover uyarısıyla listeler; liste satırı adındaki uyarı istisnadır, dokunulmaz.

2.2 Palet kuralları

  • Nötr yalnızca slate. gray, zinc, neutral, stone yazılmaz.
  • indigo, purple, violet, fuchsia, pink, cyan, teal, lime, green, yellow yeni kullanım açmaz. Tek istisna "Gösterge karesi" satırındaki dolu bg-indigo-500 ve bg-green-600 zeminleri (Bilal'in kararı, 23 Eyl 2026); yazı, kenarlık ya da başka ton/opaklıkta bu renkler yine yasak. (bg-violet-50 text-violet-600 tek bir mevcut durum çipidir; yeni yere taşıma — üniversite sayfasında "Vakıf" çipi bu yüzden hap + ikonla değiştirildi, §4.12.) İkinci istisna: üst çubuktaki "Beta" sürüm rozeti, dolu bg-indigo-500 (§4.14, Bilal'in kararı, 7 Eki 2026) — gösterge karesiyle aynı mor, yine yalnız dolu zemin.
  • Gradyan metin (bg-clip-text text-transparent) ve parlama gölgesi (shadow-[0_0_…]) yok.
  • Hex/oklch değeri sınıf içine yazılmaz (text-[#…]); token ya da Tailwind tonu kullanılır. Risk renklerinin SVG karşılığı src/lib/risk.ts içindeki RISK_PIN_RENK'ten okunur.
  • Renk tek başına anlam taşımaz: risk rengi her zaman metin etiketiyle birlikte gider (RISK_ETIKET, DILIM_ETIKET — üçüncü dilimin görünen adı "Güvenli"). Tür ayrımı (devlet / vakıf) da renkle değil ikon + metinle yapılır.
  • Renkli dolu zeminde beyaz yazı: turuncu ve yeşil zeminde küçük beyaz yazı WCAG AA'nın altında kalır (sitenin turuncu CTA'sı da aynı ikiliyi kullanır). Bu zeminlerde etiket font-bold, sayı en az text-3xl; uzun metin konmaz.

2.3 Karanlık mod

Bilal'in kararı (4 Eki 2026): sitede açık / koyu / sistem teması var; varsayılan açık. Seçici src/components/tema-secici.tsx (footer'da), sağlayıcı src/components/tema-saglayici.tsx (next-themes, <html class="dark">). Renklerin tek kaynağı src/app/globals.css içindeki .dark bloğu.

Nasıl çalışır: bileşenlere dark: yazılmaz; palet token'ları çevrilir.

Açık temadaki sınıf Koyu temada ne olur
bg-card (yüzey: kart, hap, form alanı, modal, çekmece) Koyu yüzey (#111826)
bg-slate-50 (gövde zemini, kart içi ikincil kutu) En koyu zemin (#080e19)
slate-100…900 (metin, kenarlık, hover zemini) Ölçek ters döner: text-slate-900 açık başlık, border-slate-200 koyu çizgi
bg-orange-50/60, bg-amber-50, bg-emerald-50, bg-red-50, border-*-200 Aynı rengin koyu tonu
text-amber-900, text-emerald-800, text-red-600 gibi koyu renkli metin Aynı rengin açık tonu
text-white, bg-orange-500, bg-primary, bg-emerald-500, bg-red-500 Değişmez

Kurallar:

  • Yüzey bg-card'dır, bg-white değil. bg-white koyu temada da beyaz kalır; yalnız gerçekten beyaz kalması gereken yerde yazılır: üniversite logosu karosu (uni-logo.tsx), kaydırıcı topuzu, rehber kapak görseli, renkli dolu zemin üstündeki bg-white/15 ikon kutusu.
  • Koyu hap (bg-slate-900: "Giriş yap", "Ara", sekme göstergesi, toast düğmesi) yazısını text-slate-50 ile alır, text-white ile değil: koyu temada hap açığa, yazı koyuya döner.
  • Koyu vurgu yüzeyi (bg-slate-950: PikselCtaYuzeyi, AramaFunnelKarti) kt-koyu-yuzey sınıfını taşır; iki temada koyu kalır, içindeki açık slate metinler çevrilmez. slate-950 metin rengi olarak kullanılmaz.
  • SVG ve satır içi stilde sabit renk yerine değişken: var(--card), var(--color-slate-200), var(--kt-harita-dolu). Risk renkleri (RISK_RENK) ve logo renkleri iki temada aynıdır.
  • Açık kalan adalar: el çizimi şemalar (kt-sema-kagit) ve iyzico logo bandı (kt-acik-logo; footer, paket ve ödeme sayfası) koyu temada beyaz kâğıt/hap üstünde durur; tek renk koyu logo (URAP) kt-koyu-cevir ile açığa çevrilir; yazdırma çıktısı her zaman açıktır (.dark bloğu @media screen içinde).
  • Yeni bir renk tonu ilk kez kullanılıyorsa (bg-sky-50 gibi) .dark bloğuna karşılığı eklenir; eklenmezse koyu temada açık renkli bir leke olarak kalır.

3. Tipografi

Dört arayüz yazı tipi (+ yalnız Kur'an metni için bir Arapça yazı tipi), her birinin tek bir işi var:

Sınıf Yazı tipi İş
font-heading Cal Sans Tüm başlıklar (h1–h3, kart başlığı) ve iri sayılar. Her zaman font-bold ile
font-sans (varsayılan) Clarity City 400–800 Gövde, buton, form, tablo
font-bricolage Bricolage Grotesque (opsz ekseni) Vurgu: hero'da italik mavi span, logo yazısı, üst çubuktaki sayfa adı (§4.14), küçük etiketler/çipler
font-mono Geist Mono Yalnızca kod/markdown blokları. Arayüzde kullanılmaz
amiriQuran.className (site-footer.tsx) Amiri Quran Yalnızca Kur'an metni: footer'daki âyet (lang="ar" dir="rtl"). Arayüz metninde kullanılmaz; önceden yüklenmez, Arapça alt kümesi âyet çizilirken iner. Aşağıdaki "serif yasak" kuralı Latin arayüz metni içindir

Ölçek (kopyala, uydurma):

  • Hero h1: font-heading text-5xl font-bold tracking-[0.015em] sm:text-6xl; vurgu kelimesi <span className="font-bricolage italic tracking-tighter font-bold text-primary">
  • Alt sayfa h1 (katalog, rehber): font-heading text-3xl font-bold leading-tight text-slate-900 sm:text-5xl
  • Bölüm h2: font-heading text-3xl font-bold sm:text-4xl (istenirse text-slate-900); alt sayfada liste bölümü başlığı font-heading text-2xl font-bold text-slate-900 sm:text-3xl
  • Panel/kart h3: font-heading text-xl font-bold · grup başlığı (fakülte vb.): font-heading text-xl font-bold text-slate-900 sm:text-2xl
  • Küçük başlık: font-heading text-base font-bold text-slate-900
  • Bölüm giriş paragrafı: max-w-xl text-lg leading-relaxed text-slate-600
  • Sayfa özet paragrafı: text-base leading-relaxed text-slate-600 sm:text-lg
  • Gövde: text-base leading-relaxed (açıklama, liste satırı adı) ya da text-sm (kart açıklaması, tablo hücresi, meta)
  • Etiket/rozet metni: text-xs font-semibold

İri sayı ölçeği (§1.1 "sayı kahramandır"):

Yer Sınıf
Özet kartı sayısı font-heading text-4xl font-bold leading-none tracking-tight text-slate-900 sm:text-5xl
Gösterge karesi, büyük font-heading text-5xl font-bold leading-none tracking-tight
Gösterge karesi, orta font-heading text-3xl font-bold leading-none
Sayının birimi (/ 198, kişi) text-base font-semibold text-slate-400 (renkli zeminde text-white/80)

Alt sınırlar:

  • Gövde metni telefonda 16 px'in (text-base) altına inmez; text-sm yalnız ikincil bilgide, text-xs yalnız ince yazıda (kaynak satırı, eksen etiketi, çip).
  • 12 px altı yok: text-[10px], text-[11px] yazılmaz (denetim uyarır).
  • Büyük harfli minik etiket yok: uppercase tracking-wide text-xs kalıbı ("PROGRAM", "TOPLAM KONTENJAN") yazılmaz; etiket büyük-küçük harfli, text-sm font-semibold.
  • İri sayıda tabular-nums yok: Cal Sans'ta sabit genişlikli rakam "daktilo" gibi aralıklı durur ("13.88 9"). tabular-nums yalnız font-sans tablo sütunlarında.
  • Yasak: Inter, Roboto, Arial, sistem fontu, serif, font-[…] keyfi font.

4. Bileşen stilleri (tek kaynaklar)

Bir eleman iki yerde görünüyorsa stili tek kaynaktan gelir. Aşağıdakiler yeniden tasarlanmaz. §4.8–§4.15 üniversite sayfasında doğdu; ikinci bir ekranda gerektiğinde kopyalanmaz, ortak bir dosyaya (src/components/…) çıkarılıp iki yer de oradan kullanır.

4.1 Buton — src/components/ui/button.tsx

  • Her buton rounded-full; h-9 varsayılan, h-11/h-12 funnel CTA'ları (44 px dokunma hedefi), size-9 ikon butonu.
  • Odak: focus-visible:ring-3 focus-visible:ring-ring/50; basınca active:translate-y-px.
  • Turuncu CTA (kanonik):
    <Button size="lg" className="cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600">
      Listemi oluştur
      <ArrowRight className="size-4" aria-hidden />
    </Button>
    
    Metin önce, ok sonda. Başta ikon yok. Sparkles yok. İstenirse active:scale-[0.97].
  • İkincil gezinme butonu ("Tüm sıralamayı gör →"):
    <Button asChild size="lg" variant="outline" className="cursor-pointer px-6 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97]">
      <Link href="…">Tüm sıralamayı gör<ArrowRight className="size-4" aria-hidden /></Link>
    </Button>
    
  • Sessiz: variant="ghost"; link görünümü: variant="link".

4.2 Rozet (bölüm başlığı üstündeki kapsül) — SectionEyebrow, src/components/pixel-decor.tsx

<SectionEyebrow>Nasıl çalışır?</SectionEyebrow>

Sınıfı: inline-flex items-center gap-2 rounded-full border border-slate-200 bg-card px-3.5 py-1.5 text-xs font-semibold text-primary + başta PixelMark. @/components/ui/badge kullanılmaz; elle pill span yazılmaz. Filtre çipleri, nav butonları ve kimlik hapları (§4.12) bu kuralın dışındadır. Rozet sayfa bölüm başlıklarının üstündedir; çekmece ve modal başlıklarında kullanılmaz (§4.10, Bilal 24 Eyl 2026).

4.3 Modal kapatma çarpısı — DialogContent varsayılanı, src/components/ui/dialog.tsx

absolute top-3 right-3 z-10 flex size-9 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-popover text-slate-500 transition-[background-color,transform] duration-150 hover:bg-slate-100 hover:text-slate-800 active:scale-[0.96] + <XIcon className="size-4" aria-hidden /> + sr-only "Kapat". Özel yerleşim gerekiyorsa showCloseButton={false} ver ve aynı sınıf setini kopyala. Alt sayfada (AltSayfa) aynı sınıf seti AltSayfaKapat üstünde kullanılır (§4.10).

4.4 Kart ve kutu

  • Landing/öne çıkan kart = sahne kartı (§4.31): flex h-full flex-col overflow-hidden rounded-2xl border border-slate-200/70 bg-card shadow-sm transition-[translate,border-color,box-shadow] duration-300 hover:-translate-y-1 hover:border-orange-500 hover:shadow-lg hover:shadow-orange-500/5; üstte piksel sahne, altında başlık + metin. Eski hâli (ikon kutusu + başlık + metin + köşede PixelCorner) 7 Eki 2026'da kaldırıldı (Bilal: "sıkıcı kart tasarımları"); yeni yerde yazılmaz. PixelCorner giriş/doğrulama kartlarının köşe süsü olarak kalır.
  • Sade kutu (form, panel, liste satırı): rounded-2xl border border-slate-200 bg-card (+ p-5/p-6). Küçük iç kutu: rounded-xl border border-slate-200 bg-slate-50. Not kutusu: rounded-lg.
  • İkon kutusu: flex size-11 items-center justify-center rounded-xl bg-primary/10 içinde size-5 text-primary ikon. Kart içinde sayının yanında küçük hâli: size-8 … sm:size-10 + size-4 sm:size-5 ikon (§4.8).
  • Gölge: shadow-sm varsayılan; hover'da shadow-lg shadow-orange-500/5. Başka gölge yok.

4.5 Risk çipi / etiketi — RiskEtiketi, src/components/risk-etiketi.tsx

Tablolar, çekmece ve rapor listesi <RiskEtiketi risk={…} /> kullanır; elle yazılmaz. Nokta + metin: <span className="size-2 rounded-full bg-emerald-500" /> yanında text-xs font-semibold text-emerald-600; metin RISK_ETIKET'ten. Renk tek başına asla.

4.6 Form alanı — Input, Select, Textarea (src/components/ui/)

Form alanı da bir haptır: üst çubuktaki arama/kullanıcı haplarıyla aynı kalıp (48 px, tam yuvarlak, slate-200 kenarlık, 16 px yazı). shadcn'in ince varsayılanı (h-8 rounded-lg border-input md:text-sm) bu projede yoktur; temel bileşenler 24 Eyl 2026'da bu dile çevrildi.

  • Metin alanı (Input): h-12 w-full rounded-full border border-slate-200 bg-card px-5 text-base text-slate-900 placeholder:text-slate-400; hover border-slate-300; odak border-primary ring-3 ring-ring/50; hata (aria-invalid) border-red-500 ring-3 ring-red-500/20; devre dışı bg-slate-50 opacity-50. md:text-sm yok — gövde 16 px altına inmez (§3) ve iOS odakta yakınlaştırmaz. Kullanım yerinde yükseklik/köşe/zemin yazılmaz (className yalnız yerleşim için: sm:flex-1, pl-12). Tek istisna hero: telefonda bir kademe iri, h-14 text-lg sm:h-12 sm:text-base.
  • Başta ikon (sıralama alanındaki kupa): kapsayıcı relative, ikon pointer-events-none absolute left-5 top-1/2 size-4 -translate-y-1/2 text-slate-400, alan pl-12.
  • Seçim (SelectTrigger): aynı hap — h-12 pl-5 pr-4 text-base, ok text-slate-400; size="sm" → h-9 px-4 text-sm (yalnız masaüstü tablo aksiyonu, §8). Açılan liste rounded-2xl border border-slate-200 bg-card p-1.5 shadow-lg; satır rounded-full py-2 pl-4 pr-9 text-base, klavye/odak bg-slate-100, seçili işareti text-primary.
  • Çok satır (Textarea): hap değil sade kutu (§4.4): min-h-24 rounded-2xl border border-slate-200 bg-card px-5 py-3 text-base; hover/odak/hata metin alanıyla aynı. Sohbet kutusu (prompt-input.tsx) kenarlıksız ve şeffaf üstüne yazar; tek istisna.
  • Kenarlıksız ham <input> yalnız kendi hap kabının içinde: il arama (sihirbaz-adimlar.tsx, h-11 rounded-full border-slate-200 kap) ve katalog arama modalı (üst şeritte h-16). Kenarlıklı ham input yazılmaz; Input kullanılır.
  • Etiket her alanda: görünür text-sm font-semibold text-slate-700 ya da sr-only. Hata mesajı alanın altında role="alert" + text-sm font-medium text-red-600; ne olduğunu ve ne yapılacağını söyler (§10.4). Sayısal alanlarda uç değerler (0, negatif, 1.000.000 üstü) ele alınır.
  • Alan + buton yan yana: flex flex-col gap-3 sm:flex-row; buton h-12 (§4.1 size="lg"), alan sm:flex-1. Telefonda alt alta, ikisi de tam genişlik.
  • Denetim: ince-form-alani (hata) — Input/SelectTrigger/Textarea üstüne h-7–h-10, rounded-sm/md/lg/xl, bg-background/border-input yazılmış; ham-input (uyarı) — kenarlıklı ham <input>.

4.7 İkonlar

Yalnızca lucide-react. Boyut: size-4 buton/satır içi (varsayılan), size-5 ikon kutusu, size-3.5 küçük çip, size-6 üstü yalnızca boş durum. Dekoratif ikon aria-hidden; tek başına ikon buton aria-label ya da sr-only metin taşır. Emoji ikon olarak kullanılmaz.

4.8 Özet kartı — OzetKart, src/components/ozet-kart.tsx

Apple Fitness özet kartının sitenin ölçüleriyle hâli. Sayfada en çok dört tane (harita yanındaki 2×2).

┌──────────────────────┐
│ 13.889          [👥] │  ← sayı solda, iri; ikon kutusu sağda, küçük
│ Kontenjan            │  ← başlık text-base font-semibold text-slate-900
│ 2026 toplamı         │  ← açıklama text-sm text-slate-500, tek satır
└──────────────────────┘
  • Kap: flex flex-col rounded-2xl border border-slate-200 bg-card p-4 sm:p-5.
  • Sayı satırı: flex items-start justify-between gap-1.5; sayı §3 "Özet kartı sayısı"; ikon kutusu flex size-8 shrink-0 items-center justify-center rounded-xl bg-primary/10 sm:size-10.
  • dl anlamı için dt (başlık) DOM'da önce gelir, görsel sıra order-* ile kurulur.
  • Telefonda kart iç genişliği ~131 px: en uzun sayı ("13.889", 36 px'te ~90 px) + 32 px ikon sığar. Daha uzun sayı gelecekse önce ölç (§9.2), sonra yaz. Ölçülen sınır: 36 px'te "1.618.988" 123 px — ikonun altına girer. 6–7 haneli sayı birimle kısalır: 245.300 → 245 + birim bin, 1.618.988 → 1,62 + birim milyon (bölüm sayfasındaki kartSayisi).
  • Kullanıldığı yerler: üniversite ve bölüm sayfası. Kartlar sayım değil cevaptır (Bilal, 6 Eki 2026: "program/kontenjan/devlet/vakıf adedi ilgi çekmiyor, öğrencinin işine yaramıyor"): öğrencinin sorusu "girmesi ne kadar zor, yıllar içinde nereye gidiyor, boş kalıyor mu". Adetler özet paragrafta kalır, karta çıkmaz. Hesap src/lib/taban-ozeti.ts (KKTC uyruklu, açıköğretim ve uzaktan satırları yelpazeye girmez; doluluk bütün satırlar. KKTC üniversitesinin kendi sayfasında kıyas evreni kurumun kendisidir: il/kampüs dışlaması kalkar, ad kuralı kalır — yoksa DAÜ gibi kurumlarda kartlar "henüz taban oluşmadı" der, 6 Eki 2026 QA). Doluluk yüzdesi boş kontenjan varken 100'e yuvarlanmaz, en çok 99 yazar.
    • Bölüm (grid grid-cols-2 gap-4 lg:grid-cols-3, telefonda tek kalan üçüncü kart col-span-2; haritası yok): En yüksek taban (sıra + üniversite adı linkli) · En düşük taban (ücretsiz devlet örgün programı ≥3 ise devlet kümesinde, açıklama "Devlet · Bingöl Üni. · 2026 taban sırası"; etiket "Devlette en düşük" 131 px'te iki satıra kırıldığı için kısa tutulur) · Boş kontenjan. Orta taban kartı 6 Eki 2026'da kaldırıldı (Bilal: fazla geldi); hesabı taban-ozeti.ts'te duruyor. Etiketlerde "en seçici" ve "en geniş kapı" denmez ("En yüksek / En düşük taban" öğrencinin kendi dili); kullanıcıya dönük metinde "koltuk" değil kontenjan yazılır. Kartın içinde piksel çizgi/seri yok (Bilal, 6 Eki 2026: "çok boğdu"); yön kelimesi yeter.
    • Üniversite (harita yanındaki 2×2): En yüksek taban (sıra + bölüm adı linkli) · En düşük taban (aynı biçim) · Doluluk (%97) · Türkiye sırası (URAP; listede olmayan kurumda Kontenjan).
    • Sayının yanındaki ad (KartBaglantisi, taban-karti.tsx) karşı sayfaya gider: bölümde üniversiteye, üniversitede bölüme; stil kaynak linkiyle aynı (font-medium text-primary hover:text-orange-500 hover:underline). Üniversite adı kısaltılır ("Koç Üni.", "… MYO").
    • Yıl yıl ayrıntı çekmecesi ("Yıllara göre taban ›": tablo + kayıtlı sıraya göre "senin sıran nereye yetti") 6 Eki 2026'da Bilal'in isteğiyle şimdilik kaldırıldı; kartların altında yalnız eski ayrıntı satırı (Akademik göstergeler / Mezun istihdamı) durur. Geri gelirse sayı dili konuşma Türkçesi olur: "sıranın yettiği program" — "yerleşirsin" denmez.
  • Tıklanabilir kart (ör. Türkiye sırası → sıralama sayfası): kartın tamamı link olur (after:absolute after:inset-0 gerilmiş link), iç kaynak linki relative z-10 ile üstte kalır; hover §2.1.
  • Açıklama altında veri görseli gerekiyorsa (ör. PixelSira) ek yuvasına konur.

4.9 Ayrıntı satırı — AkademikAyrinti, akademik-ayrinti.tsx

Özet kartlarının altında "fazlası burada" satırı (Apple Sağlık'taki "Tüm verileri göster").

  • mt-4 flex w-full items-center gap-4 rounded-2xl border border-slate-200 bg-card p-4 sm:p-5
    • hover §2.1 + active:scale-[0.99].
  • Solda ikon kutusu (size-11), ortada iki satır: başlık font-heading text-lg font-bold, altında önizleme truncate text-sm text-slate-500 — içeride ne olduğunu söyler ("Hoca başına 25 öğrenci"), boş "Daha fazla" yazmaz. Sağda ChevronRight size-5 text-slate-400.
  • Dokununca alt sayfa açılır (§4.10).
  • Bir sayfada birden çok satır alt alta durabilir; her biri mt-4, kartlara en yakın konu en üstte. Bugün her sayfada tek satır var (üniversite: "Akademik göstergeler"; bölüm: "Mezun istihdamı").

4.10 Alt sayfa — AltSayfa, src/components/ui/alt-sayfa.tsx

Kabuk tek kaynak (Bilal, 7 Eki 2026: "bottom drawer yerine bottom sheet"): eski vaul çekmecesi kaldırıldı; yerinde Arc UI "Bottom sheet"ten taşınan AltSayfa var. Sayfa parmağı birebir izler: tutamaçtan, başlık alanından (AltSayfaSurukle) ya da içerik en üstteyken gövdeden aşağı çekince kapanır; yukarı çekince lastik gibi direnir; bırakınca hızını taşıyarak durağına oturur; kapanırken yakalanıp geri açılabilir. Perde zamanlayıcıyla değil sayfanın konumuyla koyulaşır. Parçalar: AltSayfa (kök) · AltSayfaTetik · AltSayfaIcerik (perde + yüzey + tutamaç) · AltSayfaGovde (kaydırılan alan mutlaka budur; sayfa onun kaydırmasıyla el sıkışır) · AltSayfaSurukle (kaydırmayan başlık alanı) · AltSayfaBaslik / AltSayfaAciklama · AltSayfaKapat. Yüzey sınıfı bileşenin içindedir (rounded-t-3xl border border-b-0 border-slate-200 bg-card shadow-2xl sm:max-w-2xl, tavan 92dvh); kullanım yerinde kap sınıfı yazılmaz. Boy içeriğe göredir. duraklar (ekran yüksekliğinin oranı) yalnız uzun, kaydırılan içerikte verilir: program ayrıntısı [0.6, 0.92] ile %60'ta açılır, yukarı çekince ya da kaydırınca tam boya çıkar (§4.19). İçinde kendi sürüklemesi olan öğe (sıralama tutamağı) data-alt-sayfa-yoksay alır. Bildirimdeki düğmeye basmak sayfayı kapatmaz. Hareketi azalt: kayma yok, yalnız opaklık.

Ayrıntı her zaman alttan açılan sayfada (AltSayfa, tutamaçlı); ekranın ortasında açılan modal değil. Çekmece kabı ve çarpı cta-sira-form.tsx'teki çekmeceyle birebir: <AltSayfaIcerik> + §4.3 çarpısı + <AltSayfaGovde className="px-4 pt-3 pb-[max(1.25rem,env(safe-area-inset-bottom))] sm:px-6">.

İçerik kuralları (Apple ayrıntı sayfası):

  • Her ekranda ortalı: başlık px-10 text-center font-heading text-2xl font-bold, altında bağlam (text-sm text-slate-500, ör. üniversite adı).
  • Kart yok. Çekmece zaten bir yüzey; içine çerçeveli kart koymak "pencere içinde pencere" olur. Gösterge kareleri (§4.11) bu kuralın istisnası değildir — onlar çerçevesiz, dolu renk.
  • Süs ayraç yok. Bölümler arasına piksel ayraç ya da çizgi konmaz; ayrım boşlukla ve yan yana dizilişle yapılır. Yalnız en alttaki kaynak satırı border-t border-slate-100.
  • Tek ekrana sığar: 375×812'de kaydırmasız. Dikine uzuyorsa öğeler yan yana dizilir, kareler kısaltılır, not kısaltılır — içerik silinmez (§9.2 ölçüm).
  • Sıra: gösterge kareleri → tek cümlelik not (text-sm text-slate-500) → ikincil buton (§4.1) → kaynaklar (logo solda, text-xs iki satır).
  • Liste çekmecesi (liste-cekmecesi.tsx, 24 Eyl 2026): başlık aynı düzende (temizle düğmesi çarpıyla aynı sınıf setinde solda). Satırlar çerçeveli kart değil, düz liste satırı (border-b border-slate-100); ad §4.15 gibi sarar, risk + taban sıra adın altında, çıkar düğmesi size-11 çerçevesiz CircleMinus — çarpı yalnız çekmeceyi kapatır (Bilal, 25 Eyl 2026: "2 çarpı var"). Listeler uzun olduğu için bu çekmece kaydırılır (tek ekran kuralının tek istisnası); alt bandı telefonda alt alta dizilir ki listeye en az ~280 px kalsın.
  • Rozet yok, ek liste yok (Bilal, 24 Eyl 2026: "buralarda badge kullanma"): çekmece ve sihirbaz modallarının başlığı üstünde SectionEyebrow durmaz; başlık + tek cümle bağlam yeter. "Saniyede gör" çekmecesi (cta-sira-form.tsx) bu düzene çevrildi: AltSayfaBaslik ortalı, AltSayfaAciklama bağlam, altında form; "neler alacaksın" çizgili ikon listesi kaldırıldı (bağlam cümlesi zaten söylüyor). Sihirbaz adımlarında çekmece başlığı sr-only, görünür başlık adımın kendisinde. Denetim: modal-rozet (hata).
  • Arama motoru uyarısı: çekmece içeriği sayfa açılırken HTML'de yoktur (kapalıyken çizilmez). Google'ın görmesi gereken metin ve zorunlu atıflar (ör. URAP sırası + payda + dönem + aktif bağlantı) çekmeceye taşınmaz, sayfada da görünür kalır.

4.11 Gösterge kareleri (masonry)

Birden çok sayıyı alt sayfada göstermenin yolu. Logodaki üç kare gibi: iki sütun, sağdaki aşağı kaymış, kare boyları farklı — ne tepeler ne bitişler hizalı.

┌────────┐
│ Türkiye│  ┌────────┐
│ sırası │  │ Hoca   │
│  5.    │  │ başına │
│ İlk %3 │  │  25    │
└────────┘  └────────┘
┌────────┐  ┌────────┐
│ 56.128 │  │ 2.225  │
└────────┘  │        │
            └────────┘
  • Kap: flex w-full max-w-md items-start gap-3; iki sütun flex flex-1 flex-col gap-3, sağdaki mt-12.
  • Kare: flex flex-col items-center justify-center rounded-3xl px-3 text-white + zemin (§2 "Gösterge karesi") + min-h-* ile farklı boy (ör. 40 / 24 / 32 / doğal).
  • Ölçüyle doğrula: komşu kareler arasında tepe ve bitiş farkı en az 24 px. 8 px fark "yanlışlıkla hizalanmış" görünür (§9.2).
  • Etiket text-sm font-bold text-white/90; sayı §3 gösterge ölçeği; vurgu satırı text-base font-bold.
  • Renk sırası: en önemli gösterge turuncu, ikincisi mavi, sonra indigo, yeşil.

4.12 Kimlik hapları (tür, il)

Başlığın altında kurumun kimliği; navbar haplarının ölçüsünde: inline-flex h-10 items-center gap-2 rounded-full border border-slate-200 bg-card px-4 text-sm font-semibold text-slate-800

  • başta size-4 text-primary ikon (Landmark devlet, Building2 vakıf, MapPin il). Tür renkle değil ikonla ayrılır. Rozet (§4.2) değildir. Devlet/vakıf hapı tür sayfasına (§4.18), il hapı şehir sayfasına linktir (Bilal, 24 Eyl 2026: "şehirlerin geçtiği her yer tıklanabilir") — aynı sınıf + hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97]. Kural genel: bir şehir adı nerede geçerse geçsin (/universiteler listesi, bölüm/sonuç/listem/ tadımlık satırlarındaki tür-il-süre metası) ilSayfaHref(il) ile /universiteler/[il]'e gider; satır metasında SATIR_IKINCIL_LINK. İstisna: satırın tamamı zaten link olan yerler (URAP sıralaması, arama sonucu) — iç içe <a> olmaz, orada düz metin kalır.

4.13 Piksel sıra şeridi — PixelSira, src/components/pixel-decor.tsx

Bir sıranın (ör. 198 içinde 5.) yerini tek satır piksel şeridinde gösterir; sıranın düştüğü dilim turuncu yanar, geri kalanı hero dokusunda. Veri taşıyan piksel olduğu için süs ayraç yasağına girmez.

  • Açık zeminde: <PixelSira sira={5} toplam={198} className="h-4" /> (8 hücre varsayılan).
  • Renkli dolu zeminde: zemin="koyu" — işaret beyaz yanar, ısı fırçası kapanır.
  • Anlamı her zaman yanındaki metin taşır ("5. / 198", "İlk %3"); şerit aria-hidden.

4.14 Üst çubuk başlık geçişi — NavBaslik, nav-baslik.tsx

iOS'taki büyük başlık davranışı: sayfa h1'i üst çubuğun altına girince üst çubuktaki "KolayTercih" yazısı yukarı kayıp söner, yerine sayfanın logosu + adı gelir; dokununca sayfa başına döner. Katalog detay sayfalarında (üniversite, bölüm) zorunlu; yeni detay sayfası eklenince aynısı yapılır:

<NavBaslik baslikId="uni-baslik" ad={uni.ad} logo={<UniLogo slug={slug} ad={uni.ad} boy="xs" />} />
<h1 id="uni-baslik" …>…</h1>

Logosu olmayan sayfada logo verilmez; üst çubukta yalnız ad görünür (bölüm sayfası — Bilal'in kararı: yerine ikon konmaz, üst çubukta süs ikona gerek yok). Logo sunucuda üretilip verilir (logo listesi istemciye inmez). Hareket: yay bounce: 0, duration: 0.35, giriş ve çıkış aynı yoldan; "hareketi azalt"ta yalnız opaklık.

Sürüm rozeti (src/components/surum-rozeti.tsx, 7 Eki 2026): logo yazısının hemen sağında "Beta" hapı + sürüm numarası. Hap Arc UI Badge (uiarc.dev/components/badge) sm boyunun karşılığı (yazı §3 alt sınırı gereği 11 yerine 12 px): inline-flex h-[22px] items-center rounded-full bg-indigo-500 px-2 text-xs leading-none font-semibold tracking-[-0.01em] text-white — renk akademik gösterge karesinin moru (§2.2 istisnası), renkli zeminde yazı font-semibold. Sürüm hapın içinde değil, yanında: text-xs font-medium text-slate-500 tabular-nums, hidden sm:inline (dar ekranda yalnız hap kalır). Rozet logo yazısıyla aynı fade sınıflarını taşır; NavBaslik yuvası açılınca birlikte söner. Sayı package.json'dan gelir (AGENTS.md "Sürümleme"); elle yazılmaz. Başka yerde tekrarlanmaz — SectionEyebrow kuralının tek istisnasıdır.

4.15 Liste satırı (program/üniversite listeleri) — src/components/liste-satiri.ts

Sınıf dizileri tek dosyada (SATIR_AD, SATIR_META, SATIR_CIP, SATIR_MOBIL_SAYI, SATIR_BUTON_KABI…); üniversite, bölüm ve /sonuc tabloları oradan okur. Yeni bir liste tablosu bu sabitleri kullanır, sınıfı elle yazmaz.

  • Risk sütunu (/sonuc) sm'den itibaren ayrı sütun; telefonda adın altındaki sayı satırına iner. Etiket §4.5: size-2 nokta + text-xs font-semibold text-{renk}-600 + RISK_ETIKET.
  • Veride BÜYÜK HARF gelen üniversite adı ekranda trBaslikDuzeni ile yazılır.
  • Ad kesilmez, sarar: whitespace-normal + block text-base font-semibold leading-snug. truncate ile "İngiliz Dili ve E…" yazılmaz.
  • Ad linkinin hover'ı mavi: transition-colors hover:text-primary hover:underline (§2.1 istisnası).
  • Telefonda yalnız ad + satır butonları sütun olarak kalır; sayısal sütunlar (taban sıra vb.) adın altındaki satıra iner: mt-1.5 flex items-center gap-1.5 text-sm text-slate-500 sm:hidden içinde değer font-semibold text-slate-900.
  • Üniversite alt satırı tek akan satır, telefonda bir kademe küçük (Bilal, 24 Eyl 2026: "mobilde çok şişko, her şey iç içe; üni adını daha küçük yazabiliriz"): adın altında üniversite adı (SATIR_ALT_AD) ile tür çipi/il/süre (SATIR_META) SATIR_ALT_GRUP içinde her genişlikte yan yana akar, sığmazsa sarar; telefonda text-xs, sm'den text-sm. /sonuc, rapor listesi, tadımlık satırı ve çekmece satırı (liste-cekmecesi.tsx) böyledir. Bu, §3 "text-xs yalnız ince yazıda" kuralının bilinçli istisnasıdır (12 px tabanının üstünde). Katalog listelerinde (ad zaten üniversite/bölüm) SATIR_GRUP: telefonda ad kendi satırında, çipler 8 px altında; sm'den aynı satırda. Ölçüm 375 px, bölüm sayfası: satır 129 px ve yüksekliği metin değil, alt alta iki 44 px düğme belirliyor — metin küçültmek orayı kısaltmaz.
  • Tür çipi: rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-semibold text-slate-700.
  • Satır butonları varsayılan size-11 (44 px); size-8 gibi küçültme verilmez. Telefonda iki buton alt alta durur (inline-flex flex-col items-center gap-2 sm:flex-row, sütun w-14 sm:w-28): yan yana 96 px yiyip adı 157 px'e sıkıştırıyordu, alt alta 273 px kalıyor (24 Eyl 2026 ölçümü).
  • Rapor listesinde (rapor-listesi.tsx) telefonda logo gizlenir (hidden sm:block): solda sıra numarası zaten satırı çapalıyor, logo adı üç satıra sıkıştırıyordu (satır 214 → 152 px). Açılan ayrıntı iç kutuları rounded-xl, etiket text-sm font-semibold text-slate-900, metin text-base.
  • Geniş ekranda ince satır (Bilal, 25 Eyl 2026: "geniş ekranda listeler çok kalın"): sm'den itibaren tür/il/süre satırı adla aynı satıra çıkar (SATIR_GRUP); lg'de hücre dolgusu py-3 ve satır düğmeleri 36 px (SATIR_DUGME_BOYU, §8 masaüstü tablo istisnası). Ölçüm 1280 px, bölüm listesi: 83 → 61 px. Telefonda değişmez (44 px düğme).
  • Satırda logo varsa (bölüm sayfası, /sonuc, rapor listesi) UniLogo boy="sm" adın solunda, items-start. sm = 48 px (size-12 rounded-xl; 36 px'ten büyütüldü — Bilal, 24 Eyl 2026: "listelerde üni logoları çok küçük kalmış"). Çekmecede üniversite satırının içindeki xs (28 px) metin içi kalır.
  • Program varyantı ("… (İngilizce) (Burslu)") adın altında ayrı satır mt-0.5 block text-sm leading-snug text-slate-600; tür çipine yapıştırılıp kesilmez.
  • Tür çipi devlet/vakıf için de aynı slate çip; vakıf violet değildir (§2.2).
  • Tablo başlığı h-12 text-sm font-semibold text-slate-500; hücre dolgusu py-4 pl-4 sm:pl-5.

4.16 Bildirim yığını (toast) — src/components/ui/bildirim.tsx

Bilal (7 Eki 2026): "toastlarımız için Toast stack kullanalım." sonner kaldırıldı; yerinde Arc UI "Toast stack"ten taşınan BildirimYigini (layout'ta bir kez) ve aynı çağrı biçimli toast var (toast.success(başlık, { description, action, id, duration }) — yalnız import yolu değişti). Bildirimler üst ortada birikir (altta çekmecenin çağrı bandı ve telefonda klavye var): yenisi yukarıdan iner, eskiler arkasına saklanıp altından 12 px şerit gösterir, en çok üçü görünür; üzerine gelince ya da dokununca yığın listeye açılır ve süre durur; sağa kaydırınca kapanır. Aynı id yeni bildirim açmaz, olanı yerinde günceller (metin dönüşür). Renkler palet token'ı olduğundan tema kendiliğinden doğru (eski sorun: sonner sistem temasına bakıp açıklamayı okunmaz ediyordu — Bilal, 24 Eyl 2026). Tür ikonu: başarı emerald-600, bilgi primary, uyarı amber-600, hata red-600, sürüyor dönen Loader2 text-primary; tür adı ekran okuyucuya yazıyla söylenir. Kutu rounded-2xl border-slate-200; başlık font-semibold text-slate-900; açıklama text-slate-600; aksiyon düğmesi üst çubuktaki koyu hap (h-9 rounded-full bg-slate-900, yazı slate-50, hover slate-700). Metin §10.4: ne oldu + ne yapılacak; kilometre taşı toast'ları (program-ekle-butonu.tsx) tek cümle açıklama + tek aksiyon taşır. İç düzen — tek hiza (Arc'ın düzeni; Bilal, 7 Eki 2026: "Arc'taki gibi hizalı görünüm olmuyor"). İkon, başlığın ilk satırı, aksiyon hapı ve çarpı aynı 36 px'lik şeridin ortasına oturur: içerik flex items-start gap-3 py-1.5 pr-1.5 pl-4; ikon kutusu h-9 w-5 (ikon size-5); metin py-2 text-sm leading-5; aksiyon hapı ve çarpı h-9 / size-9, sağda gap-1 tek grup. Tek satırlık bildirim 48 px'tir ve her şey kutunun tam ortasındadır; çok satırlıda ikon ve çarpı ilk satırla hizalı kalır. Aksiyonun yeri içeriğe göre: açıklama yoksa hap başlığın yanında, sağda ("Çıkarıldı · Geri al" tek satır); açıklama varsa metnin altında, metinle aynı sol hizada (mt-2.5) — yanında durursa Türkçe açıklamayı üç-dört satıra sıkıştırır. Eksi kenar boşluğuyla hizalama yapılmaz (eski hâlde çarpı ilk satırdan 4 px aşağıdaydı); yeni bir öğe eklenirse o da 36 px'lik şeride oturtulur.

4.17 Şehir çipleri — SehirCipleri, src/features/katalog/components/sehir-cipleri.tsx

Şehre göre üniversite gezinmesi (/universiteler üstü ve /universiteler/[il] altı). Sihirbazın il çipiyle aynı kalıp; etkileşimli çip olduğu için rozet (§4.2) değildir: inline-flex h-10 cursor-pointer items-center gap-1.5 rounded-full border px-3.5 text-sm font-semibold transition-[background-color,border-color,color,transform] duration-150 active:scale-[0.97]

  • pasif border-slate-200 bg-card text-slate-700 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500, bulunulan şehir border-primary bg-primary text-white + aria-current="page". Ad yanında üniversite sayısı font-normal tabular-nums text-slate-400 (aktifte text-white/80).
  • Çip satırında yalnız 2+ üniversiteli şehirler (≈28) durur; 90'ı aşkın şehrin tamamı /universiteler#tum-sehirler altındaki A–Z üç sütunlu metin listesindedir (§1.1 "sık bakılan önde, ayrıntı bir dokunuş derinde"). Satırın sonunda "Tüm şehirler (N)" çipi.
  • Şehir sayfası (il-icerik.tsx) katalog detay düzenindedir (§5.2): yol satırı, başlık yüzeyi (SehirYuzeyi: relative isolate overflow-hidden rounded-3xl border border-slate-200 bg-card p-6 sm:p-8, PikselZemin ton="acik" seed 31, harita kabı haric), içinde h1 "İstanbul Üniversiteleri Taban Puanları 2026", kimlik hapları (MapPin il + üniversite sayısı), özet paragraf; sağda (lg, 24rem sütun) ya da altta (telefon) şehri temsil eden piksel harita SehirPikselHaritasi. Sonra kompakt CtaSiraForm, PagePixelDivider (seed 71), devlet / vakıf / KKTC-yurt dışı öbekleri — her biri §4.15 liste satırı (UniSatirlari: kenarlıklı rounded-xl liste, 48 px logo, SATIR_AD_DUZ ad, SATIR_META içinde tür çipi + program sayısı, satırın tamamı link, sağda kayan ok; Bilal, 24 Eyl 2026: "il kısmında üniler küçük gözüküyor" — /universiteler dizinindeki iki sütunlu kompakt UniLinkleri burada kullanılmaz), "Diğer şehirler" çipleri ve mavi CTA bandı. Şehir adı trBaslikDuzeni + tire sonrası baş harf (Bakü-Azerbaycan). Bir üniversite programı olan her ilde sayılır (ODTÜ Ankara + KKTC).
  • Şehir piksel haritası — sehir-piksel-haritasi.tsx: hero'daki dot-matrix Türkiye'nin kendisi (Bilal, 24 Eyl 2026: ince taramalı ilk sürüm "oyunsu Apple/Duolingo hissine uymuyor" diye geri alındı; seçenekler A/B/C arasından "A, pikseller C'deki gibi iri" seçildi). Izgara 56 sütun × 24 satır (scripts/il-izgara-uret.ts → src/lib/il-izgara-verisi.ts; her il en az 2×2 kare; Bilal: "piksel detaylarını azalt"), kare hücrenin %74'ü, altı farklı opaklık, serpinti yok, text-primary zemin, imleç yaklaşınca turuncuya ısınma (usePixelHeat, meet/slice ve canlı viewBox ile). Bulunulan ilin kareleri fill-orange-500, hücrenin %88'i kadar iri, 35 ms arayla belirir (kt-piksel-belir) ve grup hâlinde nabız atar (animate-pulse 3.6 s); hareketi azalt açıkken dolu ve durağan. KKTC/yurt dışı: ülke kontürü mavi doku, şehir merkezinde 2×2 hücrelik tek iri turuncu kare; şehri bilinmeyen "KIBRIS" için ülkenin tamamı turuncu. Markup hero'daki gibi deterministik string (dangerouslySetInnerHTML). role="img" + "İstanbul Türkiye haritasında". Üniversite sayfasının konum kartı (universite-konum-haritasi.tsx) aynı bileşeni kullanır. Veri taşıyan pikseldir (§1.2), süs ayraç yasağına girmez.
  • Harita arka plandır, kesilmez (Bilal, 24 Eyl 2026: "canvas net bir şekilde kesiliyor, çok kötü"; "harita bulunduğu yerin tamamını kaplasın"). Şehir sayfasında SehirYuzeyi kartını doldur (slice) ile kaplar, metin üstünde; kenarlar mask-image ile erir — telefonda yukarıdan (metnin altında belirir), lg'de soldan (sağ yarıda belirir). Metin sütunu lg'de %58, kart en az 26rem; telefonda altta 12–14rem harita payı. Üniversite sayfasında harita dört özet kartın arkasına sarkar (Bilal, 24 Eyl 2026): ızgara relative isolate, üçüncü sütun yalnız yer tutar, harita absolute -inset-x-4 -inset-y-8 -z-10 katmanda; lg'de sağdan sola, telefonda üst satırdan aşağı doğru uzun rampalı mask. Mask rampaları uzun tutulur (şeffaf → %6 → %30 → siyah); kısa rampa "kanvas" gibi okunur. Sert kenarlı, kırpılmış bir SVG asla görünmez.
  • Yakınlaşma (Bilal, 24 Eyl 2026: "ilin bulunduğu yere doğru harita büyüsün, sayfa yüklendikten sonra delay ile motion ile"): SSR tüm ülke; yüklenince 0,6 s sonra viewBox sıçramasız yayla (spring, bounce 0, 1,6 s; Apple'ın damping 1'i — ease-out "sert" duruyordu) ilin çevresindeki kutuya kayar — en çok 2,4 kat (ülke haritasında şehir işaretine 1,8 kat). Kutu kabın o anki oranında kurulur ve il odakHiza ile kabın istenen noktasına gelir (şehir sayfası: lg'de x 0,74 / y 0,5, telefonda x 0,5 / y 0,78; üniversite sayfası: lg'de x 0,82 / y 0,5 — üçüncü sütun, telefonda y 0,17 — üst satır). Kareler büyür, il kadraja gelir; ısı fırçası viewBox'ı canlı okur. Hareketi azalt açıkken kutuya doğrudan atlanır. Sayfa başına tek yakınlaşma.

4.18 Tür sayfaları — /universiteler/devlet, /universiteler/vakif (tur-icerik.tsx)

Bilal (24 Eyl 2026): "vakıf ve devlet de tıklanabilir olmalı, özel sayfalar yapabilirsin, kreatif". Şehir sayfasının iskeleti (§4.17) ile: yol satırı, SehirYuzeyi başlık yüzeyi, kimlik hapları (tür + öteki türe geçiş hapı), özet paragraf, kompakt CtaSiraForm, üç OzetKart (üniversite / program / şehir; grid grid-cols-2 gap-4 lg:grid-cols-3, üçüncü telefonda tam genişlik), "Şehre göre" çipleri (sayfa içi #sehir-… çapaları), şehir şehir §4.15 UniSatirlari, altta mavi CTA bandı.

  • Kreatif: başlık yüzeyindeki dot-matrix Türkiye'de bu türden üniversitesi olan her il turuncu yanar (TurkiyePikselHaritasi iller=[…]), yakınlaşma yok — "devlet üniversiteleri Türkiye'nin neresinde" tek bakışta. Vakıfta harita seyrek yanar; bu bilginin kendisidir.
  • Tür çipi tek kaynak TurCipi (src/components/tur-cipi.tsx): devlet/vakıf (ve Vakıf MYO) tür sayfasına link, KKTC/yurt dışı düz çip; /sonuc, /listem, tadımlık, bölüm sayfası ve şehir/tür satırları bunu kullanır. Satırın tamamı link olan yerde kullanılmaz.
  • /universiteler dizinindeki "Devlet Üniversiteleri" / "Vakıf Üniversiteleri" başlıkları da tür sayfasına link.

4.19 Program ayrıntı çekmecesi — program-ayrinti.tsx (eski adı "Netler paneli")

Bilal (24 Eyl 2026): "bu kısımlar design md'ye uygun yap, belirt ki bir daha bu hata olmasın". Panel ortada açılan Dialog ve text-xs hücreli bir tabloydu; iki kural birden çiğnenmişti. Kural: program satırından açılan her ayrıntı (netler, akademik göstergeler, kontenjan geçmişi) §4.10 alt sayfadır — AltSayfa, kap ve çarpı cta-sira-form.tsx çekmecesiyle birebir, başlık px-10 text-center font-heading text-2xl font-bold, altında tek cümle bağlam text-sm text-slate-500. İçindeki tablo §4.15'tir: başlık SATIR_BASLIK, hücre text-sm (gövde text-xs'e inmez, §3), sayılar font-sans tabular-nums, en yeni yıl koyu (font-semibold text-slate-800/900), eski yıllar text-slate-500; toplam satırı ("Yerleşme puanı") border-t border-slate-200 + font-semibold text-slate-900; ilk sütun pl-0. Boş ve hata durumu text-base text-slate-500. Denetim: tablo-minik-yazi (hata) — TableCell/ TableHead içinde text-xs yazılamaz. Dialog yalnız arama penceresi (katalog-arama) ve sihirbaz modalı içindir; yeni bir ayrıntı için Dialog açılmaz.

  • 6 Eki 2026 — netlerden tüm ayrıntıya: satırın yuvarlak düğmesi (Info ikonu, "ayrıntı") tek çekmece açar; veri /api/program-ayrinti. Sıra: başlık = program adı, bağlam = üniversite · il · fakülte; künye hapları (§4.12 ölçüsü, link değil: süre + tür, dil, öğretim türü (örgün değilse), burs/ücret, akreditasyon, baraj, öğretim üyesi sayısı, yalnız kız/erkek koşulu, kampüs ilçesi — yalnız verisi olanlar); "Yıllara göre" tablosu (yıl, taban sıra, puan, kontenjan, yerleşen); "Kontenjan türleri (yıl)" dl satırları (yalnız >0 olanlar; özel kontenjanın ayrı taban sırasının elimizde olmadığı notu); "Son yerleşenin netleri" (eski tablo + OBP katsayısı satırı; 0,18 = meslek lisesi ek puanı notu); "Yerleşme koşulları (N)" yerel details ile kapalı başlar; "Mezun istihdamı" ve "Üniversite" tek paragraf; en altta kaynak satırı border-t border-slate-100 text-xs. Bölüm başlıkları font-heading text-base font-bold, notlar text-sm text-slate-500; süs ayraç yok, kart yok. İçerik uzun olduğu için çekmece kaydırılır (liste çekmecesi gibi; §4.10 tek ekran kuralının ikinci istisnası). Açık listem satırında aynı çekmece varyant="metin" ile "Program ayrıntısı" metin düğmesinden açılır ("Haritada gör" kalıbı).

4.20 Danışman sohbeti — sohbet-client.tsx, arac-pilleri.tsx

Sohbet kabuğu prompt-kit bileşenleridir (src/components/ui/: prompt-input, message, chat-container + scroll-button, prompt-suggestion, loader, markdown); yeni bir sohbet parçası gerekince önce prompt-kit'e bakılır (shadcn add https://prompt-kit.com/c/<ad>.json). Bilal (6 Eki 2026): "tool use durumunda pill'li bir UI; danışmanla konuş alanı motion ile genişletilebilir olmalı; UI için prompt-kit kullan."

  • Araç hapları (AracPilleri): danışman veriye bakarken cevabın üstünde hap satırı — §4.17 kompakt çip (inline-flex h-8 items-center gap-1.5 rounded-full border border-slate-200 bg-card pl-2.5 pr-3 text-xs font-semibold text-slate-700), başta durum ikonu size-3.5: sürüyor Loader2 animate-spin text-primary, bitti Check text-emerald-600, hata CircleAlert text-red-600. Metin öğrenci dilinde ve zamanı söyler ("Programlara bakıyorum…" → "Programlara baktım"); hata sözle ("… (veri gelmedi)"), renk tek başına değil (§2.2). Aynı araç birden çok kez çağrıldıysa tek hap + "×2". Haplar cevap bitince kalır (danışmanın neye baktığı güven verir); kayıtlı geçmişte araç parçası olmadığından yalnız canlı cevapta görünür. Hap aşağıdan 4 px gelir, ikon durumla çapraz söner (yay, bounce 0, 0,3/0,2 s); hareketi azalt'ta yalnız opaklık. role="status" aria-live="polite". prompt-kit'in Tool bileşeni kullanılmaz: ham araç adı (program_ara), İngilizce rozet, JSON girdi/çıktı ve dark: sınıfı taşır — öğrenciye araç adı ve iç kimlik gösterilmez (danisman-prompt.ts); yalnız durum modeli (input-streaming → output-available | output-error) ortaktır.

  • Genişletme — yerinde büyür, komşular yeniden akar (Bilal, 6 Eki 2026: tam ekran/perde denemesi "çok kötü"; "div'in smooth genişlemesi, diğer alanların kendini yeniden boyutlandırması"). Başlıktaki Maximize2 düğmesi (size-7, öteki başlık düğmeleriyle aynı sınıf) iki şeyi aynı yayla (§6, SOHBET_GENISLEME_GECISI) sürer: sayfa önce panelin üstü sticky hizasına (top-28, 7rem) gelecek kadar yayla kayar, panelin boyu oradan alt progressive blur'un (.kt-sayfa-blur-alt, 7rem) üstüne kadar uzar — yani ekran − 14rem; sayfa o kadar kaymıyorsa kalan fark boydan düşülür, panel bulanık şeride girmez (Bilal, 6 Eki 2026: "aşağı kısmı progressive blura takılıyor") (ölçülen px'ten hedefe animate(el, { height }), bitince satır içi değer bırakılır) ve /listem ızgarasında sohbet sütunu genişler — sütun genişliği CSS değişkeni --sohbet-kolon (lg 380 px, xl 440 px; lg:grid-cols-[minmax(0,1fr)_var(--sohbet-kolon)]), animate(izgara, { "--sohbet-kolon": "<px>" }) ile ızgara genişliğinin %60'ına (en çok 760 px) büyür; liste ve harita daralan sol sütunda kendini yeniden akıtır. Telefonda (lg altı) yalnız boy uzar. Minimize2 geri alır; sohbet durumu (useChat, kaydırma) korunur. Hareketi azalt: geçişsiz. Perde, sabit konum, ayrı Dialog/AltSayfa yok — sohbet yeniden kurulmaz, sayfa zıplamaz.

  • Dar hâlin boyu — sayfa en üstteyken de bulanık şeridin üstünde biter (Bilal, 7 Eki 2026: "yüksekliğini alttan kısalım, progressive blur üzerine geliyor, sığmıyor"). Sınıf tek yerde: SOHBET_DAR_BOY (sohbet-client.tsx) = h-[calc(100dvh-23.75rem)] min-h-[340px] sm:h-[calc(100dvh-24.75rem)] lg:h-[calc(100dvh-21.5rem)]. Düşülen pay = panelin sayfa en üstteykenki üst boşluğu (sezon bandı + site başlığı + main py-12 + ızgara mt-8; ölçüldü: telefonda 251, 768 px'te 267, 1280 px'te 217 px) + 7rem şerit + 1rem nefes. Eski 18rem sezon bandını saymıyordu. Paketsizdeki 480 px'lik panel aynı sayıları max-h olarak taşır. Sezon bandı ya da başlık boyu değişirse bu üç sayı yeniden ölçülür (§9.2).

  • Elle boyutlandırma ve telefonda sıra (Bilal, 7 Eki 2026): geniş ekranda liste ile sohbet arasındaki boşlukta BolmeTutamaci durur (§4.25); sürükleyince aynı --sohbet-kolon değişkeni değişir (sohbet 320–820 px, liste en az 420 px), çift tık varsayılana döner. "Genişlet" düğmesi elle verilen genişlikten devam eder; "Daralt" varsayılana döner. Telefonda (lg altı) danışman en üsttedir: sütun kabı max-lg:contents, sohbet max-lg:order-first, paketsizdeki paket kartı max-lg:order-last — harita ve liste sohbetin altında akar.

  • Bağlantı hapları (sohbet-baglanti.tsx, Bilal 6 Eki 2026: "chat link verdiğinde kod gibi veriyor"): danışman cevabındaki site içi adres (/rehber/…, /universite/…, /bolum/…, /universiteler/<il>, /paket, /listem) prompt-kit Source kalıbında küçük satır içi hap (ilk sürüm h-7 "çok yer kaplıyordu"): inline-flex h-6 items-center gap-1 rounded-full border border-slate-200 bg-card pl-1.5 pr-2 text-xs font-medium text-primary + türü söyleyen size-3.5 ikon (BookOpen rehber, Landmark üniversite, GraduationCap bölüm, MapPin şehir, Coins paket, ListChecks listem), hover §2.1, sr-only tür etiketi. Metin markdown bağlantısının başlığıdır (prompt kuralı: [Yazının başlığı](/rehber/slug)); model adresi çıplak ya da backtick içinde yazarsa aynı hap slug'dan türetilen adla çizilir (baglantilariIsaretle, InlineKod). Dış bağlantı (https://) yeni sekmede açılan altı çizili düz link. prompt-kit Source'un Google favicon'u ve muted paleti dış siteler içindir, alınmadı. Sohbet balonu prose sınıfı taşır ama typography eklentisi yok — bağlantı/kod görünümü bu bileşenlerden gelir.

  • Bağlantı önizlemesi — imleci izleyen mini pencere (Bilal, 6 Eki 2026: motion-primitives Cursor örneği + "aramada yaptığın gibi MacBook penceresi gibi bir kanvas"): rehber, üniversite, bölüm ve şehir haplarının üzerine gelince (yalnız (hover: hover) and (pointer: fine); dokunmatikte yok) body'ye portal'lanan 288 px'lik pencere imleci yayla izler (useSpring stiffness 450 / damping 40, imlecin 18 px sağ altı; kenara sığmazsa sol/üst) ve height 0 → auto, opacity, scale 0,3 → 1 ile açılır, aynı yoldan kapanır (spring, 0,3 s, bounce 0 — §6; örnekteki 0,1 bilinçli alınmadı). Pencere dili aramadaki mini tarayıcıyla aynı (katalog-arama.tsx KESFET_TONLARI slate): rounded-xl border border-slate-200/80 bg-card shadow-lg shadow-slate-900/5, çubuk h-6 bg-slate-50/90

    • üç size-2 bg-slate-300 nokta (1 / 0,65 / 0,35) + adres hapı (kolaytercih.com/rehber/…, text-xs text-slate-500). Rehberde gövde yalnız kapak: tam RehberKapak (compact yok) 1200×630 çizilip scale(288/1200) ile pencereye oturur — yazı, logo ve piksel süs kesilmez; başlık/özet/iskelet yok. Üniversite/bölüm/şehir gövdesi p-3: UniLogo md ya da §4.4 ikon kutusu, başlık font-heading text-sm font-bold line-clamp-2, özet text-xs leading-5 text-slate-500 line-clamp-3, künye text-xs font-medium text-slate-500 ("URAP 18/198"). Veri /api/onizleme?yol= (bir gün cache, hap başına bir kez; iskelet yok, başlık hap metninden hemen çizilir). pointer-events-none, aria-hidden — bilgi hapın kendisinde. Hareketi azalt: izleme yok, yalnız opaklık.
  • Araç adımları — prompt-kit Steps (src/components/ui/steps.tsx + collapsible.tsx; Bilal: "Steps de olsun duruma göre"): bir cevapta iki ve daha çok araç varsa haplar yerine Steps: başlık text-xs font-semibold text-slate-500 sürerken "Veriye bakıyorum · 2/3", bitince "3 adımda baktım", solunda durum ikonu (hover'da prompt-kit'in ok değişimi); açılır gövdede solda w-0.5 bg-slate-200 çubuk, sağda her adım text-xs font-medium text-slate-700 + durum ikonu. Açık başlar, kullanıcı kapatabilir; açılma animate-collapsible-down/up (tw-animate-css), hareketi azalt'ta geçişsiz. Tek araçta hap kalır. Palet slate'e çevrildi (muted/popover yok).

  • Liste uyarıları sohbette, danışmanın ağzından (Bilal, 6 Eki 2026: "bu tarz uyarıları danışmanın turuncu danışmanla konuş logosu ile chatte vermesi daha uygun"). Listenin kendisinden çıkan uyarılar (dağılım havuza uyarlandı, tüm tercihler tek şehirde — liste-uyarilari.ts) listenin üstünde sarı kutu olarak çizilmez; sohbetin açılışında, "Danışman özeti"nin hemen altında "Danışman uyarısı" mesajı olur: avatar DanismanAvatar renk="turuncu" (panel başlığındaki işaretin rengi, durağan — avatarda hareket yalnız "düşünüyor" demektir), etiket özetle aynı (text-xs font-semibold text-slate-500), balon işaretin turuncusunda dolu zemin (bg-orange-500 font-medium text-white — Bilal, 6 Eki 2026: "uyarı bubble'ı danışmanın logosu backgroundında olmalı"); birden çok uyarı tek avatarın altında ayrı balonlardır. Bu, §2.2'deki "turuncu dolu zeminde uzun metin konmaz" kuralının bilinen tek istisnasıdır: uyarı en çok iki kısa cümledir, daha uzun metin bu balona konmaz; öteki danışman balonları gri kalır (bg-slate-100 text-slate-800). Renk tek başına anlam taşımaz: "Danışman uyarısı" etiketi her zaman yazılıdır (§2.2). Sohbet ilerlese de kalır. Yeni bir liste uyarısı gerekince listeUyarilari'na eklenir, sayfaya yeni kutu açılmaz.

  • Liste revizyonu sohbette (Bilal, 7 Eki 2026: "revize sistemi tamamen chate taşınsın"; geri bildirim: eski kutudan "ilk 5 X ilinden olsun" denince liste değişmiyordu — not modele serbest metin gidiyor, sıra ve havuz koddan belirleniyordu). /listemdeki revizyon kutusu kaldırıldı; başlıktaki "Revize et" düğmesi sohbet kutusunu odaklar (sohbetiOdakla). Danışman belirsiz isteği soru formuyla netleştirir (soru_sor → §4.33 SohbetAnketi, balonun altında sade kutu), sonra liste_revize aracıyla yapısal kural verir (il/alan/tip farkı, "ilk N" ölçütü, çıkar/ekle, iskelet; lib/revizyon-kurali.ts); liste koddan yeniden kurulur, sayfa router.refresh() ile yenilenir, hap "Listeni yeniden kurdum" olarak kalır. Form cevabı kredi harcamaz. Kayıtlı geçmişte form ve revizyon sonucu chat_messages.metadan geri kurulur.

4.21 Sayı rulosu — SayiRulo, src/components/ui/sayi-rulo.tsx

Ekranda değişen sayı (üst çubuk rozeti ve kredi hapı, "Listende 5/24", çekmece sayacı, danışman kredi rozeti, "40 / 312 program", üst şeridin sezon geri sayımı, giriş formunun "Yeniden gönder (59)" sayacı, kaydet bildirimindeki seçim sayısı) rulo gibi döner: eklemede yukarı, çıkarmada aşağı; basamak artınca yeni sütun yayla açılır. Yazı boyu/rengi kapsayıcıdan gelir. Yay §6 varsayılanı; hareketi azalt'ta düz metin; ekran okuyucu düz metni okur. Kaynak Arc UI "Number field" (uiarc.dev, 6 Eki 2026); oradaki −/+ adım butonları ve sürükleme alınmadı — sıralama girişi Input hapı olarak kalır (§4.6), rulo yalnız gösterime takılır. Durağan sayıya (taban sıralaması, kontenjan) takılmaz. Geri sayım gibi basamak dolgusu isteyen sayaçta enAzBasamak={2} ("05") ve sabit yon={-1} (00 → 59 sarması da aşağı döner) verilir; sitede ikinci bir rakam kütüphanesi yoktur (@number-flow/react 6 Eki 2026'da kaldırıldı, üst şerit de bu ruloyu kullanır).

4.22 Kayan vurgulu seçim hapları — SecimHaplari, src/components/ui/secim-haplari.tsx

Tek seçimli hap grubunda seçili vurgu yeniden boyanmaz, tek yüzey olarak seçenekten seçeneğe kayar (layoutId). ayrik: kenarlıklı ayrı haplar + mavi dolu vurgu (puan türü çipleri — hero ve CTA formu). kapsul: tek kapsülde koyu hap, yazı text-slate-50 (tema seçici). Yay §6; hareketi azalt'ta vurgu yerinde belirir. Kaynak Arc UI "Chip group" (6 Eki 2026). Çok seçimli çipler (sihirbaz alan/il) bu desene girmez — onlar §4.24 SecimCipi'dir (seçilince tik büyür).

4.23 Kaydırma eylemi — KaydirmaGrubu + KaydirmaSatiri, src/components/ui/kaydirma-eylemi.tsx

Bilal (7 Eki 2026): "Arc'taki swipe action'ı bizdeki listeye getir." "Kendi Listem" satırı sola kaydırılınca altından "Çıkar" eylemi açılır (80 px, bg-red-500 text-white, ikon + yazı); sonuna kadar çekilince eylem satırın tamamını kaplar ve bırakınca uygulanır, dokunmatikte eşikte kısa titreşim verir. Aynı anda tek satır açık kalır; başka yere dokunmak ya da Escape kapatır. Çıkarma §10.5 gibi geri alınabilir bildirimle biter. Eylem, satırda görünen bir düğmeyle de yapılabilmelidir (listede CircleMinus): klavye ve ekran okuyucu yolu odur, kaydırılan kopya aria-hidden. Dikey sıralama tutamağı ayrı kalır. Tonlar: tehlike (kırmızı; etiket sonucu söyler), vurgu (mavi), notr (slate). Kaynak Arc UI "Swipe actions"; "Diğer eylemler" menüsü alınmadı. Yeni bir listede kaydırma gerekirse bu bileşen kullanılır, elle drag="x" yazılmaz.

4.24 Seçim çipi ve çip grubu — SecimCipi + CipGrubu, src/components/ui/cip-grubu.tsx

Bilal (7 Eki 2026): "chip group'u pills seçimi olan yerlerde kullanalım." Çok seçimli hap seçimlerinin tek kaynağı (sihirbazın alan, şehir, üniversite tipi, öncelik ve özel kontenjan çipleri). Sınıf §4.17 çipi (44 px; kucuk 40 px; seçili border-primary bg-primary text-white; ton="bilgi" pasifte mavi ton). Seçilince başta tik kendini çizerek büyür, yazı yana kayar, çipin kenarı yayla izler, komşular akışla yer açar — seçili hâl renk + tik'tir (§2.2). CipGrubu gruba ad verir (etiket) ve ok tuşlarıyla çipten çipe geçirir. Kaynak Arc UI "Chip group"; komşuları layout projeksiyonuyla kaydırma alınmadı (kayan alt sayfa ve ölçülen sihirbaz paneli içinde erken ölçüm satırları kaydırıyordu), "+N daha" katlaması da yok. Tek seçimde kayan vurgu §4.22.

4.25 Bölme tutamacı — BolmeTutamaci, src/components/ui/bolme-tutamaci.tsx

Bilal (7 Eki 2026): "Resizable panels ile danışmanın bulunduğu sayfada ölçeklendirme yapılabilsin." Yan yana iki alanın arasındaki 24 px'lik boşlukta duran ayırıcı: dinlenirken silik bir tutamaç (h-10 w-1.5 bg-slate-300), üzerine gelince / odakta / sürüklerken turuncu ve uzun (§2.1), yanında ince turuncu çizgi. İşaretçiyi birebir izler, sınırın ötesinde lastik gibi direnir ve bırakınca sınıra döner. role="separator": ok tuşları 16 px (Shift 64 px), Home / End sınırlar, çift tık varsayılan. Genişliği çağıran tutar (oku / yaz / sinirlar); /listem'de ızgaranın --sohbet-kolon değişkeni (§4.20). Yalnız lg ve üstünde görünür. Kaynak Arc UI "Resizable panels"; sabit boylu kap ve bölmeyi tamamen kapatma alınmadı (sayfa kayıyor, sohbet yapışkan).

4.26 Yazı dönüşümü — YaziDonusumu, src/components/ui/yazi-donusumu.tsx

Kısa bir ifade yerinde bir sonrakine dönüşür: ortak harfler yeni yerine süzülür, yeniler netleşerek gelir, gidenler bulanıp söner, genişlik yayla izler. Şu an sayfada kullanılmıyor: ana sayfa başlığındaki dönen vurgu ("gerçek veriyle" → "risk hesabıyla" → "gerekçesiyle") 7 Eki 2026'da geri alındı (Bilal: "diğer ana sayfa bileşenleri eski hâline gelsin"); başlık yine sabit "gerçek veriyle" yazar. Bileşen dosyası duruyor. Kaynak Arc UI "Text morph". Yeni kullanım: yalnız birkaç harfi değişen kısa durum yazısı; paragraf ya da uzunluğu çok değişen metin dönüştürülmez (Bilal'in 24 Eyl 2026'da kaldırdığı "yazılıp silinen satır" geri gelmez).

4.27 Kart destesi — KartDestesi, src/components/ui/kart-destesi.tsx

Kartlar tek tek sorulur: üstteki kart sağa/sola sürüklenip fırlatılır (parmağın hızını taşır), arkadakiler o uzaklaştıkça kalkar; aynı karar düğmelerle ve ok tuşlarıyla verilir, "Geri al" kartı çıktığı yerden getirir. Kart rounded-3xl border border-slate-200 bg-card, boyu --kart-boyu (19rem); düğmeler 44 px hap — sol ikincil (hover §2.1), orta sessiz, sağ mavi dolu (turuncu yalnız funnel CTA'sı). Sürüklerken beliren damgalar hap; onay damgası mavi tonda (yeşil risk dilindedir, burada kullanılmaz). Kaynak Arc UI "Card stack".

  • "Bu program listene girer mi?" demosu (deste-demosu.tsx, veri landing-verisi.ts ornekProgramlar): örnek sıralamaya (Sayısal 85.000) göre gerçek yedi devlet programı. Kartta künye şeridi (il · Devlet), ad, üniversite, iri taban sıralaması (§1.1) ve RiskEtiketi. Uydurma sayı yok; veri okunamazsa çizilmez. Bitince tek turuncu CTA forma götürür. Ana sayfadan çıkarıldı (7 Eki 2026) — Bilal: "bunu oyunlaştırmada ilerde kullanacağız". Dosyalar duruyor; şu an hiçbir sayfada çizilmiyor.

4.28 Veri akışı — VeriAkisi, src/features/pazarlama/components/veri-akisi.tsx

Ana sayfa "Nasıl çalışır" bölümünde, üç adımın (§4.32) altında: ortada KolayTercih işareti, çevresinde altı girdi; her girdiden merkeze düz çizgi iner, üzerinde piksel kare akar. Solda öğrencinin üç seçimi (turuncu ikon ve kare), sağda YÖK Atlas'ın üç verisi (mavi ikon ve kare); ayrımı etiket ve yan taşır, renk eşlik eder (§2.2). Akış CSS'tir (kt-akis, globals.css), yalnız ekrandayken oynar; hareketi azalt'ta kareler durur. Esin React Bits "Center Flow"; kod bizim — parlama ve bulanıklık yok, akış içeri doğru. Yeni bir girdi eklenirse sihirbaz/havuz kurallarıyla aynı olmalı (/meraklisina şemasıyla çelişmez).

  • Çizgi düz, karolar beyaz (Bilal, 7 Eki 2026: "aradaki yerler solid çizgi olsun, etrafındaki kartların bg'si ve görünümü daha iyi olabilir"). Çizgi var(--color-slate-300), 1,5 px (vectorEffect="non-scaling-stroke"), karonun merkezinden işaretin merkezine çekilir ve karoların altında kalır; kesik/noktalı çizgi yazılmaz. Girdi karosu size-14 rounded-2xl border border-slate-200 bg-card + size-6 ikon; ortadaki karo size-24 rounded-3xl border border-slate-200 bg-card. Renkli soluk zemin (bg-orange-50/60, bg-primary/10) kaldırıldı: karo dolu olmalı ki çizgi içinden görünmesin. Gölge yok (§6).
  • Kartsız, zeminsiz; bilgiler iki yanında, onlar da kartsız (Bilal, 7 Eki 2026: "kartın dışında, arka plansız, sağında solunda da alttaki bilgiler olacak şekilde"; aynı gün: "hero'daki gibi ferah"). Geniş ekranda (lg+) üç sütun (lg:grid-cols-[minmax(0,1fr)_22rem_minmax(0,1fr)], xl'de orta 24rem, dikeyde ortalı): solda dürüstlük notu — SectionEyebrow + h3 (font-heading text-2xl font-bold text-balance, ikinci yarısı hero başlığındaki vurgu: font-bricolage font-bold tracking-tighter text-primary italic) + text-base paragraf, sola yaslı, max-w-xs; ortada animasyon; sağda üç sayı alt alta, sağa yaslı (YÖK Atlas girdilerinin yanında — sayılar o verinin sayılarıdır). Sayı §1.1: font-heading text-4xl font-bold leading-none tracking-tight text-primary sm:text-5xl, birim ("yıl") §3'teki gibi font-sans text-base font-semibold text-slate-400, etiket text-sm font-semibold text-slate-500. Çerçeve, zemin, ayırıcı çizgi ve sayının yanında piksel süs yok. lg altında tek sütun, her şey ortalı: animasyon → sayılar (sm'de üçü yan yana) → dürüstlük notu.
  • İşaret site başlığındaki logonun animasyonunu oynar (AnimasyonluMark, varsayılan "rota": kareler sırayla birbirinin yerine süzülür). Başlıkta üzerine gelince, burada ekrandayken sürekli (oynat); ekrandan çıkınca kareler yerine oturur. Nabız + tüm karoyu döndüren eski hâl (kt-akis-donus) yanlıştı ve kaldırıldı (Bilal, 7 Eki 2026). Hareketi azalt'ta durağan.

4.29 Program duvarı — ProgramDuvari, src/features/pazarlama/components/program-duvari.tsx

Şu an sayfada kullanılmıyor: ana sayfa "Sorun" bölümünden 7 Eki 2026'da çıkarıldı (Bilal: "diğer ana sayfa bileşenleri eski hâline gelsin"); bölüm yine yalnız üç kartla açılır. Dosya duruyor. Tarif: "Binlerce ihtimal"in resmi: aramadaki mini pencere dilinde (rounded-2xl, üç noktalı h-9 çubuk, §4.20) bir tuvalde piksel kareler satır satır akar — her kare bir program; aralarında tam 24 turuncu kare sırayla belirir ve yerinde kalır (senin listen). İmleç yaklaştığı satırları hızlandırır. Izgara hero'nun ölçüsü (hücre 10, nokta 7.4, köşe 2), mavi doku opaklıkları aynı; renk CSS'ten okunur, tema değişince yeniden çizilir. Tek <canvas>, ekrandayken ~30 fps; hareketi azalt'ta durağan. Anlamı altındaki cümle söyler. Esin React Bits "Squares Terminal"; koyu CRT ekranı, parlama ve tüp eğimi alınmadı (koyu yüzey yalnız kapanışta, §1.2; parlama gölgesi yok, §2.2).

4.30 Süzülen haplar — SuzulenHaplar, src/features/pazarlama/components/suzulen-haplar.tsx

Ana sayfa "Katalog ücretsiz" bölümü: en çok aranan bölüm ve şehir sayfalarına giden haplar (§4.12 kimlik hapı, GraduationCap / MapPin, hover §2.1; her üçüncü hap bir kademe iri). Bölüm ekrana girince haplar yukarıdan hafif eğik düşüp oturur (tek, hafif sekme — düşen nesne, §6); imleç gezdikçe her hap kendi derinliğinde en çok 18 px süzülür, arkadaki piksel kareler ters yöne kayar. Haplar akışla dizilir (375 px'te üst üste binmez) ve SSR'da görünür linktir; yalnız katalogda sayfası olan adlar çizilir. Dokunmatikte süzülme yok; hareketi azalt'ta yalnız belirir. Esin React Bits "Parallax Pills"; kod bizim.

4.31 Piksel sahne ve sahne kartı — PixelSahne, src/components/pixel-decor.tsx

Bilal (7 Eki 2026): "landing'de en beğendiğim yer hero'daki Türkiye kısmı; buradaki gibi ferah ve marka kimliğimizi yansıtacak şekilde sıkıcı kart tasarımlarını da güncelle." Hero haritasının dili (hücre 10, nokta 7.4, köşe 2, altı opaklık, imleçle turuncuya ısınma, nabız atan turuncu vurgu) küçük resimlere taşınır. Sahne, harita gibi satır satır bir ızgaradan çizilir: # doku pikseli, - silik piksel, o turuncu vurgu.

  • Sahne süs değildir, kartın söylediğini çizer. Ana sayfa "Sorun" kartları: "24 tercih, binlerce ihtimal" → yoğun piksel alanı, içinde tam 24 turuncu kare; "Geçen yılın puanı yetmiyor" → her yıl başka boyda altı çubuk, yalnız sonuncusunun tepesi turuncu; "Danışman lüks haline geldi" → basamak basamak tırmanan merdiven, tepesi turuncu. Ne çizeceğini bilmediğin karta sahne koyma; rastgele doku sahne değildir. Sayı söyleyen sahnede (24) kare sayısı tutar.
  • Sahne kartı (§4.4 sınıfı): üstte sahne yuvası border-b border-slate-100 bg-slate-50 px-6 py-8 (hero'yla aynı zemin), altında p-6 içinde h3 (font-heading text-xl font-bold text-balance) + mt-2 text-base leading-relaxed text-slate-600. Kartta ikon kutusu ve köşe pikseli yok — sahne ikisinin yerini tutar. Izgaralar 24×8; üç kart aynı boyda sahne taşır.
  • Zemin değildir. §10.8'deki "piksel zemin yalnız CTA yüzeylerinde" kuralı sürer: sahne yazının arkasına serilmez, kendi yuvasında durur ve üstüne metin gelmez. Çekmece, modal ve katalog kartlarına sahne konmaz (§4.8: özet kartının içinde piksel seri "çok boğdu").
  • ton="dolgun" aynı dokunun koyu hâlidir (opaklık 0,64–1); okunması gereken şekiller (rakam) için. Sahne aria-hidden'dır; anlamı başlık taşır.

4.32 Adım rakamları — PixelRakam, src/components/pixel-decor.tsx

Ana sayfa "Nasıl çalışır"ın üç adımı kartsızdır (Bilal, 7 Eki 2026, §4.31'deki istek): adım numarası hero'nun piksel diliyle yazılmış iri rakamdır (5×7 ızgara, h-24, ton="dolgun"), altında h3 (mt-6 font-heading text-xl font-bold text-balance) ve mt-2 max-w-sm text-base leading-relaxed text-slate-600; her şey ortalı. md'den itibaren rakamlar düz bir çizgiyle birbirine bağlanır (h-0.5 rounded-full bg-slate-200, rakamın ortasında; veri akışındaki düz çizgiyle aynı dil). Telefonda adımlar alt alta, çizgisiz. Yapı ol > li; rakam aria-hidden, başlığın başında sr-only "1. adım:". Turuncu numara rozeti, ikon ve kart çerçevesi kaldırıldı. Yeni bir rakam gerekirse ızgarası RAKAMLAR'a eklenir (bugün 1–3).

4.33 Soru formu — questionnaire.tsx (shadcn Questionnaire) + SohbetAnketi, sohbet-anketi.tsx

shadcn'in questionnaire kayıt öğesi (ilkel @shadcn/react/questionnaire) sitenin diline çevrildi: muted / input / foreground token'ları yok. Sorular tek tek gösterilir; sağ üstte ilerleme 1 / 3 (text-xs font-semibold text-slate-500 tabular-nums). Seçenek satırı §4.4 sade kutu + §4.17 çip dili: min-h-11 rounded-2xl border border-slate-200 bg-card px-3.5 py-2.5 text-sm font-semibold text-slate-700, hover tek turuncu, seçili border-primary bg-primary text-white ve başındaki kutu tik olur (seçili hâl renk + tik, §2.2); sağda klavye harfi küçük kutuda. Serbest cevap alanı §4.6 hapı (h-11 rounded-full). Düğmeler sitenin Button'u (sm): Geri (outline), Atla (ghost; yalnız zorunlu olmayan soruda), İleri / "Cevapları gönder" (default). Hata text-sm font-medium text-red-600. Kapanmış form tek satır: "Formu cevapladın." (yeşil tik) ya da "Form kapandı; isteğini yazarak söyleyebilirsin." Yeni bir anket/soru akışı gerekince bu bileşen kullanılır; radio/checkbox'lı yeni form tasarlanmaz.

5. Yerleşim

5.1 Genel

  • Sayfa kabı: mx-auto max-w-6xl px-4. Metin sütunu: max-w-xl (paragraf) / max-w-2xl–max-w-3xl (uzun içerik).
  • Landing bölümü: <section className="py-20 sm:py-24">; alt sayfalar py-12–py-16.
  • Bölüm başlık bloğu (kanonik):
    <div className="flex flex-col items-center gap-4 text-center">
      <SectionEyebrow>Sorun</SectionEyebrow>
      <h2 className="font-heading text-3xl font-bold sm:text-4xl">…</h2>
      <p className="max-w-xl text-lg leading-relaxed text-slate-600">…</p>
    </div>
    
    Ardından içerik mt-12; kart ızgarası grid gap-6 md:grid-cols-3 (yalnızca gerçekten üç eşdeğer öğe varsa; üçe tamamlamak için içerik uydurulmaz).
  • Alt sayfa başlığının altında PagePixelDivider (mt-6/mt-8), her sayfada farklı seed.
  • Landing bölümleri arasında çizgi yok; PixelDivider (mx-auto w-56, farklı seed).
  • Boşluk ölçeği: 4 → 6 → 8 → 12 → 16/20 → 24. Ara değer (mt-7, gap-5) yeni yerde açılmaz.
  • Mobil önce (trafiğin ~%90'ı 375 px): uzun adlar sarar (§4.15); tablo yatay kaydırmaz, dar ekranda sütunlar satır altına iner; sabit alt çubuk klavyeyle çakışmaz; vh yerine dvh.

5.2 Geniş ekran dışında ortala

Alt sayfaların (katalog, detay) başlık bloğu lg (1024 px) altında ortalı, lg'de sola yaslıdır — mobil uygulama gibi telefonda ve tablette her şey ortada, masaüstünde tablo ve kartlarla aynı hizada:

  • Yol satırı: flex flex-wrap items-center justify-center gap-1.5 text-sm text-slate-500 lg:justify-start
  • Logo + h1: flex flex-col items-center gap-4 text-center lg:flex-row lg:text-left — logo telefonda başlığın üstünde, ortada.
  • Kimlik hapları: flex flex-wrap items-center justify-center gap-2 lg:justify-start
  • Özet paragraf: mx-auto … text-center lg:mx-0 lg:text-left
  • Sayfa ayracı: mx-auto … lg:mx-0; liste bölümü ve grup başlıkları text-center lg:text-left.
  • Ortalanmaz: liste/tablo satırlarının içeriği (göz satırdan satıra kayarken ortalı liste yorar), form alanları, uzun rehber metni.
  • Alt sayfa (§4.10) içeriği her ekranda ortalıdır.

5.2.1 Sayfalama — Sayfalama, sayfalama.tsx

Haplar h-11 (44 px), hover §2.1. Telefonda (sm altı) tek satır kalsın diye yalnız Önceki · aktif sayfa · Sonraki görünür; diğer numaralar hidden sm:inline-flex ile HTML'de durur (tarayıcı botları tüm sayfaları görür). 375 px'te 7 sayfalık şerit iki satıra kırılıyordu.

5.2.2 Dilim sekmeleri (Hayal / Dengeli / Güvenli) — program-tablosu.tsx

Tek satırda üç hap 375 px'e sığmıyordu (418 px, sayfa yana kayıyordu). Telefonda grid w-full grid-cols-3, hapın içinde ikon+ad üstte, sayı altta; sm'den tek satır. Hap en az 44 px (min-h-11), hover §2.1.

5.2.3 Karşılaştırma tablosu (ana sayfa) — yatay kaydırma yok

Dört sütunlu tablo yalnız lg'de. Altında her özellik kendi satırında (başlık ortalı text-base font-semibold), üç cevap altında üç sütun; KolayTercih sütunu bg-primary/5 kutuda. Sütun adları üstte yapışık: sticky top-24 sm:top-32 (site başlığı telefonda 96 px, sm'den itibaren 128 px — ölçüldü). Bilal, 25 Eyl 2026: "kaydırması gerekiyor, olmamalı".

5.3 Verimli ve havadar

  • İlişkili öğeler yan yana dizilir (iki sütun) — tek sütunda alt alta uzayan panel yapılmaz.
  • Yan yana dizmek "hepsini tek şeride sıkıştırmak" değildir: 23 Eyl'de denenen yatay "bilgi şeridi" (harita dahil altı değer tek satırda, yana kayan) reddedildi — harita küçüldü, sayılar ezildi, ekran kalabalıklaştı.

6. Derinlik, katman ve hareket

Derinlik gölgeyle değil piksel katmanı ve hareket farkıyla verilir: başlık bloğu gövdeden hafif hızlı akar (Parallax strength={16} başlık, 7 içerik, 26 ayraç). Sahne kartları (§4.31) hover'da 4 px yükselir. Modal arka planı bg-black/10 + hafif blur. Yığın: içerik < sabit bar < çekmece/modal (z-50).

Hareket kuralları (Apple, motion/react):

  • Varsayılan yay: { type: "spring", bounce: 0, duration: 0.35 } — sekmesiz, sakin. Sekme yalnızca kullanıcı bir şeyi fırlattıysa (sürükle-bırak).
  • Arc UI'dan taşınan bileşenlerin yayları, eğrileri ve lastik direnci tek dosyada: src/lib/hareket.ts (YAY.akici panel/yığın, YAY.donusum biçim, YAY.birakma parmak bıraktıktan sonraki tek hafif sekme). Yeni bir Arc bileşeni yay uydurmaz, buradan alır; sınıflar Arc'ın CSS modülünden değil bu belgeden gelir.
  • Giriş ve çıkış aynı yoldan (aşağıdan geldiyse aşağı gider).
  • Basınca anında tepki: active:scale-[0.97] (buton), [0.99] (geniş satır), [0.96] (çarpı).
  • Hover'da ok translate-x-0.5 kayar; kart yükselmesi yalnız landing kartında.
  • Kaydırmaya bağlı tetik IntersectionObserver ile (kaydırma dinleyicisi değil).
  • "Hareketi azalt": kayma/yay yok, yalnız opaklık (useReducedMotion, motion-reduce:transition-opacity).

7. Yap / Yapma

Yap Yapma (AI izi)
Rozet için SectionEyebrow Badge import'u, elle rounded-full border … px-3.5 py-1.5 span
CTA: metin + sondaki ArrowRight Başta Sparkles/yıldız ikonu, "✨"
Nötr = slate; vurgu = primary mavi; aksiyon ve hover = orange-500 indigo/purple primary, mor→mavi gradyan, gray/zinc nötr
Hover'da tek turuncu (orange-500); liste satırı adı mavi (§2.1 istisnası) Liste dışında hover'da mavi; aynı ekranda orange-600 yazı + orange-300 kenarlık
Kart: rounded-2xl border-slate-200 bg-card shadow-sm Her şeyde rounded-3xl, camsı backdrop-blur kartlar, parlama gölgesi
Sayı kartın en iri öğesi, ikon sağda küçük İkon üstte büyük, sayı küçük; BÜYÜK HARFLİ text-xs etiket
Sayfada ≤4 özet sayı, fazlası ayrıntı satırı → alt sayfa 6+ kartı sayfaya dizmek ya da hepsini yatay şeride sıkıştırmak
Harita gibi nefes alanını olduğu gibi bırakmak Nefes alanını küçültüp bilgi şeridine gömmek
Alt sayfada kartsız, ortalı, tek ekrana sığan içerik Çekmece içinde çerçeveli kart; bölümler arasında süs piksel ayraç
Gösterge kareleri masonry (kaymış sütun, farklı boy) Hizalı eşit ızgara; 8 px'lik "neredeyse hizalı" kaymalar
Liste satırında ad sarar, sayı alt satıra iner truncate ile yarım ad; 32 px satır butonu
Hareket: Reveal, piksel ısısı, kt-unblur, sekmesiz yay; animate-ping yalnızca "şu anda canlı" noktasında Her elemanda fade-up, whileHover scale 1.05, animate-bounce
Başlık font-heading, vurgu font-bricolage Inter/Roboto/serif, tek kelimelik BÜYÜK HARF etiket, 10–11 px yazı
Risk rengi + metin etiketi; tür ayrımı ikonla Renk tek başına, "yerleşirsin" gibi vaat cümlesi
Üç kart yalnızca üç gerçek öğe varsa Hero + üç kart iskeleti refleksi
Yüzey bg-card, tek koyu vurgu yüzeyi; karanlık mod token'dan (§2.3) dark: sınıfı, yüzeyde bg-white, koyu hapta text-white
Kapatma çarpısı DialogContent varsayılanı Başka boyut/renkte çarpı
Form alanı hap: Input/SelectTrigger varsayılanı (h-12 rounded-full), yalnız yerleşim sınıfı eklenir Kullanım yerinde h-9 rounded-lg bg-background; kenarlıklı ham <input>; md:text-sm

8. Duyarlılık

  • Kırılma noktaları: 375 (temel), 640 sm:, 768 md:, 1024 lg:. Her bileşen önce 375'te tasarlanır. Ortalı ↔ sola yaslı geçişi lg'dedir (§5.2).
  • Dokunma hedefi en az 44 px (h-11, size-11); satır içi küçük buton h-9 yalnızca masaüstü tablo aksiyonlarında.
  • Başlık ölçeği bir kademe düşer (text-3xl → sm:text-5xl alt sayfa h1), gövde 16 px altına inmez.
  • Modal genişliği max-w-[calc(100%-2rem)]; ayrıntı her zaman alt sayfada (AltSayfa, §4.10), alttan açılır.
  • Çekmece içeriği 375×812'de kaydırmasız sığar (§4.10).
  • prefers-reduced-motion: her animasyonun sade karşılığı var (motion-reduce:animate-none, .kt-unblur-sade, useReducedMotion).

9. Ajan için brief şablonu ve iş akışı

9.1 Brief

Yeni bir UI işi istenince önce şu beş satır doldurulur, sonra kod yazılır:

Amaç:      Kim, hangi ekranda, ne yapacak? (ör. veli, /paket, fiyatı karşılaştırıp satın alacak)
Referans:  Sitedeki en yakın mevcut ekran/bileşen (dosya yolu). Yoksa üniversite sayfası.
Tek kaynak: Kullanılacak kanonik parçalar (SectionEyebrow, Button+ArrowRight, OzetKart, AkademikAyrinti, NavBaslik…)
Durumlar:  boş / yükleniyor / hata / başarılı / girişsiz / kredisiz — hangileri var?
His:       Ekranın tek ana işi ne? Hangi 4 sayı önde, ne bir dokunuş derinde?

"Modern", "temiz", "şık" gibi yön belirtmeyen kelimeler kullanılmaz; yön = bu dosya.

9.2 Ölç, tahmin etme

Bu dilde sorunların çoğu koddan görünmez (taşma, sığma, hizalanma). Tasarım işinde:

  • Sığma: metin genişliğini tarayıcıda ölç (gizli span + getBoundingClientRect); "sanırım sığar" ile yazma. Örnek: özet kartında "13.889" 36 px'te 95 px.
  • Hizasızlık: masonry'de karelerin top/bottom değerlerini ölç; komşu fark ≥ 24 px.
  • Tek ekran: çekmecede kaydırma kabının scrollHeight ≤ clientHeight (375×812).
  • Genişlikler: 375 / 768 / 1280 px'te bak; ortalı ↔ sola yaslı geçişini lg'de doğrula.
  • Uç veri: en uzun ad ("Adana Alparslan Türkeş Bilim ve Teknoloji Üniversitesi"), en büyük sayı, verisi eksik kurum (URAP'ta olmayan, istatistiği olmayan).

9.3 Tuzaklar (23 Eyl 2026'da yaşandı)

  • Prettier'ı toplu çalıştırma. Depo prettier düzeninde değil; bir dosyayı prettier'dan geçirmek yüzlerce satırlık biçim farkı üretir ve başkasının kaydedilmemiş işine karışır. Yalnız kendi yazdığın satırları elle düzenle.
  • Geliştirme sunucusunda ilk tık. Kod değişikliğinden hemen sonra sunucu derleyip sayfayı tazeleyebilir; o anda yapılan tıklama boşa gider. "Çekmece açılmıyor" demeden önce sayfa hazır olduktan sonra tekrar dene.
  • Sayfada ikinci <header>. Bölüm sayfasında içerik <header>'ı var; site üst çubuğunu querySelector("header") ile değil, bilinen bir öğenin closest("header")'ı ile bul.
  • "use client" dosyasından sabit import etme. Sunucu bileşeni o sabiti değer olarak değil istemci referansı olarak alır; paylaşılan sabit ayrı dosyada durur ya da elle yazılır.

9.4 Site taraması için denetim uyarıları

pnpm tasarim:denetim bu dilin eski izlerini uyarı olarak listeler (lint'i kırmaz, dönüşüm listesidir): minik-yazi (10–11 px), buyuk-harf-etiket (uppercase + tracking-wide), mavi-hover (§2.1), iri-sayi-tabular (Cal Sans + tabular-nums), ham-input (§4.6 kenarlıklı ham input). mavi-hover §4.15 kanonik liste satırı adını (text-base font-semibold leading-snug + hover:text-primary hover:underline aynı satırda) kendiliğinden atlar — istisna uyarı vermez (Bilal'in kararı, 24 Eyl 2026). Eski truncate text-sm adlar yine uyarır; önce §4.15'e çevrilir. Bir ekranı dönüştüren ajan o ekrandaki uyarıları sıfırlar ya da neden kaldığını yazar.

Bilerek bırakılan uyarılar (24 Eyl 2026 taraması sonunda 12):

  • meraklisina-demo.tsx (8 × minik-yazi): SVG viewBox 640 birim; 375 px'te 0,54 ölçekle çiziliyor, 11 birimlik yazı ekranda 5,9 px (ölçüldü). 12'ye çıkarmak yalnız 6,5 px eder ve etiketler çakışır — çözüm telefona ayrı (dikey) çizim; ayrı iş.
  • secimlerim-paneli.tsx (4): hiçbir yerde kullanılmıyor (ölü kod); dönüştürülmedi, silinmesi ayrı iş.

9.5 Bitirmeden

pnpm tasarim:denetim sıfır hata (uyarılar raporda listelenir) + 375 px'te tek bakış (taşma, üst üste binme, dokunma hedefi, çekmece tek ekran) + §9.2 ölçümleri.

  • Yeni ayrıntı paneli mi? Dialog değil AltSayfa (§4.10, §4.19). İçinde tablo mu? §4.15 sınıfları, hücre text-sm, text-xs yok. Buton mu? Gölge yok, hover tek turuncu (§2.1, §6).

10. Samimi ton, ilerleme ve kutlama (öğrenci ekranları)

Bilal'in isteği (25 Eyl 2026): "Duolingo gibi basit ve oyunsu, Apple gibi irdeleyici, samimi." Araştırma ve kaynaklar: docs/tasarim/2026-09-25-samimi-arayuz-arastirmasi.md. Özü: bizim öğrencimiz için samimi = güven; neşe dayatılmaz.

10.1 Her ekranın tek cümlelik cevabı

  • Öğrenci ekranı h1 ile açılır ve ilk paragraf öğrencinin kendi durumunu sayıyla söyler. Örnek (/sonuc, SonucBasligi): "85.000. sıradasın (Sayısal). 4.760 program sana açık; aşağıda riskine göre ayrıldı."
  • Altında liste durumu (ListeDurumuSatiri): boşsa ne yapılacağı, doluysa "Listende 5/24 program · 19 yer kaldı" düğmesi (çekmeceyi açar).

10.2 İlerleme

  • Sayıyla ve dürüst: "7/24", "Adım 2/3: Şehir". Yüzde, sahte hız, yapay ilerleme yok.
  • Sihirbaz adım göstergesi adlı (Alan · Şehir · Öncelik); dolum scale-x ile soldan, duration-300 ease-[cubic-bezier(0.23,1,0.32,1)], hareketi azalt'ta geçişsiz.
  • Liste çekmecesinde risk dağılımı metinle (RiskEtiketi + sayı). Riskleri bilinen 6+ tercihli listede güvenli yoksa tek cümle ipucu — vaat değil, gerekçe.

10.3 Kutlama

  • Yalnız öğrencinin kendi yaptığı küçük adımda: ilk program (1/24) ve dolu liste (24/24). Bir kez, sakin bir bildirimle; aradaki eklemeler sessiz (düğme ✓, sayaç artar).
  • Yerleşme gibi sonuçlarda kutlama yok; açıkta kalan öğrenciye neşeli dil yok.
  • Hareket: starting:scale-95 starting:opacity-0 + güçlü ease-out, 300 ms altı; konfeti, ses, sekme (bounce) yok. Hareketi azalt'ta yalnız opaklık.

10.4 Metin

  • Sen dili, etken çatı, fiil düğme ("Listemi aç", "Sıralamamı gir"). Şirin/zekice etiket yok.
  • Hata: ne olduğu + ne yapılacağı; suçlama ve ünlem yok. "Hay aksi", "Eyvah", "Oops" yok (denetim: samimiyetsiz-unlem). "Buraya tıkla" yok; link ne açtığını söyler.
  • Bekleme metni "…" ile biter ("Kontrol ediliyor…").
  • "Kredi" dili: gerçek parayı sanal birime çevirmek aldatıcı desenler listesinde ("para birimi karmaşası"). Kredinin TL karşılığı pakete göre değiştiği için (≈4–5 TL) ekranda TL gösterip göstermemek Bilal'in kararına bırakıldı (25 Eyl 2026, açık).

10.5 Geri alınabilir işlem

  • Listeden çıkarma ve listeyi temizleme anında olur ama 8 sn "Geri al" bildirimi verir; çıkanlar eski sıralarına döner (geriAlinabilirCikar, liste-cekmecesi.tsx). Beklenen işlemde "Emin misin?" penceresi açılmaz (Apple: beklenen kayıpta uyarı yok).

10.6 Anlamsal yapı

  • Sayfa başına tek h1; bölümler h2. Başlıklarda text-balance.
  • Odak almayan durum değişikliği ekran okuyucuya duyurulur: role="status" (liste sayacı, sihirbaz adımı, bekleme). Bildirim yığını (§4.16) bunu kendisi yapar.
  • Açılır satır: aria-expanded + aria-controls (APG disclosure).
  • Site geneli "İçeriğe geç" linki layout.tsx'te; içerik kabı #icerik.
  • Çekmece kaydırma alanı overscroll-contain.

10.7 Almadıklarımız (Duolingo'dan)

Seri (streak), kayıp korkusu, puan/XP, rozet koleksiyonu, liderlik tablosu, maskot, sahte aciliyet/kıtlık, utandırarak onay. Tercih günlük alışkanlık değil, tek seferlik kaygılı bir karar.

10.8 CTA bandı — CtaBandi, src/components/cta-bandi.tsx

Kanonik CTA bandı — mavi zemin + PixelMasonry (Bilal'in kararı, 24 Eyl 2026: "Kendi Listem" çekmecesindeki bandın eski hâli daha güzeldi; örnek odur). Kabuk tek kaynaktan gelir, içerik çağıranındır:

<CtaBandi seed={8}>                       {/* buyuk: ortalı, px-5 py-8 sm:p-12 */}
  <h2 className="font-heading text-2xl font-bold text-balance sm:text-3xl">…</h2>
  <p className="mx-auto mt-3 max-w-xl text-base leading-relaxed text-white/90">…</p>
  <Button size="lg" className="mt-6 w-full cursor-pointer bg-orange-500 text-white hover:bg-orange-600 active:scale-[0.97] sm:w-auto">
    Yapay Zeka listemi kur<ArrowRight className="size-4" aria-hidden />
  </Button>
</CtaBandi>

<CtaBandi etiket="div" boyut="kompakt" className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
  …başlık + alt satır solda, buton sağda (çekmece)…
</CtaBandi>

Çekmecedeki kompakt bandın açık hâli (bileşenin ürettiği sınıflar):

<div className="relative isolate flex flex-col gap-3 overflow-hidden rounded-2xl bg-primary px-5 py-4 text-left text-white sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:py-5">
  <div aria-hidden className="pointer-events-none absolute inset-x-0 -inset-y-6 -z-10 text-white">
    <PixelMasonry seed={8} />
  </div>
  <div className="min-w-0">
    <p className="font-heading text-xl font-bold sm:text-2xl">Risk analizini biz yaptık</p>
    <p className="mt-1 hidden truncate text-sm leading-relaxed text-white sm:block">
      Her seçimin yerleşme riski hazır — son kararı sen ver.
    </p>
  </div>
  <Button size="lg" className="h-12 w-full shrink-0 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600 active:scale-[0.97] sm:w-auto">
    Listemde aç
    <ArrowRight className="size-4" aria-hidden />
  </Button>
</div>
  • Zemin bg-primary (sitenin mavisi), köşe rounded-2xl, yazı beyaz; alt satır da beyaz (text-white, slate-300 değil). Piksel dokusu PixelMasonry (Bilal, 24 Eyl 2026: "arka planda büyüklü küçüklü, masonry şeklinde"): 2–4 hücrelik kareler 4×4'lük makro hücrelere kaymış düşer, çakışmaz ama hizaya girmez. Doku kabın gerçek ölçüsüne göre üretilir (ResizeObserver; sabit çizimi ölçeklemek yüksek kartlarda görünen kısmı boş banda düşürüyordu, 24 Eyl 2026'da yaşandı): kısa kenarın %30'u kadar kenar çerçevesi kenara doğru yoğunlaşır, orta tamamen boş; küçük kare yok (2–4 hücre), iri kare daha silik; durağan — imleç ısı fırçasına katılmaz, üzerine gelince hiçbir şey olmaz (Bilal, 24 Eyl 2026); yalnız seyrek turuncu vurgu kareleri kendi kendine yavaşça nefes alır. Kap relative isolate overflow-hidden, doku -inset-y-6 -z-10. Eşit ızgaralı eski PixelField kaldırıldı.
  • Tek turuncu buton, metin önce ok sonda (§4.1). Telefonda alt alta ve tam genişlik; sm'de yan yana, buton sağda.
  • Büyük (sayfa kapanışı) hâlinde aynı band ortalı ve iri: px-5 py-8 text-center sm:p-12, -inset-y-10, h2 font-heading text-2xl font-bold sm:text-3xl, paragraf text-white/90.
  • Kullanıldığı yerler: /sonuc'taki üç panel (sihirbaz, giriş bekleyen, "24 tercihlik listen hazır"), /meraklisina kapanış kartı (DemoKapanisCta), katalog altındaki CtaSiraForm kart varyantı, "Kendi Listem" çekmecesinin altı (kompakt), katalog üstü kompakt satırın kayıtlı sıralamalı hâli ("Sıralaman … tabanlarının neresinde? · Sıralaman kayıtlı: …"; Bilal, 24 Eyl 2026: "bu kısma piksel dokusu ekle"). O satır CLS için tek section içinde iki hâl taşıdığından CtaBandi'yi sarmaz; kompakt bandın sınıf setini birebir alır (relative isolate overflow-hidden rounded-2xl bg-primary px-5 py-4 text-left text-white sm:py-5 + ilk çocuk PikselZemin), kenarlık saydam kalır ki iki hâlin kutusu aynı olsun. Aynı sayfadaki iki band farklı seed alır.

Piksel zemin yalnız CTA ve başlık yüzeylerinde — PikselZemin, src/components/piksel-zemin.tsx (Ana sayfa kartlarındaki piksel sahne zemin değildir; kendi yuvasında duran resimdir, §4.31.) (Bilal, 24 Eyl 2026: önce "her CTA benzeri kısmın arkasında olmalı", sonra "/sonuc'taki kartın arkasına da piksel koymuşsun; pikseller CTA'larda olacak sadece"). CTA yüzeyi = çağrı yüzeyi: mavi CtaBandi, koyu kapanış kartı PikselCtaYuzeyi, arama penceresindeki koyu kart. Ton ikidir: ton="koyu" (renkli zemin, beyaz kareler) ve ton="acik" (beyaz zemin, text-slate-400 kareler; turuncu vurgu kareleri aynı). Bilal (24 Eyl 2026): "her kısımda mavi arka kullanmışsın, çeşitlendir; beyaz arka planda piksel de güzel görünüyor" — bu yüzden CtaBandi ton="beyaz" (slate kenarlık, koyu yazı, paragraf text-slate-600) var ve aynı sayfada iki bant üst üste gelmesin diye dönüşümlü kullanılır: /universiteler altı ve /meraklisina kapanışı beyaz; şehir sayfası altı, /sonuc panelleri, çekmece altı mavi. Şehir sayfasının başlık yüzeyi (§4.17) de açık tonlu piksel zemindir. Beyaz içerik kartlarına (tadımlık, /listem üretim/kilit kartları, paket kartı, kaydet bandı, katalog üstü kompakt satırın form hâli, boş durumlar, sıralama-yok sayfası) konmaz — 24 Eyl'de denendi ve geri alındı. Aynı kompakt satırın kayıtlı sıralamalı hâli ise formsuz tek butonlu bir çağrı olduğundan mavi banttır ve dokuyu alır (yukarıda). Kap relative isolate overflow-hidden; zemin ilk çocuk; kareler beyaz. Doku kabın gerçek ölçüsüne göre üretilir: yalnız kenar çerçevesinde (kısa kenarın %30'u), orta tamamen boş; küçük kare yok, 2–4 hücrelik (17/27/37 px) kareler, iri olan seyrek ve daha silik (Bilal: "çok fazla piksel, küçük olanlar hiç olmasın").

Kapanış yüzeyi — PikselCtaYuzeyi, src/components/piksel-cta-yuzeyi.tsx (yalnız ana sayfa kapanışı "Tercih listen, pişmanlık listesi olmasın"). Bilal'in kararı (24 Eyl 2026): "orası bayağı iyiydi; özellikle 24'lük pikseller tablo gibi — bu tür kreatif, interaktif şeyler çok güzel." Arama penceresindeki kartın dili: rounded-3xl border border-blue-400/20 bg-slate-950 text-white, arka planda PixelMasonry (seed ile), tek turuncu CTA. Yazılıp silinen satır yok (Bilal, 24 Eyl 2026: kaldırıldı); FUNNEL_METINLERI yalnız arama penceresindeki kartta (arama-funnel-karti.tsx) kalır.

  • Kreatif — PikselListe, src/components/piksel-liste.tsx: 24 kare = 24 tercih, hero'nun nokta ölçüsüyle (hücre 10, nokta 7.4, rx 2). Örnek modda liste kendini kurar (5 hayal · 13 dengeli · 6 güvenli, 110 ms arayla), yalnız ekrandayken. İmleç yakın kareleri büyütür; kart içindeki düğmeye imleç/odak gelince 24 kare birden dolar; dokunmada basılan kare ve komşuları nabız atar (kt-piksel-nabiz). Hareketi azalt: dolu, durağan. Renk her zaman PikselListeAciklama metniyle.
  • Piksel tablosunun arkası boş kalır (Bilal, 24 Eyl 2026: "arkasına çok piksel yığılmış"): tablo kabı haric ile zemine verilir, doku onun çevresini (14 px payla) her genişlikte boş bırakır. Kural genel: bir kreatif ya da iri sayı piksel zeminin üstüne geliyorsa haric ile boşaltılır; doku ile kreatif üst üste binmez.
  • Bu yüzey sayfada bir kez ve yalnız kapanışta durur; ara paneller ve çekmece mavi banttır. Yeni bir kreatif fikri (veriyi piksele çeviren, imlece tepki veren) önce burada denenir.
  • Çekmece başlığında denenen "gerçek liste" pikseli (12×2, her kare tercihin riski) kaldırıldı: başlığı çok dolu gösteriyordu (Bilal, 24 Eyl 2026). Başlık sayı + ilerleme çubuğu + risk dağılımı metniyle kalır.

10.9 Kayıtlı sıra satırı (katalog üstü, profilli) — cta-sira-form.tsx kompakt

Bilal (24 Eyl 2026): "bu kısım UI kötü, Apple görünümü yok, yazılar küçük". §1.1 "sayı kahramandır" uygulanır: mavi bantta (§10.8 kompakt kabuk + PikselZemin) iri kupa kutusu (flex size-14 items-center justify-center rounded-2xl bg-white/15 + Trophy size-7), yanında sıra font-heading text-3xl font-bold leading-none tracking-tight sm:text-4xl (Cal Sans'ta tabular-nums yok, §3) ve altında text-sm font-semibold text-white/80 "sıra · Sayısal"; başlık font-heading text-xl font-bold leading-tight text-balance sm:text-2xl. Buton yazısız (Bilal, 24 Eyl 2026: "buton cılız kaldı, yazılı bir buton olmasın" — §4.1'in "metin + sondaki ok" kuralının bilinçli istisnası): flex size-14 items-center justify-center rounded-full bg-orange-500 text-white + ArrowRight size-7. Gölge yok (§6: derinlik gölgeyle verilmez; ilk sürümdeki shadow-lg shadow-orange-500/30 kaldırıldı) ve hover'da renk değişmez — iri dolu turuncu yüzeyde orange-600 kırmızımsı okunuyor (Bilal, 24 Eyl 2026); tepki hover:scale-[1.04] + ok 2 px kayar, basınca scale-[0.95]. Metinli CTA butonlarında hover:bg-orange-600 kanonik kalır (§2.1); aria-label + title "Sıralamana uygun programları gör". Bandın tamamı gerilmiş linkle (after:absolute after:inset-0, §4.8) tıklanabilir. Telefonda iki satır: başlık (text-lg) üstte, altında kupa+sayı ile ok yan yana (flex justify-center gap-5; kupa kutusu ve ok telefonda 48 px, sm'den 56 px); lg'de tek satır (sayı · başlık · ok). Blok formun yüksekliğini aşamaz — aşarsa overflow-hidden kap üstten kırpar (24 Eyl 2026'da üç satırlı ilk sürümde başlık kesildi; ölç, §9.2).