/* ==========================================================================
   Rota — Tasarım sistemi (token'lar, temel öğeler, bileşenler)

   Renk katmanı iki basamaklıdır:

   1. **Palet** (`--p-*`) — ham renkler. Yalnız burada hex geçer.
   2. **Anlam** (`--brand`, `--surface`, `--danger`…) — bileşenlerin
      kullandığı isimler. Bileşenler paleti *doğrudan* okumaz.

   Bu ayrım koyu tema içindir: ileride `[data-theme="dark"]` bloğu yalnız
   ikinci basamağı yeniden bağlar, tek bir bileşen kuralı bile değişmez.
   Koyu tema bu fazda **açılmadı**; yalnız yolu açık bırakıldı.

   Oran kuralı: ekranın ~%88'i beyaz ve soğuk nötr yüzeydir, ~%12'si
   denetimli vurgudur. Yardımcı renkler (mercan, antik altın, mineral mavi)
   dekorasyon değil durum taşır: bir şey mercana boyanıyorsa kullanıcıdan
   ilgi bekliyor demektir.

   Metin katmanı üç basamaktır ve adları tasarım belgesiyle birebir aynıdır:
   `--text-primary` (mürekkep), `--text-secondary` (okunur ikincil),
   `--text-muted` (yalnız sessiz meta). Eski `--text-subtle` bu dosyada
   `--text-muted` oldu; ikinci basamak `--text-secondary`ye taşındı.
   ========================================================================== */

