# 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 (`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 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 `` - 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):** ```tsx ``` Metin önce, ok sonda. Başta ikon yok. `Sparkles` yok. İstenirse `active:scale-[0.97]`. - **İkincil gezinme butonu** ("Tüm sıralamayı gör →"): ```tsx ``` - 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` ```tsx Nasıl çalışır? ``` 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. 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]` + `` + `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: `` + sağ üstte ``. (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 `` kullanır; elle yazılmaz. Nokta + metin: `` 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 **hap**tı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-white 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-white 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-white 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 ``** 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 ``. ### 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` **ç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: `DrawerTitle` ortalı, `DrawerDescription` 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-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. Rozet (§4.2) değildir. Tür hapı etkileşimsizdir; **il hapı şehir sayfasına link**tir (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 `` 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: `` (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: ```tsx } />

…

``` 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`. - **Ü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 (toast) — `src/components/ui/sonner.tsx` + `globals.css` Tema **light'a sabit** (karanlık mod yok, §1.2): sistem koyu temadayken sonner açıklamayı beyaza yakın griye çevirip beyaz zeminde okunmaz ediyordu (Bilal, 24 Eyl 2026: "toast açıklaması okunmuyor"). 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` beyaz yazı, 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. ### 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-white 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-white 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 (`UniLinkleri`), "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 konum kartında radyal mask. 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,7 s sonra viewBox 1,1 s boyunca güçlü ease-out (`0.23, 1, 0.32, 1`) ile 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; konum kartı: orta). 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. ## 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ü: `
`; alt sayfalar `py-12`–`py-16`. - Bölüm başlık bloğu (kanonik): ```tsx
Sorun

…

…

``` 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ç). 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ı | | 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 ``; `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 ç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 `
`.** Bölüm sayfasında içerik `
`'ı 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. ## 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). Bildirimler (sonner) 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: ```tsx {/* buyuk: ortalı, px-5 py-8 sm:p-12 */}

…

…

…başlık + alt satır solda, buton sağda (çekmece)… ``` Çekmecedeki kompakt bandın açık hâli (bileşenin ürettiği sınıflar): ```tsx

Risk analizini biz yaptık

Her seçimin yerleşme riski hazır — son kararı sen ver.

``` - 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`** (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.