Files
kolaytercih/docs/tasarim/DESIGN.md
bilalgursen 309fb73a34 feat(tasarim): rapor listesi ve tadımlık satırı "şişko ve sade" dile göre
- Risk etiketi src/components/risk-etiketi.tsx'e çıkarıldı; /sonuc,
  çekmece ve rapor listesi oradan kullanıyor
- Rapor satırı §4.15: ad sarar, üniversite adı ayrı satırda, telefonda
  risk + taban sıra adın altında, logo gizli (satır 214 → 152 px),
  aç/kapa düğmesi 44 px, hover tek turuncu
- Açılan ayrıntı: 16 px metin, 14 px koyu etiket, rounded-xl iç kutular
- Tadımlık satırı aynı satır düzenine geçti
- Tercih değişti penceresi, liste gövdesi ve yazdırma sayfasında
  10-11 px / büyük harfli etiketler kalktı

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 00:57:27 +03:00

36 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

  • Zemin her zaman beyaz; koyu zemin yalnızca CTA bandı ve çekmece başlığı gibi tek bir vurgu yüzeyinde (PixelField ile).
  • İ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 yoktur. dark: sınıfı yazılmaz (.dark token'ları shadcn kalıntısıdır).

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.)
  • 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.

3. Tipografi

Dört 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

Ö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-white 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.

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 (Drawer) aynı sınıf seti DrawerClose üstünde kullanılır (§4.10).

4.4 Kart ve kutu

  • Landing/öne çıkan kart: <Card className="relative h-full overflow-hidden border-slate-200/70 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:border-orange-500 hover:shadow-lg hover:shadow-orange-500/5"> + sağ üstte <PixelCorner className="absolute right-4 top-4" />. (Kodda hâlâ hover:border-primary/30 hover:shadow-primary/5; §2.1 geçiş notu.)
  • Sade kutu (form, panel, liste satırı): rounded-2xl border border-slate-200 bg-white (+ 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

shadcn Input, Select, Textarea, Slider. Etiket her alanda; hata mesajı alanın altında, ne olduğunu ve ne yapılacağını söyler. Sayısal alanlarda uç değerler (0, negatif, 1.000.000 üstü) ele alınır.

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-white 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ı (bölümde dört kart: Program, Devlet, Vakıf, En iyi sıralama; grid grid-cols-2 gap-4 lg:grid-cols-4, haritası olmadığı için).
  • 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-white 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).

4.10 Alt sayfa (Drawer) içeriği

Ayrıntı her zaman alttan açılan sayfada (Drawer handleOnly, tutamaçlı); ekranın ortasında açılan modal değil. Çekmece kabı ve çarpı cta-sira-form.tsx'teki çekmeceyle birebir: DrawerContent className="max-h-[92dvh] bg-white sm:mx-auto sm:max-w-2xl sm:border-x sm:border-slate-200 sm:shadow-2xl".

İç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. 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.
  • 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-white 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. Etkileşimli değildir; rozet (§4.2) değildir.

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.

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.
  • 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.
  • Satırda logo varsa (bölüm sayfası) UniLogo boy="sm" adın solunda, items-start.
  • 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.

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.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ç). Kartlar 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).
  • 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-white 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
Beyaz zemin, tek koyu vurgu yüzeyi İstenmemiş karanlık mod, dark: sınıfı
Kapatma çarpısı DialogContent varsayılanı Başka boyut/renkte çarpı

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 çekmecede (Drawer), 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). 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.

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.