:root {
  color-scheme: light;

  /* --- Palet: lacivert (koyu yüzey) ---
     Lacivert artık birincil *eylem* rengi değil. Düğmeyi lacivert bırakmak,
     aynı tonu hem "buradasın" hem "buraya bas" için kullanmak demekti ve
     ikisi de zayıflıyordu.

     Logo da artık lacivert değil: görsel varlıklar #4F46C8'e çevrildi
     (bkz. TASARIM-SISTEMI.md, "Logo rengi"). Bu jetonlar yalnız koyu
     yüzeylerin ve auth şeridinin zeminidir — kimlik rengi değil. */
  --p-navy-900: #0d1526;
  --p-navy-800: #13203a;
  --p-navy-700: #172033;
  --p-navy-300: #9fb0cc;
  --p-navy-200: #c3cee2;
  --p-navy-100: #dee6f4;
  --p-navy-050: #eef2fa;

  /* --- Palet: royal indigo (birincil eylem) ---
     Merdivenin ekseni **#4F46C8** (500) ve yumuşak yüzeyi **#EFEEFF**
     (100). İkisi de tasarım kararıdır, türetme değil; aradaki basamaklar
     onlara göre yazıldı. */
  --p-indigo-700: #3a32a4;
  --p-indigo-600: #453cb4;
  --p-indigo-500: #4f46c8;
  --p-indigo-200: #d5d2f4;
  --p-indigo-100: #efeeff;
  --p-indigo-075: #f2f1ff;
  --p-indigo-050: #f7f6ff;

  /* --- Palet: soğuk nötrler (zemin, çizgi) ---
     Zemin mavi-griye çalar (#F3F6FB) ve kart saf beyazla onun üstüne
     çıkar: yükselti burada gölgeyle değil, iki yüzey arasındaki ton
     farkıyla anlatılır. Sol menü kendi basamağını kullanır (025) —
     tuvalden *açık*, karttan koyu; böylece gezinme, içeriğin arkasında
     duran bir şerit gibi okunur. */
  /* Faz 29: tuval bir basamak **derinleşti** (#F3F6FB → #EEF2F9).

     Gerekçe ölçüm: kart (beyaz) ile tuval arasındaki karşıtlık 1.083:1 idi
     ve bu, iki yüzeyin ekranda tek bir düzlem gibi okunması demek. Kartı
     ayıran şey pratikte yalnız 1 pikselik sınırdı; sayfa "beyaz bir zeminde
     çizilmiş kutular" gibi duruyordu, "zeminin üstünde duran kâğıtlar" gibi
     değil. Yeni değerde fark **1.123:1** — aynı ailede kalıyor, yarım ton
     iniyor, kart kendiliğinden yükseliyor.

     Alt sınırı beklenen jeton koymadı. Tahmin `--p-ink-400`dü (sessiz meta
     metni doğrudan bu zeminin üstüne düşüyor); ölçünce sınırı **`--success`**
     (#137C6A) koydu — "Tamamlandı" metni de tuvalin üstünde duruyor ve o
     yeşil, mürekkep basamaklarından daha dar bir paya sahip. Ölçüler bu
     zeminde: success **4.54:1**, ink-400 4.64, ink-600 5.52. Bir basamak
     daha koyuda (#ECF1F8) success 4.49 ile AA'yı **0.01** kaçırıyordu.

     Yani "daha da koyulaşsın" isteğinin cevabı bu jeton değil, gölge katmanı
     (bkz. `--shadow-card`): tuval AA'nın izin verdiği son yere kadar indi,
     kalan derinliği gölge taşıyor. Buradan aşağısı ancak durum renklerini
     koyulaştırarak alınabilir ve o, kazandığından çoğunu götürür — ekranın
     yarısını ilgilendiren bir kararı, dört rozeti karartarak ödemek olurdu.

     Yan etki bilinçli: tuval (100) ile çukur yüzey (150) artık neredeyse
     **aynı basamakta** (#EEF2F9 / #EDF1F8). Merdiven bozulmadı, kısaldı ve
     bu bir sorun değil: çukur yüzey kartın *içinde* bir oyuktur, tuval
     kartın *dışındadır* — ikisi hiçbir yerde yan yana görünmüyor. 150'yi
     koyulaştırarak araları açılamazdı: o jeton aynı zamanda `--border-soft`
     (satır arası çizgi) ve orada bir basamak koyu, listeyi kareli deftere
     çeviren şeyin ta kendisi. */
  --p-cool-000: #ffffff;
  --p-cool-025: #f8fafd;
  --p-cool-050: #f6f9fd;
  --p-cool-100: #eef2f9;
  --p-cool-150: #edf1f8;
  --p-cool-200: #e4e9f2;
  --p-cool-250: #dce3ef;
  --p-cool-300: #cfd8e7;
  --p-cool-400: #b9c4d6;

  /* --- Palet: mürekkep (metin) ---

     İki alt basamak koyulaştırıldı. Eski değerler ölçülünce sınıfta
     kalıyordu: `--p-ink-400` beyaz üzerinde **2.78:1**, `--p-ink-600` ise
     beyazda 4.81:1 olsa da kart içinde (`--surface-sunken`, #ebeef2)
     4.5'in altına düşüyordu. WCAG AA gövde metni için 4.5:1 ister ve bu
     iki jeton yalnız dekor değil, tarih/sayı/açıklama gibi *okunması
     gereken* metinleri taşıyor.

     Yeni değerlerin en kötü zemini (sunken) karşısındaki oranı:
       --p-ink-600  6.18:1     --p-ink-400  4.57:1

     Bedeli, "çok soluk" basamağın kaybolması: 2.78:1'lik bir gri ile AA
     aynı anda mümkün değil. Hiyerarşi bundan sonra yalnız renkten değil,
     boyut ve ağırlıktan da gelmeli (`--fs-xs`, `font-weight`). */
  /* Ana metin tasarım kararıdır: #172033. İki gri basamak ise **istenen
     #748096'nın aynı hue ailesinde koyulaştırılmış** hâli. Sebep yukarıdaki
     ölçüm: #748096 beyazda 3.98:1 kalıyor, kart içi sunken yüzeyde daha da
     düşüyor — bu iki jeton dekor değil, tarih/sayı/açıklama taşıyor.
     Koyulaştırma iki basamak; ekranda ton aynı okunur, ölçümde AA geçer.
     Ölçüt en kötü zemin olan `--surface-sunken`; `test_faz11_duzen.py`
     içindeki kontrast testi bu iki jetonu dört yüzeye karşı ölçüyor. */
  --p-ink-900: #172033;
  --p-ink-600: #56617a;
  --p-ink-400: #626d82;

  /* --- Palet: yardımcılar ---
     Her yardımcı renk üç basamak taşır: metin tonu (-600), dolgu (-100) ve
     çizgi (-200). Dolu yüzey gerekirse -500 kullanılır. */
  /* Mineral mavi — güçlü ikincil eylem, bilgi, nötr meta.

     `-500` dolu yüzeydir (`.btn-strong`) ve **üstünde beyaz yazı durur**;
     o yüzden ölçüsü metin tonuyla aynı sıkılıkta. #4B83B6 iken beyaz yazı
     4.02:1'de kalıyordu — düğmenin kendisi okunmuyordu. Faz 18'de aynı hue
     ailesinde koyulaştırıldı (#457AAB, beyazla 4.54:1). */
  /* Faz 27: mineral, kendi **200** dolgusunun üstünde metin olmak zorunda
     kaldı (huninin "Teklif gönderildi" basamağı) ve 600 orada 3.75:1 ile
     AA'nın altında kaldı. 700 yalnız o dolgunun mürekkebidir; düz yüzeyde
     mineral metin yine 600'dür. */
  --p-mineral-700: #2f5779;
  --p-mineral-600: #3d6e9c;
  --p-mineral-500: #457aab;
  --p-mineral-200: #c7daea;
  --p-mineral-100: #e6eff6;
  /* Arktik mavi — sessiz bilgi, ikincil veri işareti. */
  /* `-600` metin basamağıdır ve "sessiz" demek "okunmasın" demek değil:
     #3A90A8 beyaz üstünde 3.66:1'di. Sessizlik renkten değil boyut ve
     ağırlıktan gelir (bkz. §1, "Metin üç basamaktır"); ton AA'ya çekildi. */
  --p-arctic-600: #30768a;
  --p-arctic-500: #53afc7;
  --p-arctic-200: #bfe2eb;
  --p-arctic-100: #e4f2f6;
  /* Seladon — olumlu sonuç (kazanıldı, tamamlandı). Metin tonu #137C6A:
     istenen #168F7A beyaz üstünde 4.00:1, kart içi çukur yüzeyde 3.54:1
     kalıyordu ve bu jeton "Kazanıldı", "Tamamlandı" gibi *okunan* rozetleri
     boyuyor. Aynı hue ailesinde bir basamak koyu; ekranda ton aynı okunur. */
  --p-celadon-600: #137c6a;
  --p-celadon-500: #1ba88f;
  --p-celadon-200: #b9e3da;
  --p-celadon-100: #e4f5f1;
  /* Antik altın — bekleyen, eksik, yaklaşan. Metin tonu #946410.
     Sarı ailesi beyaz üstünde en zor okunan ailedir: istenen #B47A13
     3.66:1 veriyordu, yani üç durum renginin en kötüsü. Koyulaştırma iki
     basamak; "Bekleyen" rozeti hâlâ altın, artık okunuyor da. */
  --p-gold-600: #946410;
  --p-gold-500: #d19a2e;
  --p-gold-200: #f0dcb4;
  --p-gold-100: #faf1e0;
  /* Yanık mercan — gecikme, takipsiz kayıt, "sahiplenilmemiş" durum.
     İstenen #C85C60 **dolgu ve çizgi** tonudur; metin basamağı (-600) bir
     tık koyu, çünkü beyaz üstünde #C85C60 4.07:1'de kalıyor ve bu jeton
     "12 gün gecikti" gibi okunması gereken satırları boyuyor.
     Faz 18: bir tık daha koyu (#B74A4F). Beyazda zaten geçiyordu ama
     ölçüt en kötü zemin ve kart içi çukur yüzeyde 4.46:1 ile sınırın
     altında kalıyordu. */
  /* Faz 27: mercan, kendi 100 dolgusunun üstünde metin olmak zorunda kaldı
     (gecikme rozeti) ve 600 orada 4.46:1 ile yine sınırın altında kaldı —
     yukarıdaki notun aynısı, bir basamak yukarıda. 700 tam bu iş için var:
     mercan **dolgu üstünde** yazıyken kullanılır, düz zeminde 600 kalır. */
  --p-coral-700: #a33f44;
  --p-coral-600: #b74a4f;
  --p-coral-500: #c85c60;
  --p-coral-200: #f0cdce;
  --p-coral-100: #fbecec;
  /* Gerçek kırmızı yalnız yıkıcı sonuç içindir (silme, hata). */
  --p-red-600: #b4353c;
  --p-red-200: #f0cbcd;
  --p-red-100: #fbe9ea;

  /* --- Marka: kimlik --- */
  /* Logo, koyu düğme, hero metni. "Rota lacivertı" ekranda az ama tok. */
  --navy: var(--p-navy-700);
  --navy-hover: var(--p-navy-800);
  --navy-active: var(--p-navy-900);
  --navy-soft: var(--p-navy-100);

  /* --- Marka: eylem --- */
  /* `--brand` birincil eylemdir: ana düğme, etkin menü çizgisi, bağlantı,
     odak halkası. Kimlikten (lacivert) ayrı tutulur. */
  --brand: var(--p-indigo-500);
  --brand-hover: var(--p-indigo-600);
  --brand-active: var(--p-indigo-700);
  --brand-soft: var(--p-indigo-100);
  --brand-softer: var(--p-indigo-050);
  --brand-border: var(--p-indigo-200);
  /* Saydam vurgular (hover zeminleri) tek yerden gelsin ki koyu temada
     `rgba(86,88,201,…)` sabitlerini tek tek avlamak gerekmesin. */
  --brand-tint-6: rgba(79, 70, 200, 0.06);
  --brand-tint-10: rgba(79, 70, 200, 0.1);
  --focus-ring: 0 0 0 3px rgba(79, 70, 200, 0.18);

  /* Güçlü ikincil eylem — "parlamento mavisi". Birincil kadar bağlayıcı
     olmayan ama nötr de olmayan işler (iletişim kaydet, dışa aktar). */
  --strong: var(--p-mineral-600);
  --strong-solid: var(--p-mineral-500);
  --strong-soft: var(--p-mineral-100);
  --strong-border: var(--p-mineral-200);

  /* --- Yüzeyler --- */
  /* Tuval. Kartlar bunun üstünde beyazla yükselir. */
  --page-bg: var(--p-cool-100);
  /* Tuvalden bir ton açık şerit: yapışkan üst gezinme, tablo başlığı. */
  --app-bg: var(--p-cool-025);
  /* Sol menünün kendi zemini. `--surface` (beyaz) ile yazılmıştı; menü o
     zaman kartla aynı yüzeye oturuyor ve tuvalin üstünde ikinci bir kart
     gibi duruyordu. Ayrı jeton, iki temada da gezinmeyi içerikten ton
     farkıyla ayırmak için (aydınlıkta #F8FAFD, koyuda #081120). */
  --sidebar-bg: var(--p-cool-025);
  --surface: var(--p-cool-000);
  --surface-soft: var(--p-cool-050);
  --surface-sunken: var(--p-cool-150);
  /* Öne çıkan modülün ferah mavi zemini (pano "bugünün odağı" gibi). */
  --hero-bg: var(--p-navy-100);
  /* "Seçili" yüzey = açık vurgu yüzeyi (#EFEEFF). Etkin menü satırı,
     seçili liste satırı ve etkin çalışma alanı aynı zemini paylaşır. */
  --selected: var(--p-indigo-100);
  --overlay: rgba(13, 21, 38, 0.44);
  /* Renkli bir zeminin üstüne çekilen yarı saydam yüzey perdesi (pano
     "bugünün odağı" şeridi). Sabit beyaz yazılmıştı; koyu temada açık bir
     sis tabakası olarak kalıyordu. */
  --wash: rgba(255, 255, 255, 0.45);
  /* Tuvalin üzerindeki soyut geometrik doku (bkz. `layout.css`, `.app`).
     İki jeton: çizgi ve çok geniş bir ışık lekesi. Değerler bilerek
     **eşik altı**: doku bir şey *anlatmaz*, yalnız boş zeminin ölü
     görünmesini engeller. Kart ve tablo kendi opak yüzeyinde durduğu için
     hiçbir metin bu dokunun üstüne düşmez. */
  --pattern-line: rgba(23, 32, 51, 0.022);
  --pattern-glow: rgba(79, 70, 200, 0.035);

  /* --- Metin --- */
  --text-primary: var(--p-ink-900);
  --text-secondary: var(--p-ink-600);
  --text-muted: var(--p-ink-400);
  --text-on-brand: #ffffff;
  /* Avatar dolgusu **nötr slate**, marka moru değil. Baş harf bir kimliktir,
     bir eylem değil; üyeler ekranında altı mor daire, sayfadaki tek birincil
     düğmeyle aynı rengi konuşup onu bastırıyordu (bkz. "mor bütçesi",
     TASARIM-SISTEMI.md Faz 18). Kendi jetonu var çünkü `--text-secondary`yi
     dolgu olarak kullanmak, metin basamağını yüzey gibi okumak demekti. */
  --avatar-bg: #56617a;
  --avatar-fg: #ffffff;
  /* `--text` eski addır ve bileşenlerde hâlâ geçiyor; tek kaynağa bağlı
     kalsın diye takma ad olarak duruyor. */
  --text: var(--text-primary);

  /* --- Çizgiler --- */
  /* `--border` yüzeyi *ayırır*, `--border-soft` yüzeyin *içini* böler:
     kartın dış çerçevesiyle satır arası çizgi aynı ağırlıkta olunca liste
     kareli deftere dönüyordu. */
  --border: var(--p-cool-200);
  --border-soft: var(--p-cool-150);
  --border-strong: var(--p-cool-300);
  --border-input: var(--p-cool-250);

  /* --- Durum renkleri (ölçülü kullanılır) --- */
  --warn: var(--p-gold-600);
  --warn-bg: var(--p-gold-100);
  --warn-border: var(--p-gold-200);
  --danger: var(--p-red-600);
  --danger-bg: var(--p-red-100);
  --danger-border: var(--p-red-200);
  --success: var(--p-celadon-600);
  --success-bg: var(--p-celadon-100);
  --success-border: var(--p-celadon-200);
  --info: var(--p-mineral-600);
  --info-bg: var(--p-mineral-100);
  --info-border: var(--p-mineral-200);

  /* --- Vurgu renkleri (durum dışı, "buraya bak" için) --- */
  --accent: var(--p-coral-600);
  --accent-bg: var(--p-coral-100);
  --accent-border: var(--p-coral-200);
  --accent-solid: var(--p-coral-500);
  /* Sessiz meta — tür, kaynak, etiket. Dikkat çekmez, ayırır. */
  --neutral-accent: var(--p-arctic-600);
  --neutral-accent-bg: var(--p-arctic-100);
  --neutral-accent-border: var(--p-arctic-200);

  /* --- Kayıt renk dili: tür ve durum (Faz 27) -------------------------
     Takvimin sözlüğü uygulamanın sözlüğü oldu. Beş renk, sabit anlam:

     · görev = mineral mavi   · iş teslimi = royal indigo
     · müşteri takibi = antik altın
     · gecikme = yanık mercan · tamamlanma = petrol yeşili

     Faz 26'da bu eşleme vardı ama tek rolü vardı: 8 piksellik bir nokta.
     Renk bütçesi açıldığında her ekran kendi dolgusunu, kendi metin
     rengini uyduracaktı — Faz 26 öncesiyle aynı hata, bir basamak yukarıda.
     Bu yüzden renk bir *değer* değil **dört rollü bir takım** olarak
     adlandırılıyor ve bileşenler hangi rolü istediklerini söylüyor:

     · `--…`        → işaretin kendisi (nokta, ikon, şerit, çizgi ucu)
     · `--…-fill`   → dolgu; rozetin ve satır tonunun zemini
     · `--…-ink`    → o dolgunun üstünde AA geçen metin
     · `--…-line`   → dolguyu zeminden ayıran çerçeve

     Sözlük yeni bir renk **tanımlamıyor**, var olanları yeniden
     adlandırıyor: her satırın sağı zaten kullanılan bir anlam jetonu.
     Kazanç tek: "gecikmenin dolgusu ne?" sorusunun tek bir cevabı var ve
     koyu tema bloğuna hiçbir şey eklenmedi — koyu blok paleti yeniden
     bağladığı için beş renk de dört rolüyle birlikte kendiliğinden koyu
     karşılığına düşüyor (ölçü: `test_faz27_*`, her çift iki temada AA).

     `-ink` neden ayrı bir basamak: dolgu 100, işaret 500 basamağından
     gelir ve 500 kendi 100'ünün üstünde 3:1 civarı kalır — okunur değil.
     Metin bir basamak daha koyudan (600/700) gelmek zorunda. */
  --kind-task: var(--strong-solid);
  --kind-task-fill: var(--strong-soft);
  --kind-task-ink: var(--strong);
  --kind-task-line: var(--strong-border);
  /* Tür sözlüğü indigoyu `--brand` üzerinden **çağırmaz**, kendi değerini
     sahiplenir. İkisi bugün aynı piksel; ayrı durmalarının nedeni anlam:
     `--brand` "birincil eylem"dir (ana düğme, etkin sekme, gezinme),
     `--kind-project` "bu kayıt bir iş teslimi"dir. Tek jetonda birleşince
     mor altı ayrı rol üstleniyordu ve renk anlamını yitiriyordu; marka
     moru bir gün kayarsa iş teslimi onunla sürüklenmemeli. */
  --kind-project: var(--p-indigo-500);
  --kind-project-fill: var(--p-indigo-100);
  /* İndigo ve mercan 700'e çıkar (bkz. `--p-coral-700` notu): 600 kendi
     100 dolgusunun üstünde 4.5'i kıl payı kaçırıyor. `--brand-active`
     adıyla çağırmak yanlış olurdu — burada okunan bir etkileşim durumu
     değil, metin rengi. */
  --kind-project-ink: var(--p-indigo-700);
  --kind-project-line: var(--p-indigo-200);
  --kind-company: var(--warn);
  --kind-company-fill: var(--warn-bg);
  --kind-company-ink: var(--warn);
  --kind-company-line: var(--warn-border);
  --state-late: var(--accent-solid);
  --state-late-fill: var(--accent-bg);
  --state-late-ink: var(--p-coral-700);
  --state-late-line: var(--accent-border);
  --state-done: var(--success);
  --state-done-fill: var(--success-bg);
  --state-done-ink: var(--success);
  --state-done-line: var(--success-border);

  /* Altıncı ton: huninin **derin** basamağı.
     ("Teklif gönderildi" — `CompanyStatus.PROPOSAL_SENT`, ton adı `strong`.)

     Firma hunisi altı basamak, ton sözlüğü beş renkti; iki komşu basamak
     ("Görüşülüyor" ve "Teklif gönderildi") aynı `info` tonuna bağlıydı ve
     **aynı rengi** basıyordu. Nokta çağında bu yalnız bir eksiklikti, dolgu
     gelince gözle görünür bir hataya dönüştü: iki satır ayırt edilemiyordu.

     Çözüm altıncı bir hue değil, aynı mavi ailesinde bir basamak **derin**
     dolgu. Neden hue değil: ölçtüm, indigo-100 ile mineral-100 arasındaki
     fark 1.02:1 — iki soluk mavi yan yana geldiğinde ayrışmıyor, hue farkı
     tek başına taşımıyor. Derinlik taşıyor (1.25:1) ve üstüne bir anlam da
     ekliyor: huni ilerledikçe rozet koyulaşıyor, "teklif masada" en çok
     takip isteyen basamak olduğu için en koyu olan da o.

     `-line` olarak 500 kullanılır: 200 dolgunun çerçevesi 200 olamaz. */
  --tone-strong: var(--strong-solid);
  --tone-strong-fill: var(--strong-border);
  --tone-strong-ink: var(--p-mineral-700);
  --tone-strong-line: var(--strong-solid);

  /* --- Grafik (veri görselleştirme) ---
     Üç hue, sabit sıra: **mor → turkuaz → nötr lacivert**. Durum renkleri
     (seladon, altın, mercan) grafikte kullanılmaz ve bu bilinçlidir: aynı
     yeşil hem "kazanıldı" hem "üçüncü seri" demeye başladığında rozetin
     anlamı buharlaşıyor. Grafik kendi ailesini kullanır, durum kendi
     ailesini.

     Sıra da rastgele değil: mor eylem rengiyle akraba olduğu için "asıl
     seri" odur, turkuaz karşıt hue ile ondan en kolay ayrılan ikinci
     seridir, nötr lacivert ise arka plandaki sessiz seri. Üçten fazla
     seri gerekirse çözüm dördüncü renk değil, grafiği bölmektir.

     İkişer basamak: `-solid` dolgu/çizgi, `-soft` zemin. */
  --chart-1: #5b52d8;
  --chart-1-soft: #e3e1fa;
  --chart-2: #2e8ea3;
  --chart-2-soft: #d9eef3;
  /* Üçüncü seri **derin** lacivert, orta gri-mavi değil. Ölçüm zorladı:
     #5A6E93 ile mor arasındaki açıklık farkı 1.12:1 idi ve iki seri gri
     basıldığında ya da renk körü bir ekranda ayırt edilemiyordu. Renk tek
     başına bilgi taşımaz kuralı burada da geçerli — ama taşıdığı kadarını
     da doğru taşımalı. Yeni değerle mor 1.54, turkuaz 2.33 uzakta. */
  --chart-3: #3c4a68;
  --chart-3-soft: #e2e8f2;

  /* --- Tipografi ---
     Manrope: geniş x-yüksekliği, dar rakam genişliği ve 800'e kadar açılan
     bir ağırlık ekseni var. Başlıkları "tok" yapan şey büyük punto değil,
     800 ağırlık + sıkı harf aralığı; gövde 400/500'de nefes almaya devam
     ediyor. */
  --font: "Manrope", "Segoe UI", system-ui, -apple-system, "Helvetica Neue",
    Arial, sans-serif;
  --fs-xs: 0.75rem;
  --fs-sm: 0.8125rem;
  --fs-base: 0.9375rem;
  --fs-md: 1rem;
  --fs-lg: 1.125rem;
  --fs-xl: 1.375rem;
  --fs-2xl: 1.75rem;
  --fs-3xl: 2.25rem;
  --fs-4xl: 2.75rem;
  /* Ekran başlığı (pano gibi tek bir "karşılama" satırı için). Punto
     genişlikle büyür; 360 px'te 1.75rem, 1440 px'te 2.75rem. */
  --fs-display: clamp(1.75rem, 1.15rem + 2.6vw, 2.75rem);

  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-black: 800;

  /* --- Mikro etiket ("eyebrow") -----------------------------------------
     Büyük harfli, harf aralığı açılmış, küçük puntolu bölüm etiketi:
     "BAŞLANGIÇ · PLAN · HEDEF", "TAMAMLANMA", "SÜZGEÇLER", tablo başlıkları,
     menü grup adları. Uygulamada **tek bir rol**, ama Faz 29'a kadar
     on altı ayrı yerde, altı ayrı harf aralığıyla (0.02 / 0.03 / 0.04 /
     0.05 / 0.06 em) ve dört ayrı ağırlıkla (500/600/700/bold) yazılmıştı.

     Tipografinin "işlevsel ama rafine değil" görünmesinin sebebi punto
     seçimi değil tam olarak buydu: aynı şeyi söyleyen etiketler ekranın her
     köşesinde biraz farklı konuşuyor, göz bunu bir sistem olarak
     okuyamıyordu. Rafinelik, az sayıda kararın **her yerde aynı** olması.

     Ölçü: 12 px / 700 / 0.06em. Aralık büyük harfte dekor değil zorunluluk —
     Manrope'un büyük harfleri dar ve 0.02em'de kelime tek bir blok gibi
     yapışıyor; 0.08em üstünde ise harfler dağılıp etiket olmaktan çıkıyor.
     Punto `--fs-xs`te sabit: bu etiket okunmak için değil, **konumlandırmak**
     için var; büyüdüğünde altındaki asıl başlıkla yarışmaya başlıyor. */
  --eyebrow-size: var(--fs-xs);
  --eyebrow-weight: var(--fw-bold);
  --eyebrow-tracking: 0.06em;

  /* --- Boşluk --- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;
  --sp-9: 56px;
  --sp-10: 72px;

  /* --- Köşe yarıçapı ---
     Kart 14 px'te durur. 20 px üstü yuvarlaklık ekranı "kutucuk
     koleksiyonu"na çevirip iş uygulaması olmaktan çıkarıyor; büyük yarıçap
     yalnız alttan açılan panel gibi fiziksel yüzeylerde. */
  --r-xs: 6px;
  --r-sm: 8px;
  /* Düğme alandan bir tık daha sıkı: yan yana duran "Kaydet" ile arama
     kutusu aynı yarıçapı taşıyınca düğme, alanın devamı gibi okunuyordu. */
  --r-btn: 9px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 18px;
  --r-2xl: 22px;
  --r-pill: 999px;

  /* --- Gölge (ölçülü) ---
     Yüzeyi *ayırmak* için değil, **yükseltmek** için. Sayfa akışında duran
     kart gölge almaz; çizgi yeter. İki istisna var:

     - `--shadow-lg` — üstte gerçekten yüzen şeyler (menü, kip, toast).
     - `--shadow-float` — sayfadaki bir-iki "öne çıkan modül".
     - `--shadow-card` — **her kartın** taban gölgesi. Kart yüzeyi tuvalden
       yalnız 1 px çizgiyle ayrılınca, birbirine yakın iki açıklık (zemin
       #F3F6FB, kart #FFFFFF) düz bir kâğıt gibi okunuyordu; bu değer kartı
       ayırmaya yetecek kadar var, sayfayı dalgalandırmayacak kadar yok.
       `--shadow-card-hover` yalnız tıklanabilir kart içindir: hover'da
       değişen tek şey sınır ve gölgedir, yer değil. */
     Faz 29 — gölge **tek katman değil**. Gerçek bir yüzeyin altında iki
     gölge vardır: nesnenin zemine değdiği yerdeki keskin, dar *temas*
     gölgesi ve odanın ışığından kalan geniş, yumuşak *ortam* gölgesi. Tek
     katmanlı `0 6px 20px` ikisini birden taklit etmeye çalışıyor ve
     ikisini de yapamıyordu: kenar yeterince keskin değil (kart zeminin
     üstünde "yüzüyor" ama nereye oturduğu belli değil), yayılma yeterince
     geniş değil (yükseklik hissi yok). Sonuç, tasarımda "sis" denen şey —
     kartın etrafındaki gri bulanıklık.

     Üç katman, üç iş: 1 pikselik temas, orta mesafede gövde, geniş ve çok
     seyreltilmiş ortam. Negatif yayılma (`-3px`, `-12px`) katmanların üst
     kenardan taşmasını keser; gölge yalnız **aşağı** düşer, çünkü ışık
     yukarıdan gelir. Toplam opaklık eskisinden yüksek ama *görünür* koyuluk
     daha düşük: yük geniş katmana dağıldı. */
  --shadow-sm: 0 1px 2px rgba(23, 32, 51, 0.05);
  --shadow-md: 0 6px 18px rgba(23, 32, 51, 0.07);
  --shadow-lg: 0 18px 50px rgba(23, 32, 51, 0.13);
  --shadow-float: 0 18px 50px rgba(23, 32, 51, 0.08);
  --shadow-card:
    0 1px 1px rgba(30, 48, 80, 0.04),
    0 4px 10px -3px rgba(30, 48, 80, 0.05),
    0 14px 30px -12px rgba(30, 48, 80, 0.1);
  --shadow-card-hover:
    0 1px 1px rgba(30, 48, 80, 0.05),
    0 8px 18px -6px rgba(30, 48, 80, 0.08),
    0 22px 44px -16px rgba(30, 48, 80, 0.14);
  /* Katman 1'in gölgesi — sayfadaki **tek** öne çıkan modül için (pano
     odak kartı). `--shadow-float` ile karıştırılmamalı: float, sayfanın
     akışının *dışında* duran bir yüzeydir (yapışkan şerit); raised, akışın
     içinde ama bir basamak yukarıda duran karttır. Aradaki fark ekranda
     yükseklik olarak okunuyor: kart 2 piksel değil, 10 piksel yukarıda. */
  --shadow-raised:
    0 1px 2px rgba(30, 48, 80, 0.05),
    0 10px 20px -8px rgba(30, 48, 80, 0.08),
    0 30px 60px -20px rgba(30, 48, 80, 0.16);
  /* Gezinme çubuğunun gölgesi **yukarı** düşer: telefondaki alt çubuk
     ekranın dibine sabitlenmiş bir yüzeydir ve içerik onun *altından*
     kayar. Tek bir üst çizgi bunu söylemiyordu — çubuk, sayfanın son satırı
     gibi duruyordu; kaydırılan liste çizginin dibinde kesiliyor ve "altında
     devam ediyor" hissi oluşmuyordu. */
  --shadow-nav: 0 -2px 10px rgba(30, 48, 80, 0.06);
  /* Dolu marka yüzeyinin (alt çubuktaki artı düğmesi) gölgesi. Ayrı jeton,
     çünkü rengi nötr değil **markanın kendisi**: mor bir dairenin altında
     gri gölge, daireyi zeminden koparıyor. Eskiden `rgba(63, 65, 166, .28)`
     diye elle yazılıydı — paletteki hiçbir renge karşılık gelmiyordu ve
     koyu temada, açılmış indigonun (#948EF7) altında koyu-mor bir leke
     bırakıyordu. */
  --shadow-brand: 0 4px 12px rgba(79, 70, 200, 0.28);

  /* --- Kaydırma gölgesi ---
     Kendi içinde kayan kapların ("aşağıda / yanda daha var") işareti.
     Kaydırma çubukları bilerek gizli (pano kartları, süzgeç paneli, süreç
     şeridi); geriye tek affordans olarak bu gölge kalıyor, yani
     görünmemesi kaybolan bir çubuktan daha pahalı.

     Ayrı bir jeton olmasının nedeni **koyu tema**: değer üç yerde birden
     `rgba(15, 23, 42, .10)` diye elle yazılmıştı ve o renk koyu-lacivert.
     Koyu yüzeyin üstünde koyu-lacivert bir gölge görünmez; üç kap da koyu
     temada "daha var" demeyi tümüyle bırakıyordu. Bir gölge, altında
     durduğu zemin kadar koyu olamaz. */
  --scroll-shadow: rgb(15 23 42 / 0.10);
  /* İskelet (`.skeleton`) parıltısının **açık** ucu. Taban
     `--surface-sunken`; parıltı ondan bir basamak açık olmak zorunda ve
     "bir basamak açık" iki temada aynı jetona denk gelmiyor. Aydınlıkta
     yüzeyin kendisi, koyuda kenarlık tonu — ikisi de kendi temasında
     sunken'dan açık. Eskiden ikisinde de `--surface-soft` yazılıydı ve
     koyu merdivende soft, sunken'dan **daha koyu**: parıltı yanlış yöne
     gidiyor, yükleniyor animasyonu ölü gri bir blok gibi duruyordu. */
  --skeleton-shine: #ffffff;

  /* --- Hareket ---
     Tek kural: kullanıcının başlattığı her değişim 150–200 ms sürer.
     Daha hızlısı fark edilmez, daha yavaşı bekletir. `--ease-out` giriş,
     `--ease-in` çıkış içindir; ikisi de sonda yavaşlayıp yumuşar. */
  --dur-1: 120ms; /* renk değişimi, hover */
  --dur-2: 170ms; /* açılma, kapanma, durum değişimi */
  --dur-3: 220ms; /* yer değiştiren büyük yüzeyler (drawer, sheet) */
  --ease-out: cubic-bezier(0.22, 0.7, 0.3, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0.4);
  --ease: cubic-bezier(0.4, 0.14, 0.3, 1);

  /* --- Ölçüler --- */
  /* Üst gezinme "ince ve sabit". 60 → **54 px**: çubukta gezinme yok,
     yalnız arama ve üç kontrol var; 60 px o yük için fazlaydı ve her
     ekranın tepesinden altı piksel çalıyordu. Menü başlığı aynı jetonu
     okuduğu için logo ile arama tek yatay çizgide kalır. */
  --topbar-h: 54px;
  --tabbar-h: 64px;
  /* Kabuk **tam genişlik**: üst çubuk ve içerik kolonu pencereyi kullanır,
     ortada 1440 px'lik bir ada bırakmaz. Geniş ekranda sınır, listelerde
     sütunları gereksiz sıkıştırıyor ve iki yanda büyük boş şeritler
     bırakıyordu. Kenarla içerik arasındaki nefes payı artık genişlik
     sınırından değil, kabuğun yatay dolgusundan geliyor (`.content`,
     `.topbar-inner`).

     Okunabilirlik sınırı ortadan kalkmadı, yalnız yerini değiştirdi:
     gereken yerde kendi bileşeninde duruyor (`--measure`, `.form-page`,
     `.form-narrow`, `.empty-state p`), sayfanın tamamında değil. */
  --shell-max: 100%;
  /* Ayrıntı sayfası da kabukla aynı genişlikte. "Bilgiler" ızgarası
     `auto-fit`/`minmax(360px, 1fr)` olduğu için genişledikçe sütun
     *sayısını* artırır, sütunu 700 px'e yaymaz — eski 1040 px'lik sınırın
     koruduğu şeyi (etiket ile değerin göz kararı taranabilir kalması)
     artık ızgaranın kendisi koruyor. */
  --record-max: 100%;
  --tap: 44px; /* en küçük dokunma hedefi */

  /* --- Maskeyle çizilen ikonlar ---
     Kural olarak ikonlar satır içi SVG'dir (`_icons.html`): renk, kalınlık
     ve erişilebilirlik tek yerden gelir. İstisna, ikonun **şablonda yeri
     olmadığı** durumdur — telefonda kırıntı yolunun başına giren geri oku
     gibi. Orada seçenek ya yedek yazı tipinden gelen bir ok karakteri
     (bozuk çıkıyordu) ya da maske; maske, çizimi setin diliyle (24'lük
     kutu, 1.8 kalınlık, yuvarlak uç) aynı tutuyor ve rengi `currentColor`
     olarak bırakıyor. Jeton olması, data-URI'nin kuralın içinde okunmaz bir
     blok hâline gelmesini engelliyor. */
  --geri-oku: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5'/%3E%3Cpath d='m11 18-6-6 6-6'/%3E%3C/svg%3E");
  /* Uzun metnin okunabilir kaldığı sınır. Sayfa geneline değil, yalnız
     paragraf sütunlarına uygulanır. */
  --measure: 68ch;
}

