+ {/* Katalog: süzülen haplar (DESIGN.md §4.30) */}
+ {haplar.length >= 6 ? (
+ <>
+
@@ -533,7 +497,7 @@ export function SihirbazAdimlar({
{/* Telefonda iki sütun, uzun ad iki satıra sarar: tek sütunda
yedi çip 44 px'le pencereyi 812 px'in dışına itiyordu. */}
-
+
{ONCELIKLER.map((o) => (
))}
-
+
Listeyi daraltmaz; programların sırasını ve gerekçelerini
yönlendirir (istihdam ve kazanç TÜİK 2025, araştırma sırası URAP,
@@ -559,7 +523,7 @@ export function SihirbazAdimlar({
Özel kontenjan durumun{" "}
(isteğe bağlı)
-
+
{OZEL_DURUMLAR.map((d) => (
))}
-
+
ÖSYM bu durumlar için ayrı kontenjan ayırır. İşaretlersen o
kontenjanı olan programlar listende öne çıkar ve danışman bunu
diff --git a/src/lib/hareket.ts b/src/lib/hareket.ts
new file mode 100644
index 0000000..9052fea
--- /dev/null
+++ b/src/lib/hareket.ts
@@ -0,0 +1,48 @@
+// Arc UI'dan (uiarc.dev) taşınan bileşenlerin ortak hareket sabitleri.
+// Arc'ın `motionTokens`'ının DESIGN.md §6'ya göre ayarlı hâli: yaylar
+// sekmesizdir; sekme yalnız kullanıcı bir şeyi bıraktığında/fırlattığında
+// (`birakma`) vardır. Yeni bir Arc bileşeni taşınırken yay buradan alınır.
+
+export const YAY = {
+ /** §6 varsayılanı: vurgu kayması, sayı rulosu, panel geçişi. */
+ varsayilan: { type: "spring", bounce: 0, duration: 0.35 },
+ /** Panel, yükseklik, yığın yerleşimi. Arc "smooth". */
+ akici: { type: "spring", visualDuration: 0.4, bounce: 0 },
+ /** Genişlik/biçim dönüşümü (çip, yazı). Arc "morph", sekmesi alınmış. */
+ donusum: { type: "spring", visualDuration: 0.42, bounce: 0 },
+ /** Parmak bıraktıktan sonraki yerine oturma. Arc "snappy": tek yerde hafif sekme. */
+ birakma: { type: "spring", visualDuration: 0.26, bounce: 0.12 },
+} as const;
+
+type Egri = [number, number, number, number];
+
+export const EGRI: { giris: Egri; standart: Egri } = {
+ /** Ekrana giren öğe: hızlı başlar, yumuşak durur. */
+ giris: [0.16, 1, 0.3, 1],
+ /** Ekrandayken değişen renk/opaklık. */
+ standart: [0.22, 1, 0.36, 1],
+};
+
+export const SURE = { anlik: 0.12, hizli: 0.16, cikis: 0.18, standart: 0.24 } as const;
+
+/**
+ * Sınırın ötesine çekilen öğenin direnci (iOS lastik bandı): parmağı izler
+ * ama her piksel bir öncekinden pahalıdır, `olcu`ya yaklaşır ve geçmez.
+ */
+export function lastik(tasma: number, olcu: number): number {
+ return (1 - 1 / ((tasma * 0.55) / olcu + 1)) * olcu;
+}
+
+/** `lastik`in tersi: ekrandaki esnemeden parmağın gerçek yolunu geri verir. */
+export function lastikTersi(esneme: number, olcu: number): number {
+ return ((1 / (1 - Math.min(esneme, olcu - 1) / olcu) - 1) * olcu) / 0.55;
+}
+
+/** Son ~80 ms'lik örneklerden bırakma hızı (px/sn); bırakmadan önce duran parmak 0 verir. */
+export function birakmaHizi(ornekler: { t: number; v: number }[], simdi: number): number {
+ const yakin = ornekler.filter((o) => simdi - o.t <= 80);
+ const ilk = yakin[0];
+ const son = yakin[yakin.length - 1];
+ if (!ilk || !son || ilk === son || simdi - son.t > 60) return 0;
+ return (son.v - ilk.v) / ((son.t - ilk.t) / 1000);
+}
From 4d30dd1305f18830c4557fec0f544fa4d6938780 Mon Sep 17 00:00:00 2001
From: bilalgursen
Date: Wed, 7 Oct 2026 17:12:53 +0300
Subject: [PATCH 03/30] =?UTF-8?q?feat(sohbet):=20liste=20revizyonu=20sohbe?=
=?UTF-8?q?te=20ta=C5=9F=C4=B1nd=C4=B1=20=E2=80=94=20soru=20formu=20ve=20y?=
=?UTF-8?q?ap=C4=B1sal=20kural?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Eski revizyon kutusu kaldırıldı: serbest metin modele gidiyor, sıra ve havuz
koddan belirlendiği için "ilk 5 X ilinden olsun" gibi isteklerin karşılığı
yoktu. Danışman artık belirsiz isteği soru formuyla (soru_sor → shadcn
Questionnaire, proje diline çevrildi) netleştirir, sonra liste_revize ile
yapısal kural verir: il/alan/tip farkı, "ilk N" ölçütü, çıkar/ekle,
iskelet (lib/revizyon-kurali.ts). Kurallar havuz, seçim ve sırada koddan
uygulanır; "ilk N" ölçütünün ili/alanı süzgece kendiliğinden eklenir.
- chat_messages.meta sütunu (göç 0006): form, form cevabı ve revizyon sonucu
kayıttan geri kurulur; form cevabı kredi harcamaz.
- Akış korumaları: form açılınca başka araç yok, revizyonda zaman aşımı uzar,
"yeniden kurdum" beyanı araçsızsa düzeltme notu.
- /listem "Revize et" sohbeti odaklar; başarılı revizyonda liste yenilenir.
- /dev/sohbet senaryosu, DESIGN.md §4.20 notu ve §4.33.
Co-Authored-By: Claude Fable 5.1
---
docs/tasarim/DESIGN.md | 272 ++++-
drizzle/0006_little_luckman.sql | 1 +
drizzle/meta/0006_snapshot.json | 1018 +++++++++++++++++
drizzle/meta/_journal.json | 7 +
package.json | 3 +-
pnpm-lock.yaml | 51 +-
src/app/api/soru/route.ts | 74 +-
src/app/listem/page.tsx | 4 +-
src/components/ui/questionnaire.tsx | 329 ++++++
.../rapor/components/arac-pilleri.tsx | 9 +-
.../rapor/components/listem-govde.tsx | 152 ++-
.../rapor/components/revizyon-kutusu.tsx | 100 --
.../rapor/components/sohbet-anketi.tsx | 144 +++
.../rapor/components/sohbet-client.tsx | 180 ++-
.../rapor/components/sohbet-senaryo-verisi.ts | 73 ++
src/features/rapor/liste-revizyon.ts | 164 +++
src/features/rapor/rapor-actions.ts | 141 +--
src/features/rapor/rapor-queries.ts | 1 +
src/features/rapor/types/rapor.ts | 44 +
src/lib/ai/araclar.ts | 301 ++++-
src/lib/ai/cikti-denetimi.ts | 19 +
src/lib/ai/danisman-prompt.ts | 56 +-
src/lib/ai/rapor.ts | 92 +-
src/lib/ai/sohbet-akisi.ts | 78 +-
src/lib/ai/sohbet-meta.ts | 192 ++++
src/lib/appdb/schema.ts | 4 +
src/lib/credits.ts | 12 +-
src/lib/rapor-havuzu.ts | 65 +-
src/lib/revizyon-kurali.ts | 220 ++++
29 files changed, 3392 insertions(+), 414 deletions(-)
create mode 100644 drizzle/0006_little_luckman.sql
create mode 100644 drizzle/meta/0006_snapshot.json
create mode 100644 src/components/ui/questionnaire.tsx
delete mode 100644 src/features/rapor/components/revizyon-kutusu.tsx
create mode 100644 src/features/rapor/components/sohbet-anketi.tsx
create mode 100644 src/features/rapor/liste-revizyon.ts
create mode 100644 src/lib/ai/sohbet-meta.ts
create mode 100644 src/lib/revizyon-kurali.ts
diff --git a/docs/tasarim/DESIGN.md b/docs/tasarim/DESIGN.md
index 91d6a88..7846c41 100644
--- a/docs/tasarim/DESIGN.md
+++ b/docs/tasarim/DESIGN.md
@@ -245,10 +245,10 @@ ve kimlik hapları (§4.12) bu kuralın dışındadır. Rozet **sayfa** bölüm
### 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).
+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: `` + sağ üstte ``. (Kodda hâlâ `hover:border-primary/30 hover:shadow-primary/5`; §2.1 geçiş notu.)
+- 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.
@@ -318,16 +318,19 @@ yanındaki 2×2).
(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ş koltuk varken 100'e yuvarlanmaz, en çok 99 yazar.
- - **Bölüm** (`grid grid-cols-2 gap-4 lg:grid-cols-4`, haritası yok): En seçici (sıra +
- üniversite adı linkli) · En geniş kapı (ücretsiz devlet örgün programı ≥3 ise devlet
- kümesinde, açıklama "Devlet · Bingöl Üni. · 2026 taban sırası"; etiket "Devlette en geniş"
- 131 px'te iki satıra kırıldığı için kısa tutulur) · Orta taban (devlet programlarını sıraya
- dizince ortadakinin sırası; açıklamada "Devlet · 2021'de 105 bin · gevşedi") · Boş koltuk.
+ 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 seçici bölüm (sıra + bölüm adı linkli) · Orta
- taban (lisans programlarının ortası) · Doluluk (`%97`) · Türkiye sırası (URAP; listede
- olmayan kurumda Kontenjan).
+ - **Ü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").
@@ -353,10 +356,26 @@ yanındaki 2×2).
en üstte. Bugün her sayfada tek satır var (üniversite: "Akademik göstergeler"; bölüm: "Mezun
istihdamı").
-### 4.10 Alt sayfa (Drawer) içeriği
-Ayrıntı her zaman **alttan açılan sayfada** (`Drawer handleOnly`, tutamaçlı); ekranın ortasında
+### 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:
-`DrawerContent className="max-h-[92dvh] bg-card sm:mx-auto sm:max-w-2xl sm:border-x sm:border-slate-200 sm:shadow-2xl"`.
+`` + §4.3 çarpısı + ``.
İçerik kuralları (Apple ayrıntı sayfası):
- **Her ekranda ortalı:** başlık `px-10 text-center font-heading text-2xl font-bold`, altında
@@ -377,8 +396,8 @@ açılan modal değil. Çekmece kabı ve çarpı `cta-sira-form.tsx`'teki çekme
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ı
+ "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
@@ -493,13 +512,30 @@ tablosu bu sabitleri kullanır, sınıfı elle yazmaz.
- 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 **sitenin temasını izler** (`useTheme().resolvedTheme`, §2.3), sistemin değil: 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
+### 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ı).
@@ -577,7 +613,7 @@ telefonda tam genişlik), "Şehre göre" çipleri (sayfa içi `#sehir-…` çapa
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** — `Drawer handleOnly`, kap ve çarpı `cta-sira-form.tsx`
+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
@@ -634,7 +670,21 @@ genişletilebilir olmalı; UI için prompt-kit kullan."
`animate(izgara, { "--sohbet-kolon": "" })` 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`/`Drawer` **yok** — sohbet yeniden kurulmaz, sayfa zıplamaz.
+ 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/`, `/paket`, `/listem`) prompt-kit `Source` kalıbında **küçük satır içi hap**
@@ -686,6 +736,16 @@ genişletilebilir olmalı; UI için prompt-kit kullan."
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). `/listem`deki 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.meta`dan 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
@@ -704,7 +764,160 @@ Tek seçimli hap grubunda seçili vurgu yeniden boyanmaz, tek yüzey olarak seç
**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 — orada her çip kendi başına yanar.
+ç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
+`