/* ==========================================================================
   Koyu tema (Faz 5)

   Token mimarisi bunun için iki basamaklıydı: aşağıda **hiçbir bileşen
   kuralı yok**, yalnız anlam basamağı yeniden bağlanıyor. Bir düğmenin,
   kartın ya da rozetin kendi kuralına dokunulmadı; dokunulsaydı iki tema
   zamanla birbirinden ayrı düşer ve "koyu temada bozuk" bir bileşen
   listesi birikirdi.

   Üç karar:

   - **Zemin saf siyah değil.** #000 üstünde beyaz metin halelenir ve kart
     sınırları kaybolur; lacivere çalan koyu nötr, açık temadaki soğuk
     nötrün karşılığıdır.
   - **Yükselti renkle anlatılır, gölgeyle değil.** Koyu zeminde gölge
     görünmez; kart zeminden **bir ton açık** olur. Gölge token'ları
     zayıflatıldı ama silinmedi (menü, kip ve toast hâlâ yüzer).
   - **Yardımcı renkler açılır, dolguları koyulur.** Açık temanın -600
     metin tonu koyu zeminde okunmuyor; metin -200/-300'e çıkar, dolgu ise
     zemine yakın koyu bir tona iner. Rozetin *anlamı* değişmez, yalnız
     kontrastı korunur.

   Varsayılan **aydınlık**tır: tercih yoksa `data-theme` hiç yazılmaz ve
   bu blok devreye girmez. "Sistem" seçeneği, sistem koyu isterken bu
   bloğu açar (`[data-theme="auto"]` + `prefers-color-scheme`). */

[data-theme="dark"] {
  color-scheme: dark;

  /* --- Palet: koyu nötrler (zemin, çizgi) ---
     Beş basamak, beş farklı yüzey: tuval (#050A16) → sol menü (#0A1322)
     → alan/girdi (#0C1727) → kart (#141F36) → yükseltilmiş (#1B2842).
     Saf siyah yok: #000 üstünde beyaz metin halelenir ve kart sınırları
     kaybolur. Yükselti burada gölgeyle değil, bu ton merdiveniyle ve
     #2C3C58'lik sınırla anlatılır.

     Merdiven Faz 18'de **açıldı** (#0D1729 → #141F36) ve tuval bir tık
     koyulaştı (#070F1E → #050A16). Gerekçe ölçüm: eski değerlerde kart ile
     tuval arasındaki karşıtlık **1.07:1** idi; 1440 px'lik bir liste
     ekranında kartın nerede bittiği görünmüyordu ve sayfa tek düz koyu
     yüzey gibi okunuyordu. Yeni aralık **1.20:1**, sınır ile kart arası
     1.48:1 — yüzey kendini ton ve çizgiyle anlatıyor, parlamadan. */
  --p-cool-000: #141f36;
  --p-cool-025: #0c1727;
  --p-cool-050: #1b2842;
  --p-cool-100: #050a16;
  --p-cool-150: #20304c;
  --p-cool-200: #2c3c58;
  --p-cool-250: #364868;
  --p-cool-300: #43587c;
  --p-cool-400: #556d94;

  /* --- Palet: metin ---
     Ana metin #F1F4FA, ikincil #B4BFD1, sessiz #A3AEC1.

     İki alt basamak Faz 18'de **açıldı** (#A5B0C4 / #8E9AAF). Eski
     değerler AA'yı geçiyordu ama koyu zeminde ölçüm yanıltıyor: aynı
     4.5:1, açık zeminde "sakin", koyu zeminde "sönük" okunur — beyaz
     metin koyu zeminde optik olarak yayılır ve gri basamak olduğundan
     daha silik görünür. Yeni değerlerin en kötü zemini (`--surface-sunken`,
     #1C2942) karşısındaki oranı 7.83:1 ve 6.49:1; basamaklar arasındaki
     fark korundu, ikisi de artık okunacak metin gibi duruyor. */
  --p-ink-900: #f1f4fa;
  --p-ink-600: #b4bfd1;
  --p-ink-400: #a3aec1;

  /* --- Palet: eylem ve kimlik ---
     Indigo koyu zeminde #4F46C8'de morlaşıp okunmuyor; eylem rengi açılır
     (#7B74F2), yumuşak zeminler ise doygunluğunu kaybedip koyular
     (#1B1D43). Merdiven açık temadakinin **tersine** sıralanır: -700 en
     açık basamaktır, çünkü "daha baskın" demek koyu temada "daha açık"
     demektir.

     Faz 18'de eksen bir basamak açıldı (#7B74F2 → #948EF7): ölçüm
     tutmuyordu. Indigo yalnız düğme dolgusu değil, **yumuşak vurgu
     yüzeyinin üstündeki metin** de oluyor (etkin menü satırı, `avatar-soft`,
     seçili liste satırı) ve #7B74F2 kendi yumuşak zemininde (#1B1D43)
     4.31:1'de kalıyordu. Yeni çift (#948EF7 / #242657) aynı yerde 5.01:1
     veriyor; en kötü zemin olan `--surface-sunken`da bile 4.70. Dolgu açıldıkça
     üstündeki yazı koyulaşır — o kural zaten `--text-on-brand`da. */
  --p-indigo-700: #aca7f9;
  --p-indigo-600: #a09af9;
  --p-indigo-500: #948ef7;
  --p-indigo-200: #45417f;
  --p-indigo-100: #242657;
  --p-indigo-075: #202250;
  --p-indigo-050: #1b1d43;

  --p-navy-900: #050a16;
  --p-navy-800: #0e1b2e;
  --p-navy-700: #b6c6df;
  --p-navy-300: #54678a;
  --p-navy-200: #334463;
  --p-navy-100: #1a2740;
  --p-navy-050: #121e33;

  /* --- Palet: yardımcılar ---
     Metin tonu (-600) açılır, dolgu (-100/-200) zemine yakın koyuya iner.
     Rozetin *anlamı* değişmez, yalnız kontrastı korunur.

     Faz 18: üç durum rengi de bir basamak **parladı** (seladon #35BFA8 →
     #3ED9BF, altın #D8A743 → #E8B95C, mercan/kırmızı #E1767A → #F08B8F) ve
     dolgular kart yüzeyi açılınca onunla birlikte yükseldi. Koyu zeminde
     "başarı yeşili" ile "uyarı sarısı" arasındaki farkı taşıyan şey
     doygunluk değil parlaklıktır; eski tonlar #141F36 kartın üstünde
     birbirine yaklaşıyor ve rozetler tek bir soluk renk ailesi gibi
     okunuyordu. */
  /* Koyu tarafta 700 daha **acik** mineraldir. */
  --p-mineral-700: #b8d5ee;
  --p-mineral-600: #9cc2e4;
  --p-mineral-500: #5a92c9;
  --p-mineral-200: #2e4b6d;
  --p-mineral-100: #1d3349;
  --p-arctic-600: #8ed8ea;
  --p-arctic-500: #55b6cf;
  --p-arctic-200: #245566;
  --p-arctic-100: #163b47;
  --p-celadon-600: #3ed9bf;
  --p-celadon-500: #23b39a;
  --p-celadon-200: #1f564d;
  --p-celadon-100: #153b36;
  --p-gold-600: #e8b95c;
  --p-gold-500: #c4933a;
  --p-gold-200: #584722;
  --p-gold-100: #3c2f17;
  /* Koyu tarafta basamaklar terse döner: 700 daha **açık** mercandır. */
  --p-coral-700: #f6a3a6;
  --p-coral-600: #f08b8f;
  --p-coral-500: #d46b6f;
  --p-coral-200: #603636;
  --p-coral-100: #422625;
  --p-red-600: #f08b8f;
  --p-red-200: #663433;
  --p-red-100: #442322;

  /* --- Anlam: açık temada palete bağlı olmayan birkaç değer --- */
  --page-bg: var(--p-cool-100);
  --app-bg: var(--p-cool-025);
  --sidebar-bg: #0a1322;
  --surface: var(--p-cool-000);
  --surface-soft: var(--p-cool-050);
  --surface-sunken: var(--p-cool-150);
  --hero-bg: var(--p-navy-100);
  --selected: var(--p-indigo-100);
  --overlay: rgba(2, 5, 12, 0.72);
  --wash: rgba(255, 255, 255, 0.05);
  /* Koyu tarafta doku bir tık görünür: koyu boş zemin, açık boş zeminden
     daha çok "delik" gibi duruyor. Yine de eşik altı — parlama yok. */
  --pattern-line: rgba(160, 190, 255, 0.03);
  --pattern-glow: rgba(148, 142, 247, 0.05);

  /* Grafik ailesi koyu zeminde parlar; sıra ve rol aynı kalır. Dolgu
     tonları `-solid` olarak kullanıldığı için 3:1'lik grafik eşiğini kendi
     zeminine (kart, #141F36) karşı geçmeleri yeter — üzerlerinde metin
     durmaz. Yumuşak basamak zeminin bir tık üstüne iner. */
  --chart-1: #948ef7;
  --chart-1-soft: #262a5c;
  --chart-2: #45c2dc;
  --chart-2-soft: #143e4a;
  --chart-3: #6b80a6;
  --chart-3-soft: #22314a;

  /* Birincil düğmenin üstündeki metin **koyuya döner**: koyu temada indigo
     dolgu açıldı (#7B74F2) ve üstünde beyaz metin 3.7:1'de kalıyordu.
     Dolgu açıldıkça yazı koyulaşır; kural tek yerde. */
  --text-on-brand: #0b1020;
  /* Koyu tarafta dolgu **açılır**, yazı açık kalır: koyu zeminde koyu bir
     daire kartın içinde bir delik gibi duruyor. #3A4B69 kartın üstünde
     1.87:1 ile ayrışıyor, üstündeki #F1F4FA yazı 7.97:1. */
  --avatar-bg: #3a4b69;
  --avatar-fg: #f1f4fa;

  --brand-tint-6: rgba(148, 142, 247, 0.1);
  --brand-tint-10: rgba(148, 142, 247, 0.16);
  --focus-ring: 0 0 0 3px rgba(148, 142, 247, 0.38);

  /* Gölge koyu zeminde görünmez ama tümüyle silinirse **yüzen** yüzeyler
     sayfaya yapışır; menü, kip ve toast için opaklık yüksek kalır.

     Akıştaki kartın gölgesi ise Faz 18'de **hafifletildi** (0.22 → 0.12).
     Eskiden kartı zeminden ayıran şey oydu, çünkü yüzey ve sınır farkı
     yetmiyordu; artık merdiven (#050A16 → #141F36) ve 1 px sınır o işi
     yapıyor. Koyu zeminde koyu gölge zaten "kir" olarak okunuyor ve iki
     kart yan yana geldiğinde aralarına gri bir bulanıklık koyuyordu. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 6px 18px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.62);
  --shadow-float: 0 16px 42px rgba(0, 0, 0, 0.42);
  --shadow-card: 0 2px 8px rgba(0, 0, 0, 0.12);
  --shadow-card-hover: 0 4px 14px rgba(0, 0, 0, 0.2);
  /* Katman 1 koyu tarafta **gölgeyle değil yüzeyle** yükselir: aydınlıkta
     üç katmanlı olan jeton burada tek katman ve zayıf. Asıl işi
     `--surface-soft` (#1B2842) yapıyor — merdivenin bir üst basamağı. Koyu
     zeminde 60 piksellik siyah bir hale, kartı yükseltmiyor, etrafına kir
     bırakıyor (aynı gerekçe `--shadow-card`ın Faz 18 notunda). */
  --shadow-raised: 0 6px 20px rgba(0, 0, 0, 0.28);
  --shadow-nav: 0 -2px 10px rgba(0, 0, 0, 0.32);
  /* Koyu tarafta marka gölgesi **açılmış** indigodan gelir ve zayıflar:
     koyu zeminde renkli bir hale, aydınlıktakinin aksine parlama gibi
     okunuyor. */
  --shadow-brand: 0 4px 14px rgba(148, 142, 247, 0.22);
  /* Koyu tarafta gölge **saf siyah** ve daha güçlü: yüzeyin kendisi zaten
     koyu, ayrım ancak ondan daha koyu bir tonla kurulabiliyor. Aydınlıktaki
     %10'luk lacivert burada hiçbir şey çizmiyordu. */
  --scroll-shadow: rgb(0 0 0 / 0.45);
  --skeleton-shine: #2c3c58;
}

/* "Sistem" seçeneği CSS'te **ayrı bir blok değildir.** `auto` tercihini
   betik çözer ve `data-theme` olarak `light` ya da `dark` yazar; burada
   yalnız iki tema durur. Alternatif, bütün bloğu
   `@media (prefers-color-scheme: dark) { [data-theme="auto"] { … } }`
   altında ikinci kez yazmaktı: yüz satırlık bir kopya, ilk unutulan
   token'da iki temanın sessizce ayrılması demekti.

   Betik yoksa tercih uygulanmaz ve ekran **aydınlık** kalır — varsayılan
   zaten odur, kayıp yok. */

/* Dokunmatik aygıtta hedefler 48 px'e çıkar. Tek yerden: `--tap`i okuyan
   her bileşen (düğme, menü satırı, ikon düğmesi, sekme) kendiliğinden
   büyür; kuralı bileşen bileşen tekrarlamak, unutulan bir bileşen
   demekti. Masaüstünde 44 px kalır — fareyle 48 px gereksiz yer kaplıyor
   ve satır yoğunluğunu düşürüyor. */
@media (pointer: coarse) {
  :root { --tap: 48px; }
}

/* ==========================================================================
   Sıfırlama ve temel
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--text);
  background: var(--page-bg);
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
  /* Yatay taşma yasağı. `clip` seçildi, `hidden` değil: `hidden` gövdeyi bir
     kaydırma kabına çevirir ve içindeki `position: sticky` öğeler (üst
     gezinme, tablo başlığı, form ayak çubuğu) yapışmayı bırakır. `clip`
     kaydırma kabı üretmeden fazlalığı keser. Taşmanın *kaynağı* yine
     düzeltilir — bu kural yalnız son emniyet. */
  overflow-x: clip;
}

/* Manrope'ta sayısal genişlikler öntanımlı olarak orantılıdır: bir tabloda
   alt alta duran "11" ve "18" farklı genişlikte çıkıyor, kolon titriyordu.
   Rakam taşıyan her yüzeyde sabit genişlik açılır. */
table, .table, .stat-value, .metric, .kbd, .badge, .count,
time, .cal-cell-date, .progress, .notif-count {
  font-variant-numeric: tabular-nums;
}

/* Başlıklar "tok": punto değil **ağırlık** ve sıkı harf aralığı. 800,
   Manrope'un en üst ağırlığı; 700'de başlıklar gövdeden yeterince
   ayrışmıyor, sayfa tek düzlemde okunuyordu. */
h1, h2, h3, h4 {
  margin: 0;
  font-weight: var(--fw-black);
  line-height: 1.2;
  letter-spacing: -0.022em;
  color: var(--text-primary);
}

h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); letter-spacing: -0.015em; }
h4 { font-size: var(--fs-md); font-weight: var(--fw-bold); letter-spacing: -0.01em; }

/* Ekran başlığı — sayfa başına en fazla bir tane. Panodaki "Bugün neyi
   ilerletiyoruz?" gibi karşılama satırları için; sıradan sayfa başlığı
   `.page-title` kalır (bkz. `.page-header`). */
.display-title {
  font-size: var(--fs-display);
  font-weight: var(--fw-black);
  line-height: 1.1;
  letter-spacing: -0.03em;
  color: var(--text-primary);
}
/* Başlığın ikinci satırı renklenir: vurgu %12'lik paya buradan girer,
   dekoratif bir şekil ya da dolu bir blok gerekmeden. */
.display-title .accent-word { color: var(--brand); }

p { margin: 0 0 var(--sp-3); }
p:last-child { margin-bottom: 0; }

/* Tanım listeleri ayrıntı ekranlarında kullanılıyor. Tarayıcı <dd> öğesine
   varsayılan 40px sol boşluk verir; ızgara tek kolona düştüğünde bu, değeri
   etiketin sağına kaydırır. */
dl, dd { margin: 0; }

/* Tarayıcı `<fieldset>` öğesine gömülü bir çerçeve ve `<legend>` için çentik
   çiziyor. Seçenek grupları (`.choice-group`) zaten kendi çerçevesini
   taşıdığı için ekranda iç içe iki kutu görünüyordu; dıştaki, tasarım
   sisteminde karşılığı olmayan bir çizgiydi. Etiket artık normal bir alan
   etiketi gibi davranır. */
fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
legend { padding: 0; }

/* HTML'in `hidden` özniteliği bir sınıf tarafından ezilmemeli: `display`
   veren her yardımcı sınıf (`stack`, `row`, `flex`) onu görünür kılıyordu.
   Öznitelikle gizlemek, sınıf eklemekten daha açık bir niyet. */
[hidden] { display: none !important; }

a {
  color: var(--brand);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

img, svg { max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Yardımcı sınıflar
   ========================================================================== */

.muted { color: var(--text-secondary); }
.subtle { color: var(--text-muted); }
.small { font-size: var(--fs-sm); }
.xsmall { font-size: var(--fs-xs); }
.strong { font-weight: 600; }
.nowrap { white-space: nowrap; }
.text-center { text-align: center; }
.text-right { text-align: right; }

.row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
/* Tek başına da kullanılabilsin: yalnız `flex-wrap` vermek, `.row` olmayan
   bir kapsayıcıda hiçbir şey yapmaz ve öğeler blok gibi alt alta düşer. */
.row-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}
.stack { display: flex; flex-direction: column; gap: var(--sp-3); }
.stack-sm { display: flex; flex-direction: column; gap: var(--sp-2); }
.stack-lg { display: flex; flex-direction: column; gap: var(--sp-5); }
.grow { flex: 1 1 auto; min-width: 0; }
/* `overflow`/`text-overflow` satır içi öğelerde geçersizdir; bu sınıf çoğunlukla
   <span> üzerinde kullanıldığı için blok seviyesine çekilir. Flex/grid öğeleri
   zaten bloklaştığı için orada davranış değişmez. */
.truncate {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.icon {
  width: 20px;
  height: 20px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-sm { width: 16px; height: 16px; }
.icon-lg { width: 24px; height: 24px; }

/* ==========================================================================
   Butonlar
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: 0 var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r-btn);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 600;
  font-size: var(--fs-base);
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out),
    color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
.btn:hover { text-decoration: none; }
/* Basınca 1px çökme: dokunmanın karşılığı olduğunu söyleyen en ucuz
   geri bildirim. Gölge veya renk sıçraması gerekmez. */
.btn:active:not(:disabled):not([aria-disabled="true"]) { transform: translateY(1px); }
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}
/* Kaydederken: düğme yerinde kalır, yazısı solar, yanında çark döner.
   Metni "Kaydediliyor…" diye değiştirmek düğmenin enini oynatıp
   yanındakileri kaydırıyordu. */
.btn.is-busy {
  position: relative;
  pointer-events: none;
  color: transparent;
}
.btn.is-busy > * { opacity: 0; }
.btn.is-busy::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border: 2px solid currentcolor;
  border-radius: 50%;
  border-top-color: transparent;
  color: var(--text-on-brand);
  animation: spin 0.65s linear infinite;
}
.btn-secondary.is-busy::after,
.btn-ghost.is-busy::after,
.btn-soft.is-busy::after { color: var(--brand); }
.btn-strong-soft.is-busy::after { color: var(--strong); }

/* Birincil — royal indigo. Sayfada **bir** tane olur: o ekranda yapılması
   beklenen iş. Gölge saç teli kalınlığında ve düğmenin kendi renginden
   türetilmiş; nötr gri bir gölge, renkli yüzeyin altında kir gibi
   duruyordu. */
.btn-primary {
  background: var(--brand);
  color: var(--text-on-brand);
  box-shadow: 0 1px 2px rgba(63, 65, 166, 0.24);
}
.btn-primary:hover { background: var(--brand-hover); }
.btn-primary:active { background: var(--brand-active); }

/* Güçlü ikincil — parlamento mavisi. Birincil kadar bağlayıcı olmayan ama
   nötr de olmayan eylemler: "İletişim kaydet", "Dışa aktar", "Taşı".
   Beyaz-çerçeveli `.btn-secondary` bu işler için fazla sessiz kalıyor,
   indigo ise ekranda ikinci bir "asıl eylem" üretiyordu. */
.btn-strong {
  background: var(--strong-solid);
  color: var(--text-on-brand);
  box-shadow: 0 1px 2px rgba(61, 110, 156, 0.24);
}
.btn-strong:hover { background: var(--strong); }

/* Aynı eylemin sakin hâli — satır içinde ya da bir kartın başlığında. */
.btn-strong-soft {
  background: var(--strong-soft);
  color: var(--strong);
}
.btn-strong-soft:hover { background: var(--strong-border); }

/* Lacivert — kimlik rengi. Yalnız `--hero-bg` zeminli bir modülün (`.card-hero`)
   içindeki tek çağrı için: o navy zeminde indigo düğme aynı aileden iki mavi
   oluyor ve ayrışmıyordu.

   Faz 15'te panodaki tek kullanıcısını kaybetti — "Bugünün odağı" kartının
   zemini mineral maviden indigoya geçince düğme de birincil indigoya döndü
   (bkz. `components.css`, `.dash-focus`). Sınıf `.card-hero` ile birlikte
   duruyor: ikisi bir çifttir, biri kalıp diğeri silinirse geriye zeminsiz
   bir düğme ya da düğmesiz bir zemin kalır. */
.btn-navy {
  background: var(--navy);
  color: var(--text-on-brand);
}
.btn-navy:hover { background: var(--navy-hover); }
.btn-navy:active { background: var(--navy-active); }

/* İkincil: beyaz yüzey, **ince** sınır, koyu metin. Sınır `--border`
   (kartın çizgisiyle aynı) — `--border-strong` ile çizildiğinde düğme
   kendi ağırlığını birincile yaklaştırıyor, iki eylem eşit sesle
   konuşuyordu. Ayrım hover'da gelir. */
.btn-secondary {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
}
.btn-secondary:hover { background: var(--surface-soft); border-color: var(--border-strong); }

.btn-soft {
  background: var(--brand-soft);
  color: var(--brand);
}
.btn-soft:hover { background: var(--brand-border); }

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
}
.btn-ghost:hover {
  background: var(--surface-soft);
  color: var(--text);
}

.btn-danger {
  background: var(--danger);
  /* Koyu temada `--danger` acik somona doner; sabit beyaz metin ~2.2:1'e
     duserdi. `--text-on-brand` tema ile birlikte koyuya cevrilir. */
  color: var(--text-on-brand);
}
.btn-danger:hover { filter: brightness(0.94); }

/* Sessiz yıkıcı eylem (Faz 19). Dolu kırmızı bir düğme, yanındaki birincil
   eylemle **aynı** ağırlıkta okunur; toplu çubukta "Uygula" ile "Seçilenleri
   sil" yan yana durup hangisinin asıl iş olduğunu belirsizleştiriyordu.
   Yıkıcılık rengi hak eder, dolgusu değil — aynı ayrım menü öğelerinde
   zaten var (`.dropdown-item.is-danger`), burada düğmeye taşınıyor. */
.btn-ghost.is-danger { color: var(--danger); }
.btn-ghost.is-danger .icon { color: var(--danger); }
.btn-ghost.is-danger:hover,
.btn-ghost.is-danger:focus-visible {
  background: var(--danger-bg);
  color: var(--danger);
}

.btn-block { width: 100%; }
.btn-sm {
  min-height: 36px;
  padding: 0 var(--sp-3);
  font-size: var(--fs-sm);
}
/* İkon düğmesi **kare ve 38 px**: 44'lük hedef, yanındaki 44 px'lik alanla
   birlikte satırı şişiriyor, tek bir simge için fazla yer kaplıyordu.
   Parmak için alt sınır hemen aşağıda yeniden `--tap`e çıkar — kural
   aygıta bağlıdır, görsele değil. */
.btn-icon {
  min-height: 38px;
  min-width: 38px;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: var(--r-btn);
}
@media (pointer: coarse) {
  .btn-icon {
    min-height: var(--tap);
    min-width: var(--tap);
    width: var(--tap);
    height: var(--tap);
  }
}

/* ==========================================================================
   Formlar
   ========================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.field-label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}

/* Yardımcı açıklama alanın hemen altında, küçük ve sakin: etiketle aynı
   puntoda yazıldığında "ikinci bir etiket" gibi okunuyor, gözü alandan
   önce kendine çekiyordu. */
.field-hint {
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--text-secondary);
}

/* Hata da aynı yerde ve aynı ölçüde durur; değişen tek şey renktir. Alanı
   kalın kırmızı çerçeveye boğmak yerine (aşağıdaki `aria-invalid` kuralı)
   mesaj taşır — form bir hatayla dolduğunda ekran alarm panosuna
   dönmesin. */
.field-error {
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--danger);
}

.input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.input-wrap .input-icon {
  position: absolute;
  left: 14px;
  color: var(--text-muted);
  pointer-events: none;
}

.input-wrap:has(.input-icon) .input { padding-left: 42px; }

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 10px var(--sp-4);
  border: 1px solid var(--border-input);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-base);
  /* Satır yüksekliği **`font: inherit`ten sonra** yazılır: kısaltma
     gövdeden gelen 1.55'i geri getiriyor, 10+10 dolgu ve 2 px çerçeveyle
     toplanınca alan `min-height`i bir piksel aşıp 45 px'e çıkıyordu. Yan
     yana duran alan (45) ile düğme (44) arasındaki o tek piksel,
     çekmecenin alt çubuğunda gözle görülür bir kayma üretiyor. */
  line-height: 1.4;
  transition: border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out),
    background-color var(--dur-1) var(--ease-out);
  /* iOS'ta odaklanınca yakınlaştırmayı önlemek için 16px taban */
}
.input:hover:not(:disabled):not(:focus),
.textarea:hover:not(:disabled):not(:focus) { border-color: var(--border-strong); }
.textarea {
  min-height: 96px;
  padding-top: var(--sp-3);
  resize: vertical;
}
.select {
  appearance: none;
  padding-right: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23667386' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
}

.input::placeholder,
.textarea::placeholder { color: var(--text-muted); }

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--focus-ring);
}

.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"] {
  /* Tam doygunluktaki `--danger` değil, sınır tonu: alanı işaretlemeye
     yetiyor, altındaki mesajın önüne geçmiyor. Odaklanınca netleşir. */
  border-color: var(--danger-border);
}
.input[aria-invalid="true"]:focus,
.select[aria-invalid="true"]:focus,
.textarea[aria-invalid="true"]:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-bg);
}

.input:disabled,
.select:disabled {
  background: var(--surface-soft);
  color: var(--text-secondary);
  cursor: not-allowed;
}

.password-toggle {
  position: absolute;
  right: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.password-toggle:hover { color: var(--text); background: var(--surface-soft); }
/* Parmakla 38 px'lik göz simgesini ıskalamak kolay; alan zaten 44 px. */
@media (pointer: coarse) {
  .password-toggle { width: var(--tap); height: var(--tap); right: 0; }
  .input-wrap:has(.password-toggle) .input { padding-right: calc(var(--tap) + 4px); }
}
.input-wrap:has(.password-toggle) .input { padding-right: 46px; }

.checkbox {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  cursor: pointer;
  font-size: var(--fs-base);
}
.checkbox input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--brand);
  cursor: pointer;
}

/* Dosya seçici: tarayıcının ham düğmesi yerine ikincil düğme görünümü.
   Metni tarayıcı yerelleştirir, biçimi bize ait. */
.input[type="file"] {
  padding: 6px var(--sp-2);
  cursor: pointer;
}
.input[type="file"]::file-selector-button {
  margin-right: var(--sp-3);
  min-height: 32px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}
.input[type="file"]::file-selector-button:hover { background: var(--surface-soft); }

/* ==========================================================================
   Kart, panel, bölüm başlığı
   ========================================================================== */

/* Kart, "bir arada duran ve **birlikte kaydırılan** veri" demektir: liste,
   tablo, form. Sayfadaki her başlık altı kart değildir — bölümleri ayırmak
   boşluğun, tipografinin ve ince çizginin işidir (`.section` aşağıda).
   Yüzey üç şeyle kurulur ve üçü bütün kartlarda aynıdır: 14 px köşe, 1 px
   sınır, `--shadow-card`. Buradaki gölge "yükseklik" anlatmaz — kartın
   nerede bitip tuvalin nerede başladığını söyler; o yüzden ölçüsü karttan
   karta değişmez. Yükseklik iddiası hâlâ `--shadow-float`ın işidir
   (`.card-float`). */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}
/* Tıklanabilir kartta hover **yalnız sınırı ve gölgeyi** güçlendirir. Yer
   değiştiren kart (translateY) komşularını da kıpırdıyormuş gibi gösterir;
   ızgaranın hizası imleç gezdikçe bozuluyordu. */
a.card:hover,
.card-link-surface:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-card-hover);
}
.card-pad { padding: var(--sp-5); }

/* --- Öne çıkan modül ------------------------------------------------------
   Tasarım sisteminde tek bir yumuşak gölge değeri var ve bu değer **her
   karta** verilmez: sayfadaki bir-iki modül (panonun odak kartı, giriş
   kartı) yükselir, geri kalanı çizgiyle durur. Gölge her yerde olursa
   hiçbir yerde olmamış gibi okunur ve sayfa dalgalanır. */
.card-float {
  border-color: var(--border-soft);
  box-shadow: var(--shadow-float);
}

/* Ferah mavi zemin. Tek renk, gradient değil: gradient bu ölçekte (400×200
   px'lik bir kart) bant üretiyor ve zeminin "düz kâğıt" okunmasını
   bozuyordu. */
.card-hero {
  background: var(--hero-bg);
  border-color: transparent;
}
.card-hero .card-title,
.card-hero h2, .card-hero h3 { color: var(--navy-active); }
/* Paletten degil anlamdan: `--hero-bg` koyu temada koyulasiyor, sabit
   lacivert metin okunmaz hale geliyordu. Opaklik da gereksizdi -- ikincil
   metnin kendi tokeni zaten dogru kontrasti tasiyor. */
.card-hero .muted { color: var(--text-secondary); }

/* --- Bölüm ritmi (karta alternatif) ---------------------------------------
   Aynı sayfadaki farklı konular arasına kart değil **boşluk** girer. Başlık
   satırı küçük ve büyük harfli, altında ince bir çizgi; konu değiştiğini
   söylemeye bu yeter. */

.section { display: flex; flex-direction: column; gap: var(--sp-4); }

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--border-soft);
}
.section-head > .row { min-width: 0; }
.section-heading {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  font-size: var(--fs-sm);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  /* Faz 29: bölüm başlığı **mürekkep**, gri değil. İkincil basamak burada
     yanlış bir tasarrufu: başlık, altındaki içerikten daha soluk yazıldığı
     için sayfa "gri bir üst satır + siyah bir liste" gibi okunuyor ve
     bölümler birbirinden ayrışmıyordu. Etiketin *sessiz* kalmasını zaten
     punto ve büyük harf sağlıyor; rengi de kısmak, hiyerarşiyi iki kez
     aşağı çekmek demekti. */
  color: var(--text-primary);
}
.section-heading .icon { width: 16px; height: 16px; color: var(--text-muted); }
/* Bölüm başlığının sağındaki sayı: "kaç tane" sorusu başlığa bakarken
   sorulur, listeyi sayarken değil. */
.section-heading .count {
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0;
}
.section-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
}

.divider {
  height: 1px;
  border: 0;
  margin: 0;
  background: var(--border);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border-soft);
}
.card-title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-md);
  /* 700 değil 600: başlık içerikten *ayrılmalı*, onu bastırmamalı. Ayrımı
     zaten altındaki ince çizgi yapıyor. */
  font-weight: var(--fw-semibold);
  letter-spacing: -0.005em;
}
/* Faz 29 — **mor bütçesi**. İkon marka renginden çıktı.

   Kart başlığındaki ikon bilgi taşımıyor: yanındaki kelime aynı şeyi zaten
   yazıyor. Marka rengi ise uygulamanın en pahalı işareti — "buraya bas"
   demek. Her kart başlığında bir mor ikon durduğunda ekranda altı sekiz
   mor nokta oluyor ve sayfadaki *tek gerçek* birincil düğme onların arasında
   kayboluyordu. Renk nadir olduğu ölçüde değerli. */
.card-title .icon { color: var(--text-muted); }
.card-body { padding: var(--sp-5); }
.card-link {
  display: inline-flex;
  align-items: center;
  /* Fareyle 32 px yeter ve kart başlığını şişirmez; dokunmatikte `--tap`
     (48 px) alt sınırın altına düşmesin — pano kartlarındaki "Tümü"
     bağlantısı denetimde 43x32 ölçülmüştü. */
  min-height: 32px;
  padding: 0 var(--sp-1);
  font-size: var(--fs-sm);
  font-weight: 600;
  /* Faz 29 — mor bütçesi. "Tümünü gör" bir **yön** bağlantısıdır, bir eylem
     değil: kaydı değiştirmez, listeyi açar. Panoda beş kart × bir mor
     bağlantı, ekranın sağ kenarına mor bir sütun diziyordu.

     Sessizleşen tek şey renk: ağırlık 600'de kalıyor, hover'da hem mora
     dönüyor hem alt çizgi alıyor. Yani "tıklanabilir" bilgisi kaybolmadı,
     yalnız **istirahatte** bağırmayı bıraktı. */
  color: var(--text-secondary);
  white-space: nowrap;
  transition: color var(--dur-1) var(--ease-out);
}
.card-link:hover { color: var(--brand); }
/* Dokunmatikte 32 px alt sınırın altında kalıyordu (pano kartlarındaki
   "Tümü"). Kural buraya yazılmalı: dosyanın başındaki `pointer: coarse`
   bloğuna konunca aynı özgüllükteki tanım onu 600 satır sonra eziyordu. */
@media (pointer: coarse) {
  .card-link { min-height: var(--tap); }
}

/* Sayfa başlığı. Eskiden 2xl başlık + altında paragraf + altında 20px boşluk
   ekranın üst dörtte birini yalnız "buradasınız" demeye harcıyordu. Artık
   başlık bir ölçü küçük, açıklama başlığın *yanında* (masaüstünde) ve
   aksiyonlar aynı satırda. */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-4);
  flex-wrap: wrap;
  min-height: 40px;
  /* Başlık ile altındaki ilk şerit (sekme ya da araç çubuğu) arası --sp-3.
     --sp-4 iken sayfanın üstünde üç ayrı 16 piksellik boşluk üst üste
     biniyordu (başlık altı, sekme altı, araç çubuğu altı): listenin ilk
     satırı ekranın üçte birinden sonra başlıyordu. */
  margin-bottom: var(--sp-3);
}
.page-header-text { min-width: 0; }
.page-title {
  font-size: var(--fs-xl);
  letter-spacing: -0.02em;
}
/* Alt başlık her zaman düz cümle değil: ayrıntı ekranlarında durum, müşteri
   ve gecikme rozetlerinden oluşan bir şerit taşıyor. Esnek kutu olmasının
   sebebi bu — rozetler arasında `&nbsp;` kadar bile olmayan boşluk kalıyor
   ve dar ekranda sarmak yerine tek satırda eziliyorlardı. Tek parça
   metinde davranış değişmez: metnin tamamı tek bir öğe olur. */
.page-subtitle {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px 6px;
  margin-top: 2px;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
}
.page-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
  flex-wrap: wrap;
}
/* Başlık satırındaki düğmeler sayfanın ana eylemi değilse büyümesin —
   ama yalnız fareyle kullanılan ekranlarda. Bu kural önce koşulsuz
   yazılmıştı ve telefonda "Yeni firma", "Düzenle", "Sil" gibi *asıl*
   eylemleri 44 px'lik dokunma hedefinin altına düşürüyordu. */
@media (pointer: fine) {
  .page-actions .btn { min-height: 38px; padding: 0 var(--sp-4); }
}

/* ==========================================================================
   Rozetler
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--brand-soft);
  color: var(--brand);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
}
.badge-neutral { background: var(--surface-sunken); color: var(--text-secondary); }
.badge-warn { background: var(--warn-bg); color: var(--warn); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-info { background: var(--brand-soft); color: var(--brand); }
/* Mercan: hata değil ama sahiplenilmesi gereken durum (gecikme, takipsiz). */
.badge-accent { background: var(--accent-bg); color: var(--accent); }
/* Mavi-gri: sessiz meta — tür, kaynak, etiket. Dikkat çekmez, ayırır. */
.badge-quiet {
  background: var(--neutral-accent-bg);
  color: var(--neutral-accent);
}
/* Bir rozetin *önünde* duran nokta, rengi okumadan durum ayırmayı sağlar
   (renk körlüğü için de tek başına renge güvenmemiş oluruz). */
.badge .dot-mark {
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: 50%;
  background: currentcolor;
}

/* ==========================================================================
   Bildirim kutuları / flash
   ========================================================================== */

.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--info-border);
  border-radius: var(--r-md);
  background: var(--info-bg);
  color: var(--text);
  font-size: var(--fs-base);
}
.notice .icon { color: var(--brand); margin-top: 2px; }
.notice-warn {
  background: var(--warn-bg);
  border-color: var(--warn-border);
}
.notice-warn .icon { color: var(--warn); }
.notice-error {
  background: var(--danger-bg);
  border-color: var(--danger-border);
}
.notice-error .icon { color: var(--danger); }
.notice-success {
  background: var(--success-bg);
  border-color: var(--success-border);
}
.notice-success .icon { color: var(--success); }

/* Sayfa başındaki kapatılabilir açıklama kutusu (`dismissible_note`):
   ardından gelen süzgeç çubuğuyla arasına sayfa ritmini koyar. Boşluk
   `.notice`'ın kendisine değil bu varyanta yazılıyor: genel kutu form ve
   panel içinde de kullanılıyor, oralarda aralığı kapsayıcının `gap`i
   veriyor ve margin ikinci bir boşluk olurdu. Marginsizken kutunun alt
   kenarı doğrudan çubuğun üst kenarına dayanıyor, iki çerçeve tek kalın
   çizgi gibi okunuyordu. */
.notice-dismiss { margin-bottom: var(--sp-3); }

/* --- Toast (flash) ---
   Kısa ömürlü, engellemeyen bildirim. Sayfanın üstünden *içeri kayarak*
   gelir; birden belirmek kullanıcıya "bu ne zaman açıldı?" dedirtiyordu. */
.flash-area {
  position: fixed;
  top: var(--sp-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  width: min(520px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  pointer-events: none;
}
.flash {
  box-shadow: var(--shadow-lg);
  background: var(--surface);
  pointer-events: auto;
  animation: toast-in var(--dur-2) var(--ease-out) both;
}
/* Kapanış: yerinde solup küçülür. Kaldırmadan önce sınıf eklenir. */
.flash.is-leaving {
  animation: toast-out var(--dur-2) var(--ease-in) both;
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.985); }
  to { opacity: 1; transform: none; }
}
@keyframes toast-out {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(-6px) scale(0.985); }
}
.flash-close {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px;
  line-height: 0;
  border-radius: var(--r-xs);
  transition: color var(--dur-1) var(--ease-out);
}
.flash-close:hover { color: var(--text); }

/* ==========================================================================
   Boş durum
   ========================================================================== */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sp-3);
  padding: var(--sp-8) var(--sp-5);
}
/* Kart içindeki boş durumlar daha derli toplu durur. */
.card > .empty-state,
.card .list > .empty-state {
  padding: var(--sp-7) var(--sp-5);
}
.empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-lg);
  background: var(--brand-soft);
  color: var(--brand);
}
.empty-state h3 { font-size: var(--fs-lg); }
.empty-state p {
  max-width: 42ch;
  color: var(--text-secondary);
}

/* ==========================================================================
   Avatar
   ========================================================================== */

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--avatar-bg);
  color: var(--avatar-fg);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.avatar-sm { width: 28px; height: 28px; font-size: var(--fs-xs); }
.avatar-lg { width: 44px; height: 44px; font-size: var(--fs-base); }
/* Yumuşak avatar **nötr**dür, mor değil.

   Mor bu arayüzde dört işi yapar ve yalnız onları: etkin menü satırı,
   bağlantı, grafik serisi, birincil eylem. `.avatar-soft` bunların hiçbiri
   değil — çalışma alanının baş harfleri, bir işin kısaltması, menüdeki
   ikon kutusu. Dördü de "buraya bas" demiyor, "bu şu" diyor.

   Bedeli ölçülebilirdi: bir liste ekranında aynı anda 12 mor daire, bir
   mor etkin menü satırı ve bir mor birincil düğme duruyordu. Sayıca
   dairelerin kazandığı bir ekranda mor artık eylem rengi değil, zemin
   dokusudur; düğme de o dokunun içinde kayboluyordu. Nötre inince ekranda
   kalan üç-dört mor yeniden bir şey söylüyor.

   Anlam taşıyan varyant (gecikme) yerinde: o zaten renkle *bilgi*
   veriyor. */
.avatar-soft { background: var(--surface-sunken); color: var(--text-secondary); }
/* Gecikmiş takvim etkinliği (Faz 7.2): günlük ajandada tek bakışta ayırt
   edilsin. Ton mercan: gecikme bir hata değil, ilgi bekleyen bir durumdur. */
.avatar-soft.is-danger { background: var(--accent-bg); color: var(--accent); }

/* ==========================================================================
   Yükleniyor
   ========================================================================== */

.spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--brand-border);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton {
  background: linear-gradient(
    90deg,
    var(--surface-sunken) 25%,
    var(--skeleton-shine) 50%,
    var(--surface-sunken) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  border-radius: var(--r-sm);
  height: 14px;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Tema değişirken **hiçbir şey** geçiş yapmaz (bkz. `app.js`, `gecissiz`).
   Jetonlar tek karede değişiyor ama bileşenlerin geçiş süreleri farklı:
   kartın sınırı 120 ms, satır zemini 170 ms, düğme dolgusu 0 ms. Aradaki
   yarım saniyede ekran iki temanın karışımı oluyor — metin çoktan koyu
   temanın beyazına dönmüşken kart hâlâ beyaz kalıyor ve o kare okunmuyor.
   Nitelik yalnız iki kare duruyor; sonrasında hover ve açılma geçişleri
   olduğu gibi devam eder. */
[data-tema-gecis] *,
[data-tema-gecis] *::before,
[data-tema-gecis] *::after {
  transition: none !important;
}

/* ==========================================================================
   Katman: üstte yüzen yüzeyler (menü, kip, çekmece)
   --------------------------------------------------------------------------
   Hepsi aynı iskeleti paylaşır: bir perde (`.overlay`) ve üstünde bir yüzey.
   Perde `hidden` özniteliğiyle kapanır — sınıfla değil; `[hidden]` kuralı
   dosyanın başında `!important` olduğu için hiçbir düzen sınıfı onu geri
   açamaz.
   ========================================================================== */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: var(--overlay);
  animation: fade-in var(--dur-2) var(--ease-out) both;
}
.overlay[hidden] { display: none !important; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* --- Kip (modal) ---
   Ortada durur, kısa karar içindir: onay, küçük form. Uzun içerik varsa
   çekmece ya da tam sayfa kullanılır. */

.modal-overlay {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  overflow-y: auto;
}
.modal {
  width: min(520px, 100%);
  max-height: calc(100dvh - 2 * var(--sp-6));
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  animation: modal-in var(--dur-2) var(--ease-out) both;
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
/* Baş şeridi **esnemez**, gövde esner (ayak şeridi kalktı; düğmeler
   gövdenin içinde). Yazılmadığında üçü de esnek
   (`flex: 0 1 auto`) kalıyor ve kip tavanına dayandığında tarayıcı üçünü
   birlikte sıkıştırıyordu: iki satıra kırılan uzun bir başlıkta ayak da
   küçülüyor, "Sil" düğmesi kendi kutusunun dışına taşıyor ve gövdenin
   kaydırması perdenin kaydırmasıyla üst üste biniyordu. `min-height: 0`
   gövdenin gerçekten kısalabilmesi için gerekli — flex öğelerinin taban
   asgarisi `auto`dur ve o, içeriğin tamamı kadardır. */
.modal-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  flex: none;
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
}
.modal-title { font-size: var(--fs-lg); }
.modal-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 0 var(--sp-5) var(--sp-5);
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* Onay düğmeleri kipin **gövdesinin içinde**, ayrı bir ayak şeridi
   değil. Yapışkan ayak telefonda cihazın gezinme çubuğuyla örtüşüyor,
   düğme görünür olsa bile basılamıyordu. Üstten ayrıcı çizgi de yok:
   gövde dolgusunun içinde kenardan kenara gitmeyen çizgi kesik duruyor,
   ayrımı boşluk veriyor. */
.modal-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
}
.modal-actions .grow { flex: 1 1 auto; }
/* Uzun etiketli ikili karar ("Düzenlemeye devam et" / "Değişiklikleri sil",
   Faz 48): telefonda yan yana sığmayıp ikişer satıra kırılıyordu. Dar
   ekranda alt alta, tam genişlik; birincil karar (son düğme) en üstte. */
@media (max-width: 479px) {
  .modal-actions.is-stack-sm { flex-direction: column-reverse; align-items: stretch; }
  .modal-actions.is-stack-sm .btn { width: 100%; }
}
/* Yıkıcı kipin başlığındaki ikon: metni okumadan önce tonu verir. */
.modal-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--r-md);
  background: var(--brand-soft);
  color: var(--brand);
}
.modal-icon.is-danger { background: var(--danger-bg); color: var(--danger); }
.modal-icon.is-warn { background: var(--warn-bg); color: var(--warn); }

/* Kipin gövdesindeki sonuç cümlesi (Faz 17).

   "Bu kayıt çöp kutusuna taşınır" ile "Dosya sunucudan da silinir; geri
   alınamaz" aynı soluk gri paragraftı: geri alınabilen ile alınamayan iş
   ekranda aynı görünüyordu. Cümle artık kendi yüzeyinde ve sol kenarında
   tonun çizgisi var.

   **Dolu kırmızı değil.** §1'in kuralı burada da geçerli: kip zaten bir
   kesinti, üstüne alarm zemini koymak kullanıcıyı okumadan onaylamaya
   iter. Zemin en açık ton, çizgi kenarda, metin ikincil renkte — belirgin
   ama sakin. */
.confirm-note {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface-soft);
  color: var(--text-secondary);
}
.confirm-note p { margin: 0; }
.confirm-note.is-danger {
  border-color: var(--danger-border);
  border-left-color: var(--danger);
  background: var(--danger-bg);
}
.confirm-note.is-warn {
  border-color: var(--warn-bg);
  border-left-color: var(--warn);
  background: var(--warn-bg);
}

/* --- Form yüzeyi (`.drawer`) ---
   Faz 18: **ekranın ortasında** açılır, klasik bir form kipi gibi. Önce
   sağdan giren bir çekmeceydi; form doldurmak listeye göz ucuyla bakılan
   bir iş değil, tam dikkat isteyen bir iştir ve yandan gelen panel hem
   okuma eksenini sayfanın kenarına kaydırıyor hem de altındaki listeyle
   "hangisi aktif" yarışına giriyordu. Ortada duran yüzeyde bakış zaten
   ekranın merkezinde; perde geri kalan her şeyi eşit uzaklıkta bırakıyor.

   Sınıf adı `drawer` kaldı: gövde şablonu, JS hedefi (`data-drawer-body`,
   `data-async-target`) ve testler bu adı kullanıyor, yerleşim değişikliği
   için hepsini yeniden adlandırmak değişikliği gereksiz yere büyütürdü.

   Telefonda kural değişmez: alttan açılan tam ekran sheet (§6). Ortalanmış
   bir kip, klavye açıldığında dar ekranda yukarı sıkışırdı. */

/* Perde ~%35 karartır ve **çok hafif** bulanıklaştırır. Ortak `--overlay`
   (%44 / koyuda %72) bir yan panelin arkasında doğruydu; ortada duran bir
   kipte aynı karartma sayfayı tümüyle siliyor ve kullanıcı "hangi kaydın
   üstündeydim" bağlamını kaybediyordu. Bulanıklık 2 px: arkadaki metni
   okunmaz yapmaya değil, kipi öne çekmeye yetecek kadar — daha fazlası
   kaydırma sırasında zayıf makinelerde kare düşürüyor. */
.drawer-overlay,
.modal-overlay { background: transparent; }

/* Karartma ve bulanıklık perdenin **kendisinde değil**, sözde elemanında.

   Ölçüldü: `backdrop-filter` konan bir kutu, `transform` gibi, içindeki
   `position: fixed` çocuklar için kapsayıcı blok kurar — kipteki seçici
   menüleri `fixed` konumlanıyor ve `offsetParent` null'dan perdeye
   dönüyor. Burada kayma çıkmıyor (perde tam viewport boyunda, ofset 0)
   ama menü konumlandırması Tur 1'de zaten bu tuzaktan çıkarılmıştı;
   aynı sınıfı ikinci kez kurmanın bedeli, bir gün perdeye dolgu ya da
   `inset` verildiğinde sessizce kayan bir menü olurdu.

   Sözde eleman kipin atası değil, kardeşidir: `offsetParent` null kalır,
   görüntü birebir aynıdır. `z-index: -1` burada doğru çalışıyor çünkü
   istenen şey tam olarak "perdenin zemininin üstünde, kipin altında" —
   `.record-panel`daki hata, oradaki isteğin bu **olmamasıydı**. */
.drawer-overlay::before,
.modal-overlay::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: rgba(13, 21, 38, 0.35);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
[data-theme="dark"] .drawer-overlay::before,
[data-theme="dark"] .modal-overlay::before {
  /* Koyu temada aynı %35 yetmez: altındaki yüzey zaten koyu, kontrast
     karartmayla değil yalnız gölge ve kenarla kurulurdu. */
  background: rgba(2, 5, 12, 0.55);
}

.drawer-overlay {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-7);
  overflow-y: auto;
}
.drawer {
  /* Kaydetme sırasındaki ilerleme çizgisi (`.is-saving::before`) buna
     göre konumlanır; geçici bir sınıfın yerleşimi değiştirmemesi için
     konumlandırma kalıcı olarak burada. */
  position: relative;
  /* Kipin yatay iç boşluğu tek yerden: baş, gövde ve ayak aynı kenara
     hizalanmazsa başlık ile ilk alan farklı eksende başlar ve yüzey
     "üç ayrı şerit" gibi okunur. */
  --kip-pad: 28px;
  width: min(460px, 100%);
  /* Tavan ekranın %88'i: kip her zaman perdeden bir miktar boşlukla
     ayrılır, yani "yüzen yüzey" hissi en uzun formda bile kaybolmaz.
     Sabit piksel (önce 760) uzun formu 1080'lik ekranda gereksiz yere
     kısaltıyor, kısa formu da değiştirmiyordu; oran ikisini de doğru
     ölçekler. */
  /* Tavan perdenin **dolgusunu da** hesaba katar. Düz `88dvh` yazılıyken
     perde (`.drawer-overlay`) kendi 2 × --sp-7 dolgusunu ekliyor ve toplam
     100dvh'yi 533 pikselin altındaki her pencerede aşıyordu: perde de
     kaymaya başlıyor, iki kaydırıcı üst üste biniyor ve "Kaydet" ayağı ilk
     bakışta ekranın dışında kalıyordu (yatay tablet, kısa masaüstü
     penceresi). `min()` iki sınırın da altında kalır. */
  max-height: min(88dvh, calc(100dvh - 2 * var(--sp-7)));
  display: flex;
  flex-direction: column;
  background: var(--surface);
  /* 16 px: kart (--r-lg, 14) ile aynı aileden ama bir kademe yumuşak.
     --r-xl (18) bu boyda bir yüzeyde köşeyi fazla yuvarlıyor. */
  border-radius: 16px;
  box-shadow: var(--shadow-lg);
  animation: modal-in var(--dur-2) var(--ease-out) both;
}

/* Baş ve ayak **beyaz**, gövde bir ton çukur (`--surface-soft`).
   Faz 18: ayırıcı 1 px çizgilerin ikisi de kalktı. Ortalanmış bir kipte üç
   yatay çizgi (perde kenarı + baş çizgisi + ayak çizgisi) yüzeyi üç ayrı
   şeride bölüyor, kip bir "pencere" gibi değil tablo gibi okunuyordu. Ton
   farkı aynı sınırı çizgisiz anlatır ve kaydırma sırasında da doğru
   davranır: içerik başın/ayağın altına girerken renk değişimi sınırı zaten
   gösterir. Alanlar gövdede beyaz kaldığı için giriş kutuları da bu ton
   sayesinde kendiliğinden ayrışır (referans kipin yaptığı da bu). */
.drawer-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  /* Baş da sıkışmaz (ayak gibi): başlık iki satıra kırıldığında tarayıcı
     onu ezip gövdeye yer açmaya çalışıyordu. */
  flex: none;
  padding: var(--sp-6) var(--kip-pad) var(--sp-4);
  background: var(--surface);
}
.drawer-title { font-size: var(--fs-lg); font-weight: 700; letter-spacing: -0.01em; }
/* Kapatma düğmesi daire: kipin tek "kaçış" düğmesi, köşeli bir kutu olarak
   baştaki başlıkla aynı ağırlıkta okunuyordu. */
.drawer-head .icon-btn {
  border-radius: 999px;
  background: var(--surface-soft);
  color: var(--text-secondary);
}
.drawer-head .icon-btn:hover { background: var(--surface-sunken); color: var(--text-primary); }
.drawer-body {
  flex: 1 1 auto;
  /* Flex öğesinin taban asgarisi `auto`dur ve o, içeriğin tamamı kadar:
     yazılmadığında gövde kısalmıyor, kip tavanını aşıyor ve kaydırma
     gövdeden **perdeye** geçiyordu (iki kaydırıcı, ekran dışına düşen
     ayak). */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--sp-5) var(--kip-pad) var(--sp-6);
  background: var(--surface-soft);
}
/* Çekmecenin işlem satırı: gövdenin son öğesi, ayrı şerit değil. Alanlarla
   arasına görünür bir ayrıcı giriyor, çünkü artık zemin değişimi yok. */
.drawer-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.drawer-actions .grow { flex: 1 1 auto; }

@media (max-width: 899px) {
  /* Telefonda perde kenardan kenara: sheet'in kendi kenar boşluğu yok. */
  .drawer-overlay { align-items: flex-end; padding: 0; }
  .drawer {
    width: 100%;
    height: auto;
    max-height: 88dvh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    animation-name: sheet-in;
  }
  /* Tam ekranda 28 px yatay boşluk alanları 375'lik ekranda gereksiz
     daraltıyor; kip kenarı zaten ekran kenarı. */
  .drawer { --kip-pad: var(--sp-5); }
  /* Düğmeler gövdenin içinde olduğu için güvenli alan payını gövde alır;
     yoksa son düğme cihazın kendi gezinme çubuğunun altında kalıyor. */
  .drawer-body { padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom)); }
}
@keyframes sheet-in {
  from { transform: translateY(24px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

/* --- Kip genişliği (Faz 19: 820 / 920 px) ---

   820 px standart, yoğun formlarda 920 px. Önce 560 px'ti; o ölçü kip
   **sağdan açılan bir çekmeceyken** doğruydu (arkada kalan şerit katman
   hissini veriyordu). Faz 18'de yüzey ekranın ortasına taşınınca şeridin
   bir işlevi kalmadı: ortada duran 560 px'lik bir kutu, 1440'lık ekranda
   iki yanında 440'ar piksel boşlukla "dar bir fiş" gibi duruyor ve form
   tek kolona sıkıştığı için gereksiz uzuyordu.

   820 px, iki kolonu ezmeden taşıyan en küçük genişlik: --kip-pad iki
   yandan 56, kolon arası 24 düşünce kolonlara 740 kalır ve 1.15/0.85
   oranında ~398 / ~342 piksel olurlar — tarih ve seçici alanlarının
   kırpılmadan sığdığı eşik burası.

   `92vw` üst sınırı dar pencere içindir: 900-980 px arası bir tarayıcıda
   820 sabit kalsaydı kip perdenin kenarına yapışırdı. */
/* Üç genişlik de **yalnız masaüstünde**. Telefonda kip tam ekrandır ve
   genişlik diye bir soru yoktur.

   Medya sorgusuna alınmaları şart, çünkü `:has()` kuralları `.drawer-wide`
   kuralından daha özgül (0,2,0 > 0,1,0) ve medya sorgusu özgüllük
   eklemiyor. Kurallar serbest dursaydı alttaki "telefonda tam ekran"
   bloğunu ezerlerdi — ölçüldü: 390 px'lik ekranda kip 359 px (92vw)
   çiziliyor, yani kenarında 31 piksel perde kalan "küçültülmüş masaüstü
   kipi" oluyordu. İstenen bunun tam tersi. */
@media (min-width: 900px) {
  .drawer-wide { width: min(820px, 92vw); }

/* Yoğun formlar (çok alanlı iş/firma kaydı) 920 px'e çıkar. Genişliği
   **gövde** belirler, kabuk değil: kabuk `layouts/app.html`da bir kez
   duruyor ve içine hangi formun geleceğini açılırken bilmiyor. `:has()`
   ile karar sunucudan gelen gövdeye bırakılır — JS'in kabuğa sınıf
   eklemesi de olurdu ama o yol formu iki yerde tanımlamak demekti. */
  .drawer:has(.drawer-form.is-dense) { width: min(920px, 92vw); }

/* Tek kararlık işlemler (taşı, kopyala, geri alınamaz onay) 560 px'te
   durur. 820 px bir kayıt formu içindir: orada genişlik iki kolona yer
   açıyor. Tek seçim ve bir onay cümlesi taşıyan bir kipte aynı genişlik
   metni ekranın bir ucundan diğerine yayıyor ve "küçük bir karar" olan
   şeyi bir sayfa gibi gösteriyor — kipin boyu, istediği dikkatin ölçüsü
   olmalı. */
  .drawer:has(.drawer-form.is-compact) { width: min(560px, 92vw); }
}

/* Bölümler arası 28 px, bölüm içi alanlar arası 16 px (`.form-col` gap'i
   zaten --sp-4). İki ölçü birbirine yaklaşırsa "Temel bilgiler" ile
   "İletişim" tek bir uzun liste gibi okunur; aradaki fark grubu anlatan
   tek işarettir. */
.drawer-wide .form-grid { gap: 28px; }

@media (max-width: 899px) {
  /* Telefonda form **tam ekran**dır, alttan yarım açılan bir sheet değil.
     Uzun bir formu 88dvh'lik bir sheet içinde doldurmak, klavye açıldığında
     görünür alanı üçte bire indiriyordu. */
  .drawer-wide {
    width: 100%;
    height: 100%;
    max-height: none;
    border-radius: 0;
    animation-name: sheet-in;
  }
}


/* --- İki kolonlu form düzeni (Faz 10) ---

   Masaüstünde temel bilgiler solda, süreç ve sorumluluk alanları sağda.
   Ayrım görsel değil kavramsal: soldaki kolon "bu kayıt nedir", sağdaki
   "bu kayıt kimde ve nerede". İkisini tek sütuna dizmek, formu doldurmayı
   bir aşağı kaydırma turuna çeviriyordu.

   Oran 1.15 / 0.85: sol kolonda uzun metin alanları (ad, açıklama, adres)
   var, sağda kısa seçiciler ve tarihler. Eşit bölmek sağ kolonda geniş
   boş alan bırakıyordu.

   Tek kolon **öntanımlıdır**; iki kolon yalnız 900 px üstünde ve yalnız
   `.is-two` ile açılır. Böylece dar bir çekmecede ya da telefonda düzen
   kendiliğinden doğru olana düşer. */
.form-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}
.form-grid > .form-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-width: 0;
}

@media (min-width: 900px) {
  .form-grid.is-two {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
    gap: var(--sp-6);
  }
  /* Kolonlar arasında ince bir ayırıcı: iki kolonun ayrı konular olduğunu
     kart çerçevesi çizmeden söyler (tasarım sistemi §3). */
  .form-grid.is-two > .form-col + .form-col {
    padding-left: var(--sp-6);
    border-left: 1px solid var(--border);
  }
}

/* Alan çiftleri (başlangıç/teslim, sorumlu/önem) kendi içinde ikişerli
   sarar. `minmax(0, …)` olmadan uzun bir seçenek metni kolonu şişirip
   ızgarayı taşırıyordu. */
.field-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: var(--sp-3);
}

/* Cümle gibi okunan alan satırı: "[2] gün [sonra] · [İş başlangıcından]"
   (şablon adımı formu, `fields/_task_template_item.html`).

   `.field-pair`den ayrı bir kural, çünkü orada iki eşit alan var; burada
   parçalar eşit değil — sayı kutusu dar, açılır kutular geniş ve aralarında
   etiket değil **sözcük** duruyor. Ortak kılavuz `baseline` değil `center`:
   kutular ve aradaki "gün" sözcüğü aynı yükseklikte olmalı, yoksa satır
   cümle gibi değil üç ayrı kutu gibi okunuyor.

   Dar ekranda sarar; sardığında da anlam bozulmaz çünkü sıra korunuyor. */
.field-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.field-cell { flex: 1 1 140px; min-width: 0; }
.field-cell.is-narrow { flex: 0 0 96px; }
.field-cell.is-wide { flex: 2 1 200px; }
.field-cell > .input,
.field-cell > .select { width: 100%; }
.field-word { color: var(--text-muted); white-space: nowrap; }

/* Koşullu alan sarmalayıcısı (`[data-field-when]`, app.js).

   Gizleme `hidden` özniteliğiyle yapılır ve tarayıcının kendi kuralı zaten
   `display: none` verir; bu satır o kuralı açıkça yineler çünkü sarmalayıcıya
   ileride bir `display` verilirse `hidden` sessizce etkisiz kalırdı — alan da
   gizlenmesi gereken yerde görünür kalırdı.

   Betik yokken sarmalayıcı `hidden` almaz, dolayısıyla alan görünür kalır:
   gizleme bir kolaylıktır, zorunluluk kuralı sunucudadır. */
[data-field-when][hidden] { display: none; }

/* ==========================================================================
   İpucu (tooltip)
   --------------------------------------------------------------------------
   Saf CSS; `title` yerine kullanılır çünkü `title` ~1 sn gecikir, dokunmatik
   ekranda hiç görünmez ve biçimlendirilemez. Kural: ipucu **açıklama**dır,
   bilgi taşımaz — kapalıyken anlaşılmayan bir şey ipucuna konmaz.
   ========================================================================== */

.tip { position: relative; }
.tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  z-index: 80;
  padding: 5px 9px;
  border-radius: var(--r-xs);
  /* Ipucu iki temada da zeminin tersi olmali. `--text-primary` aydinlikta
     koyu, koyuda acik; `--surface` tam tersi. Paletten sabitlenince koyu
     temada beyaz-ustunde-beyaz cikiyordu. */
  background: var(--text-primary);
  color: var(--surface);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 3px);
  transition: opacity var(--dur-1) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
.tip:hover::after,
.tip:focus-visible::after { opacity: 1; transform: translate(-50%, 0); }
.tip-right::after {
  bottom: auto;
  top: 50%;
  left: calc(100% + 8px);
  transform: translate(-3px, -50%);
}
.tip-right:hover::after,
.tip-right:focus-visible::after { transform: translate(0, -50%); }
/* Üst çubuktaki öğelerde ipucu yukarı açılamaz: çubuk zaten ekranın
   tepesinde, ipucu görüntü alanının dışında kalıyor ve hiç görünmüyordu. */
.tip-bottom::after {
  bottom: auto;
  top: calc(100% + 8px);
  transform: translate(-50%, -3px);
}
.tip-bottom:hover::after,
.tip-bottom:focus-visible::after { transform: translate(-50%, 0); }
/* Dokunmatikte ipucu asılı kalıyor ve altındakini tıklanamaz gösteriyordu. */
@media (pointer: coarse) {
  .tip::after { display: none; }
}

/* ==========================================================================
   Klavye tuşu
   ========================================================================== */

.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  background: var(--surface);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
}

/* ==========================================================================
   Açılır seçim (native select yerine)
   --------------------------------------------------------------------------
   Kritik nokta: gerçek `select` DOM'dan **silinmez**. Görünmez kılınır,
   üstüne erişilebilir bir listbox çizilir. Böylece form gönderimi,
   doğrulama, `required`, otomatik doldurma ve betiğin çalışmadığı durum —
   hepsi olduğu gibi kalır. JS yüklenmezse kullanıcı normal seçiciyi görür.
   ========================================================================== */

.select-shell { position: relative; display: block; min-width: 0; }
/* Ham seçiciyi gizlerken `display:none` kullanılmaz: gizli alan odak
   alamaz, tarayıcı "bu alanı doldurun" uyarısını gösteremez. */
.select-shell > select.is-enhanced {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.select-btn {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: var(--tap);
  padding: 8px var(--sp-3) 8px var(--sp-4);
  border: 1px solid var(--border-input);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-base);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}
.select-btn:hover { border-color: var(--border-strong); }
.select-btn[aria-expanded="true"] {
  border-color: var(--brand);
  box-shadow: var(--focus-ring);
}
.select-btn .select-value { flex: 1 1 auto; min-width: 0; }
.select-btn .select-value.is-placeholder { color: var(--text-muted); }
.select-btn .chevron {
  flex: none;
  color: var(--text-muted);
  transition: transform var(--dur-2) var(--ease-out);
}
.select-btn[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.select-btn:disabled {
  background: var(--surface-soft);
  color: var(--text-secondary);
  cursor: not-allowed;
}
.select-shell.is-invalid .select-btn { border-color: var(--danger); }

/* Menü `fixed`, `absolute` değil — konumu betik hesaplar.
   Gerekçe: tablo satırlarındaki seçiciler `.table-wrap` içinde duruyor ve o
   kapta `overflow-x: auto` var. CSS'te bir eksen `visible` olmaktan çıkınca
   diğeri de `auto` olur, yani kap iki eksende de kırpar: mutlak konumlanan
   menü tablonun alt kenarında kesiliyor, kabın içinde ikinci bir kaydırma
   çubuğu açıyordu. Toplu güncelleme çubuğunda (`max-height` + `overflow-y`)
   aynı şey oluyordu. Ham `<select>` açılır penceresi işletim sistemi
   tarafından çizildiği için hiç kırpılmıyordu; bu kayıp, zenginleştirmenin
   getirdiği bir gerilemeydi. */
.select-menu {
  position: fixed;
  z-index: 75; /* kip ve çekmecenin (70) üstünde: kip içindeki seçici de açılmalı */
  /* Genişliği **içerik** belirler, tetikleyici değil. Alt sınırı (düğme
     genişliği) app.js yazar; burada yalnız tavan durur. Liste tablosunda
     düğme hücreye sığmak için daralıyor ("Yeni" ≈ 70px) ve menü ona
     zorlanınca her seçenek "Y…", "G…" diye tek harfe iniyordu — sorumlu
     adları da aynı şekilde kesiliyordu. `.quick-pop-opts` ve
     `.row-menu-panel` bu kalıbı zaten kullanıyor; seçici menüsü istisna
     kalmıştı. Tavan telefonda ekranı taşırmasın diye `92vw` ile paylaşılır. */
  width: max-content;
  max-width: min(320px, 92vw);
  max-height: 280px;
  overflow-y: auto;
  /* Kaydırma çubuğu `max-content` genişliğine dahil edilmez; yer ayrılmazsa
     liste uzunken son harf çubuğun altında kalır. */
  scrollbar-gutter: stable;
  overscroll-behavior: contain;
  padding: var(--sp-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  animation: pop-in var(--dur-2) var(--ease-out) both;
}
.select-menu[hidden] { display: none !important; }
@keyframes pop-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

.select-opt {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: 38px;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--text);
  font-size: var(--fs-base);
  cursor: pointer;
  scroll-margin: var(--sp-1);
}
.select-opt .label { flex: 1 1 auto; min-width: 0; }
.select-opt .check { flex: none; color: var(--brand); opacity: 0; }
.select-opt[aria-selected="true"] { font-weight: 600; }
.select-opt[aria-selected="true"] .check { opacity: 1; }
/* Vurgu fareyle değil klavyeyle yönetilir: `:hover` ile karışırsa ok
   tuşuyla gezerken imlecin durduğu yer seçimi çalıyor. */
.select-opt.is-cursor { background: var(--selected); }
.select-opt.is-disabled { color: var(--text-muted); cursor: not-allowed; }
.select-group-label {
  padding: var(--sp-2) var(--sp-3) var(--sp-1);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Küçük varyant: araç çubuklarındaki sıralama/süzgeç seçicileri.
   Ham `.select-sm` yalnız dolguyu daraltıyor, yüksekliği `.select`ten
   (`min-height: var(--tap)`) miras alıyordu. Kabuğa geçerken bu unutuldu
   ve liste satırlarındaki hızlı güncelleme seçicileri telefonda 36 px'e
   düştü. Dokunmatikte tam hedef, farede dar. */
.select-shell.is-sm .select-btn {
  min-height: 36px;
  padding: 4px var(--sp-2) 4px var(--sp-3);
  font-size: var(--fs-sm);
}
@media (pointer: coarse) {
  .select-shell.is-sm .select-btn { min-height: var(--tap); }
}

/* ==========================================================================
   Anahtar (switch) — iki durumlu ayarlar için
   ========================================================================== */

.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--tap);
  cursor: pointer;
}
.switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.switch .track {
  position: relative;
  width: 38px;
  height: 22px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--border-strong);
  transition: background-color var(--dur-2) var(--ease-out);
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-2) var(--ease-out);
}
.switch input:checked + .track { background: var(--brand); }
.switch input:checked + .track::after { transform: translateX(16px); }
.switch input:focus-visible + .track { box-shadow: var(--focus-ring); }
