/* ==========================================================================
   Rota — Bölüm bileşenleri (istatistik kartları, listeler, sekmeler, tablo)
   Sonraki fazlarda da bu bileşenler kullanılır.
   ========================================================================== */

/* --- İstatistik kartları --------------------------------------------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4);
}

/* Sayı kutusu da bir karttır: aynı 14 px köşe, aynı 1 px sınır, aynı
   `--shadow-card`. Tıklanabilir olanda hover'da değişen tek şey **sınır ve
   gölge**; kutu yerinden oynamaz. Önceki `translateY(-1px)` ızgarada
   imlecin gezdiği yeri yukarı kaydırıyor, dört kutunun taban hizası
   sürekli bozuluyordu. */
.stat-card {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  color: inherit;
  transition: border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}
a.stat-card:hover {
  text-decoration: none;
  border-color: var(--border-strong);
  box-shadow: var(--shadow-card-hover);
}

/* İkon kutusu nötr: sayacın ne saydığını *söyleyen* bir işaret, tıklanacak
   bir eylem değil (bkz. `base.css`, `.avatar-soft` — aynı gerekçe). */
.stat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--r-md);
  background: var(--surface-sunken);
  color: var(--text-secondary);
}
.stat-icon .icon { width: 18px; height: 18px; }
.stat-icon.is-warn { background: var(--warn-bg); color: var(--warn); }
/* "Gecikmiş" gerçek bir hata değil, sahiplenilmesi gereken bir durum:
   kırmızı yerine mercan. Kırmızı, sistemin bozulduğu yere saklı. */
.stat-icon.is-danger { background: var(--accent-bg); color: var(--accent); }
.stat-icon.is-quiet { background: var(--neutral-accent-bg); color: var(--neutral-accent); }

.stat-label {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: 1.3;
}
.stat-value {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-black);
  letter-spacing: -0.025em;
  line-height: 1.15;
}

/* --- Kart ızgarası ---------------------------------------------------- */

.card-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-4);
  /* Kısa kart, uzun komşusunun boyuna uzayıp içinde boşluk bırakmasın. */
  align-items: start;
}

/* --- Liste satırları -------------------------------------------------- */

.list { display: flex; flex-direction: column; }

.list-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 56px;
  padding: var(--sp-3) var(--sp-5);
  border-bottom: 1px solid var(--border-soft);
  color: inherit;
}
.list-row:last-child { border-bottom: 0; }
/* Satır iki şey olabilir: gidilen bir yer (`<a>`) ya da yapılan bir iş
   (`<button>` — "Diğer" sayfasındaki tema anahtarı). İkisi aynı görünür,
   çünkü listedeki ağırlıkları aynı; düğmenin tarayıcı varsayılanları
   (zemin, çerçeve, ortalanmış metin, daralan genişlik) sıfırlanır. */
a.list-row,
button.list-row { transition: background-color var(--dur-1) var(--ease-out); }
a.list-row:hover,
button.list-row:hover { background: var(--surface-soft); text-decoration: none; }
button.list-row {
  width: 100%;
  border: 0;
  border-bottom: 1px solid var(--border-soft);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
button.list-row:last-child { border-bottom: 0; }

.list-row-main { min-width: 0; flex: 1 1 auto; }
.list-row-title { font-weight: 600; }
.list-row-meta {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.list-row-meta .dot-sep { color: var(--text-muted); }

/* --- Kayıt meta satırı (`_row.html` › `meta_line`, Faz 45) -------------
   Bilgi hiyerarşisinin görsel tarafı. Sıra şablonda sabit (durum · sorumlu ·
   tarih · ikincil); burada yalnız **ağırlık, ton ve kırpma** kararı var —
   kart boyutu büyümez, satır tek satırdır.

   Üç kademe:
     1. durum       — kaydın kendi mürekkebi (`--text`), 500 ağırlık
     2. sorumlu/tarih — ikincil mürekkep; gecikmiş tarih mercan + 600
     3. ikincil     — soluk (`--text-muted`): sektör, müşteri adı, görev
                      sayısı, kaynak alan. Okunur ama öne çıkmaz.

   Kırpma sırası tersten: önce ikincil bilgi daralır, sonra sorumlunun adı;
   durum ve tarih hiç daralmaz (`flex: none`). Sarma yok — sararsa kartların
   yüksekliği bir merdivene dönüşür (mobil sakin kartın gerekçesi, §6). */
.rec-line {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--text-secondary);
}
.rec-line-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: none;
}
.rec-line-item + .rec-line-item::before {
  content: "·";
  margin-right: var(--sp-2);
  color: var(--text-muted);
  flex: none;
}
/* Sade durumun kendi iç dolgusu satırı hizadan kaydırıyordu: satırın ilk
   öğesi başlıkla aynı sol kenardan başlamalı. */
.rec-line-status .status.is-plain { padding-left: 0; }
.rec-line-status .status { font-weight: 500; }
.rec-line-owner { flex: 0 1 auto; }
.rec-line-owner .truncate { max-width: 22ch; }
.rec-line-owner .avatar-xs { flex: none; width: 18px; height: 18px; font-size: 9px; }
.rec-line-date.is-soon { color: var(--warn); font-weight: 600; }
/* Solukluk tek kanaldan gelmiyor: `--text-muted` AA sınırında tutulduğu
   için (`base.css`, ink-400 gerekçesi) ikincil bilgi sekonderden yalnız bir
   ton açık. Ayrım **boyutla** tamamlanıyor: bir basamak küçük (`--fs-xs`),
   400 ağırlık. Satır yüksekliği durumun ve avatarın, küçülen öğe onu
   değiştirmez. */
.rec-line-extra {
  flex: 0 1 auto;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 400;
}
.rec-line-extra .is-alert { color: var(--state-late-ink); }
.list-row-aside {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex: none;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}

/* --- Sekmeler --------------------------------------------------------- */

.tabs {
  display: flex;
  gap: var(--sp-4);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
  margin-bottom: var(--sp-2);
}
/* Kaydırılabilir şeridin son sekmesi ekran kenarında yarım kalmasın. */
.tabs::after {
  content: "";
  flex: none;
  width: var(--sp-1);
}
.tabs::-webkit-scrollbar { display: none; }

.tab-link {
  display: inline-flex;
  align-items: center;
  /* Şerit kaydırılabilir (`.tabs` -> `overflow-x: auto`) ama sekmeler
     esnek kalınca sığmayınca kaydırılmak yerine büzülüyor; `nowrap` olan
     metin de kutusundan taşıp komşu sekmenin üstüne biniyordu (dar ekranda
     "Geçmiş" ile "İşlem geçmişi" iç içe geçiyordu). Sekme kendi genişliğini
     korur, sığmayan şerit kayar — tasarlanan davranış zaten buydu. */
  flex: none;
  /* Faz 17: farede 38 px. `--tap` (44) her aygıtta uygulanınca sekme
     şeridi, altındaki içerikten daha kalın bir bant oluyordu; dokunma
     hedefi kuralı (§7) zaten aygıta bağlıdır ve aşağıda `pointer: coarse`
     altında aynen duruyor. Çizgi de metne yaklaştı: 2 px'lik işaret 44
     piksellik bir kutunun dibinde, ait olduğu sözcükten kopuyordu. */
  min-height: 38px;
  padding: 0 2px;
  border-bottom: 2px solid transparent;
  color: var(--text-secondary);
  font-weight: 600;
  font-size: var(--fs-sm);
  white-space: nowrap;
}
@media (pointer: coarse) { .tab-link { min-height: var(--tap); } }
.tab-link {
  transition: color var(--dur-1) var(--ease-out),
    border-color var(--dur-2) var(--ease-out);
}
.tab-link:hover { color: var(--text-primary); text-decoration: none; }
/* Üst gezinmedeki etkin bölüm işaretiyle **aynı** dil: koyu metin + altında
   indigo çizgi. Eskiden metin de indigoya dönüyordu; sayfada üç ayrı yerde
   (üst menü, sekme, bağlantı) üç farklı "etkin" görünümü vardı. */
.tab-link.is-active {
  color: var(--text-primary);
  font-weight: var(--fw-bold);
  border-bottom-color: var(--brand);
}

/* --- Filtre çubuğu ---------------------------------------------------- */

/* `flex-direction` açıkça yazılır: bu çubuk `.stack-sm` gibi bir yığın
   yardımcısıyla birlikte kullanılırsa, yönü belirtmemek kolona düşmesine
   ve `flex-basis`in genişlik yerine yüksekliğe uygulanmasına yol açar. */
.toolbar {
  display: flex;
  flex-direction: row;
  /* `center`: çubukta artık etiketli alan yok (etiketler süzgeç panelinin
     içinde). `flex-end` ile arama kutusu, düğmelerden bir-iki piksel aşağıda
     oturuyor ve çubuk eğri görünüyordu. */
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-3);
}
.toolbar .field { margin: 0; }
/* Arama kutusu boş kalan bütün genişliği yutuyordu: 1440 px'lik ekranda
   tek satırlık bir aramaya 1500 px'lik kutu düşüyor, yanındaki "Ara"
   düğmesi de ekranın öbür ucunda kalıyordu. Büyümesine izin var ama bir
   yerde durur. */
.toolbar .search-field { flex: 1 1 220px; min-width: 0; max-width: 460px; }

/* Çip **etiket değil, seçimdir** (Faz 2): yalnız çoklu katılımcı ya da
   kaldırılabilir gerçek bir seçim çipe girer. Marka rengiyle dolu olduğu
   sürece listede durumla yarışıyor, göz önce ona gidiyordu — oysa kapsam
   ya da katılımcı, satırın en az acil bilgisi. Nötr yüzey + kenarlık:
   okunur ama sessiz. Renk, durumun ve gecikmenin tekelindedir. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* 1 px kenarlık eklendi; dolgu o kadar azaltıldı ki dış ölçü değişmesin. */
  padding: 5px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface-soft);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 500;
}
.chip { transition: background-color var(--dur-1) var(--ease-out); }
.chip button {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  padding: 0;
  line-height: 0;
}

/* --- Tablo (yalnızca masaüstü) ---------------------------------------- */

.table-wrap { overflow-x: auto; }

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
}
/* Başlık şeridi kendi zeminini taşır. Beyaz üstünde beyaz başlık ile veri
   arasındaki tek fark punto oluyordu; ilk satır başlık mı veri mi diye
   bakmak gerekiyordu. */
.table th {
  text-align: left;
  font-size: var(--eyebrow-size);
  /* 700 değil 600: başlık şeridi kendi zeminini zaten taşıyor, bir de
     kalın yazılınca veriyle yarışan ikinci bir katman oluyordu. */
  font-weight: var(--fw-semibold);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
  /* Başlık ve hücre **aynı** yatay dolguyu kullanır. Eskiden ikisi de
     --sp-4'tü ama hücreye farklı sınıflar (rozet, avatar, çubuk) kendi
     boşluğunu ekleyince sütun başlığı ile değeri birkaç piksel kayıyordu;
     tek değişkene bağlanınca sütunlar yukarıdan aşağı aynı çizgide. */
  padding: var(--sp-2) var(--sp-4);
  background: var(--surface-soft);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
/* Satır arası çizgi kartın dış çerçevesinden **ince**: ikisi aynı ağırlıkta
   olunca yirmi satırlık bir tablo kareli deftere dönüyordu. */
.table td {
  padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: 0; }
/* Satır **52 px**. Dolgu tek başına yetmiyordu: bir hücrede rozet, öbürün-
   de düz metin olunca satır yüksekliği satırdan satıra 48-56 arasında
   oynuyor ve liste titriyordu. `height` tabloda alt sınır gibi davranır —
   tek satırlık içerik tam 52'de durur, saran metin büyümeye devam eder. */
.table tbody tr {
  height: 52px;
  transition: background-color var(--dur-1) var(--ease-out);
}
.table tbody tr:hover { background: var(--surface-soft); }
.table tbody tr.is-selected { background: var(--selected); }
/* Tıklanabilir satır (Faz 48): boş alana tıklamak kaydı açar (`app.js`,
   `data-row-link`). İmleç bunu söyler, satır üstündeyken ad da hover
   rengini alır — hedefin "bu satırın kaydı" olduğu okunur. Betiksiz
   tarayıcıda satır sıradan kalır; tıklanır olan yalnız bağlantıdır. */
.js .table tbody tr[data-row-link] { cursor: pointer; }
.js .table tbody tr[data-row-link]:hover .cell-title a { color: var(--brand); }
/* Etkileşimli alanların üstünde imleç kendi anlamına döner: onay kutusu,
   hızlı alanlar ve menü satır yönlendirmesini tetiklemez. */
.js .table tbody tr[data-row-link] .select-col,
.js .table tbody tr[data-row-link] .quick-form,
.js .table tbody tr[data-row-link] .row-actions { cursor: default; }
/* Başlık satırı tabloyla birlikte kaymasın: uzun listede hangi kolonun ne
   olduğunu hatırlamak için yukarı dönmek gerekiyordu. */
.card .table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-soft);
}
/* Başlık şeridi artık kendi zeminini taşıdığı için kartın yuvarlak
   köşesini kare gösteriyordu: `.card` üzerinde `overflow: hidden` yok
   (olsaydı yapışkan başlık kırpılırdı), dolayısıyla köşeyi hücrenin
   kendisi izlemek zorunda. */
.card .table thead tr:first-child th:first-child {
  border-top-left-radius: calc(var(--r-lg) - 1px);
}
.card .table thead tr:first-child th:last-child {
  border-top-right-radius: calc(var(--r-lg) - 1px);
}

/* --- İlerleme çubuğu -------------------------------------------------- */

/* Her ikisi de şablonlarda <span> olarak yazılıyor. `display` verilmezse
   satır içi kalırlar ve `width`/`height` yok sayılır — dolgu hiç çizilmez. */
.progress {
  display: block;
  /* 6 -> 4 piksel. Çubuk listede bir **ölçü**, bir yüzey değil: 6 pikselde
     satırdaki en kalın yatay öğe oluyor ve rozetle yarışıyordu. Dolgunun
     nerede bittiği 4 pikselde de okunuyor (bitiş kenarı zaten geçişle
     koyulaşıyor, aşağıya bkz.). */
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  overflow: hidden;
}
.progress-bar {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  /* Düz tek ton. Çubuk 6 pikselken iki basamaklı bir geçiş kullanıyordu —
     gerekçe, dolgunun nerede bittiğinin seçilmesiydi. 4 piksellik bir
     şeritte geçişin kendisi görünmüyor, yalnız rengi belirsizleştiriyor:
     bitiş kenarını zeminle arasındaki kontrast zaten söylüyor. */
  /* Faz 27: mor → petrol yeşili. Bu çubuğun ölçtüğü şey her kullanımında
     aynı: **tamamlanan görev oranı** ("Görev tamamlanma", "3/7 görev").
     Yani bir marka yüzeyi değil, sözlükteki tamamlanma kanalının sürekli
     hâli — nokta "bitti" der, çubuk "ne kadarı bitti" der. Mor kalması
     aynı ekranda birincil eylem düğmesiyle aynı rengi konuşması demekti;
     eski gerekçe ("tek seri taşıyan çubuk marka rengindedir") rengin bir
     *anlamı* olmadığını varsayıyordu, oysa burada var.

     Kategori çubukları (`.chart-1..3`, sektör dağılımı) grafik ailesinde
     kalıyor ve bu kuralı 0,2,0 ile eziyor: orada ölçülen tamamlanma değil,
     "hangi dilim kimin". */
  background: var(--state-done);
  /* Sıfırdan büyük ama çok küçük bir oran ("%1") görünmez kalmamalı: bir
     iş başlamışsa çizgi de başlamış görünmeli. */
  min-width: 3px;
  transition: width var(--dur-3) var(--ease-out);
}
/* Gerçekten sıfırsa çizgi hiç çizilmez — yukarıdaki en küçük genişlik,
   "biraz ilerledi" yalanını söylemek için değil. */
.progress-bar[style*="width: 0%"] { min-width: 0; }

/* --- Grafik serisi ---------------------------------------------------------
   Tek seri taşıyan çubuk (bir işin ilerlemesi, bir oran) marka rengindedir:
   orada "kaçıncı seri" diye bir soru yok. Birden çok **kategori** yan yana
   geldiğinde ise renk ayırt edici olur ve grafik ailesine geçilir
   (`--chart-1..3`: mor, turkuaz, nötr lacivert — bkz. `base.css`).

   Renk tek başına bilgi taşımadığı için her çubuğun yanında adı ve sayısı
   duruyor; ramp yalnız aşamaları göz kararı gruplanabilir yapıyor. */
.progress-bar.chart-1 { background: var(--chart-1); }
.progress-bar.chart-2 { background: var(--chart-2); }
.progress-bar.chart-3 { background: var(--chart-3); }

@media (prefers-reduced-motion: reduce) {
  .progress-bar { transition: none; }
}

/* --- Tanım listesi (ayrıntı ekranları) -------------------------------- */

.detail-list { display: flex; flex-direction: column; gap: var(--sp-3); }
.detail-row {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: start;
}
.detail-label { color: var(--text-secondary); font-size: var(--fs-sm); }

/* --- Ayarlar --------------------------------------------------------- */

.setting-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--border-soft);
}
.setting-row:last-child { border-bottom: 0; }
.setting-row .setting-text { min-width: 0; }
.setting-row .setting-text p {
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  margin: 2px 0 0;
}

/* --- Duyarlı ölçekleme ----------------------------------------------- */

/* Kart sayısı ekrana göre değişir (yetkiye bağlı olarak 4 ya da 5). Sabit 4
   kolon, 5. kartı tek başına alt satıra düşürüp sağda büyük bir boşluk
   bırakıyordu; kolon sayısı sığdığı kadar olsun. */
@media (min-width: 640px) {
  .stat-grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
}

@media (min-width: 1000px) {
  .card-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .card-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 639px) {
  .list-row { padding: var(--sp-3) var(--sp-4); }
  .detail-row { grid-template-columns: minmax(0, 1fr); gap: 2px; }

  /* Rozetler ve eylemler adın yanında durmaya çalışırken satırın yarısını
     alıyor, geriye kalan yere sıkışan e-posta üç noktayla kesiliyor ve alt
     bilgi satırı ortasından kırılıyordu — ayıraç noktası tek başına bir
     satırda kalacak kadar. 899 px'te rozetlerin kendi arasında sarılmasına
     izin verilmişti; telefonda yetmiyor, çünkü sorun rozetlerin sarılması
     değil aynı satırı paylaşmaları. Yan sütun kendi satırına iner, üstteki
     ad ve e-posta tam genişliği kullanır. */
  /* Yalnız yan sütun %100 taban alır: avatar ile ad aynı satırda kalır,
     yan sütun altlarına iner. `.list-row-main` de %100 verilseydi avatar
     tek başına bir satırda kalırdı. */
  .list-row { flex-wrap: wrap; }
  .list-row-aside {
    flex: 1 1 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
  }

  /* İstisna: liste kartı satırında yan sütunun içinde yalnız "aç" oku var
     (`.list-row-link` ile gelen desen). Ona da %100 taban verilince ok
     kendi satırında tek başına, hem de sola yaslı duruyordu — ekranda
     boşlukta asılı duran bir ">" işaretinden başka bir şey değildi. Ok
     adın yanında kalır; asıl yer kaplayan hızlı işlem alanları
     (`.quick-row`, %100) zaten alt satıra iniyor. */
  .list-row-link + .list-row-aside {
    flex: 0 0 auto;
    margin-left: auto;
  }

  /* Panonun kart listelerinde yan sütun **tek bir şey** taşıyor: huninin
     sayısı, teslimin tarihi. Genel kuralın tam satıra indirmesi orada iki
     zarar veriyordu — altı aşamalı huni on iki satıra çıkıp kartın
     yüksekliğini ikiye katlıyor, ve "Yeni" ile "2" arasındaki bağ kopup
     sayı bir sonraki aşamanın başlığı gibi okunuyordu.

     Genel kuralın gerekçesi (rozetler + eylemler adın yarısını yiyor)
     burada yok: bu asideler rozet değil, tek bir sayı ya da tarih. */
  .dash-card .list-row-aside {
    flex: 0 0 auto;
    margin-left: auto;
    justify-content: flex-end;
  }

  /* İstisnanın istisnası: yan sütunda ok değil **işlem** varsa (rozetler +
     "Düzenle" + davet yenileme) yukarıdaki `flex: 0 0 auto` onu küçülmez ve
     sarılmaz yapıyor. `.badge` zaten `white-space: nowrap`; sonuç 360 px'te
     14 px yatay taşma ve sağdan kesilen bir "Düzenle" düğmesiydi (üyeler
     sayfası, çok üyeli alan). Ölçüm turu bunu göremiyordu: tur tek üyeli
     bir alanda koşuyor ve o satırda "Davet bekliyor" rozeti hiç çizilmiyor.

     Kural ok desenini bozmadan yalnız işlem taşıyan yan sütunu geri
     esnetiyor: tam satır tabanı + sarma. Opt-in bir sınıf, çünkü "içinde ok
     mu işlem mi var" CSS'in seçebileceği bir şey değil. */
  .list-row-link + .list-row-aside.list-row-actions,
  .list-row-aside.list-row-actions {
    flex: 1 1 100%;
    margin-left: 0;
    justify-content: flex-start;
    flex-wrap: wrap;
    row-gap: var(--sp-2);
  }

  /* Alt bilgi telefonda alt alta okunur; ayıraç noktalarına gerek kalmaz
     ve orta yerinden kırılan satır sorunu kökten biter. */
  .list-row-meta { flex-direction: column; align-items: flex-start; gap: 2px; }
  .list-row-meta .dot-sep { display: none; }
}

/* ==========================================================================
   Form düzeni — dar form kolonu, eylem satırı, seçenek kartları
   ========================================================================== */

.form-narrow {
  max-width: 560px;
}

.form-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding-top: var(--sp-2);
}

.form-actions .grow { flex: 1; }

/* Radyo seçenekleri: tıklama alanı bütün kart (mobilde parmakla kolay). */
.choice-group {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* WTForms çoklu seçim alanları bu sınıfı bir <ul> üzerine basar; madde
   işaretleri ve 40px girinti kalırsa alan ham liste gibi görünür. Kutucuklar
   da varsayılan 13px'te kalmasın — dokunma hedefi en az 44px olmalı. */
ul.choice-group {
  list-style: none;
  margin: 0;
  padding: 0;
}
ul.choice-group > li {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
}
ul.choice-group input[type="checkbox"],
ul.choice-group input[type="radio"] {
  width: 18px;
  height: 18px;
  margin: 0;
  flex: none;
  accent-color: var(--brand);
  cursor: pointer;
}
ul.choice-group label {
  flex: 1 1 auto;
  min-width: 0;
  cursor: pointer;
}

/* 44 px'lik dokunma hedefi **parmak** içindir. Fareyle açılan çekmecede
   dört seçenek 52 px aralıkla dizilince alan, formun geri kalanından iki
   kat gevşek bir boşluk adasına dönüşüyordu: kutucuklar birbirine ait
   görünmüyor, göz aşağıdaki alanı kaybediyordu. İmleç ince olduğunda
   satırlar sıkışır — etiketin tamamı hâlâ tıklanabilir. */
@media (pointer: fine) {
  ul.choice-group { gap: 2px; }
  ul.choice-group > li { min-height: 32px; }
}

.choice {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border-input);
  border-radius: var(--r-md);
  background: var(--surface);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.choice:hover { border-color: var(--border-strong); }

.choice-input {
  margin: 3px 0 0;
  accent-color: var(--brand);
  flex: none;
}

.choice-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.choice-title {
  font-weight: 600;
  color: var(--text);
  font-size: var(--fs-base);
}

.choice-hint {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: 1.45;
}

/* Seçili seçenek belirgin olsun. */
.choice:has(.choice-input:checked) {
  border-color: var(--brand);
  background: var(--brand-softer);
}

.choice:has(.choice-input:focus-visible) {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.choice.is-disabled,
.choice:has(.choice-input:disabled) {
  opacity: 0.6;
  cursor: default;
}


/* ==========================================================================
   Faz 3 — firma listesi ve ayrıntısı
   ========================================================================== */

/* Masaüstü tablosu mobilde küçültülmez; ayrı liste görünümü kullanılır.
   İki görünüm aynı veriyi işaretler, biri gizlenir. */
.only-desktop { display: none; }
.only-mobile { display: block; }

@media (min-width: 900px) {
  .only-desktop { display: block; }
  .only-mobile { display: none; }
}

/* `only-*` ikizi ama `display` **dayatmaz**, yalnız gizler. Fark önemli:
   `.only-desktop` bir düğmeye verildiğinde onu `display: block` yapıyor ve
   `inline-flex` hizalamasını (ikon + metin ortalaması) bozuyordu. Bu ikisi
   iki çizimi olmayan, tek çizimi belli bir ölçüde saklanan öğeler için. */
/* 900-1100 px: masaüstü iskeleti açık ama yan menü 236 px alıyor ve içeriğe
   ~460-830 px kalıyor. Yedi sütunlu listelerde iş adı `.cell-title`ın
   `min-width: 16ch` tabanına oturup iki satırda kesiliyordu. Bu bantta
   ikincil sütun düşer ve hücre dolgusu daralır: ad yeniden okunur olur.
   Sütunu gizleyen sınıf `th` ve `td`ye birlikte konur, yoksa satır kayar. */
@media (min-width: 900px) and (max-width: 1100px) {
  .hide-compact { display: none !important; }
  .table th, .table td { padding-left: var(--sp-3); padding-right: var(--sp-3); }
}

@media (max-width: 899px) { .hide-mobile { display: none !important; } }
@media (min-width: 900px) { .hide-desktop { display: none !important; } }

/* Sayfalama: dokunma hedefi tam boy, ok düğmeleri kenarlarda. */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.pager-actions { display: flex; gap: var(--sp-2); }

/* (Faz 6 — `.filter-chips` / `.filter-chip` silindi. Tek kullanıcısı panonun
   hazır dönem kısayollarıydı; o da sade satırlara indi: `.range-preset`.) */

/* Gecikme **yanık mercandır, kırmızı değil** (Faz 2): kırmızı bu arayüzde
   yıkıcı eylemin (silme) rengi ve geciken bir tarih bir hata değil, bir
   iştir. Aynı sebeple `.is-alert` de aynı aileden okur; ikisi tek dil olsun
   diye `.due` oraya hizalandı. Renk tek başına taşımasın diye kalın yazıyla
   birlikte gelir.

   Faz 27 "arka plan yok" kuralını kaldırmıştı ve gerekçesi o gün doğruydu:
   dolgu gürültü yapmıyordu, çünkü hap **yalnız** değildi — aynı satırda
   durum rozeti de tür işareti de dolguluydu. Renkli tek kutuyu gürültü
   yapan şey rengin kendisi değil yalnızlığıydı.

   Faz 32 o gerekçeyi **tersinden** okuyor. Faz 31 listelerin, Faz 32 panonun
   durum kapsüllerini sadeye aldı; komşu dolgular gittiğinde geriye ekranın
   tek renkli kutusu olarak gecikme hapı kaldı, yani Faz 27 öncesinin tam
   koşulu geri geldi. Üstelik en kötü yerde: "3 gün gecikti" bir durum değil,
   **tarihin okunuşu**dur ve satırın tarih kolonunda diğer tarihlerle aynı
   dikey hizada durur — hap o hizayı tek satırda bozuyordu.

   Artık gecikme her yüzeyde tek biçimde konuşuyor: yanık mercan, kalın,
   **zeminsiz** metin. `.is-alert` bunu detay ve panelde zaten böyle yapıyordu
   (bkz. o bloğun gerekçesi: dolgu "kısa ve tek parça" yüzeylerin işi); iki
   sınıf nihayet aynı şeyi aynı araçla söylüyor. Renk tek başına taşımasın
   diye kalın yazıyla birlikte gelir. */
.due {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  color: var(--state-late-ink);
  font-weight: 600;
}

/* Görüşme geçmişi zaman çizgisi. */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline-item {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.timeline-item:last-child { border-bottom: 0; }
/* Zaman çizgisinin ikon dairesi de nötr. Görüşme geçmişinde alt alta on
   kayıt var; on mor daire, sayfadaki tek birincil eylemi bastırıyordu. */
.timeline-icon {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--surface-sunken);
  color: var(--text-secondary);
}
.timeline-body { min-width: 0; flex: 1 1 auto; }
.timeline-head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.timeline-note { white-space: pre-wrap; margin: 4px 0 0; }

@media (max-width: 899px) {
  .timeline-item { padding: var(--sp-4); }
}


/* --- Faz 5.2: @etiket ve dosya ekleri ----------------------------------- */

/* Etiket, metnin içinde bir *vurgu*dur; bağlantı değildir. Tıklanabilir
   göstermek, tıklayınca hiçbir yere gitmediği için yanıltıcı olurdu. */
/* Kendi yorumunda yazan kural: etiket bir *vurgu*, bağlantı değil. O hâlde
   bağlantı rengini de kullanmamalı — mor bu arayüzde "tıklanır" demektir ve
   metnin ortasındaki mor bir kelime, tıklanınca hiçbir yere gitmediği için
   sözünü tutmuyordu. Ayrışmayı artık zemin ve ağırlık taşıyor. */
.mention {
  color: var(--text-primary);
  background: var(--surface-sunken);
  border-radius: var(--r-sm);
  padding: 0 4px;
  font-weight: 600;
}

.attachments {
  list-style: none;
  margin: var(--sp-2) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.attachment {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 6px var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
}
.attachment a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  color: var(--text);
  text-decoration: none;
}
.attachment a:hover { color: var(--brand); text-decoration: underline; }
.attachment .attachment-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}
.attachment .attachment-size { color: var(--text-secondary); font-size: 12px; flex: none; }
/* Dokunma hedefi 44px'in altına düşmesin (mobil kuralı). */
.attachment button { min-height: 32px; }

.upload-hint { color: var(--text-secondary); font-size: 12px; }

/* Faz 17: dosya alanı artık `class="input"` taşıyan çıplak bir
   `<input type="file">` değil.

   Tarayıcının kendi dosya girdisi üç yüzden sırıtıyordu: "Dosya Seç /
   Seçili dosya yok" metni işletim sisteminden geliyor (çevrilemez),
   düğmesi bizim düğme dilimize benzemiyor ve `.input` çerçevesi ona
   "doldurulacak bir alan" görünümü veriyordu — oysa bu isteğe bağlı bir
   ek. Kesik çizgi, "buraya bir şey koyabilirsin" demenin en sessiz yolu:
   dolu bir çerçeve zorunluluk, kesik çerçeve davettir. */
.upload-drop {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface-soft);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.upload-drop:hover,
.upload-drop:focus-within {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--text-primary);
}
.upload-drop .icon { flex: none; color: var(--text-muted); }
.upload-drop:hover .icon,
.upload-drop:focus-within .icon { color: var(--brand); }
/* Girdinin kendisi görünür kalır (dosya seçildiğinde adını yazan tek
   şey odur) ama kabuğun içinde durur: çerçevesiz, zeminsiz. */
.upload-drop input[type="file"] {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: none;
  padding: 0;
  color: inherit;
  font: inherit;
  font-size: var(--fs-sm);
}
.upload-drop input[type="file"]:focus { outline: none; }
/* Tarayıcının kendi düğmesi bizim düğme dilimize çevrilir: aynı yarıçap,
   aynı sınır, aynı punto. Çevrilemeyen tek şey üstündeki yazı — onu
   işletim sistemi koyuyor, bu yüzden yanına Türkçe etiketi biz yazıyoruz
   (`.upload-drop-text`). */
.upload-drop input[type="file"]::file-selector-button {
  margin-right: var(--sp-2);
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-btn);
  background: var(--surface);
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--fs-xs);
  cursor: pointer;
}
.upload-drop input[type="file"]::file-selector-button:hover {
  border-color: var(--border-strong);
  color: var(--text-primary);
}
.upload-drop-text { flex: none; }


/* --- Faz 5.3: bildirimler ----------------------------------------------- */

.notif-count {
  flex: none;
  border-radius: 10px;
  background: var(--brand);
  color: var(--text-on-brand);
  font-size: 11px;
  font-weight: 700;
  padding: 1px 7px;
}
.notif-open {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.notif-open:hover .notif-title { text-decoration: underline; }


/* Genel Bakış: henüz bağlanmamış sayaçlar.
   "0" yerine "—" gösterilir — ölçülmeyeni sıfır diye sunmak yanıltıcı.
   Kutu soluk durur ki gerçek sayaçlarla karışmasın. */
.stat-card.is-pending { background: var(--surface-soft); box-shadow: none; }
.stat-card.is-pending .stat-value { color: var(--text-muted); }

.stat-note {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  margin-top: 2px;
}


/* --- Faz 4: işler ve görevler ---------------------------------------- */

/* Sekme çubuğunun altındaki ikinci seviye (hazır görünümler): ana
   sekmelerle karışmasın diye daha sakin durur. */
.tabs-soft { border-bottom: 0; gap: var(--sp-1); }
.tabs-soft .tab-link { font-size: var(--fs-sm); padding: 6px 10px; }

/* İlerleme hücresi: sayı üstte, çubuk altta. Yüzde tek başına
   gösterilmez — "8/10" sayının nereden geldiğini söyler. */
.progress-wrap { display: flex; flex-direction: column; gap: 4px; min-width: 120px; }
.progress-wrap .progress { width: 100%; }

/* Görev listesi (iş ve görev ayrıntısında).

   Faz 17: liste artık kendi kartının içinde değil, **bölümün bandına
   yapışık tek bir yüzey** (`section_head(attached=true)` + `.card
   .task-list`). Önceki hâlde bir görev ayrıntısında dört ayrı beyaz kart
   alt alta duruyordu — alt görevler, bağımlılıklar, bekleyenler, aktivite —
   ve dördü de aynı genişlikte, aynı gölgede, aynı köşede olduğu için sayfa
   "kutu yığını" gibi okunuyordu. Bölümü ayıran şey artık bandın başlığı;
   satırları ayıran şey ince çizgi. */
.task-list { display: flex; flex-direction: column; }
.task-row {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--border-soft);
}
.task-list .task-row:first-child { border-top: 0; }
.task-row.is-subtask { padding-left: calc(var(--sp-4) + var(--sp-6)); background: var(--surface-soft); }
/* Zeminli satır (alt görev, ekleme satırı) yüzeyin son satırıysa kartın
   köşesinden taşmasın. `overflow: hidden` tercih edilmedi: aynı kabın
   içinde konumlanan menüler ve tarih popover'ları kırpılırdı. */
.task-list > :last-child {
  border-bottom-left-radius: var(--r-lg);
  border-bottom-right-radius: var(--r-lg);
}
/* Satırın kendisi bağlantı değil (içinde form var), bu yüzden vurgu
   satıra yazılır: göz hangi satırda olduğunu bilsin. */
.task-row:hover { background: var(--surface-soft); }
.task-row.is-subtask:hover { background: var(--surface-sunken); }

/* Ekleme satırı listenin **son satırı**: ayrı bir form bloğu değil.
   Listenin altında serbest duran alan, hangi listeye ekleyeceğini
   boşlukla anlatmak zorunda kalıyordu. */
.task-add {
  align-items: center;
  gap: var(--sp-2);
  background: var(--surface-soft);
}
/* Yüzeyin içindeki açıklama / "kayıt yok" satırı da bir satırdır: `p`nin
   genel alt boşluğu burada çizginin altında boş bir bant bırakıyordu. */
.task-list > p.task-row { margin: 0; }
/* `max-width: none` — `.input-sm` masaüstü tablosu için 150 px'lik bir
   tavan taşıyor; ekleme satırında alan satırın kalanını almalı. */
.task-add .input,
.task-add .select { flex: 1 1 220px; min-width: 0; max-width: none; }
.task-add > .btn { flex: none; }
.task-main { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; }
.task-main a { font-weight: 600; }
.task-main a.task-done { color: var(--text-muted); text-decoration: line-through; }

/* Tamamlama düğmesi: dokunma hedefi 32px, tik yalnız tamamlanınca görünür. */
.task-check {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  color: transparent;
  cursor: pointer;
}
.task-check:hover { color: var(--text-muted); }
.task-check.is-done {
  background: var(--success);
  border-color: var(--success);
  color: var(--text-on-brand);
}

/* Satır içi hızlı güncelleme formları — tabloda yer kaplamasın. */
.quick-form { margin: 0; display: inline-flex; align-items: center; gap: var(--sp-2); }
.select-sm, .input-sm { padding: 6px 8px; font-size: var(--fs-sm); min-width: 0; }
.input-sm { max-width: 150px; }
/* Sağ boşluk kısayolla ezilmemeli: açılır ok arka plan görseli olarak
   `right 14px`te duruyor, pay daralınca metnin üstüne biniyor. */
.select-sm {
  max-width: 170px;
  padding-right: 32px;
  background-position: right 10px center;
}

/* Mobil kartta satır içi hızlı işlem.

   Kartın tamamı bağlantıyken içine form konamaz (HTML bağlantı içinde form
   yasaklar); bu yüzden satır `<div>`, başlık ise bağlantı olur. Görünüm
   değişmez: bağlantı satırın tıklanabilir ana alanı olmayı sürdürür. */
/* `flex: 1 1 auto` olmadan bağlantının taban genişliği içeriğinden gelir;
   uzun firma adı satırı doldurunca yanındaki ok kendi satırına düşüyor ve
   tek başına duran bir ">" işareti kalıyordu. Şimdi bağlantı büzülür, ok
   satırın sonunda kalır, hızlı işlem alanları (`.quick-row`, %100 genişlik)
   yine alt satıra iner. */
.list-row-link {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
  color: inherit;
}
.list-row-link:hover { text-decoration: none; }

/* Alanlar mobilde ikişerli sarar; masaüstündeki 150-170px sınırı burada
   dar kalırdı, dokunma hedefi küçülürdü. */
.quick-row { width: 100%; gap: var(--sp-2); margin-top: var(--sp-2); }
.quick-row .quick-form { flex: 1 1 45%; }
.quick-row .quick-form .select-sm,
.quick-row .quick-form .input-sm { width: 100%; max-width: none; }

/* Alan etiketi (`_quick.html`). Varsayılanı görünmez — `.visually-hidden`
   ile birebir aynı bildirimler, ayrı bir sınıf olmasının tek nedeni
   bağlama göre geri açılabilmesi. Liste satırında ve kayıt panelinde alanın
   adı komşu kolon başlığında ya da `<dt>`de zaten yazıyor; etiketi ikinci
   kez basmak aynı kelimeyi iki kez okuturdu. */
.quick-label {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Üç nokta menüsündeki hızlı güncelleme — Faz 36.

   Burada komşu başlık yok: panel "Hızlı güncelleme" yazısının altında üç
   çıplak kutu gösteriyordu ve hangisinin durum olduğunu ancak içindeki
   değeri tanıyan biri anlıyordu ("Devam ediyor" bir durum mu, bir kişi mi?).
   Panoyu telefonda kullanan için bu menü **durum değiştirmenin tek yolu**
   (sürükleme orada sütun görmez), yani tahmin edilmesi gereken bir şey
   olamaz: her alan kendi satırında ve üstünde adı yazar.

   Yan yana iki alan (`flex: 1 1 45%`) bırakılsaydı 360 pikselde kutular
   150 piksele iner, üstlerindeki ad kırpılırdı — etiketi görünür yapıp
   okunmaz bırakmak hiç yapmamaktan kötüdür. */
.row-menu-panel .quick-row { flex-direction: column; align-items: stretch; }
.row-menu-panel .quick-row .quick-form {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}
.row-menu-panel .quick-row .quick-label {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
}

@media (max-width: 899px) {
  .task-row { padding: var(--sp-4); }
  .task-row.is-subtask { padding-left: calc(var(--sp-4) + var(--sp-5)); }
}


/* ==========================================================================
   Sayfa ritmi ve kart iç boşlukları
   ========================================================================== */

/* Kardeş kartlar arasında hiç margin yoktu; sayfa gövdesini `stack` ile
   sarmayan ekranlarda kartlar tek bir beyaz blok gibi birbirine yapışıyordu.
   Yığın sarmalayıcısı olan yerlerde `gap` zaten iş görür, orada devre dışı. */
.content-inner > .card + .card,
.content-inner > .card + section.card,
.content-inner > section.card + .card,
.content-inner > section.card + section.card {
  margin-top: var(--sp-4);
}

/* Kenardan kenara liste/tablo içeren kartlar (`card-pad` yok): yığın boşluğu
   satır kenarlıklarının arasında havada duran çizgiler bırakıyordu. */
.card.stack:not(.card-pad),
.card.stack-sm:not(.card-pad) { gap: 0; }

/* Böyle bir kartın altındaki özet satırı ("7 iş listeleniyor") kendi
   dolgusu olmadığı için kart kenarlığına yapışıyordu. */
.card.stack:not(.card-pad) > p,
.card.stack-sm:not(.card-pad) > p {
  margin: 0;
  padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid var(--border);
}

/* Form kartlarında etiket–alan mesafesi (8px) ile alan–alan mesafesi (12px)
   birbirine çok yakındı; etiketin hangi alana ait olduğu okunmuyordu. */
.card-pad.stack { gap: var(--sp-5); }

/* Bildirim satırında gövde metni ile tür etiketi satır içi olduğu için
   yan yana akıyordu. */
.notif-open > * { display: block; }

@media (min-width: 640px) and (max-width: 899px) {
  /* Dar ekranda rozetler satırın yarısını yiyip adı/e-postayı eziyordu.
     Tablet aralığıyla sınırlı: telefonda (<=639px) yan sütun zaten kendi
     satırına iniyor ve sola yaslanıyor. Aralık açıkça yazılmazsa iki kural
     da eşleşir ve dosyada sonra geldiği için bu kazanır — rozetler kendi
     satırlarında sağa yaslanıp 'Düzenle' tek başına alta düşerdi. */
  .list-row-aside {
    flex: 0 1 auto;
    flex-wrap: wrap;
    justify-content: flex-end;
  }
}

@media (max-width: 899px) {
  /* Kart kenardan kenara olduğunda alt bilgi de dar dolguya uysun.
     Bu kural telefonu da kapsamalı, o yüzden yukarıdaki tablet aralığının
     dışında duruyor. */
  .card.stack:not(.card-pad) > p,
  .card.stack-sm:not(.card-pad) > p { padding: var(--sp-3) var(--sp-4); }
}


/* Kart *dışında* duran bölüm başlığı: altındaki kartın kendi başlığıyla
   karışmasın diye biraz daha küçük ve sakin, üstünde kendi payı var. */
.section-title {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  margin: var(--sp-6) 0 var(--sp-3);
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--text-secondary);
}

/* ==========================================================================
   Toplu ekleme sihirbazı (Faz 6.1)
   ========================================================================== */

/* Adım göstergesi: 1 Veriler — 2 Kontrol — 3 Kaydet. */
.stepper {
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3);
  list-style: none;
  margin: 0 0 var(--sp-4);
  padding: 0;
}
.stepper-item {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-2);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: 600;
}
/* Ayırıcı çizgi öğenin kendisinden çıkar; ayrı <span> eklemek şablonu
   gereksiz kalabalıklaştırırdı. */
.stepper-item + .stepper-item::before {
  content: "";
  width: var(--sp-6);
  height: 1px;
  background: var(--border-strong);
}
.stepper-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--border);
  color: var(--text-secondary);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.stepper-item.is-active { color: var(--text); }
.stepper-item.is-active .stepper-num {
  background: var(--brand);
  color: var(--text-on-brand);
}
.stepper-item.is-done { color: var(--text-secondary); }
/* Tamamlanan adım geçmişte kaldı: etkin adım (dolu mor) ile aynı aileden
   olması, hangisinin "şu an" olduğunu belirsizleştiriyordu. */
.stepper-item.is-done .stepper-num {
  background: var(--surface-sunken);
  color: var(--text-secondary);
}

/* Kolon eşleştirme ızgarası. Kolon sayısı veriye göre değişir; sabit kolon
   sayısı yerine sığdığı kadar (bkz. `stat-grid` ile aynı gerekçe). */
.map-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-3);
  align-items: start;
}
.map-grid .field { margin: 0; }

/* Beklenen kolonlar: virgülle ayrılmış düz metin (eskiden rozet listesiydi,
   gerekçe `company_bulk.html` içinde). Okunabilirlik sınırı var çünkü bu bir
   cümle; geniş ekranda uçtan uca uzayan tek satır taranamıyor. */
.bulk-columns {
  margin: 0;
  max-width: var(--measure);
  color: var(--text-secondary);
  line-height: 1.7;
}

/* Yapıştırma alanı: sekmeyle ayrılmış veri hizalı görünsün. */
.textarea.mono {
  font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
  font-size: var(--fs-sm);
  white-space: pre;
  overflow-x: auto;
}

/* Atlanacak satır: silik ama okunur. `opacity` yerine renk düşürmek, içindeki
   rozetin ve bağlantının kontrastını korur. */
.is-muted { color: var(--text-muted); }
tr.is-muted td { color: var(--text-muted); }

/* Uyarı satırı — tablo satırının hemen altında, aynı hücre hizasında. */

/* "Bu satır için işlem" — etiket ile açılır liste yan yana, mobilde alt alta. */
.row-action {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
}
.row-action .field-label { margin: 0; white-space: nowrap; }

/* Sekme şeridi düğmelerden oluşuyor (JS ile panel değiştiriyor); `.tab-link`
   bağlantı için yazıldığından düğme varsayılanları temizlenir. */
button.tab-link {
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  font: inherit;
  cursor: pointer;
}

@media (max-width: 899px) {
  .row-action {
    flex-direction: column;
    align-items: stretch;
  }
  .row-action .field-label { white-space: normal; }
}

/* ==========================================================================
   Toplu seçim ve toplu güncelleme çubuğu (Faz 6.2)

   Kural: **JavaScript olmadan da çalışır.** Kutucuklar ve çubuk varsayılan
   olarak açıktır; `html.js` varsa çubuk seçim yapılana kadar gizlenir ve
   mobilde liste "Seç" düğmesiyle seçim kipine girer. Böylece JS yüklenmezse
   kullanıcı özelliği tamamen kaybetmez, yalnız kolaylıkları kaybeder.
   ========================================================================== */

/* Yalnız JS varken anlamlı denetimler (sayfadakileri seç, Seç düğmesi,
   seçimi temizle). JS yokken hiç çizilmezler: çalışmayan bir düğme,
   olmayan düğmeden kötüdür. */
.needs-js { display: none; }
.js .needs-js { display: inline-flex; }

/* --- Satır kutucuğu --- */
.select-col { width: 44px; }

.select-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Dokunma hedefi: 44px (Faz 5.4'te ölçüldü). */
  min-width: var(--tap);
  min-height: var(--tap);
  margin: 0;
  cursor: pointer;
}

.select-input {
  width: 18px;
  height: 18px;
  accent-color: var(--brand);
  cursor: pointer;
}

/* Mobil listede satır bir bağlantıdır; kutucuk bağlantının **içine**
   konamaz (iç içe tıklama hedefi). Bu yüzden kardeş olarak durur. */
.select-row {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--border);
}

.select-row:last-child { border-bottom: 0; }
.select-row .list-row { flex: 1 1 auto; min-width: 0; border-bottom: 0; }
.select-row:has(.select-input:checked) { background: var(--selected); }

/* JS varsa mobil seçim kutucukları "Seç" denene kadar gizli durur.
   Seçici birleşiktir (`.only-mobile.list`): liste ile mobil bayrağı **aynı**
   öğede durur, alt öğede değil. */
.js .only-mobile.list .select-cell { display: none; }
.js .only-mobile.list.is-selecting .select-cell { display: inline-flex; }

.bulk-toggle-row {
  align-items: center;
  gap: var(--sp-2);
  padding-bottom: var(--sp-2);
}

/* Satırın tek içeriği “Seç” düğmesidir ve o `needs-js`tir: betik yokken
   satır boş kalır, yalnız kendi boşluğunu çizerdi. Açıklama metni buradan
   kaldırıldı (telefonda üç satıra kırılıyordu); seçim başlayınca sayı zaten
   işlem çubuğunda “N firma seçildi” olarak yazıyor. */
html:not(.js) .bulk-toggle-row { display: none; }

/* Mobilde tek başına duran düğme; dokunma hedefi 44px'in altına düşmemeli. */
.bulk-toggle-row .btn { min-height: var(--tap); }

/* Kip açıkken beliren yönerge (Faz 36). Kendi satırında: düğmenin yanına
   yazılsaydı 360 pikselde cümle üç parçaya kırılırdı — bu satırdan bir kez
   kaldırılmasının nedeni de buydu. Şimdi yalnız kip açıkken duruyor, yani
   sürekli yer kaplamıyor ve tam gerektiği anda okunuyor.

   `:empty` kuralı yok: boş `<p>` zaten yüksekliksiz ve `display: none`
   olsaydı canlı bölge ağaçtan çıkardı (bkz. `_bulk_bar.html`). */
.bulk-hint { flex: 1 1 100%; margin: 0; }

/* --- İşlem çubuğu --- */
.bulk-bar {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--brand-border);
  border-radius: var(--r-lg);
  background: var(--brand-softer);
}

/* JS varken: seçim yapılmadan çubuk görünmez. Boş çubuk, kullanıcıya
   "bir şey seçtin" izlenimi verirdi. */
.js .bulk-bar { display: none; }
.js .bulk-bar.is-open { display: flex; }

.bulk-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  justify-content: space-between;
}

.bulk-count { font-weight: 600; }

.bulk-scope {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  cursor: pointer;
}

.bulk-scope input { width: 18px; height: 18px; accent-color: var(--brand); }
.bulk-scope strong { color: var(--text); }

.bulk-fields {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: flex-start;
}

.bulk-field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  flex: 1 1 180px;
  min-width: 0;
  margin: 0;
}

.bulk-field .select, .bulk-field .input { width: 100%; }

/* Tarih tetikleyicisi liste satırı için "rozet" gibi tasarlandı: içeriğine
   göre daralır, dar dolgu. Çubukta komşuları tam genişlikte iki kutu olduğu
   için aynı alan yarım boy bir etiket gibi okunuyordu — burada gerçek bir
   alan gibi çizilir. Takvim simgesi sağ kenara yaslanır ki üç alanın da sağ
   ucunda aynı işaret dizilsin. */
.bulk-field .date-pick { width: 100%; }
.bulk-field .date-pick-btn { width: 100%; justify-content: space-between; }

.bulk-clear {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  cursor: pointer;
}

/* Nötr eylemle yıkıcı eylem arasındaki ince çizgi; ikisi de hayalet düğme
   olduğu için sınırı renk değil boşluk + çizgi anlatır. */
.bulk-sep {
  flex: none;
  width: 1px;
  align-self: stretch;
  min-height: 20px;
  background: var(--border);
}

.bulk-actions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
}

/* Seçim "filtreye uyan tümü"ne çevrildiğinde satır kutucukları anlamsızdır;
   sönükleşir ve JS onları devre dışı bırakır. */
.bulk-scope-on .select-input { opacity: 0.4; }

@media (max-width: 899px) {
  /* Mobilde alt işlem çubuğu: ekranın altına yapışır, sekme çubuğunun
     üstünde durur ve güvenli alanı (çentikli ekranlar) hesaba katar. */
  .js .bulk-bar.is-open {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
    z-index: 30;
    margin: 0;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    border-bottom: 0;
    background: var(--surface);
    box-shadow: var(--shadow-lg);
    /* `62vh` iki kez yanlıştı: `vh` mobilde adres çubuğunun altını da
       sayıyor ve çubuk zaten `--tabbar-h` kadar yukarıdan başlıyor.
       Kısa ekranda toplam üstten taşıyor, "Seçilenleri güncelle" düğmesi
       görünmez oluyordu. */
    max-height: calc(62dvh - var(--tabbar-h));
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .bulk-field { flex: 1 1 140px; }
}

/* ==========================================================================
   Takvim (Faz 7.2)
   Masaüstü: ay/hafta grid'i + liste görünümü. Telefon: günlük ajanda.
   ========================================================================== */

.cal-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.cal-nav {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.cal-period {
  min-width: 160px;
  text-align: center;
}

/* Izgaranın iç çizgileri kartın dış çerçevesinden **ince**: ikisi aynı
   ağırlıktayken 42 hücrelik ay, kareli deftere dönüyor ve göz hücreleri
   değil çizgileri tarıyordu (aynı karar tabloda da alındı, bkz. `.table
   td`). Dış çerçeveyi kart çiziyor, ızgaranın kendi üst/sol çizgisi yok. */
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  overflow: hidden;
  border-radius: calc(var(--r-lg) - 1px);
}

.cal-col-head {
  padding: 6px var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--text-secondary);
  text-align: center;
  background: var(--surface-soft);
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border-soft);
}
.cal-col-head:last-child { border-right: 0; }

/* 108 -> 92 px. Hücre üç etkinlik + tarih rozetini taşımak zorunda, daha
   fazlasını değil: dördüncüsü zaten "+N daha"ya düşüyor. Altı satırlık bir
   ayda 16 pikselin altı 96 piksel eder — ızgaranın ilk ekranda bitmesi ile
   bitmemesi arasındaki fark tam olarak bu. */
.cal-cell {
  min-height: 92px;
  padding: 6px;
  border-bottom: 1px solid var(--border-soft);
  border-right: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Son sütun ve son satır kendi çizgisini çizmez: kartın kenarlığı zaten
   orada ve iki çizgi üst üste binince kenar kalınlaşıyordu. */
.cal-grid > .cal-cell:nth-child(7n) { border-right: 0; }

.cal-grid-week .cal-cell { min-height: 220px; }

.cal-cell.is-outside { background: var(--surface-soft); }
.cal-cell.is-outside .cal-cell-date { color: var(--text-muted); }

.cal-cell.is-today { background: var(--brand-softer); }
.cal-cell.is-today .cal-cell-date {
  background: var(--brand);
  color: var(--text-on-brand);
}

.cal-cell-date {
  align-self: flex-start;
  min-width: 22px;
  height: 22px;
  padding: 0 var(--sp-1);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
}
.cal-cell-date:hover { text-decoration: none; background: var(--selected); }
.cal-cell.is-today .cal-cell-date:hover { background: var(--brand-hover); }

.cal-cell-events {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* Etkinlik satırı: 3 pikselik sol vurgu türü, metin işi söyler. Dolgu
   1 piksel inceldi ve ikon 14 pikselde sabitlendi — hücreye üçüncü satır
   ancak böyle sığıyor. */
.cal-event {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 1px 5px;
  /* Sol kenar **düz**: dört köşe birden yuvarlanınca 3 piksellik renkli
     çizgi bir parantez gibi kıvrılıyor ve tür işareti olmaktan çıkıyordu. */
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  border-left: 3px solid var(--brand-border);
  background: var(--brand-softer);
  color: var(--text);
  /* `--fs-xs` (12 px) değil `--fs-sm` (13 px): takvim hücresindeki metin
     ekrandaki en küçük yazıydı, üstelik en çok taranan yerlerden biri —
     kullanıcı gün hücresine "ne vardı" diye bakıyor, okumaya çalışmıyor.
     Bir basamak büyütmek hücre yüksekliğini değiştirmiyor (satır aralığı
     zaten bu boyutu taşıyor) ama satır belirgin biçimde okunur oluyor. */
  font-size: var(--fs-sm);
  min-width: 0;
}
.cal-event:hover { text-decoration: none; background: var(--selected); }
.cal-event .icon { flex: none; color: var(--text-secondary); }

/* Tür renkleri (redesign Faz 3). Üçü de anlam token'ı; palet doğrudan
   okunmaz. Mineral mavi = görev (en sık ve en nötr olan), royal indigo =
   iş teslimi (eylem rengi: teslim bir taahhüttür), antik altın = müşteri
   takibi ("bekleyen, yaklaşan" rengi — takip tam olarak budur).

   Eskiden görev indigo, teslim altın, takip seladondu ve seladon "olumlu
   sonuç" demekti: henüz yapılmamış bir takip başarı rengiyle çiziliyordu. */
/* Kuralların kendisi aşağıda, dolgularla **tek blokta** (bkz. "Izgara
   hücresindeki etkinliğin zemini" notu). Faz 27'ye kadar burada bir şerit
   kuralı, orada bir zemin kuralı vardı: aynı üç seçici dosyanın iki ayrı
   yerinde yaşıyor ve türün rengini değiştirmek iki yerde düzeltme
   istiyordu. Tür artık tek yerde tanımlı. */

.cal-event.is-late {
  /* Gecikme = yanik mercan (`--accent`); kirmizi yikici sonuca (silme, hata)
     saklidir.

     Faz 27: zemin de boyanıyor. Eski gerekçe ("dolu gün hücresi bir uyarı
     duvarına dönüyor") 500 basamağı bir dolgu içindi; sözlüğün `-fill`
     rolü hücre yüzeyine 1.15:1 ile oturuyor ve duvar kurmuyor. Geciken
     kayıt zaten en çok aranan kayıt — onu tür renginden ayıran şeyin
     yalnızca 3 piksel olması azdı.

     Tür kurallarını (0,1,0) **özgüllükle** eziyor; dosyada onlardan önce
     yazılmış olması bilinçli bir güven değil, sadece yerini korumasıdır. */
  border-left-color: var(--state-late);
  background: var(--state-late-fill);
  color: var(--state-late-ink);
  font-weight: 600;
}
.cal-event.is-late .icon { color: var(--state-late-ink); }

.cal-more {
  padding: 2px var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-secondary);
}
.cal-more:hover { text-decoration: none; color: var(--brand); }

.cal-list-day-head {
  padding: var(--sp-2) var(--sp-5);
  font-weight: 700;
  color: var(--text-secondary);
  border-top: 1px solid var(--border);
  background: var(--surface-soft);
}
.cal-list-day-head.is-today { color: var(--brand); }

.cal-day-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
}

.cal-day-title {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}


/* ==========================================================================
   Dokunma hedefleri (Faz 8.5)
   --------------------------------------------------------------------------
   Tasarım sistemi "en az 44 px" diyor ve `--tap` bunun için tanımlı, ama
   ölçüldüğünde altı bileşen bu sınırın altındaydı: küçük düğmeler (36),
   süzgeç rozetleri (34), görev tamamlama düğmesi (32), şifre göster düğmesi
   (38) ve çoklu seçim kutucukları (13-18). Kurallar tek tek yazıldığı için
   her biri kendi başına makul görünüyordu; sınırın altında olduklarını ancak
   hepsi birden ölçülünce fark ettik.

   Sorgu genişliğe değil **işaretleme aygıtına** bağlı. Dar bir masaüstü
   penceresi fareyle kullanılıyorsa 36 px düğme sorun değil; geniş bir tablet
   parmakla kullanılıyorsa sorundur. `max-width` sorsaydık ikisini de yanlış
   yanıtlardık.

   Görünen boyut çoğunlukla değişmiyor: dairesel görev düğmesi ile şifre
   düğmesinin *görünürü* aynı kalıp yalnız dokunma alanı büyüyor. Bir tik
   kutusunu 44 px çizmek arayüzü şişirirdi; 44 px'lik alanı ona vermek
   yetiyor.
   ========================================================================== */

@media (pointer: coarse) {
  /* `min-width` yalnız 44 px'den dar olan düğmeyi etkiler, yani yazılı
     düğmeler olduğu gibi kalır; büyüyen tek şey takvimin ay/gün okları ve
     daveti yeniden gönder gibi salt ikonlu düğmeler. Yükseklik tek başına
     yetmiyordu: bunlar 42x44'tü ve yanlarında başka düğme vardı. */
  .btn-sm { min-height: var(--tap); min-width: var(--tap); }

  /* Sekme şeridi: yükseklik 44 ama kısa etiketli sekme ("İşler") 34 px
     genişliğinde kalıyordu. Yatay dolgu ile eşiğe çıkar; şerit zaten
     kaydırılabilir olduğu için taşma riski yok. */
  .tab-link { padding: 0 var(--sp-2); min-width: var(--tap); justify-content: center; }

  /* Görünen daire 32 px kalır, dokunulan alan 44 px olur. */
  /* `.password-toggle` zaten `position: absolute`; burada `relative`
     verilmesi onu akışa geri sokup daraltıyordu (38 -> 34 px). Konumlanmış
     olması sözde öğe için de yetiyor, dokunulmuyor. */
  .task-check {
    position: relative;
  }
  .task-check::after,
  .password-toggle::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--tap);
    height: var(--tap);
    transform: translate(-50%, -50%);
  }

  /* Satır 44 px yüksekliğindeydi ama tıklanan etiket 23 px'ti: aradaki
     boşluğa dokunmak hiçbir şey yapmıyordu. Etiket satırı doldursun. */
  ul.choice-group > li > label {
    display: flex;
    align-items: center;
    align-self: stretch;
    min-height: var(--tap);
  }

  /* Metin yanında duran tekil kutucuklar (ör. "Üste sabitle"): tarayıcı
     varsayılanı 13 px. Kutunun kendisi büyümese de etiketi hedef olur. */
  label:has(> input[type="checkbox"]),
  label:has(> input[type="radio"]) {
    min-height: var(--tap);
    align-items: center;
  }

  /* Ayrıntı ekranındaki telefon, e-posta ve web sitesi bağlantıları.
     Telefonda bunlar birincil dokunma hedefi — numaraya dokunup aramak
     ekranın var oluş sebeplerinden biri — ama satır yüksekliği 19 px'ti.
     Burada dokunma alanını görünmez biçimde büyütmek yetmez: komşu
     satırların bağlantıları arasında yalnız 12 px boşluk var, büyüyen iki
     alan üst üste binerdi. Satırın kendisi büyüyor; etiket de onunla
     hizalansın diye ortalanıyor. */
  .detail-row:has(> dd > a) { align-items: center; }
  .detail-row > dd > a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
  }

  /* Görev satırındaki başlık bağlantısı. Altındaki üstbilgi satırı
     tıklanabilir değil, o yüzden alan büyütmek komşu bir hedefi
     çalmıyor; satır yüksekliği de değişmiyor. */
  .task-main > a { position: relative; }
  .task-main > a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: var(--tap);
    transform: translateY(-50%);
  }

  /* (Faz 6 — etkin süzgeç çipleri düz metne indi; dokunulacak bir hedef
     kalmadı. Satırın tek bağlantısı "Temizle" ve o `.xsmall` kuralıyla
     zaten aşağıdaki genel eşiğe giriyor.) */

  /* Cümle içindeki sekme çapraz göndermesi ("... İşlem geçmişi sekmesine
     bakın"). Metin akışındaki bir bağlantıyı kutu olarak büyütmek satır
     yüksekliğini bozar; görünmeyen alan büyür, yazı olduğu yerde kalır.
     Paragraf tek bağlantı içerdiği için komşu hedef çalınmıyor. */
  .tab-crossref { position: relative; display: inline-block; }
  .tab-crossref::after {
    content: "";
    position: absolute;
    left: -4px;
    right: -4px;
    top: 50%;
    height: var(--tap);
    transform: translateY(-50%);
  }
}

/* Varsayılan 13 px kutucuk her aygıtta küçük. Çoklu seçim listesindeki
   ölçüyle (18 px) aynı hizaya getirilir. */
input[type="checkbox"],
input[type="radio"] {
  width: 18px;
  height: 18px;
  accent-color: var(--brand);
}

/* --------------------------------------------------------------------------
   Liste araç çubuğu ve süzgeç katmanı (Faz 10)
   --------------------------------------------------------------------------
   Önceki düzende süzgeçler sayfanın akışındaydı: masaüstünde sekmeler,
   arama, durum çipleri ve (işlerde) kapsam çipleri dört ayrı sıra kaplıyor,
   telefonda açılan panel listeyi aşağı itiyordu. Veriden önce gelen kontrol
   yüksekliği geniş ekranda bile 300 pikseli geçiyordu.

   Yeni kural: **tek kompakt araç çubuğu** — arama · sıralama · Filtreler ·
   yeni kayıt — ve süzgeçler onun üstünde *yüzen* bir katmanda:

     · Masaüstü — düğmeye bağlı popover (`position: absolute`). Açılması
       sayfadaki hiçbir şeyi kaydırmaz.
     · Telefon  — perdeli, alttan açılan panel (bottom sheet).

   Tek işaretleme iki düzeni de besler; fark yalnız burada.
   -------------------------------------------------------------------------- */

.filters-shell { display: flex; flex-direction: column; min-width: 0; }

/* Araç çubuğunun liste ekranındaki hâli. `.toolbar` başka yerlerde de
   kullanıldığı için kural kabuğa bağlanır, çubuğun kendisine değil. */
.filters-shell > .toolbar {
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  /* **Sarmaz.** Flex satırı, öğelerin *esneyebilir* değil *varsayılan*
     genişliğine bakarak kırılır: arama kutusunun 220 px'lik `flex-basis`i,
     kutu 140 px'e daralabilecekken bile satırı taşırmış sayılıyordu. 900
     ile 1100 px arasında sonuç şuydu — sağdaki üçlü (Sektör · Filtreler ·
     Yeni firma) tek satıra sığmıyor, en sondaki "Yeni firma" tek başına
     alta düşüyor ve çubuk iki katlı, dengesiz bir şeye dönüşüyordu.

     Sarmalamayı kapatınca kırılacak bir satır kalmaz: dar gelen genişliği
     yalnız arama kutusu öder (tek `flex-shrink` sahibi o), kontroller
     yerinde kalır. Telefonda zaten böyleydi; kural artık her ölçüde
     geçerli, çünkü gerekçesi ölçüye değil çubuğun kendisine ait. */
  flex-wrap: nowrap;
}

/* Arama sola yapışır, kontroller sağa: aradaki boşluk görünmez bir öğedir.
   Telefonda kaybolur, yoksa tek başına bir satır kaplardı. */
.toolbar-gap { flex: 1 1 auto; min-width: 0; }

/* Sarmayan çubukta daralma **tek bir öğenin** işidir: arama kutusunun.
   Düğmeler ve süzgeç yuvaları esnemez — daralan bir "Yeni firma" ikonunu
   kırpar, daralan bir arama kutusu yalnız daha az yer tutar. */
.filters-shell > .toolbar > .btn,
.filters-shell > .toolbar > .sector-dock { flex: 0 0 auto; }

/* --- Süzgeç düğmesi ---------------------------------------------------- */

.filter-dock { position: relative; flex: 0 0 auto; }
.filter-btn[aria-expanded="true"] { border-color: var(--brand); color: var(--brand); }
/* Etkin süzgeç, paneli kapalıyken de belli olur: sınır marka rengine döner
   ama metin nötr kalır — açık panelin (yukarıdaki kural) iki kanalı varken
   bunun bir kanalı var, ikisi karışmıyor. Dolu bir zemin kullanılmadı:
   başlık şeridinde tek bir ikincil düğme, yanındaki birincil "Yeni kayıt"
   ile yarışmamalı. */
.filter-btn.is-on { border-color: var(--brand-border); }
.filter-btn.is-on .icon { color: var(--brand); }
/* Sayı düğmenin *içinde* durur ("Filtreler 3"): ayrı bir rozet, düğmenin
   yanında ikinci bir nesne gibi okunuyordu. */
.filter-btn .count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--brand);
  color: var(--text-on-brand);
  font-size: var(--fs-xs);
  font-weight: 700;
}

/* --- Başlık satırının taşma menüsü (Faz 11) ---------------------------
   Telefonda ikincil eylemler ("Toplu ekle", "Görev") üç noktanın arkasına
   girer. Panel `position: fixed`: `data-menu-anchor` ile `app.js`
   konumlandırır, satır menüsüyle ve süzgeç açılırıyla aynı gerekçe. */
.over-menu { position: relative; flex: none; }
.over-menu-panel {
  position: fixed;
  top: auto;
  right: auto;
  z-index: 60;
  min-width: 220px;
}

/* Betik yokken düğme hiçbir şey açmaz. Menü kaybolmaz, **düzleşir**:
   tetikleyici gizlenir, öğeler başlık satırına olduğu gibi iner. Yoksa
   betiksiz telefonda "Toplu ekle" hiç ulaşılamaz olurdu — düğmesi
   `hide-mobile`, menüsü de kapalı. */
html:not(.js) .over-menu > .btn { display: none; }
html:not(.js) .over-menu-panel {
  position: static;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  animation: none;
}
html:not(.js) .over-menu-panel[hidden] { display: block !important; }

/* Telefonda çubuk tek satırdır (`flex-wrap: nowrap`), ama betik yokken
   süzgeç paneli yüzen katman olmaktan çıkıp kendi satırına iner — o zaman
   sarmalama geri gelmeli, yoksa panel çubuğa sıkışırdı. */
html:not(.js) .filters-shell > .toolbar { flex-wrap: wrap; }


/* --- Panel: telefonda sheet, masaüstünde popover ------------------------

   Buradaki kurallar **taban**dır ve telefonun kabuğunu çizer: perdeli,
   alttan açılan bir yüzey. Perde `.filter-pop`un kendisidir ve
   `data-menu-backdrop` sayesinde tıklanınca kapanır (app.js).

   Faz 18 bu kabuğu her genişliğe almış, masaüstünde ortalanmış bir kip
   yapmıştı; gerekçesi eski popover'ın iki kusuruydu (sağ kenara yapışması,
   boyunun düğmenin yerine bağlı olması). Faz 19 kusurları kaynağında
   çözüp popover'a döndü — aşağıdaki `min-width: 900px` bloğu ve app.js'teki
   `popoverMu`. Süzgeç listenin üstünde çalışır; onu seçerken listeyi
   perdelemek, kullanıcıyı sonucu görmeden karar vermeye zorluyordu. */

.filter-pop {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-7);
  background: var(--overlay);
  animation: fade-in var(--dur-2) var(--ease-out) both;
}
.filter-pop[hidden] { display: none; }
.filter-pop-panel {
  width: min(420px, 100%);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  animation: pop-in var(--dur-2) var(--ease-out) both;
  /* Faz 18: yükseklik artık düğmenin yerine bağlı değil — kip ortada
     duruyor, ölçüsünü pencereden alıyor. `--filter-pop-max` değişkeni
     betiğin yazdığı bir ölçüydü (`filtrePaneliSigdir`); kaldırıldı,
     çünkü ortalanmış bir kipte "üstümde ne kadar yer kaldı" sorusunun
     karşılığı yok. */
  max-height: min(calc(100dvh - 2 * var(--sp-7)), 620px);
}
.filter-pop-head { flex: none; }
.filter-pop-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.filter-pop-title { flex: 1 1 auto; font-size: var(--fs-sm); font-weight: 700; }
/* Faz 18: her genişlikte görünür. Panel artık düğmesine tutturulmuş bir
   popover değil, perdeli bir kip — kipin kapatma düğmesi olur. Eskiden
   masaüstünde gizliydi, çünkü panelin yanındaki her yer tıklanabilir bir
   sayfaydı; şimdi perde var ve "buradan nasıl çıkılır" sorusunun görünür
   bir cevabı olmalı. */
.filter-pop-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) 0;
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
}
.filter-pop-close:hover { color: var(--text); }
/* Gövde kaydırılır, ama **kaydırıldığı belli olmalı**.

   Eski ölçüde (`min(60vh, 460px)`) panel üçüncü bölümün başlığını tam
   ortadan kesiyordu: ekranda "DURUM" yazısının yalnız üst yarısı kalıyor,
   kaydırma çubuğu da (overlay scrollbar) durağan hâlde çizilmediği için
   kullanıcı bunu "yarısı açılmış, bozuk bir panel" olarak okuyordu.

   İki şey birlikte düzeltir:

   1. **Sınır yükseldi.** Pencere ne kadar yer veriyorsa o kadar; ilk iki
      bölüm artık bütünüyle sığıyor.
   2. **Kaydırma gölgesi.** Üstte/altta kalan içerik soluk bir geçişle
      biter. Gölge `background-attachment: local` ile içerikle birlikte
      kayar: içerik bittiğinde kendiliğinden kaybolur, yani "aşağıda daha
      var" ile "bitti" ayrımı hiçbir betik olmadan görünür. */
.filter-pop-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-4);
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Faz 31 — kaydırmanın **görünür** işareti.

     Gölge tek başına yetmiyordu: panel beş gruba çıkınca alt kenardaki
     soluk geçiş "liste burada bitti" diye de okunabiliyor ve kullanıcı
     kaydırmayı hiç denemiyor. İnce ama görünür bir çubuk, "aşağıda daha
     var" cümlesini belirsizlik bırakmadan söyler.

     `overscroll-behavior: contain`: panelin sonuna gelindiğinde kaydırma
     arkadaki sayfaya **zincirlenmez**. Zincirlendiğinde panel açıkken
     tekerleği çevirmek listeyi kaydırıyor, panel yerinde duruyor ve
     ekranda "kaydırma çalışmıyor" hissi doğuyordu. */
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
  scrollbar-gutter: stable;
  overscroll-behavior: contain;
  background:
    linear-gradient(var(--surface) 40%, transparent) top / 100% 26px,
    linear-gradient(transparent, var(--surface) 60%) bottom / 100% 26px,
    radial-gradient(farthest-side at 50% 0, var(--scroll-shadow), transparent) top / 100% 11px,
    radial-gradient(farthest-side at 50% 100%, var(--scroll-shadow), transparent) bottom / 100% 11px;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
}
.filter-pop-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--border);
  flex: none;
}

/* --- Gruplar ve seçenekler --------------------------------------------- */

.filter-group { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.filter-group-title {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
}
/* Faz 6: seçenekler sarmalanan haplar değil **alt alta satırlar**.

   Üç grup (sıralama · görünüm · durum) üst üste üç hap bulutu çiziyordu.
   Sarmalanan haplarda grubun nerede bittiği okunmuyor, satır sayısı seçenek
   uzunluğuna göre her ekranda değişiyor ve seçili hap — ters kontrastlı dolu
   yüzey — panelin en baskın nesnesi oluyordu; oysa panelde baskın olması
   gereken tek şey "Sonuçları göster" düğmesidir.

   Alt alta satırda grup sınırı kendiliğinden görünür, uzun etiket kırpılır
   ve seçim satır başındaki işaretle anlatılır. */
.filter-opts { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

/* Bölüm başlığı artık bir `summary`. Masaüstünde panel zaten kısa ve bütün
   bölümler açık durur; orada başlık **bugünkü gibi** düz bir etiket gibi
   davranmalı — tıklanmaz, imleç değişmez, ok işareti çizilmez. Dar ekranda
   ise gerçek bir denetimdir: dokunma hedefi tam boy ve dönen bir ok taşır.
   Ok `.more-fields > summary` ile aynı dil (bkz. aşağıdaki Faz 5 bloğu);
   kopyalanmasının nedeni iki bileşenin farklı punto ve renkte olması. */
.filter-group > summary { list-style: none; cursor: pointer; }
.filter-group > summary::-webkit-details-marker { display: none; }

@media (min-width: 900px) {
  .filter-group > summary { pointer-events: none; cursor: default; }
}

@media (max-width: 899px) {
  .filter-group > summary {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    min-height: var(--tap);
  }
  .filter-group > summary::before {
    content: "";
    flex: none;
    border: 5px solid transparent;
    border-left: 5px solid currentColor;
    transition: transform var(--dur-2) var(--ease-out);
  }
  .filter-group[open] > summary::before { transform: rotate(90deg); }
  /* Kapalı bölüm yalnız başlığı kadar yer kaplamalı. `<details>` burada bir
     flex kolon ve `row-gap: 8px`, kapalıyken bile `summary` ile (gizli)
     içerik yuvası arasına o boşluğu koyuyor: dört kapalı bölüm 32 piksel
     boş şerit demekti ve panel, başlıkları birbirinden kopmuş gibi
     gösteriyordu. */
  .filter-group:not([open]) { gap: 0; }
  .filter-group > summary:focus-visible {
    box-shadow: var(--focus-ring);
    border-radius: var(--r-sm);
  }
}

/* Girdi gizlenir ama **silinmez**: `display: none` onu sekme sırasından da
   çıkarır, süzgeçler klavyeyle seçilemez olurdu. Ölçü kuralı
   `input[type="radio"]` kadar belirgin yazılmak zorunda — genel kural
   18x18 dayatıyor ve gizli kutucuk paneli aşağı itiyordu.

   İki tür de tek tek yazılıyor: `.filter-opt-input` tek başına (0,1,0)
   özgüllüğünde kalır ve genel `input[type="checkbox"]` kuralını (0,1,1)
   yenemez. Onay kutusu unutulduğunda sektör seçicisindeki kutular gerçekten
   ekrana çiziliyordu — etiketin yanında ikinci, işlevsiz bir kare. */
input[type="radio"].filter-opt-input,
input[type="checkbox"].filter-opt-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.filter-opt {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: 34px;
  padding: 0 var(--sp-2);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out),
              color var(--dur-1) var(--ease-out);
}

/* Görünür seçim işareti. Gerçek `input` görsel olarak gizli (yukarıdaki
   kural) ama satırda seçilebilirliği anlatan bir şey kalmalıydı: hap
   gidince "bu satır tıklanabilir mi?" sorusu ortada kaldı.

   Biçim türü söyler — radyoda daire ("biri"), onay kutusunda kare
   ("birden çok"). Girdinin türü etikete sınıf olarak yazılıyor, çünkü CSS
   kardeşin türüne bakıp **etiketi** biçimlendiremez. */
.filter-opt::before {
  content: "";
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--border-strong, var(--border));
  background: var(--surface);
  transition: border-color var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out);
}
.filter-opt.is-radio::before { border-radius: 50%; }
.filter-opt.is-check::before { border-radius: 4px; }

.filter-opt:hover { background: var(--surface-soft); color: var(--text); }
.filter-opt .truncate { min-width: 0; flex: 1 1 auto; }
/* Sayı sağa yaslanır: satırlar alt alta olduğu için sayılar da bir kolon
   oluşturur ve "hangi durumda kaç kayıt var" dikey taranabilir. */
.filter-opt .count { margin-left: auto; flex: 0 0 auto; opacity: 0.7; font-weight: 500; }

/* Seçili süzgeç **renkle değil, kontrastla** işaretlenir (Faz 2): panelde
   yan yana duran dört marka renkli çip, araç çubuğundaki birincil düğmeyle
   aynı ağırlıkta görünüp "burada eylem var" diyordu.

   Faz 6: dolu koyu yüzey de bırakıldı. Alt alta beş satırın birinde tam
   kontrastlı bir blok, listede bir "delik" gibi okunuyordu. Artık işareti
   işaret taşıyor; satır yalnız hafifçe vurgulanır ve yazı koyulaşır. */
.filter-opt-input:checked + .filter-opt {
  background: var(--selected, var(--surface-soft));
  color: var(--text-primary);
  font-weight: 600;
}
.filter-opt-input:checked + .filter-opt::before {
  border-color: var(--brand);
  background: var(--brand);
  /* İç boşluk, işaretin "dolu" görünmesini sağlayan tek şey: ayrı bir tik
     ikonu çizmek yerine kutunun içine kendi zemin rengini basıyoruz. */
  box-shadow: inset 0 0 0 3px var(--surface);
}
.filter-opt-input:checked + .filter-opt .count { opacity: 0.8; }
.filter-opt-input:focus-visible + .filter-opt {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

/* --- Aranabilir çoklu seçim (Faz 6) ------------------------------------- */

.filter-picker { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }

/* `.needs-js` ortak kuralı `inline-flex` dayatıyor; arama kutusu ise
   `.input-wrap`in konumlandırma kabı olmak zorunda. Birleşik seçici iki
   kuralı da tek yerde uzlaştırır — hangisinin kazandığını dosya sırasına
   bırakmamak için. */
.js .filter-picker-search.needs-js { display: block; }
.filter-picker-search .input { width: 100%; max-width: none; }

/* Kendi kaydırma alanı var: panel gövdesi zaten kaydırılabilir ama iki
   yüzlerce satırlık bir sektör listesi, altındaki grupları erişilemez
   kılardı. */
.filter-picker-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: 240px;
  overflow-y: auto;
  /* Kaydırma zinciri burada **kesilir**. Liste, kendisi de kayan bir panel
     gövdesinin içinde duruyor (telefonda üstüne bir de alttan açılan sheet
     biniyor): parmak listenin dibine geldiğinde sıra bir üstteki yüzeye
     geçiyor ve kullanıcı sektör seçerken panelin tamamını kaydırıyordu. */
  overscroll-behavior: contain;
  min-width: 0;
}
.filter-picker-empty {
  margin: 0;
  padding: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* Kendi açılırının içindeyken grup başlığı gereksiz: panelin başlığı zaten
   "Sektör" diyor ve hemen altında ikinci kez yazmak aynı kelimeyi iki
   basamakta tekrarlamak olurdu. Ana süzgeç panelinde ise başlık **şart** —
   orada sektör, diğer grupların arasındaki bir grup. Ayrım işaretlemede
   değil yerde olduğu için kural da yere bağlanıyor. */
[data-sector-pop] .filter-group-title { display: none; }

/* --------------------------------------------------------------------------
   Etkin süzgeç etiketleri — araç çubuğunun altında, tek satırda.

   Sarmalanan satır listeyi aşağı itiyordu: dört süzgeç seçiliyken etiketler
   üç sıra kaplıyor, tablo ekranın altına kayıyordu. Satır artık sabit
   yükseklikte; sığmayan etiketlere yatay kaydırmayla ulaşılır.
   -------------------------------------------------------------------------- */

.active-filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-4);
  min-width: 0;
}
/* Faz 19: tek satır düz metin yerine **kaldırılabilir** sakin etiketler.

   Faz 6 çipleri kaldırmıştı ve gerekçesi hâlâ geçerli: marka renkli, dolgulu,
   çerçeveli bir çip kümesi satırı listeden önce gelen ikinci bir araç
   çubuğuna çeviriyor. Kaldırma geri geldi ama çip geri gelmedi — etiket
   dolgusuz, ikincil renkte ve yalnız 1px çerçeveli. Göz onu bir düğme
   kümesi değil, bir *not* olarak okur; üstüne gelince çerçeve koyulaşıp
   tıklanabilir olduğunu söyler.

   Genişlik sınırı var: uzun bir arama metni ("Arama: ...") tek başına satırı
   yiyip diğer süzgeçleri kaydırmanın arkasına itiyordu. */
.active-filter-list {
  flex: 1 1 260px;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.active-filter {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  max-width: 30ch;
  padding: 2px var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  text-decoration: none;
}
.active-filter .icon {
  flex: none;
  width: 12px;
  height: 12px;
  opacity: 0.55;
}
.active-filter:hover,
.active-filter:focus-visible {
  border-color: var(--border-strong);
  color: var(--text);
}
.active-filter:hover .icon,
.active-filter:focus-visible .icon { opacity: 1; }

/* Dokunmatikte etiket aynı zamanda bir hedeftir; 12px'lik çarpıyı değil
   etiketin tamamını nişan alıyoruz, o yüzden yüksekliği parmağa açılır. */
@media (pointer: coarse) {
  .active-filter { min-height: 32px; }
}

.active-filters-clear {
  flex: 0 0 auto;
  color: var(--text-secondary);
  text-decoration: underline;
  white-space: nowrap;
}

/* "Kayıtlı görünüm" rozeti — süzgeçlerin önceki tercihten geldiğini söyler.
   Özet metniyle karışmasın diye kenarlığı yok, dolgusu yok: sessiz bir etiket.
   Tıklanınca tercihi sıfırladığı için hover'da altı çizilir. */
.saved-view {
  flex: 0 0 auto;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  white-space: nowrap;
  text-decoration: none;
}
.saved-view:hover,
.saved-view:focus-visible { color: var(--text); text-decoration: underline; }

/* --- Masaüstü: düğmeye bağlı geniş popover (Faz 19) --------------------

   `.filter-pop` burada perde olmaktan çıkıp **konumlanan kutunun kendisi**
   olur: `inset` serbest bırakılır, `left/top` (ya da devrilmişse `bottom`)
   ve `max-height` app.js'teki `konumlaMenu` tarafından yazılır. Yatayda 8px
   kenar payıyla kırpılır, dikeyde yer yoksa yukarı devrilir.

   Kutu flex kolondur ve boyu üstten kırpıldığı için içteki `.filter-pop-panel`
   büzülebilmelidir: `max-height` tabanı burada kaldırılır, sığdırmayı dış
   kutu yapar, gövde kendi içinde kayar. Böylece "Sonuçları göster" hangi
   yükseklikte açılırsa açılsın görünür kalır. */
@media (min-width: 900px) {
  .filter-pop {
    inset: auto;
    display: flex;
    flex-direction: column;
    /* 420px'lik kip genişliği uzun durum/sektör etiketlerini iki satıra
       kırıyordu; popover listeyi perdelemediği için daha geniş olabilir. */
    width: min(30rem, calc(100vw - 2 * var(--sp-4)));
    padding: 0;
    background: none;
    animation: none;
  }
  .filter-pop-panel {
    width: 100%;
    min-height: 0;
    max-height: none;
  }
  /* Faz 31 — kaydırmanın tabanı **CSS'te**, betikte değil.

     Yukarıdaki kural panelin kendi yükseklik sınırını kaldırıyor ve
     sığdırmayı dış kutuya bırakıyor; dış kutunun ölçüsünü ise `app.js`
     yazıyor. Yani "panel ekrana sığıyor mu?" sorusunun cevabı tek bir
     betik satırına bağlıydı: o ölçü yazılmadığı (ya da pencereye göre
     fazla geldiği) anda panel serbestçe uzuyor, gövde hiç taşmadığı için
     `overflow-y: auto` da devreye girmiyordu — süzgeç listesi uzayınca
     alttaki gruplar ve "Sonuçları göster" düğmesi erişilemez hale geldi.

     Sınır artık kaydırılan öğenin kendisinde: gövde en fazla ekranın
     yarısından biraz fazlası kadar uzar, gerisi kayar. Betiğin yazdığı
     daha dar ölçü hâlâ geçerli (flex zaten küçültür); bu yalnız taban. */
  .filter-pop-body { max-height: 62dvh; }
}


/* --- Telefon: panel alttan açılır -------------------------------------- */

@media (max-width: 899px) {
  /* Telefonda kip ortada değil **altta**: başparmağın olduğu yer orası ve
     klavye açıldığında ortalanmış bir kutu yukarı sıkışırdı. */
  .filter-pop {
    align-items: flex-end;
    padding: 0;
  }
  .filter-pop-panel {
    width: 100%;
    max-height: 85dvh;
    border: 0;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    animation-name: sheet-in;
    animation-duration: var(--dur-3);
  }
  .filter-pop-head { padding: var(--sp-4) var(--sp-4) var(--sp-3); }
  .filter-pop-title { font-size: var(--fs-md); }
  .filter-pop-body { flex: 1 1 auto; max-height: none; }
  .filter-pop-foot { padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom)); }
  .filter-pop-foot .btn { min-height: var(--tap); }

  /* --- Telefonda çubuk: arama + filtre + artı ---------------------------
     Eski hâlinde altı öğe vardı (toplu ekle · arama · Ara · sıralama ·
     filtre · Yeni) ve 360 px'te dört satıra sarıyordu: listeden önce 190
     pikselden fazla kontrol. Üçü buradan çıktı — toplu ekleme başlıktaki üç
     nokta menüsüne, sıralama süzgeç paneline, "Ara" masaüstüne. Kalan üçü
     tek satıra sığar, bu yüzden sarmalama da kapatılır: sarmalama açıkken
     uzun bir yer tutucu metni arama alanını taşırıp düğmeleri alta
     atabiliyordu. */
  /* (Sarmalama kapalı olması artık her ölçüde geçerli — gerekçe yukarıda,
     `.filters-shell > .toolbar`.) */
  .toolbar .search-field { flex: 1 1 auto; max-width: none; }
  /* Boşluk öğesi telefonda tek başına bir satır kaplardı. */
  .toolbar-gap { display: none; }

  /* Süzgeç düğmesi ikona iner. Etiket `display: none` ile değil kırpılarak
     gizlenir (`.visually-hidden` ile aynı bildirimler): düğmenin erişilebilir
     adı her ölçüde "Filtreler" kalmalı, yoksa ekran okuyucuya yalnız bir
     ikon kalırdı. Sayı görünür durur — düğme ikona inince "açık süzgeç var
     mı?" sorusunu yanıtlayan tek şey o. */
  .filter-btn {
    flex: none;
    min-width: var(--tap);
    padding: 0 var(--sp-3);
  }
  .filter-btn .filter-btn-text {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  /* Panodaki dönem düğmesi bu kuralın **istisnasıdır**: etiketi işlevin
     adını ("Filtreler") değil **seçili değeri** taşıyor. Kırpılsaydı
     telefonda hangi dönemin seçili olduğunu söyleyen hiçbir şey kalmazdı —
     oysa bu bilgi, panelin kapalı hâlinde de okunabilir olmalı (eski
     `.range-head` satırının tek işi buydu).

     Sıkışıklık gerekçesi de burada geçerli değil: liste araç çubuğunda üç
     öğe yarışıyordu, bu satırda başlık ve tek bir düğme var. Dar ekranda
     düğme kendi satırına iner (`.dash-head` kuralı), böylece başlık da
     kırpılmaz. */
  .range-dock .filter-btn .filter-btn-text {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip: auto;
  }

  /* "Yeni" tek başına neyin yeni olduğunu söylemiyordu ve kısaltıldığı hâlde
     yanındaki iki düğme kadar yer kaplıyordu. Telefonda yuvarlak bir artı
     olur: adı `aria-label` ve `title` ile durur, yani ekran okuyucu ve
     uzun basış ikisi de "Yeni firma" der. Yuvarlak biçim bilerek — sayfanın
     tek asıl eylemi, diğer iki düğmeden şekliyle de ayrılmalı. */
  /* Telefonda araç çubuğunun "Yeni …" düğmesi yuvarlak bir ikona iner.
     Alt sekme çubuğunun ortasındaki genel "yeni kayıt" düğmesi de dolu
     indigo bir daire: ikisi aynı ekranda yan yana durunca iki özdeş
     birincil eylem görünüyor ve hangisinin ne yarattığı okunmuyordu.

     Bu düğme **bağlamsal** ("bu listeye yeni kayıt"), alttaki genel. O
     yüzden aynı rengin sakin tonuna iner: yeri, ölçüsü ve hedefi
     değişmez — ekranda dolu daire tek kalır. */
  .toolbar-new {
    flex: none;
    width: var(--tap);
    min-width: var(--tap);
    height: var(--tap);
    padding: 0;
    border-radius: 50%;
  }
  .toolbar-new.btn-primary {
    background: var(--brand-soft);
    color: var(--brand);
    box-shadow: none;
  }
  .toolbar-new.btn-primary:hover { background: var(--brand-border); }

}

@media (pointer: coarse) {
  /* Seçenekler artık tam genişlikte satır: yüksekliği eşiğe çıkarmak satır
     aralarını açmıyor, çünkü yan yana durmuyorlar. (Faz 6'da çip
     kalıbındaki görünmez `::after` dokunma alanı ve etkin süzgeç çipleriyle
     ilgili kurallar buradan kaldırıldı — ikisi de artık yok.) */
  .filter-opt { min-height: var(--tap); }
  .range-preset { min-height: var(--tap); }

  /* Özet satırının iki bağlantısı. Çipler düz metne inince "Temizle"
     süzgeci kaldırmanın **tek** yolu oldu ve artık tek süzgeçte de
     çiziliyor; ölçüm turunda 42x19 px ile eşiğin altında çıktı.

     Görünen yazı büyütülmez — satır tek sıra kalmalı, yoksa listeden önce
     gelen kontrol yüksekliği yine artar. Büyüyen, `::after` ile serilen
     görünmez alan. Satırdaki iki bağlantı arasında `--sp-3` boşluk var,
     yani 44 px'lik alanlar üst üste binmiyor. */
  .active-filters-clear,
  .saved-view { position: relative; }
  .active-filters-clear::after,
  .saved-view::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: var(--tap);
    transform: translateY(-50%);
  }
}

/* --- Betik yokken -------------------------------------------------------
   Süzgeçsiz bir liste ekranı bırakılmaz. `html.js` yoksa panel yüzen katman
   olmaktan çıkar, araç çubuğunun altına kendi satırına yerleşir ve açık
   kalır; düğme de anlamsızlaştığı için gizlenir. İçerideki alanlar gerçek
   radyo düğmeleri olduğu için "Uygula" betiksiz de çalışır. */

html:not(.js) .filter-btn { display: none; }
/* `order` bilerek: panel kendi satırına inerken "Yeni kayıt" düğmesini
   de altına itiyordu — düğme çubuğun sonunda kalmalı. */
html:not(.js) .filter-dock { flex: 1 1 100%; position: static; order: 9; }
html:not(.js) .filter-pop {
  position: static;
  inset: auto;
  display: block;
  /* Kipin perde boşluğu da geri alınır: satır içinde duran bir panelin
     etrafında 32 piksellik bir çerçeve, araç çubuğundan kopuk görünürdü. */
  padding: 0;
  background: none;
  animation: none;
}
html:not(.js) .filter-pop[hidden] { display: block !important; }
html:not(.js) .filter-pop-panel {
  width: 100%;
  max-height: none;
  border-radius: var(--r-md);
  box-shadow: none;
  animation: none;
}
html:not(.js) .filter-pop-panel { max-height: none; }
html:not(.js) .filter-pop-body { max-height: none; }
html:not(.js) .filter-pop-close { display: none; }

/* (Faz 6 — "katlanan panel" (`.filter-panel` / `data-filter-panel`) silindi.
   Geriye kalan tek kullanıcısı panonun dönem seçicisiydi; o da liste
   ekranlarıyla aynı `.filter-pop` açılırına geçti. İki ayrı açılır dili
   tutmanın bir gerekçesi kalmamıştı.) */

/* Müşteriyi potansiyele döndürme: kapalı, açıklamalı, onaylı işlem.
   Süreç kutusunun geri kalanından ayrılsın diye üstten çizgiyle ayrılır —
   yanlışlıkla "bir alan daha" gibi okunmamalı. */
/* Şeridin son öğesi: sağa yaslanır, kapalıyken tek satır yer tutar.
   Açıldığında kendi satırına iner ve üstünde bir ayırıcıyla ayrılır —
   yıkıcıya yakın bir eylem, sıradan alanların arasına karışmamalı. */
.revert-block { margin-left: auto; align-self: center; }
.rec-strip > .revert-block[open] {
  flex: 1 1 100%;
  margin-left: 0;
  border-top: 1px solid var(--border);
  padding-top: var(--sp-3);
}
.revert-block > summary { list-style: none; cursor: pointer; }
.revert-block > summary::-webkit-details-marker { display: none; }
.revert-form { margin-top: var(--sp-3); max-width: 520px; }
/* Faz 17: üç satır içi `style` buradan sınıfa taşındı. Kural aynı, yeri
   değişti — satır içi stil, tema değişkenlerini okuyamadığı ve koyu temada
   sessizce eskidiği için bu dosyada yeri yok. */
.revert-text { margin: 0; }
.revert-check { gap: var(--sp-2); align-items: flex-start; }
.rec-quick-note { margin: 0; }
/* Yüzeyin içindeki açıklama satırı da bir satırdır (bkz. `.task-list > p`). */
.list > p.list-row { margin: 0; }

/* --- Firmadaki kişiler (Faz 40) -------------------------------------------
   Blok bir `<details>`: firmaların çoğunda tek muhatap var ve rehber orada
   sürekli açık durursa Bilgiler sekmesinin yarısını boş bir kutu yer.
   Kapalıyken tek satır, açıkken kendi listesi (gerekçe: `company_detail.html`).

   `summary` bir düğme gibi okunmalı ama düğme **değil**: tarayıcının kendi
   açma/kapama davranışı betiksiz de çalışıyor. Bu yüzden yalnız imleç ve
   ok döndürmesi ekleniyor; varsayılan üçgen işaretçi (`list-style`) iki
   tarayıcıda iki farklı yerde çizildiği için kendi okumuzla değiştiriliyor. */
.person-block {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}
.person-summary {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3);
  cursor: pointer;
  list-style: none;
  font-weight: 600;
}
.person-summary::-webkit-details-marker { display: none; }
.person-summary:hover { background: var(--surface-soft); }
.person-summary-title { margin-right: var(--sp-1); }
/* Ok her zaman sağ uçta ve açıkken yukarı bakar: bloğun durumu başlığa
   bakınca anlaşılmalı, tıklayıp denemeye gerek kalmadan. */
.person-caret {
  margin-left: auto;
  color: var(--text-muted);
  transition: transform 120ms ease;
}
.person-block[open] > .person-summary > .person-caret { transform: rotate(180deg); }
/* "Kişi ekle" başlık satırının sağ ucunda, okun önünde: rehber kapalıyken
   de görünür. Başlık kalın; düğme kendi ağırlığını korusun. */
.person-summary-add { margin-left: auto; font-weight: 500; }
.person-summary-add + .person-caret { margin-left: 0; }
.person-body {
  padding: 0 var(--sp-3) var(--sp-3);
}
.person-empty { margin: 0; max-width: 60ch; }
/* Satırın sağındaki iki ikon düğmesi yan yana kalsın; `list-row-actions`
   sarma davranışını zaten veriyor, buradaki yalnız aradaki boşluk. */
.person-actions { gap: var(--sp-1); }


/* (Faz 6 — `.range-shell` / `.range-head` silindi; panonun dönem seçicisi
   artık `.range-dock` içinde bir `.filter-pop` açılırı.) */

/* Telefon takviminde "Bugün" + tarihe atlama satırı. Gün oklarının altında
   durur: okların yerini almaz, onların yetmediği yerde devreye girer. */
.cal-jump {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: 0 var(--sp-4) var(--sp-3);
}
.cal-jump-field { margin: 0; flex: 1 1 auto; min-width: 0; }
.cal-jump .input-sm { width: 100%; max-width: 200px; }
/* Zaten bugündeyken "Bugün" düğmesi sönükleşir ama kaybolmaz: kaybolan
   düğme, yerini bir sonraki düğmeye verip yanlış tıklamaya yol açıyordu. */
.btn.is-disabled { opacity: 0.5; pointer-events: none; }


/* ==========================================================================
   Açılır seçim — bağlam boyutları
   --------------------------------------------------------------------------
   `.select-sm` gibi boyut sınırları gerçek `<select>` üzerindeydi. Alan
   zenginleştirilince o öğe görünmez oluyor ve sınır hiçbir şeyi
   sınırlamıyor; kısıt görünen kabuğa taşınmalı. Aksi halde satır içi hızlı
   güncelleme seçicileri tablo hücresini genişletip kolonları kaydırıyordu.
   ========================================================================== */

.quick-form .select-shell { max-width: 170px; }
/* Kişi seçici (`data-person`, Faz 47): düğmede avatar + kısa ad
   ("MB Meryem B."). Avatar daralmaz, ad gerekirse kırpılır (`.truncate`
   zaten üstünde); soyadının tamamı ve "(sistem admini)" gibi ekler düğmede
   değil `title`da ve açılan listededir. Ekleyen sütununun 132 px'lik
   tavanında (aşağıda) "Meryem Bilginer (si…" yerine "MB Meryem B." okunur. */
/* Sıkı dolgu: 132 px'lik tavanda ada ~70 px kalsın diye (avatar 22 + iki
   aralık + ok 14 + kenarlar). "Meryem B." bu ölçüye sığar; 8/8/16 ile
   sığmıyor, "Meryem…" oluyordu. */
.select-shell.is-person .select-btn { padding-left: 6px; gap: 6px; }
.select-shell.is-person .select-btn .chevron { width: 14px; height: 14px; }
.select-shell.is-person .select-avatar { flex: none; }
.select-shell.is-person .select-avatar[hidden] { display: none; }
.quick-row .quick-form .select-shell { width: 100%; max-width: none; }
.toolbar .select-shell,
.filter-row .select-shell { min-width: 0; }
.bulk-field .select-shell { width: 100%; }
/* Dokunmatikte seçenek satırı tam dokunma hedefine çıkar. */
@media (pointer: coarse) {
  .select-opt { min-height: var(--tap); }
}


/* ==========================================================================
   Faz 8 — Liste ekranları: sakin satır, gecikmeli denetim
   --------------------------------------------------------------------------
   Sorun: listeler "sürekli açık form" gibi görünüyordu. Her satırda üç
   çerçeveli denetim (durum, sorumlu, tarih) ve her durumda dolu bir hap
   vardı; 20 satırlık bir sayfada 60 kutu + 20 renkli hap çiziliyor, göz
   veriyi değil kontrolleri tarıyordu.

   Çözüm üç kuralda toplanır:

   1. **Denetim dinlenir, kaybolmaz.** Hızlı güncelleme alanları DOM'da
      aynen kalır (form sözleşmesi, `noscript`, klavye erişimi değişmez);
      yalnız *çerçevesi* satırın üzerine gelinene / odak satıra girene
      kadar saydamdır. Kaldırmak değil, susturmak: böylece yerini koruyup
      düzen kaymasına yol açmaz.
   2. **Renk hapta değil noktada.** Dolu hap yerine renkli nokta + düz
      metin (`.status`). Ayırt edicilik durur, gürültü gider.
   3. **Eylemler satırın sonunda toplanır** (`.row-actions`): üzerine
      gelince beliren üç nokta menüsü. Her satıra dağılmış düğme yerine
      tek, öngörülebilir yer.
   ========================================================================== */

/* --- 1. Durum göstergesi: nokta + metin ------------------------------- */

/* `.badge` yerine listelerde bu kullanılır. Rozet hâlâ ayrıntı
   ekranlarında ve sayımlarda duruyor; orada tek bir hap gürültü değil,
   vurgudur. Listede yirmi tanesi gürültüdür. */
/* Durum rozeti — üç rol, iki kabuk (Faz 27).

   Ton sınıfları (`.status-info`, `.status-warn`, …) artık **renk değeri
   yazmıyor**, üç değişken bağlıyor: dolgu, çerçeve, mürekkep. Değeri iki
   ayrı kabuk okuyor:

   · `.status`       — salt okunur gösterge (detay, panel, çekmece, pano)
   · `.quick-status` — yerinde düzenlenen alan (üç liste)

   İkisi aynı şeyi gösterip farklı görünüyordu ve bu bir kaza değil yapısal
   bir boşluktu: ton sınıfı ortaktı ama rengi *kabuklar* yazıyordu, yani
   aynı durum listede ve detayda iki farklı yoğunlukta çiziliyordu. Şimdi
   ton bir kez tanımlanıyor, kabuklar yalnız ölçü veriyor.

   Kabukların ayrı kalmasının nedeni duruyor: biri metin, diğeri kontrol.
   `.quick-status` çerçeve çizmez — içindeki seçici hover'da kendi
   çerçevesini alıyor ve iki çerçeve iç içe geçiyordu. */
.status,
.quick-status {
  --st-fill: var(--surface-soft);
  --st-line: var(--border-soft);
  --st-ink: var(--text-secondary);
}
.status {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  padding: 2px var(--sp-2);
  border: 1px solid var(--st-line);
  border-radius: var(--r-pill);
  background: var(--st-fill);
  color: var(--st-ink);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1.55;
  white-space: nowrap;
}
.status .dot-mark {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  /* Halka artık beyazı değil **rozetin kendi dolgusunu** taklit ediyor.
     Sabit `--surface` yazıldığında, tonlu zeminin üstünde noktanın çevresine
     beyaz bir tasma takıyordu. */
  box-shadow: 0 0 0 2px var(--st-fill);
  background: var(--text-muted);
}

/* Renk tek başına yetmiyordu.

   Beş durumun ikisi (Planlandı = `neutral`, İptal = `quiet`) iki farklı
   griydi: `--text-muted` ile `--neutral-accent` yan yana gelmediği sürece
   ayrışmıyor, listede alt alta gelince "hangisi iptal?" sorusu okumadan
   yanıtlanamıyordu. Renk körlüğünde Aktif/Beklemede ayrımı da aynı derde
   düşüyor.

   Bu yüzden durum artık **üç işaretle** birden konuşuyor:

   · **Renk** — noktanın rengi (eskisi gibi).
   · **Biçim** — henüz başlamamış durum *içi boş* halka, yürüyen durum
     *dolu* nokta. "Başladı mı?" sorusu renge bakmadan yanıtlanır.
   · **Ağırlık** — kapanmış kayıt (Tamamlandı, İptal) sessizleşir: metin
     `--text-muted`e iner. Açık kayıt normal kontrastta kalır.

   "Kapanmış kayıt alarm vermez, sessizleşir" kuralı da buradan geliyor.

   Faz 27 dördüncü kanalı açtı: **dolgu**. Renk bütçesi kısıtı kalktığında
   ilk kazanan durum göstergesi oldu, çünkü burada renk süs değil verinin
   kendisi — kullanıcı listeye "hangisi bekliyor, hangisi bitti" diye
   bakıyor. Nokta kalıyor (biçim kanalı onun üstünde), metin kalıyor; dolgu
   ikisinin altına giriyor.

   Tamamlanma bu fazda ton sınıfından da renk aldı: `.status-success` artık
   petrol yeşili bir rozettir. Faz 26'da yalnız metni soluklaşıyordu ve
   "kapandı" ile "önemsiz" ayrımı okunamıyordu. */
/* Durum tonları **tür sözlüğünden okumaz**.

   Faz 27'nin ilk turunda `.status-info` `--kind-project-*`e, `.status-warn`
   `--kind-company-*`e bağlanmıştı. Değer olarak çalışıyordu ama kabloyu
   yanlış yere takıyordu: "Devam ediyor" rengini *iş teslimi türünden*
   alıyordu, yani ekranda mor bir kapsül olarak çıkıyordu. Görevin türü mavi,
   durumu da mavi olmalıyken, durum kapsülü türün morunu basıyordu — iki
   katman tek jetonda kısa devre yapmıştı.

   Kural: **tür** ne olduğunu söyler (görev mavi, iş teslimi mor, takip
   amber), **durum** nerede olduğunu söyler (yapılacak gri, devam ediyor
   mavi, tamamlandı petrol yeşili, gecikti mercan). İki soru ayrı, iki
   sözlük ayrı. Bir kapsülün rengi hiçbir zaman kayıt türünden gelmez.

   `.status-warn` için değerler bugün aynı (antik altın hem "Beklemede"
   durumu hem takip türü); yine de `--warn-*` üzerinden çağrılıyor ki
   takip türünün rengi değiştiğinde "Beklemede" onunla sürüklenmesin. */
.status-info {
  --st-fill: var(--info-bg);
  --st-line: var(--info-border);
  --st-ink: var(--info);
}
.status-warn {
  --st-fill: var(--warn-bg);
  --st-line: var(--warn-border);
  --st-ink: var(--warn);
}
.status-success {
  --st-fill: var(--state-done-fill);
  --st-line: var(--state-done-line);
  --st-ink: var(--state-done-ink);
}
/* Huninin derin basamağı — iki komşu durum aynı rengi basıyordu.

   "Görüşülüyor" ile "Teklif gönderildi" ikisi de `info` tonundaydı: aynı
   ton, aynı dolgu, ayırt edilemeyen iki satır. Gerekçenin tamamı ve ölçüler
   `base.css`, `--tone-strong` bloğunda. */
.status-strong {
  --st-fill: var(--tone-strong-fill);
  --st-line: var(--tone-strong-line);
  --st-ink: var(--tone-strong-ink);
}
.status-danger {
  --st-fill: var(--danger-bg);
  --st-line: var(--danger-border);
  --st-ink: var(--danger);
}
.status-accent {
  --st-fill: var(--state-late-fill);
  --st-line: var(--state-late-line);
  --st-ink: var(--state-late-ink);
}
/* Sade kip — dolgu düşer, nokta + metin kalır.

   Faz 27 dolguyu açtığında iş ve firma listelerinde her satır dolu bir
   kapsül taşımaya başladı. Hapın kendisi küçüktü; sorun sayıydı. Yirmi
   satır = yirmi renkli kutu, yani `.status`un `.badge` yerine var olma
   gerekçesinin ta kendisi, bir basamak yukarıda geri gelmişti.

   Çözüm dolguyu geri almak değil, **bütçelemek**: dolgu bir vurgudur ve
   vurgu ancak seyrekken vurgudur. Faz 27 iki istisna tanımlamıştı (gecikme,
   tamamlanma); Faz 31 tamamlanmayı, Faz 32 gecikmeyi de kapattı. Sade kipin
   sözü artık istisnasız: **tekrar eden satırda zemin yok.** Gecikme kanalı
   kaybolmuyor, araç değişiyor — dolgu yerine mürekkep (aşağıda).

   Nokta hiçbir koşulda düşmez — renk kanalı orada duruyor, kaybolan şey
   yalnız zemin. Mürekkep `--text`e döner çünkü sade satırda metni tonlu
   bırakmak, dolgusuz bir rozeti "yarım çizilmiş" gösteriyordu. */
.status.is-plain,
.quick-status.is-plain {
  --st-fill: transparent;
  --st-line: transparent;
  --st-ink: var(--text);
}
/* Faz 31 — tamamlanmanın dolgusu sade kipte **geri alındı**.

   Faz 27 iki istisna tanımlamıştı: gecikme ve tamamlanma sade satırda da
   dolgu alsın. Gecikme istisnası duruyor (aşağıda) çünkü kullanıcıdan iş
   bekliyor. Tamamlanma beklemiyor — ve bedeli ekranda ölçüldü: iş
   listesinin durum sütununda beş durumdan dördü dolgusuz nokta + metin,
   biri petrol yeşili kapsüldü. Göz o sütunda bir *sıra* değil, bir
   *istisna* okuyor; "Tamamlandı neden farklı çiziliyor?" sorusunun iyi bir
   cevabı yoktu.

   Renk kaybolmuyor: nokta hâlâ petrol yeşili (`.status-success .dot-mark`).
   Değişen yalnız zemin — sade kipin sözü artık koşulsuz: *listede dolgu yok*.

   Faz 32 — aynı söz **panoda** da geçerli. `plain` geçmeyen yüzey olarak
   pano bırakılmıştı; bedeli ölçüldüğünde Genel Bakış 23 dolu kapsül
   basıyordu (Bugün kartında 16 satır, huninin 6 basamağı, odakta 1), yani
   listede kapatılan desen bir ekran ötede duruyordu. Dolgu artık yalnız
   kayıt **ayrıntısı**, sağ **panel** ve panonun tek katman-1 kartı olan
   "Bugünün odağı"nda. Kural tek cümle: kapsül tekrar ediyorsa sade.

   ...ve gecikme de bu kuralın içinde — bu kez dolgusuyla **birlikte
   mürekkebiyle**. Faz 27'nin son istisnası şuydu: geciken kayıt hangi
   durumda olursa olsun durum göstergesi mercana dönerdi. Önce kapsül
   olarak, Faz 32'nin ilk turunda yalnız metin rengi olarak. İkisi de aynı
   hatayı yapıyordu: **durum etiketi durumu söyler.** "Devam ediyor" kırmızı
   yazıldığında ekranda okunan şey "devam ediyor ama bir terslik var" oluyor;
   oysa geciken şey durum değil **tarih**tir. Kullanıcının ilk sorusu da bu
   oldu: "devam ediyor, yapılıyor neden kırmızı?"

   Gecikme bu yüzden tek bir yerde söyleniyor: tarihin kendisinde (`.due` /
   `.is-alert` — "3 gün gecikti"). O metin her yüzeyde durumun yanı başında
   duruyor (liste tarih kolonu, panonun satır sonu, ayrıntı meta satırı, sağ
   panel), yani kanal kaybolmuyor — **tek** sahibine dönüyor. Renk hâlâ tek
   kanal değil: gecikmeyi metnin kendisi de söylüyor.

   Bu yüzden burada kural yok: `is-alert` artık `.status` / `.quick-status`
   üstüne hiç basılmıyor (`_row.html`, `status` makrosundan `alert`
   parametresi kaldırıldı). Geri eklenecekse önce yukarıdaki cümle
   çürütülmeli. */
.status-info .dot-mark { background: var(--info); }
.status-strong .dot-mark { background: var(--tone-strong); }
.status-warn .dot-mark { background: var(--warn); }
.status-success .dot-mark { background: var(--success); }
.status-danger .dot-mark { background: var(--danger); }
.status-accent .dot-mark { background: var(--accent); }

/* Başlamamış (Planlandı / Yapılacak) ve iptal edilmiş durum **içi boş**
   halka çizer.

   Halka `box-shadow: inset` ile değil `background` ile yapılıyor. Neden:
   liste satırlarında nokta `.quick-status > .dot-mark` kuralından geçiyor
   ve o kural kendi `box-shadow`unu yazıyor — aynı özgüllükte, dosyada daha
   sonra. `inset` halka orada sessizce siliniyor ve nokta bütünüyle
   kayboluyordu. `background` iki kuralda da yazılmadığı için çakışma yok;
   beyaz dış halka (zemin ayırıcı) `box-shadow`da kalmayı sürdürür.

   Halkanın **içi** de `--st-fill`den geliyor (Faz 27): sabit `--surface`
   ile yazıldığında, tonlu rozetin üstündeki "içi boş" nokta boş değil
   *beyaz dolu* görünüyordu — biçim kanalı tam tersini söylemeye başlıyordu.
   İki ton sınıfı nötr kaldığı için bugün fark etmiyor; renk bütçesi bir
   daha genişlerse (Planlandı'ya dolgu verilirse) kendiliğinden doğru
   davranacak. */
.status-neutral .dot-mark {
  background: radial-gradient(circle at 50% 50%, var(--st-fill) 0 1.7px, var(--text-muted) 1.7px);
}
.status-quiet .dot-mark {
  background: radial-gradient(circle at 50% 50%, var(--st-fill) 0 1.7px, var(--neutral-accent) 1.7px);
}

/* İptal edilmiş durum üstü çizilidir.

   Çizgi yeni bir dil değil: tamamlanmış görevin adı listede zaten üstü
   çizili yazılıyor. "Bu kayıt artık yürümüyor" cümlesini renk körlüğünde
   de okunabilen tek işaret o.

   Faz 27'de `.status-success` bu kuraldan **çıktı**: tamamlanma artık
   soluk bir metin değil petrol yeşili bir rozet. İkisi aynı kuralda
   dururken "bitti" ile "iptal" aynı griye iniyordu — oysa biri olumlu bir
   sonuç, diğeri sonuçsuzluk. İptal nötr kalıyor (arctic), tamamlanma
   rengini alıyor. */
.status-quiet {
  color: var(--text-secondary);
  text-decoration: line-through;
  text-decoration-color: var(--text-muted);
}
/* Açılır seçici kapanmış kaydın çizgisini miras almaz: orada okunan şey
   kaydın durumu değil, seçilebilecek durumların listesidir. */
.status-quiet .select-menu,
.status-quiet .dropdown { text-decoration: none; color: var(--text); }

/* (Faz 32 — `.status.is-alert` / `.quick-status.is-alert` silindi. Gecikme
   durum göstergesini artık ne dolguyla ne mürekkeple boyuyor; gerekçenin
   tamamı yukarıda, sade kip bloğunun sonunda. Gecikmenin tek sahibi tarih
   metnidir: `.due` ve `.is-alert`.) */


/* --- 2. Uzun ad: en fazla iki satır ----------------------------------- */

/* `.truncate` tek satır kırpar ve uzun firma adlarının yarısını yutuyordu.
   İki satır, satır yüksekliğini öngörülebilir tutarken adın tamamına
   yakınını gösterir. `anywhere`: boşluksuz uzun bir dize (URL benzeri ad)
   kolonu taşırmasın. */
.clamp-2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* Ad kolonu iki yandan da sınırlanır. Üst sınır olmazsa tek uzun kayıt
   bütün kolon genişliklerini kendine çeker; **alt** sınır olmazsa tersi
   olur — dar bir pencerede tablo, esnemeyen tarih/durum kolonlarını
   koruyup ad kolonunu 50 piksele ezerek her satırı "Karad…"e çevirir. */
.cell-title { max-width: 44ch; min-width: 16ch; }


/* --- 3. Satır sonu eylemleri ------------------------------------------ */

.actions-col { width: 1%; }
.table td.actions-cell { padding-left: var(--sp-2); padding-right: var(--sp-3); }

.row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 2px;
}

.row-btn {
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
}

/* Farede sessiz dur, ihtiyaç anında görün. Dokunmatikte `:hover` diye bir
   an olmadığı için düğme her zaman açıktır — aksi halde telefonda menüye
   hiç ulaşılamazdı. Klavye için `:focus-within` şart: Tab'layan kullanıcı
   görünmez bir düğmeye odaklanamaz. */
/* Kural yalnız **masaüstü tablosunda**. Mobil kartta üç nokta menüsü,
   kayda ulaşmanın tek yolu (düzenleme denetimleri karta yerleşmiyor);
   orada gizlenirse hiçbir işleme erişilemez. Dar bir masaüstü penceresinde
   de mobil liste çizilir ve orada `hover: hover` geçerlidir — yani
   "telefonda nasılsa görünür" varsayımı tek başına yetmezdi. */
@media (hover: hover) {
  .table tbody tr .row-btn {
    opacity: 0;
    transition: opacity var(--dur-1) var(--ease-out);
  }
  .table tbody tr:hover .row-btn,
  .table tbody tr:focus-within .row-btn,
  .table tbody tr .row-btn[aria-expanded="true"],
  .table tbody tr .row-btn:focus-visible {
    opacity: 1;
  }
}

/* Menü paneli `.table-wrap` içindeki `overflow` tarafından kırpılmasın:
   konumu betik hesaplar (`.select-menu` ile aynı gerekçe). */
.row-menu { position: relative; }
.row-menu-panel {
  position: fixed;
  top: auto;
  right: auto;
  z-index: 60;
  min-width: 208px;
}
.row-menu-panel .dropdown-item { min-height: 38px; }
.row-menu-panel form { margin: 0; }
.row-menu-panel .dropdown-item.is-danger { color: var(--danger); }
.row-menu-panel .dropdown-item.is-danger .icon { color: var(--danger); }
.row-menu-panel .dropdown-item.is-danger:hover { background: var(--danger-bg); }
@media (pointer: coarse) {
  .row-menu-panel .dropdown-item { min-height: var(--tap); }
  /* Menünün "Düzenle / Sil" satırları 44'e çıkarken hızlı alanlar 30
     pikselde kalıyordu. Panoda durum değiştiren parmağın dokunduğu kutu
     tam olarak bu: menüdeki en küçük hedef, menünün en çok kullanılan
     hedefiydi. */
  .row-menu-panel .quick-row .select-sm,
  .row-menu-panel .quick-row .input-sm { min-height: var(--tap); }
}

/* Telefonda menü **alt panel** olur (Faz 5). Masaüstündeki küçük açılır
   kutu 360 pikselde kartın yanında açılıyordu: tetikleyici sağ üstteyken
   panel ekranın kenarına yaslanıyor, hızlı güncelleme alanları (durum,
   sorumlu, tarih) 200 piksellik bir şeride sıkışıyordu. Alt panel aynı
   içeriği tam genişlikte verir ve parmağın zaten durduğu yere açılır.

   Konumu normalde betik hesaplıyor ve **satır içi** yazıyor (`data-menu-anchor`
   → `style="top: …; left: …"`); bu yüzden alt panelin kuralları `!important`.
   Dikiş bilinçli ve geçici: `app.js` bu kırılımda konum hesabını atladığında
   `!important`ler düşer. Tek yerde ve tek kırılımda duruyor, üstelik yanlış
   giderse sonuç "menü yanlış yerde açılır", veri kaybı değil.

   Alt kenar `--tabbar-h` + güvenli alan kadar yukarıda: sabit alt
   navigasyonun üstünü örtmesi, son menü öğesini dokunulamaz yapardı —
   toplu işlem çubuğunda (`.bulk-bar.is-open`) çözülen aynı çakışma. */
@media (max-width: 719px) {
  .row-menu-panel {
    position: fixed !important;
    top: auto !important;
    left: 0 !important;
    right: 0 !important;
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px)) !important;
    width: auto !important;
    min-width: 0;
    max-height: calc(70dvh - var(--tabbar-h));
    overflow-y: auto;
    overscroll-behavior: contain;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: var(--shadow-lg);
  }
  /* Panel tam genişlikteyken hızlı güncelleme alanları da yayılır. */
  .row-menu-panel .quick-row .quick-form { width: 100%; }
}


/* --- 4. Hayalet satır içi düzenleyici --------------------------------- */

/* Hızlı güncelleme alanı okunurken metin, düzenlenirken alandır.
   `.quick-form` yalnız üç liste ekranında kullanılır (`_quick.html`), bu
   yüzden kural genel yazılabilir. Çerçeve *renk* değiştirir, kalkmaz:
   `border-color: transparent` kutu ölçüsünü korur, satır üzerine gelince
   hiçbir şey kaymaz. */
.quick-form .select-btn,
.quick-form .input-sm {
  border-color: transparent;
  background: transparent;
  color: var(--text);
  transition: border-color var(--dur-1) var(--ease-out),
    background-color var(--dur-1) var(--ease-out);
}
.quick-form .select-btn .chevron {
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
/* Tarih alanının takvim simgesi de aynı ritmi izler. */
.quick-form input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}

.table tbody tr:hover .quick-form .select-btn,
.table tbody tr:hover .quick-form .input-sm,
.table tbody tr:focus-within .quick-form .select-btn,
.table tbody tr:focus-within .quick-form .input-sm,
.quick-form .select-btn[aria-expanded="true"],
.quick-form .select-btn:focus-visible,
.quick-form .input-sm:focus {
  border-color: var(--border-input);
  background: var(--surface);
}
.table tbody tr:hover .quick-form .select-btn .chevron,
.table tbody tr:focus-within .quick-form .select-btn .chevron,
.quick-form .select-btn[aria-expanded="true"] .chevron,
.table tbody tr:hover .quick-form input[type="date"]::-webkit-calendar-picker-indicator,
.table tbody tr:focus-within .quick-form input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 1;
}

/* Dokunmatikte hover yok: alanlar her zaman kendini gösterir, yoksa
   telefonda görünmez kutulara dokunmak gerekirdi. */
@media (hover: none) {
  .quick-form .select-btn,
  .quick-form .input-sm {
    border-color: var(--border-input);
    background: var(--surface);
  }
  .quick-form .select-btn .chevron { opacity: 1; }
}


/* --- 5. Satır vurgusu ------------------------------------------------- */

.table tbody tr.is-open,
.list-calm .select-row.is-open {
  background: var(--selected);
  box-shadow: inset 3px 0 0 var(--brand);
}


/* --- 6. Mobil sakin kart ---------------------------------------------- */

/* Telefonda satır dört bilgiyi taşır: ad, durum, sorumlu avatarı ve önemli
   tarih. Düzenleme denetimi karta *yerleşmez*; üç nokta menüsünden açılır.
   Eskiden her kartın altında üç tam genişlik alan duruyordu ve liste
   kaydırılamayacak kadar uzuyordu (kart başına ~180 px). */
.list-calm .select-row { align-items: stretch; }
.list-calm .list-row {
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: nowrap;
  padding: var(--sp-3) var(--sp-4);
}
.list-calm .list-row-title { font-weight: 600; line-height: 1.35; }
/* Meta satırı **sarmaz**. Sarınca kart yüksekliği içeriğe göre değişiyor,
   liste düzensiz bir merdivene dönüşüyordu (bir kartta iki satır, yanındakinde
   üç). Tek satır, sabit ritim. Sığmayan kısım kırpılır ve bu yüzden şablonda
   sıra **önem sırasıdır**: önce durum, sonra tarih, en sonda kırpılmaya aday
   ikincil ad (müşteri / iş). */
/* `flex-direction` burada açıkça yazılmalı: yukarıdaki mobil blok
   (`@media (max-width: 899px)`) `.list-row-meta`yı sütuna çeviriyor ve
   ayıraç noktalarını gizliyor. O kural eski, yoğun kartın kuralıydı —
   her alan kendi satırına iniyordu. Sakin kart tam tersini istiyor:
   dört bilgi tek satırda, ayıraçlarla. Özgüllük yetse de yalnız
   *yazılmış* özellikler ezilir; `flex-direction` yazılmazsa sütun kalır. */
.list-calm .list-row-meta {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: nowrap;
  overflow: hidden;
  margin-top: 2px;
}
.list-calm .list-row-meta .dot-sep { display: inline; }
.list-calm .list-row-meta > .status { flex: none; }
.list-calm .list-row-meta > .nowrap { flex: none; }
.list-calm .list-row-meta > .truncate { min-width: 0; }
/* 400 pikselin altında şerit **sarar**.

   Kap `only-mobile`, yani hep dar; şeritte üç esnemeyen öğe var (durum
   çipi, tarih, ekleyen) ve daralabilen tek öğe `.truncate`. O sıfıra
   indikten sonra kalan içerik `overflow: hidden` ile **ortasından**
   kesiliyordu: üç nokta yok, yarım kelime var ("12 Mar 2026 anlaş"). Üç
   nokta bir kırpma işaretidir; işaretsiz kırpma, veriyi yanlış okutur.

   Çözüm `.today-row-meta`nın dokunmatik bloğundakiyle aynı: sarmayı aç,
   ayırıcı noktayı düşür (satır atlaması ayrımı zaten yapıyor; nokta
   yalnız yan yana dizilen bir şeritte iş görür). */
@media (max-width: 400px) {
  .list-calm .list-row-meta {
    flex-wrap: wrap;
    overflow: visible;
    row-gap: var(--sp-1);
  }
  .list-calm .list-row-meta .dot-sep { display: none; }
}
/* Sorumlu avatarı satırın sonunda, eylem düğmesinin solunda durur:
   "kimde?" sorusu tek kolonda dikey taranabilsin. */
.row-owner {
  display: inline-flex;
  align-items: center;
  flex: none;
}
.row-owner .avatar { width: 30px; height: 30px; font-size: var(--fs-xs); }
.row-owner-empty {
  width: 30px;
  height: 30px;
  border-radius: var(--r-pill);
  border: 1px dashed var(--border-strong);
  flex: none;
}
/* Hücre içinde kişi: küçük avatar + ad. `.row-owner` yalnız avatar taşır ve
   `flex: none`tur; yanına ad koyunca uzun isim hücreyi genişletip tabloyu
   kaydırma çubuğuna sokuyordu. Burada kısalan **ad**dır (`min-width: 0` +
   `.truncate`), sütun değil. */
/* Ekleyen sütunu yöneticide bir seçici taşır ve `.quick-form`un 170 px'lik
   genel tavanıyla tabloyu 1280 px'de 32 px taşırıyordu. Burada daha dar bir
   tavan var: düğmede ad kırpılsa da menü artık **içeriğe** göre açılıyor
   (bkz. base.css `.select-menu`), yani seçim yapmak zorlaşmıyor. */
@media (max-width: 1439px) { .cell-creator .select-shell { max-width: 132px; } }

.cell-user {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  max-width: 100%;
}
.cell-user .avatar { width: 24px; height: 24px; font-size: var(--fs-xs); flex: none; }

.list-calm .list-row-aside { display: none; }


/* --- 7. Seçim kipi: araç çubuğu yerini seçim çubuğuna bırakır --------- */

/* İstenen davranış: seçim başlayınca arama/sıralama/süzgeç satırı yerini
   "N kayıt seçildi + toplu işlemler" satırına bırakır. Bu yüzden toplu
   form artık listenin dibinde değil, araç çubuğunun *yanında* (aynı
   `.filters-shell` içinde) duruyor — DOM'da kardeş, ekranda aynı yer.

   `form` iç içe geçmez: ikisi de `.filters-shell`in doğrudan çocuğu.
   Satırlardaki kutucuklar toplu forma `form="toplu-form"` ile bağlı
   kaldığı için bu taşıma hiçbir gönderimi değiştirmez.

   Değiştirme yalnız `.js` altında: betik yokken iki çubuk da görünür
   kalır, çünkü "seçim başladı" anını bilen şey betiktir.

   Ve yalnız masaüstünde. Telefonda seçim çubuğu araç çubuğunun yerine
   geçmiyor, ekranın **altına** yapışıyor (aşağıdaki mobil bloğu) — orası
   başparmağın olduğu yer. Değişim mobilde de uygulansaydı yukarıda araç
   çubuğundan boşalan bir delik kalır, yerine hiçbir şey gelmezdi. */
@media (min-width: 900px) {
  .js .filters-shell.is-selecting > .toolbar,
  .js .filters-shell.is-selecting > .active-filters {
    display: none;
  }
}

/* Araç çubuğunun alt boşluğuyla aynı (`.filters-shell > .toolbar`): çubuk
   yerini seçim çubuğuna bırakırken listenin üstündeki aralık değişmemeli,
   yoksa seçim başlar başlamaz liste birkaç piksel zıplar. Mobilde çubuk
   ekranın altına yapıştığı için oradaki kural (`margin: 0`) daha özgül
   ve bunu ezer. */
.filters-shell > .bulk-bar { margin: 0 0 var(--sp-3); }


/* --- 8. Kayıt paneli (Faz 10) ----------------------------------------- */

/* Bir kayda tıklamak sayfayı değiştirmez.

   Masaüstünde sağdan bir panel açılır; liste ve kaydırma konumu arkada
   olduğu gibi durur. Panel `fixed`, yani listenin kaydırma kabına hiç
   dokunmaz ve listeyi **daraltmaz**, üstüne biner.

   Daraltmanın neden yanlış olduğu ölçüldü: içeriğe sağdan boşluk
   verildiğinde tablo o boşluğu esnemeyen kolonlardan (durum, tarih) değil
   ad kolonundan kısıyor ve her satır "Karad…"e dönüyordu. Panelin
   açılması listeyi yeniden diziyordu — tam da olmaması gereken şey.
   Panelin örttüğü sağ kolonlardaki veri zaten panelin içinde yazıyor.

   `top` sıfır değil üst gezinmenin boyu: `.topbar` yapışkan (z-index 40) ve
   içinde bölüm bağlantıları, arama, bildirim ve kullanıcı menüsü duruyor.
   Panel sıfırdan başlasaydı hepsini örterdi — yan panel kipsel bir pencere
   değil, yan yana çalışan bir yüzey; arkadaki gezinmeyi kapatmaz. */

/* Genişlik `clamp`: 500 px altında iki kolonlu üst bilgi (durum + sorumlu)
   alt alta düşüp paneli uzatıyor, 560 px üstünde ise metin satırı
   okunabilir ölçüyü (~68ch değil ama ~55ch) aşmadan yalnız boşluk
   büyüyordu. Aradaki bant, tasarımdaki 500–560 px isteğinin karşılığı. */
/* Faz 18: panel de **ortada** açılır (form kipiyle aynı gerekçe, §6).
   Sağdan gelen yüzey okuma eksenini ekranın kenarına kaydırıyor, arkadaki
   liste ile "hangisi aktif" yarışına giriyordu. Ortada duran kip, perdesi
   sayesinde bu soruyu sormuyor.

   Bedeli kabul edildi: panel artık kipsel, yani açıkken arkadaki liste
   kaydırılmıyor ve panel kapanmadan listeye tıklanmıyor. Karşılığında
   davranış her genişlikte **tek**: telefonda zaten kipseldi (tam ekran
   sheet), masaüstünde ayrı bir kural yaşatmak gerekmiyor. */
.record-panel {
  --panel-w: clamp(500px, 36vw, 620px);
  /* Ortalama `transform` ile **yapılamaz**: `transform`, içindeki
     `position: fixed` kutular için yeni bir kapsayıcı blok kurar ve perde
     (`::before`) ekranı değil panelin kendi kutusunu kaplardı — ölçüldü,
     perde görünmüyordu ve tıklama arkadaki menüye geçiyordu.
     `inset: 0` + `margin: auto` aynı ortalamayı transformsuz yapar. */
  position: fixed;
  inset: 0;
  margin: auto;
  z-index: 65;
  width: var(--panel-w);
  height: fit-content;
  max-width: calc(100% - 2 * var(--sp-7));
  /* Boy sınırı form kipiyle aynı: yüzen yüzey hissini etrafındaki boşluk
     verir, perdeye yapışan bir kutu ikinci bir sayfa gibi okunur. */
  max-height: min(calc(100dvh - 2 * var(--sp-7)), 760px);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  /* Gövdenin zemini (`--bg` tonu) köşeleri taşmasın: yuvarlatılmış bir
     kutunun içinde kare biten bir zemin, kipin köşelerini "kırık"
     gösteriyordu. Panel içindeki açılır menüler `fixed` konumlanıyor,
     onlar bu kırpmadan etkilenmez. */
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  /* Kipin kendisi yalnız **sönümlenerek** gelir; yükselme hareketi
     `.panel-shell`e verildi. Sebep yine kapsayıcı blok: panele konan bir
     `transform` animasyon süresince perdeyi bozar. */
  animation: fade-in var(--dur-2) var(--ease-out) both;
}
.record-panel .panel-shell {
  /* Dolgu `both` değil **`backwards`**.

     `both`, animasyon bittikten sonra son kareyi "dolu" bırakıyor ve son
     kare `transform: none` yazsa bile tarayıcı orada **birim matris**
     hesaplıyor (ölçüldü; aynı tespit `app.js` içindeki `kapsayiciOfset`
     yorumunda da var). Birim matris de bir `transform`tur ve içindeki
     `position: fixed` kutular için yeni bir kapsayıcı blok kurar.

     Zinciri şuydu: kabuk kapsayıcı blok olur → panelin içindeki hızlı
     düzenleme popover'ları (`.quick-pop-panel`, `.select-menu`) artık
     görüntü alanına değil kabuğa göre konumlanır → kabuk da
     `.record-panel`in içinde ve orada `overflow: hidden` var → panelin alt
     kenarına yakın açılan bir popover **kesiliyordu**. `kapsayiciOfset`
     yalnız kaymayı telafi ediyor; kırpmayı edemez, çünkü kırpma konum
     hesabının değil kapsayıcı zincirinin sonucu.

     Yukarıdaki yorum ("panel içindeki açılır menüler `fixed`, onlar bu
     kırpmadan etkilenmez") tam olarak bu yüzden yanlıştı.

     `backwards` görüntüyü değiştirmez: animasyon aynen çalışır, yalnız
     bittikten sonra hiçbir şey "dolu" bırakılmaz ve `transform` öğenin
     kendi değerine — yani yokluğa — döner. */
  animation: panel-in var(--dur-2) var(--ease-out) backwards;
  /* Görünen beyaz yüzey burada, `.record-panel`de değil: perde
     (`::before`) panelin zeminini örtüyor, kabuğu örtemiyor. Köşeleri
     panelin `overflow: hidden`ı kırpıyor, bu yüzden kabuğa ayrıca
     `border-radius` gerekmiyor. */
  background: var(--surface);
}

/* Perde ayrı bir düğüm değil, panelin kendi `::before`u: kabuk
   `layouts/app.html` içinde tek bir `<aside>` ve onu ikiye bölmek betiğin
   iki düğümü birlikte açıp kapatmasını gerektirirdi — açık kalan yarım bir
   perde, kapanmayan bir kip demektir.

   DİKKAT — `z-index: -1` perdeyi panelin *kendi zemininin* arkasına
   **atmaz**. Panel `position: fixed` + `z-index: 65` ile bir yığın bağlamı
   kuruyor ve bağlam içinde boyama sırası şudur: (1) kök elemanın zemini,
   (2) negatif z-index çocuklar, (3) akıştaki içerik. Yani perde zeminin
   *üstüne*, metnin *altına* düşüyordu: panelin içi de dışı kadar
   griydi (ölçüldü: ikisi de rgb(149,152,160)) ve yüzey şeffaf/bozuk
   görünüyordu. Bu yüzden asıl zemin `.panel-shell`e taşındı (aşağıda) —
   perde artık gerçekten her şeyin arkasında.

   Perdeye tıklayınca kapanır: `.overlay` olmadığı için katman yığınının
   kuralı işlemiyor, panel modülü `event.target === panel` kontrolüyle
   kendi kapatıyor (app.js). */
.record-panel::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--overlay);
}
.record-panel[hidden] { display: none; }

@keyframes panel-in {
  from { transform: translateY(8px) scale(0.98); }
  to { transform: none; }
}

/* Telefon ve tablet: aynı panel tam ekran bir sheet olur.

   `inset: 0` ve z-index 70 — alt sekme çubuğunun (z-index 50) *üstünde*.
   Altında kalsaydı çubuk sheet'in alt işlem satırını örterdi; ölçüm
   turunun "alt menü içeriği kapatıyor" başlığı tam olarak bu.

   Perde yok, çünkü yüzey ekranın tamamını kaplıyor: arkasında tıklanacak
   bir yer bırakmayan bir perde yalnız bir katman daha demekti. */
.record-panel.is-sheet {
  top: 0;
  inset: 0;
  /* Ortalamanın tamamı geri alınır: `margin: auto` kalsaydı tam ekran
     sheet, kendi içinde ortalanmış bir kutuya dönüşürdü. */
  margin: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  --panel-w: 100%;
  border: 0;
  border-radius: 0;
  animation: sheet-in var(--dur-3) var(--ease-out) both;
}
/* Sheet'te yükselme hareketi panelin kendisinde; kabuk ikinci kez
   oynamaz. */
.record-panel.is-sheet .panel-shell { animation: none; }
/* Sheet ekranın tamamını kaplıyor: arkasında karartılacak bir şey yok. */
.record-panel.is-sheet::before { display: none; }

.panel-shell {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}

/* --- Panel başlığı: ad, durum, sorumlu ve aksiyonlar ------------------- */

/* Başlık yapışkan değil, kabuğun sabit ilk satırı: gövde kayarken başlık
   yerinde kalır ama kendi gölgesini üretmez. Uzun firma adı sarar,
   kırpılmaz — "Karadeniz Reklam ve Tanıtım Hizmetleri" bir panelin
   başlığında üç noktaya dönüşmemeli, kullanıcı hangi kayıtta olduğunu
   oradan okuyor. `overflow-wrap: anywhere` boşluksuz uzun değeri
   (e-posta, adres) de kırar. */
/* Seçiciler `.panel-shell` ile kapsanır (Faz 6). `.panel-head` ve
   `.panel-title` bu dosyada **iki kez** tanımlı: biri burada (kayıt
   çekmecesi), biri panonun alt bölümlerinde. İkisi de çıplak sınıf olduğu
   için aynı özgüllükteydiler ve sonra gelen pano kuralı yalnız *kendi
   yazdığı* özellikleri eziyordu; yazmadıkları (`flex-direction: column`,
   `padding`, `background`) buradan sızıyordu. Sonuç: panodaki panel
   başlıkları satır değil **dikey ve ortalanmış** çiziliyordu.

   Çekmecenin başlığı her zaman `.panel-shell` içinde yaşıyor — hem iki
   şablonda (`_record_panel.html`, `_member_panel.html`) hem de `app.js`'in
   kurduğu iskelette. Kapsam eklemek bu yüzden davranışı değiştirmiyor,
   yalnız çakışmayı bitiriyor: iki taraf da artık kendi kapsamında. */
.panel-shell .panel-head {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.panel-head-top {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
}
.panel-shell .panel-title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-lg);
  font-weight: 700;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
/* Kapatma ve "tam sayfa" düğmeleri başlıkla aynı satırda, sağda. Sarmaz:
   başlık uzadıkça düğmeler değil satır büyür. */
.panel-head-tools {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

/* Durum / sorumlu / önem şeridi. Rozetler sarar; 500 px'te üç rozet ve bir
   avatar tek satıra sığmıyor ve sığdırmaya çalışmak ya kırpma ya yatay
   kaydırma demekti. */
.panel-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
.panel-meta > * { min-width: 0; }
/* Faz 45: durum · sorumlu · tarih satırı ortak sözlükten (`.rec-line`).
   Tür rozeti satırın başında kendi öğesi; meta satırı kalan genişliği alır
   ve dar panelde önce ikincil bilgiyi, sonra sorumlunun adını kırpar. */
.panel-meta .panel-line { flex: 1 1 auto; }
/* Üye panelinin e-posta satırı (`_member_panel.html`); kayıt paneli artık
   sorumluyu `.rec-line` içinde basıyor. */
.panel-owner {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.panel-owner .truncate { max-width: 18ch; }

/* Birincil aksiyonlar. Sarar ve her düğme dokunma hedefini korur. */
.panel-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.panel-actions form { display: contents; }

.panel-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--sp-4);
  /* Güvenli alan payı gövdenin dibinde: son satır artık işlem düğmesi
     olabiliyor ve telefonda sheet ekranın tamamını kaplıyor. Masaüstünde
     `env()` sıfır dönüyor, koşul gerekmiyor. */
  padding-bottom: calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

/* Yıkıcı eylem satırı: panelin dibine yapışan ayrı bir şerit **değil**,
   gövdenin son öğesi (Faz 40). Yapışkan çubuk telefonda cihazın kendi
   gezinme çubuğuyla örtüşüyor, "Sil" görünür olduğu hâlde basılamıyordu;
   güvenli alan payını artık gövde alıyor. Kiplerde verilen kararla aynı —
   tek bir yerde "düğme içeriğin içinde kayar" kuralı. */
.panel-end {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
}
.panel-end .grow { flex: 1 1 auto; }

/* Panel içindeki tanım satırları. Etiket kolonu sabit, değer esner.
   360 px'te (sheet) etiket kolonu 104 px'te değeri 3–4 karaktere
   düşürüyordu; orada satır alt alta iner. */
.panel-rows { display: flex; flex-direction: column; gap: var(--sp-2); }
.panel-row {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: start;
}

/* Değer kolonunun **tek bir sol kenarı** olmalı.

   Satırların değerleri üç farklı şeyle çiziliyor: düz metin (`row`),
   hayalet düzenleyici (`inline_view`) ve hızlı güncelleme alanı
   (`quick_select` / `quick_date`). Üçünün de kendi dolgusu var ve yalnız
   `.inline-view` bunu negatif kenar boşluğuyla geri alıyordu. Sonuç,
   panelde tırtıklı bir kenardı: "Müşteri" metni bir hizada, hemen altındaki
   "Durum" seçicisi 10 px içeride, "Teslim" tarihi 8 px içeride.

   Aynı şey dikeyde de vardı: seçici kutusu 44 px yüksekliğindeydi, düz
   metin 20 px. Etiket satırın tepesinde, değer ortasında kalıyordu.

   Kural: **her değer 28 px'lik aynı kutuda, aynı sol kenardan başlar.**
   Etiket de aynı kutuyu alır, böylece ikisi tek çizgide okunur. Denetimler
   dolgularını negatif kenar boşluğuyla geri verir — çerçeve üzerine
   gelindiğinde metnin *dışında* çizilir, metni itmez. */
.panel-row > dt,
.panel-row > dd {
  display: flex;
  align-items: center;
  min-height: 28px;
  margin: 0;
  min-width: 0;
}
.panel-row > dt { color: var(--text-secondary); font-size: var(--fs-sm); }
.panel-row > dd { flex-wrap: wrap; gap: var(--sp-2); overflow-wrap: anywhere; }
/* Çok satırlı değer (açıklama, ilerleme çubuğu) ortalanmaz: blok olarak
   akar ve satırın tepesinden başlar. */
.panel-row > dd > .inline-edit { flex: 1 1 100%; min-width: 0; }
/* İlerleme çubuğu panelin sağ kenarına kadar uzanıyordu; değer kolonunun
   geri kalanıyla aynı ölçüde durur. */
.panel-row > dd > .progress-wrap { flex: 1 1 100%; min-width: 0; max-width: 260px; }

.panel-row .quick-form { display: flex; flex: 1 1 auto; min-width: 0; }
/* Seçicinin kabuğu esner: liste satırındaki 170 px'lik sınır burada
   değeri ("Devam ediyor", "Can Yılmaz") üç noktaya kırpıyordu. */
.panel-row .quick-form .select-shell {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 240px;
}
.panel-row .quick-form .input-sm { max-width: 240px; }
.panel-row .quick-form .select-btn,
.panel-row .quick-form .input-sm {
  min-height: 28px;
  padding-block: 2px;
  padding-left: var(--sp-2);
  margin-left: calc(var(--sp-2) * -1);
}
.panel-row .quick-form .input-sm { padding-right: var(--sp-2); }
/* Boş tarihin yerine konan tire de aynı sol kenardan başlar: `left`
   değeri liste satırındaki dolguya göre yazılmış, panelde alan kendi
   dolgusunu negatif kenar boşluğuyla geri veriyor. */
.panel-row .quick-empty { left: 0; }

@media (max-width: 419px) {
  .panel-row { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .panel-row > dt { min-height: 0; }
}

/* Dokunmatikte 28 piksellik hiza kuralı **dokunma hedefine yenilir**.

   Yukarıdaki 28 px, panelin masaüstündeki en iyi kararı: her değer aynı
   kutuda, aynı sol kenardan başlıyor ve düz metin ile seçici tek çizgide
   okunuyor. Telefonda aynı kural üç denetimi (durum, sorumlu, tarih)
   parmağın yarısı kadar bir şeride indiriyordu — ölçüm turu üç ekranda da
   bunu yakaladı.

   Hizanın burada ödediği bedel zaten düşük: telefonda panel tam ekran bir
   sheet ve satır 419 pikselin altında kendi kolonuna iniyor, yani etiket
   ile değer artık yan yana değil. Kaybedilen hizadan çok, kazanılan hedef
   önemli. */
@media (pointer: coarse) {
  .panel-row .quick-form .select-btn,
  .panel-row .quick-form .input-sm {
    min-height: var(--tap);
    padding-block: var(--sp-2);
  }
  .panel-row > dd { min-height: var(--tap); }
}

/* Gövdenin panel açıkken hangi durumda olduğunu söyleyen kanca. */
body.has-panel { --panel-w: clamp(500px, 36vw, 560px); }


/* --- 8b. Yerinde düzenleme -------------------------------------------- */

/* Ayrı bir "Düzenle" sayfasına gitmek, tek bir telefon numarasını
   düzeltmek için üç sayfa geçişi demekti: listeden ayrıntıya, ayrıntıdan
   forma, formdan geri. Alan artık okunduğu yerde düzenlenir.

   Görünen hâl bir *düğme*dir, girdi değil. Yirmi tane çerçeveli input
   yan yana durduğunda panel bir forma dönüşüyor ve okunması gereken veri
   okunmuyordu. Çerçeve yalnız düzenlemeye geçilince gelir. */
.inline-edit { display: block; min-width: 0; }

.inline-view {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: 28px;
  padding: 2px var(--sp-2);
  margin-left: calc(var(--sp-2) * -1);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: text;
  overflow-wrap: anywhere;
}
.inline-view:hover { background: var(--surface-soft); border-color: var(--border); }
.inline-view:focus-visible { outline: none; box-shadow: var(--focus-ring); border-color: var(--brand-border); }
.inline-view .icon { flex: 0 0 auto; opacity: 0; color: var(--text-muted); transition: opacity var(--dur-1); }
.inline-view:hover .icon,
.inline-view:focus-visible .icon { opacity: 1; }
/* Dokunmatikte hover yok: kalem ikonu hep görünür, yoksa alanın
   düzenlenebilir olduğu hiçbir yerden anlaşılmaz. */
@media (hover: none) {
  .inline-view .icon { opacity: .6; }
}
.inline-view.is-empty { color: var(--text-muted); }

.inline-form { display: flex; flex-direction: column; gap: var(--sp-2); }
.inline-form-row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.inline-form .input,
.inline-form .textarea,
.inline-form .select { width: 100%; }

/* Görünürlük kuralı. Betik varken görünen hâl düğmedir; form yalnız o alan
   düzenlemeye alınınca (`is-editing`, app.js) açılır. Bu kural yazılmadığı
   sürece düğme ile form aynı anda çiziliyordu: panel bir forma dönüşüyor,
   okunacak veri okunmuyor ve mobilde ekran gereksiz uzuyordu.

   Betiksiz tarayıcıda tersi geçerli: düğme hiçbir şey yapamayacağı için
   gizlenir, form açık durur. "Bu alan düzenlenebilir" vaadi her iki durumda
   da tutulur; değişen yalnız görünüşüdür. */
html.js .inline-edit .inline-form { display: none; }
html.js .inline-edit.is-editing .inline-form { display: flex; }
html.js .inline-edit.is-editing .inline-view { display: none; }
html:not(.js) .inline-view { display: none; }


/* --- 8c. İskelet ve kaydetme göstergesi -------------------------------- */

.skeleton-stack {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.skeleton-stack .skeleton { height: 14px; }
.skeleton-stack .skeleton:first-child { height: 20px; }

/* `prefers-reduced-motion` altında shimmer durur ve iskelet donuk gri bir
   blok olarak kalır — hareketsiz ama yine de "burada içerik olacak"
   diyen bir yer tutucu. Boş bırakmak yerine bu tercih edildi. */
@media (prefers-reduced-motion: reduce) {
  .skeleton { background: var(--surface-sunken); }
}

/* Kaydetme sırasındaki küçük ilerleme göstergesi.

   Düğmedeki çark (`.btn.is-busy`) yetmiyor: panelde bir seçici
   değiştirildiğinde form kendiliğinden gidiyor ve basılan bir düğme
   olmuyor. İnce çizgi kabın üst kenarında koşar, yer kaplamaz ve
   içeriği oynatmaz. */
/* `position: relative` **verilmiyor**. Verilseydi kayıt paneli
   (`position: fixed`) kaydetme sırasında akışa düşer, ekranın ortasına
   zıplardı. Çizginin ihtiyacı olan tek şey konumlanmış bir ata; panel
   zaten `fixed`, çekmece için `.drawer`a kalıcı `relative` verildi
   (`base.css`). Geçici bir sınıfın kalıcı bir yerleşimi değiştirmesi
   her zaman kaza olur. */
.is-saving::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  z-index: 2;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, transparent, var(--brand), transparent);
  background-size: 40% 100%;
  background-repeat: no-repeat;
  animation: kaydediliyor 1s var(--ease) infinite;
}
@keyframes kaydediliyor {
  from { background-position: -40% 0; }
  to { background-position: 140% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .is-saving::before { animation: none; background: var(--brand-soft); background-size: 100% 100%; }
}


/* --- 9. Düzenlenebilir durum: renk noktası + hayalet seçici ----------- */

/* Durum hem *okunacak* hem *değiştirilecek* bir alan. Seçiciyi sakinleştirip
   rengi tamamen atmak, listenin tek bakışta taranabilirliğini götürüyordu;
   rengi bırakıp seçiciyi bırakmak da eski gürültüye dönmekti.

   Çözüm ikisini ayırmak: renk noktası göstergenin işi, seçici düzenlemenin.
   Nokta her zaman görünür (durum bir bakışta okunur), seçici satır üzerine
   gelinene kadar çerçevesizdir. `.status-*` sınıfları noktanın rengini
   verdiği için burada yalnız ölçü tanımlanır. */
.quick-status {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  /* Faz 27: dolgu buraya da geldi — aynı durum listede ve detayda aynı
     yoğunlukta okunsun. Çerçeve yok (bkz. `.status` bloğundaki not:
     içindeki seçici hover'da kendi çerçevesini alıyor). */
  padding: 2px var(--sp-2);
  border-radius: var(--r-pill);
  background: var(--st-fill);
  color: var(--st-ink);
}
/* Rengi bilerek **vermiyor**: `.status-*` kuralları yukarıda, bu kuralın
   önünde duruyor ve özgüllükleri eşit. Burada bir `background` yazılsa
   sonra geldiği için tonu ezer, bütün noktalar griye dönerdi. Ton sınıfı
   her zaman birlikte basılır (`class="quick-status status-{{ tone }}"`). */
.quick-status > .dot-mark {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--st-fill);
}
.quick-status .quick-form { min-width: 0; }


/* --- 10. Seçim çubuğu: araç çubuğunun yerine geçen tek satır ---------- */

/* Toplu işlem çubuğu listenin dibindeyken iki sorun vardı: seçim yapmak
   için yukarıda, uygulamak için aşağıda durmak gerekiyordu; ve çubuk
   açıldığında sayfa aşağı kayıp satırların yerini değiştiriyordu.

   Şimdi araç çubuğuyla **aynı yeri** paylaşıyor. Seçim başlayınca arama /
   sıralama / süzgeç satırı gizlenir, seçim çubuğu onun yerinde belirir:
   ekran zıplamaz, göz aynı noktada kalır.

   Mobilde kural değişmiyor — orada çubuk zaten ekranın altına yapışıyor
   (yukarıdaki `@media (max-width: 899px)` bloğu) ve başparmağın altında
   durması doğru davranış. */
@media (min-width: 900px) {
  /* Çubuk üç bloğun toplamı değil, tek bir **denetim satırı**dır: soldaki
     özne, ortadaki alanlar ve sağdaki düğmeler aynı alt çizgiye oturur.
     Bloklar kendi içinde ortalandığında (`align-items: center`) boyları
     farklı olduğu için — özne iki satır, alan etiket+kutu, düğme tek kutu —
     hiçbir denetim diğeriyle aynı hizaya gelmiyor, çubuk "biri yukarıda
     biri aşağıda" okunuyordu. Hizayı alt kenar verir: etiket iki satıra
     kırılsa bile kutular yerinden oynamaz. */
  .filters-shell > .bulk-bar {
    --bulk-ctl-h: 36px;  /* `.select-shell.is-sm .select-btn` ile aynı */
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--sp-3) var(--sp-4);
    margin-top: 0;
    padding: var(--sp-3) var(--sp-4);
  }

  /* Sayım ve kapsam seçimi solda, sabit genişlikte: alanlar sayıca
     değiştiğinde (firma 3, görev 4 alan) sayım yerinden oynamasın. İnce
     dikey çizgi "neyi seçtim"i "ne yazacağım"dan ayırır; ayırıcı olmadan
     iki metin, alan etiketleriyle aynı sütun dizisinin parçası gibi
     okunuyordu. */
  .filters-shell > .bulk-bar .bulk-head {
    flex: 0 0 auto;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    align-self: stretch;
    gap: 2px;
    padding-right: var(--sp-4);
    border-right: 1px solid var(--brand-border);
  }

  /* Seçim sayısı çubuğun öznesidir: "neyi" güncellediğini söyleyen tek
     metin o. Kapsam kutucuğu onun dipnotu — ve iki satır **aynı** sol
     kenardan başlar: kutucuk metnin soluna taşarsa üstteki sayı içeri
     kaçmış gibi duruyor, blok kendi içinde kayık okunuyordu. */
  .filters-shell > .bulk-bar .bulk-count {
    padding-left: calc(16px + var(--sp-2));
    font-size: var(--fs-md);
    line-height: 1.3;
  }
  .filters-shell > .bulk-bar .bulk-scope { min-height: 0; font-size: var(--fs-xs); }
  .filters-shell > .bulk-bar .bulk-scope input { width: 16px; height: 16px; }

  /* Alanlar eşit genişlikte. Taban `150px` verildiğinde artan yer eşit
     paylaşılsa da başlangıç farkı kalıyor, uzun içerikli alan komşusundan
     geniş çıkıyordu; taban 0 olunca üçü de aynı ölçüde çizilir. */
  .filters-shell > .bulk-bar .bulk-fields {
    flex: 1 1 auto;
    align-items: flex-end;
    gap: var(--sp-3) var(--sp-4);
  }
  .filters-shell > .bulk-bar .bulk-field { flex: 1 1 0; min-width: 150px; gap: 4px; }
  .filters-shell > .bulk-bar .bulk-actions { flex: 0 0 auto; gap: var(--sp-2); }

  /* Çubuk bir *form* değil bir *şerit*: alan etiketleri tam boy form
     etiketi gibi yazıldığında (14px/600) çubuğu üç satıra çıkarıyor ve
     asıl bilgiyle — kaç kayıt seçildiğiyle — aynı ağırlıkta okunuyordu.
     Burada etiket bir başlık değil, alanın adı. */
  .filters-shell > .bulk-bar .field-label {
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: 1.2;
    color: var(--text-secondary);
  }

  /* Üç denetim de aynı yükseklikte: 30 ile 36 piksel yan yana durduğunda
     göz tek satır değil iki kademe görüyor. Ölçü seçicinin kabuğundan
     gelir, diğerleri ona uyar. */
  .filters-shell > .bulk-bar .bulk-field .select-btn,
  .filters-shell > .bulk-bar .bulk-field .input-sm,
  .filters-shell > .bulk-bar .bulk-field .date-pick-btn,
  .filters-shell > .bulk-bar .bulk-actions .btn { min-height: var(--bulk-ctl-h); }
  .filters-shell > .bulk-bar .bulk-field .date-pick-btn {
    padding: 4px var(--sp-2) 4px var(--sp-3);
    font-size: var(--fs-sm);
  }
  .filters-shell > .bulk-bar .bulk-sep { align-self: center; height: 20px; min-height: 0; }

  /* "Takip tarihini kaldır" kutucuğu alanın **altında** üçüncü bir satır
     açıyor ve çubuğun boyunu tek başına belirliyordu (diğer alanlar iki
     satır, bu üç). Etiket satırının sağına alındı: aynı alana ait iki
     bilgi, aynı hizada. Yerleşim açıkça yazılır — otomatik yerleştirme
     denetimi etiketin yanına koyardı. Kutucuk artık alanın sağ kenarına
     yapışır (denetim de tam genişlikte olduğu için) — daha önce dar
     tetikleyicinin metrelerce sağında, sahipsiz bir kutu gibi duruyordu. */
  .filters-shell > .bulk-bar .bulk-field:has(.bulk-clear) {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: var(--sp-2);
    row-gap: 4px;
    align-items: center;
  }
  .filters-shell > .bulk-bar .bulk-field:has(.bulk-clear) > .field-label {
    grid-column: 1;
    grid-row: 1;
  }
  .filters-shell > .bulk-bar .bulk-field:has(.bulk-clear) > .bulk-clear {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }
  .filters-shell > .bulk-bar .bulk-field:has(.bulk-clear)
    > :not(.field-label):not(.bulk-clear) {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  /* Kutucuk etiket satırında duruyor: 18 px'lik kutu o satırı komşu
     alanların etiket satırından yüksek yapıyor ve alttaki denetimi tek
     başına aşağı itiyordu. Dokunma hedefi kuralı burada geçerli değil —
     telefonda çubuk bambaşka (ekrana yapışan) bir düzende çiziliyor. */
  .filters-shell > .bulk-bar .bulk-clear { line-height: 1.2; }
  .filters-shell > .bulk-bar .bulk-clear input { width: 14px; height: 14px; margin: 0; }

  /* Tek satıra sığması için ikincil açıklama masaüstünde düşer; kural zaten
     her alanın "değiştirme" seçeneğinde yazılı. */
  .filters-shell > .bulk-bar .bulk-actions .xsmall { display: none; }

  /* Geniş ama dokunmatik ekran (tablet, dokunmatik dizüstü): ortak ölçü
     tam dokunma hedefine çıkar. Hiza kuralı değişmez — tek bir değişkeni
     büyüttüğü için üç denetim yine aynı boyda kalır. Aynı sebeple kutucuk
     da küçültülmez. */
  @media (pointer: coarse) {
    .filters-shell > .bulk-bar { --bulk-ctl-h: var(--tap); }
    .filters-shell > .bulk-bar .bulk-clear input { width: 18px; height: 18px; }
  }
}


/* --- 11. Menü içindeki hızlı güncelleme (mobil kart) ------------------ */

/* Telefonda durum / sorumlu / tarih alanları karta sürekli yerleşmiyor;
   üç nokta menüsünün başında duruyorlar. Menü dar olduğu için alanlar tam
   genişlikte alt alta dizilir — `.quick-row`un liste içindeki ikişerli
   sarması burada iki daracık kutu üretirdi. */
.row-menu-panel .quick-row {
  flex-direction: column;
  width: auto;
  margin: var(--sp-2) var(--sp-1) var(--sp-2);
  gap: var(--sp-2);
}
.row-menu-panel .quick-row .quick-form { flex: 0 0 auto; width: 100%; }
.row-menu-panel .quick-row .quick-form .select-shell { max-width: none; width: 100%; }
.row-menu-panel .quick-row .quick-form .input-sm { width: 100%; max-width: none; }

/* Menü içindeki alan "hayalet" olmaz: kabı zaten bir menü, saklanacak
   gürültü yok. Üstelik menü satırın *dışında* açıldığı için satır hover'ı
   alanı hiç aydınlatmaz — kural olmasa görünmez kutulara dokunmak
   gerekirdi. */
.row-menu-panel .quick-form .select-btn,
.row-menu-panel .quick-form .input-sm {
  border-color: var(--border-input);
  background: var(--surface);
}
.row-menu-panel .quick-form .select-btn .chevron { opacity: 1; }
.row-menu-panel .quick-form input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: 1;
}

/* Menüdeki alanlar bölümü, altındaki işlem öğelerinden ince bir çizgiyle
   ayrılır: "değiştir" ile "git / sil" farklı ağırlıkta kararlar. */
.row-menu-panel .quick-row + form,
.row-menu-panel .quick-row + .dropdown-item {
  border-top: 1px solid var(--border);
  margin-top: var(--sp-1);
  padding-top: var(--sp-1);
}


/* --- 12. Boş tarih alanı: ipucu değil tire ---------------------------- */

/* Boş bir `<input type="date">` tarayıcının biçim ipucunu gösterir:
   "dd.mm.yyyy". Alan çerçeveliyken bu bir ipucudur; çerçevesizken (sakin
   liste) veri sanılan bir metne dönüşür — yirmi satırda yirmi kez, hiçbiri
   tarih değil. Kolon boş görünmeli ve diğer boş hücrelerle aynı dili
   konuşmalı: tire.

   İpucu kaldırılmıyor, **erteleniyor**: satırla ilgilenildiği anda (üzerine
   gelme, odak) alan kendini normal bir tarih alanı olarak gösterir. */
.quick-form { position: relative; }

.quick-form.is-empty > input[type="date"] { color: transparent; }

.quick-empty {
  position: absolute;
  left: var(--sp-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}

.table tbody tr:hover .quick-form.is-empty > input[type="date"],
.table tbody tr:focus-within .quick-form.is-empty > input[type="date"],
.quick-form.is-empty > input[type="date"]:focus,
.row-menu-panel .quick-form.is-empty > input[type="date"],
.quick-pop-panel .quick-form.is-empty > input[type="date"] {
  color: var(--text);
}
.table tbody tr:hover .quick-empty,
.table tbody tr:focus-within .quick-empty,
.quick-form.is-empty:focus-within .quick-empty,
.row-menu-panel .quick-empty,
.quick-pop-panel .quick-empty {
  display: none;
}

/* Dokunmatikte hover yok; alanlar zaten çerçeveli çizildiği için ipucu da
   normal biçimde görünür. */
@media (hover: none) {
  .quick-form.is-empty > input[type="date"] { color: var(--text); }
  .quick-empty { display: none; }
}


/* ==========================================================================
   Aktivite akışı (Faz 10)
   --------------------------------------------------------------------------
   Notlar, yorumlar, iletişim geçmişi ve sistem hareketleri tek kronoloji.
   Süzgeç ve ekleme kipi gizli radyo düğmeleriyle çalışır: betiksiz de
   çalışsın diye. Bedeli, seçili durumu her tür için ayrı kuralla yazmak —
   `:checked + label` kullanılamıyor, çünkü radyolar kardeş seçicinin
   ulaşabilmesi için etiketlerinden ayrı bir düzeyde duruyor.
   ========================================================================== */

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

/* --- Ekleme alanı: üç kip, tek yüzey --------------------------------- */

.composer {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.composer-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Şerit kaydırılabilir: 360 px'te üç kip yan yana sığmıyor ve sarmak
   çubuğu iki satıra çıkarıp altındaki formu aşağı itiyordu. */
.composer-tabs {
  display: flex;
  gap: var(--sp-1);
  padding: var(--sp-2);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}
.composer-tabs::-webkit-scrollbar { display: none; }

.composer-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 0 0 auto;
  min-height: 36px;
  padding: 0 var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-1), color var(--dur-1);
}
.composer-tab:hover { background: var(--surface-soft); color: var(--text); }
.composer-tab .icon { flex: 0 0 auto; }

.composer-panes { padding: var(--sp-3); }
.composer-pane { display: none; }

/* Kip başına üç kural: seçili görünüm, odak halkası, açık pane. */
#kip-note:checked ~ .composer-tabs [for="kip-note"],
#kip-comment:checked ~ .composer-tabs [for="kip-comment"],
#kip-contact:checked ~ .composer-tabs [for="kip-contact"] {
  background: var(--selected);
  color: var(--brand);
}
#kip-note:focus-visible ~ .composer-tabs [for="kip-note"],
#kip-comment:focus-visible ~ .composer-tabs [for="kip-comment"],
#kip-contact:focus-visible ~ .composer-tabs [for="kip-contact"] {
  box-shadow: var(--focus-ring);
}
#kip-note:checked ~ .composer-panes > [data-kip="note"],
#kip-comment:checked ~ .composer-panes > [data-kip="comment"],
#kip-contact:checked ~ .composer-panes > [data-kip="contact"] {
  display: block;
}

.composer-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding-top: var(--sp-1);
}

/* Yazma alanı dinlenme hâlinde tek satır.

   Ekleme alanı ayrıntı ekranının **üstünde** duruyor ve açıkken üç satırlık
   bir kutu, kesik çizgili dosya yüzeyi, bir onay kutusu ve bir düğme
   kaplıyordu: yaklaşık 260 piksel, yani ilk ekranın yarısı. Oysa o ekrana
   gelenlerin çoğu bir şey yazmaya değil, olan biteni okumaya geliyor —
   akış, kendisini yazma formunun altından bakarak gösteriyordu.

   Açılma koşulu odak: alana tıklayan (ya da Tab'la gelen) kişi tam formu
   görür, düğme dahil — `:focus-within` düğmeye basarken de sürer.
   Doğrulama hatasında form odaksız yeniden çizilir, o yüzden `:has(...)`
   ile hata varsa alan açık kalır; yoksa kullanıcı hatayı görür ama
   düzeltip gönderecek düğmeyi göremezdi.

   Yalnız not ve yorum katlanır: iletişim kaydı çok alanlı bir formdur,
   onun yarısını gizlemek kısaltmak değil sakatlamak olurdu. */
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="note"] .textarea,
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="comment"] .textarea {
  /* 44 = 10 + 22 + 10 + 2 (dolgu + satır + dolgu + çerçeve) ve aynı
     zamanda `--tap`. Tabanın 12 piksellik üst dolgusu bu yükseklikte
     satırı aşağı itip yer tutucuyu kırpıyordu — alan boş görünüyor,
     tıklanacak yer olduğu hiç belli olmuyordu. */
  height: var(--tap);
  min-height: 0;
  padding-top: 10px;
}
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="note"] .field-hint,
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="note"] .upload-drop,
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="note"] .composer-actions,
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="comment"] .upload-drop,
.composer:not(:focus-within):not(:has(.field-error)) .composer-pane[data-kip="comment"] .composer-actions {
  display: none;
}
@media (prefers-reduced-motion: no-preference) {
  .composer-pane .textarea { transition: height 120ms ease-out; }
}

/* --- Süzgeç şeridi ---------------------------------------------------- */

.feed-filter-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.feed-filters {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  scrollbar-width: none;
  /* Kaydırılabilir şeridin son çipi ekran kenarında yarım kalmasın. */
  padding-right: var(--sp-4);
  scroll-padding-inline: var(--sp-4);
}
.feed-filters::-webkit-scrollbar { display: none; }

.feed-filter {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 0 0 auto;
  min-height: 32px;
  padding: 0 var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-1), border-color var(--dur-1), color var(--dur-1);
}
.feed-filter:hover { border-color: var(--border-strong); color: var(--text); }
/* Şerit, altındaki listeyle **aynı** dili konuşur.

   Akış satırlarının ikonu türüne göre renklenince şerit yarım kaldı: aynı
   dört türü adıyla sayan çipler tamamen nötrdü. Kullanıcı "Notlar"a basıp
   aşağıda turkuaz ikonlar görüyordu ve iki gösterge arasında görsel bir
   bağ yoktu — renk bir yerde başlayıp bir yerde bitiyorsa kural değil kaza
   gibi okunur.

   Nokta `::before` ile geliyor, şablona yeni bir eleman eklenmeden:
   çipin kimliği zaten `for` özniteliğinde yazılı. "Hepsi" çipi bilerek
   noktasız — bir tür değil, türlerin yokluğu. */
.feed-filters [for="suz-contact"]::before,
.feed-filters [for="suz-note"]::before,
.feed-filters [for="suz-comment"]::before,
.feed-filters [for="suz-activity"]::before {
  content: "";
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
}
.feed-filters [for="suz-contact"]::before { background: var(--warn); }
.feed-filters [for="suz-note"]::before { background: var(--neutral-accent); }
.feed-filters [for="suz-comment"]::before { background: var(--info); }
.feed-filters [for="suz-activity"]::before { background: var(--text-muted); }
.feed-filter .count {
  color: var(--text-muted);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

#suz-hepsi:checked ~ .feed-filters [for="suz-hepsi"],
#suz-contact:checked ~ .feed-filters [for="suz-contact"],
#suz-note:checked ~ .feed-filters [for="suz-note"],
#suz-comment:checked ~ .feed-filters [for="suz-comment"],
#suz-activity:checked ~ .feed-filters [for="suz-activity"] {
  /* Nötr dolu: bir süzgeç sekmesi, sayfadaki birincil eylemle aynı
     ağırlıkta görünemez. `.filter-opt` ile tek karar. */
  background: var(--text-primary);
  border-color: var(--text-primary);
  color: var(--surface);
}
#suz-hepsi:checked ~ .feed-filters [for="suz-hepsi"] .count,
#suz-contact:checked ~ .feed-filters [for="suz-contact"] .count,
#suz-note:checked ~ .feed-filters [for="suz-note"] .count,
#suz-comment:checked ~ .feed-filters [for="suz-comment"] .count,
#suz-activity:checked ~ .feed-filters [for="suz-activity"] .count {
  /* Dolu zemindeki ikincil sayı: rengi temadan alır, sessizliği
     opaklıktan. Sabit beyaz, koyu temada açık indigo zeminin üstünde
     görünmez oluyordu. */
  color: var(--text-on-brand);
  opacity: .75;
}
/* Seçili çipin zemini koyu mürekkep: 600 basamağındaki tür renkleri onun
   üstünde okunmaz. Nokta burada rengini değil **varlığını** korur — hangi
   türde olduğunu zaten seçili çip söylüyor; renk kanalı asıl işini
   seçilmemiş çiplerde, yani gözün taradığı yerde yapıyor. Sayının
   opaklık kuralıyla aynı karar. */
#suz-contact:checked ~ .feed-filters [for="suz-contact"]::before,
#suz-note:checked ~ .feed-filters [for="suz-note"]::before,
#suz-comment:checked ~ .feed-filters [for="suz-comment"]::before,
#suz-activity:checked ~ .feed-filters [for="suz-activity"]::before {
  background: var(--text-on-brand);
  opacity: .75;
}
#suz-hepsi:focus-visible ~ .feed-filters [for="suz-hepsi"],
#suz-contact:focus-visible ~ .feed-filters [for="suz-contact"],
#suz-note:focus-visible ~ .feed-filters [for="suz-note"],
#suz-comment:focus-visible ~ .feed-filters [for="suz-comment"],
#suz-activity:focus-visible ~ .feed-filters [for="suz-activity"] {
  box-shadow: var(--focus-ring);
}

/* Süzme. `display: none` seçildi, `visibility` değil: gizlenen satır yer
   kaplamamalı, yoksa "Notlar" süzgeci sayfayı kısaltmaz, yalnız
   boşaltırdı. */
#suz-contact:checked ~ .feed-list > .feed-item:not([data-tur="contact"]),
#suz-note:checked ~ .feed-list > .feed-item:not([data-tur="note"]),
#suz-comment:checked ~ .feed-list > .feed-item:not([data-tur="comment"]),
#suz-activity:checked ~ .feed-list > .feed-item:not([data-tur="activity"]) {
  display: none;
}

/* --- Düzen notu ---------------------------------------------------------
   Panonun ızgarası `.today-layout` → `.overview` → `.dash` diye iki kez
   taşındı (bu dosyanın sonundaki "12 kolonlu ızgara" bloğu). Eski kuralın
   **gerekçesi** hepsinde korundu: yan yana duran iki *değişken boylu*
   kolonda kısa kalan tarafın yanında kart boyu boşluk kaçınılmazdır. 12
   kolonlu düzende bunun karşılığı `align-items: start` + `max-height`:
   kolonlar birbirinin boyuna uzamaz, uzayan kart kendi içinde kayar.

   Kaldırılan bir kural var: özetin yapışkanlığı (`position: sticky`). Bir
   kolonun yapışkan olması, yanındakinin ondan uzun olmasını gerektirir;
   ızgarada artık iki kolon da sınırlı boyda. */

/* --- Bugün: tek akış --------------------------------------------------- */

.today-flow { display: flex; flex-direction: column; overflow: hidden; }

/* Grup başlığı bölüm başlığı değil: "Bugün" zaten bölümün adı, bunlar onun
   üç parçası. Üç kez daha `section-head` çizmek ekranda dördüncü bir
   hiyerarşi basamağı uydurmak olurdu; akış içinde ayırıcı bir şerit yeter. */
.today-group-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  margin: 0;
  padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface-sunken);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
  /* Kartın kendi kaydırmasında ekranda kalır — satırların sol kenarındaki
     renkli şerit bunun yerine duruyordu (gerekçe aşağıda, `.today-row`).
     Zemin opak olmak zorunda: saydam bir yapışkan başlık, altından geçen
     satırla üst üste biner. `z-index` 40'ın altında kalmalı, yoksa
     satırdan açılan popover başlığın arkasına düşer. */
  position: sticky;
  top: 0;
  z-index: 1;
}
.today-group-head .icon { flex: none; width: 16px; height: 16px; color: var(--text-muted); }
/* Grup ikonu türün rengini taşır; aynı renk aşağıda satırların sol kenarında
   tekrar eder. İkisi de uygulamanın genelindeki `kind-task` / `kind-company`
   renkleridir — pano kendine ayrı bir renk dili uydurmuyor. */
.today-group-head.is-task .icon { color: var(--kind-task); }
.today-group-head.is-followup .icon { color: var(--kind-company); }
/* Faz 27 — başlık da türün tonunu taşıyor.

   Faz 26'da satırların sol kenarındaki renkli şerit kaldırılmış, yerine bu
   başlık yapışkan yapılmıştı: tür satır başına değil **grup başına bir kez**
   söylenecekti. Doğru karardı ama yarım kaldı — başlık türü söylüyor, rengi
   söylemiyordu; tür rengi tek bir 16 piksellik ikonda kalıyordu.

   Dolgu tam buraya ait: kapsayıcıya ad veren bir yüzey, satırın kendisi
   değil. On satırlık kartta boyanan alan hâlâ iki şerit; ama artık "bugünün
   görevleri" bloğu mavi, "takipler" bloğu amber okunuyor ve bu, kaydırırken
   kaybolmayan tek işaret. Şeridin çözdüğü sorunun gerçek çözümü buydu. */
.today-group-head.is-task {
  background: var(--kind-task-fill);
  border-bottom-color: var(--kind-task-line);
  color: var(--kind-task-ink);
}
.today-group-head.is-followup {
  background: var(--kind-company-fill);
  border-bottom-color: var(--kind-company-line);
  color: var(--kind-company-ink);
}
/* Başlıktaki sayı ve nokta kendi zeminine göre hizalanır; `--text-secondary`
   tonlu zeminde kaybolan tek parçaydı. */
.today-group-head.is-task .dash-count,
.today-group-head.is-followup .dash-count { color: inherit; }
.today-group-head.is-task { --dot-ring: var(--kind-task-fill); }
.today-group-head.is-followup { --dot-ring: var(--kind-company-fill); }
/* Grubun sayısı kart başlığındakiyle **aynı yuva**: `.dash-count`. Eskiden
   burada dolu zeminli küçük bir hap vardı ve kartın kendi sayısı soluk bir
   `.muted small`dı — aynı bilgi, iki farklı ağırlık, iki farklı kap. Hap
   düştü; grup başlığı zaten kendi zemini ve büyük harfleriyle ayrılıyor,
   içindeki sayının ikinci bir kaba ihtiyacı yok. */
.today-group-head .dash-count { color: var(--text-secondary); }
/* Grup başlığından önce her zaman bir çizgi olur ama **iki tane** olmaz:
   satırların alt çizgisi başlığın üst çizgisini gereksiz kılar, boş grubun
   ise alt çizgisi yoktur. */
.empty-state + .today-group-head { border-top: 1px solid var(--border); }

/* Satır <div>, başlık bağlantı: HTML bağlantı içinde düğme yasaklar ve
   satırın meta şeridi artık popover tetikleyicileri taşıyor. */
.today-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 44px;
  padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--border);
  min-width: 0;
  transition: background-color var(--dur-1) var(--ease-out);
}
.today-row:last-child { border-bottom: 0; }
.today-row:hover { background: var(--surface-soft); }

/* Satırın sol kenarında tür rengi taşıyan 3 piksellik bir şerit vardı.
   Çözdüğü sorun gerçekti — kart 340 pikselde sınırlı, grup başlığı yukarı
   kayınca geriye birbirinin aynı satırlar kalıyor ve "bu bir görev mi,
   takip mi" sorusu ancak başa dönülerek cevaplanıyordu.

   Ama bedeli de gerçekti: on satırlık bir kartta kartın sol kenarı boydan
   boya renge dönüyordu. Aynı gerekçeyle ajandadaki çizgi Faz 25'te
   kaldırılmıştı; burada duruyor olması tutarsızlıktı.

   Sorunun kaynağı **rengin eksikliği değil, başlığın kaybolmasıydı**; o
   yüzden düzeltme de orada: grup başlığı kartın kendi kaydırmasında
   yapışkan durur. Tür bilgisi kaydırma boyunca ekranda kalır (üstelik
   satır başına değil, grup başına bir kez) ve satırlar boyanmaz.

   Kuralın kendisi başlığın asıl tanımında (yukarıda) duruyor; burada
   ikinci bir blok açmak, `background`u orada bırakıp `position`u burada
   tutmak olurdu ve yapışkan bir başlığın saydam kalması tam olarak
   gözden kaçan kusurdur. */

.today-check { flex: none; }
/* Panoda tamamlama halkası 32 yerine 26 piksel. İş ayrıntısındaki görev
   listesinde 32 doğru ölçü — orada tamamlamak sayfanın **asıl** işi. Panoda
   satırın asıl işi kaydı açmak; boş bir 32 piksellik halka, iki satırlık bir
   satırda başlıktan daha ağır duruyordu.

   Yalnız fare için: dokunmatikte hedef `--tap` (44/48 px) kalır, onu
   aşağıdaki `pointer: coarse` bloğu veriyor. */
@media (pointer: fine) {
  .today-check .task-check { width: 26px; height: 26px; }
  .today-check .task-check .icon { width: 14px; height: 14px; }
}

.today-row-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
  /* Gerilmiş bağlantının kapsayıcı bloğu (aşağıdaki `::after`). Satırın
     kendisi değil: tıklama alanı satırın tamamını kaplıyordu ve onay
     kutusunun çevresi, sağdaki tarih hücresi, satırın dolgusu — hepsi
     "kaydı aç" sayılıyordu. */
  position: relative;
}

/* Tarih sağ kolonda. Satırların sağ yarısı boş duruyordu; tarih sağa
   geçince bütün satırlarınki aynı dikey hizaya oturuyor ve gecikmişler tek
   sütun taranarak bulunuyor (aynı kalıp "Yaklaşan teslimler"de de var).

   Gerilmiş bağlantının **dışında**: buradaki değer kendi popover'ını açar
   ve satırı açmaz. */
.today-row-aside {
  flex: none;
  display: flex;
  align-items: center;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
/* --- Kayıt adının rengi (Faz 24) --------------------------------------
   Aynı firma, aynı iş; listede marka renginde, panoda siyah yazılıyordu.
   Masaüstü tablolarındaki ad çıplak bir `<a>` olduğu için tabanın bağlantı
   rengini alıyor (`base.css`), pano satırları ve mobil kartlar ise adı bir
   kapsayıcı bağlantının içine koyduğu için `color: inherit` ile taban
   metin rengine düşüyordu. Fark biçimsel bir kazadan geliyordu, karardan
   değil.

   Karar şu: **kayıt adı marka renginde yazılır** — kaydın kendisine giden
   kapı odur ve listede göz onu arar. Renk tek başına bilgi taşımaz
   (tıklanabilirliği imleç, satır vurgusu ve alt çizgi de söyler), bu yüzden
   tasarım sisteminin 1. bölümüne aykırı değil; taşıdığı şey ekranlar arası
   tutarlılık. Meta satırı (durum, tarih, ikincil ad) dışarıda kalır: orası
   bağlantı değil bağlamdır.

   --- Faz 29: renk değişti, kural durdu -------------------------------------
   Faz 24'ün asıl kazancı "kayıt adı **her ekranda aynı** yazılır" kuralıydı
   ve o duruyor — aşağıdaki seçici listesi hâlâ tek bir bildirime bağlı.
   Değişen, o bildirimin değeri.

   Sebep ölçek: bu seçici listesi uygulamanın en kalabalık metnini boyuyor.
   Yirmi satırlık bir listede yirmi mor ad, panoda dört, takvimde bir düzine
   daha... "Marka rengi = birincil eylem" kuralı böyle bir hacimde ayakta
   kalamıyor; mor, ekranın **taban metin rengi** hâline geliyor ve asıl
   birincil eylem (tek bir dolu düğme) onun içinde kayboluyordu. Renk nadir
   olduğu ölçüde işaret; her yerdeyken yalnızca bir ton.

   Kayıt adı artık mürekkep ve **600 ağırlıkta** yazılıyor: satırdaki meta
   metninden (400) ağırlıkla ayrışıyor, tıklanabilirliğini imleç, satır
   vurgusu ve hover'daki alt çizgi + mor söylüyor. Yani üç ayrı işaret
   kaybolmadı, yalnızca dördüncüsü (istirahatteki renk) geri alındı. */
.today-row-title,
a.list-row .list-row-title,
.list-row-link .list-row-title,
.feed-mini-title,
.cell-title a {
  color: var(--text-primary);
  font-weight: var(--fw-semibold);
}
/* Hover'da mor **geri geliyor**: rengin eylemle bağı kopmuyor, yalnız
   istirahatte susuyor. Alt çizgi zaten `base.css`teki `a:hover`tan geliyor;
   kapsayıcı bağlantıların içindeki başlıklar için burada tekrarlanıyor. */
a.list-row:hover .list-row-title,
.list-row-link:hover .list-row-title,
.cell-title a:hover,
.today-row:hover .today-row-title,
.today-row-title:hover,
.feed-mini:hover .feed-mini-title { color: var(--brand); }

/* Satır başlığı kart başlığıyla **yarışmaz**. İkisi de 15 px/600'dü; kayıt
   adı marka rengini alınca eşitlik bozuldu ve satırlar kartın kendi
   başlığından daha baskın okunmaya başladı ("Bugün"ün altındaki dört ad, üst
   şeritten daha güçlü). Ad bir basamak aşağı iner: 15 → 13 px. Ağırlık ve
   renk yerinde kalır, yani satır hâlâ kartın en belirgin metnidir — ama
   kapsayıcısının altında durur.

     15 px / 600  kart başlığı  (Bugün · Yaklaşan teslimler)
     13 px / 600  kayıt adı     (marka renginde, tıklanır)
     13 px / 400  meta          (durum · tarih · ikincil ad)

   Tek basamak: ad ile meta arasındaki farkı punto değil ağırlık ve renk
   taşır — üç ayrı punto, satırı merdivene çevirirdi. */
.today-row-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.35;
}
/* Pano kartlarının liste satırları (Yaklaşan teslimler, huni) aynı ölçüyü
   izler; liste *ekranları* dışarıda kalır — orada satır, sayfanın kendisidir
   ve üstünde yarışacak bir kart başlığı yoktur. */
.dash-card .list-row-title { font-size: var(--fs-sm); }
.today-row-title:hover { text-decoration: underline; }
.today-row-meta {
  display: flex;
  /* Tek satır ve taşan **kırpılır**. Sarmalı bırakıldığında satır üçe
     çıkıyordu: uzun bir iş adı kendi satırına düşüyor, önündeki ayırıcı
     nokta bir önceki satırın sonunda yalnız kalıyordu. Taşan şey burada
     ikincil bir bağlam (işin adı) ve `.truncate` onu üç noktayla bitiriyor —
     satır boyu sabit kalıyor, kart daha çok kayıt gösteriyor.

     Dokunmatikte sarma geri geliyor (aşağıdaki `pointer: coarse` bloğu):
     orada meta şeridi 44 piksellik bir dokunma bandı ve içindeki çipler
     kırpılmak yerine alt satıra inmeli. */
  flex-wrap: nowrap;
  overflow: hidden;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  min-width: 0;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.today-row-meta .dot-sep { color: var(--text-muted); }
.today-row-meta > .truncate { min-width: 0; }

/* Aynı sarma kuralı **dar pencerede fareyle** de geçerli.

   Aşağıdaki `pointer: coarse` bloğu bu şeridin üst üste binmesini
   dokunmatik için çözüyor (`flex-wrap: wrap` + `> * { flex: none }`), ama
   kuralı işaretçi türüne bağlamak dar-pencere-fare senaryosunu dışarıda
   bırakıyordu: 400 piksele daraltılmış bir masaüstü penceresinde şerit yine
   ellipsis'siz kesiliyor. Kırpmayı doğuran şey işaretçi değil **genişlik**;
   kural da genişliğe bağlanmalı. Dokunma hedefi boşlukları orada kalıyor —
   onlar gerçekten işaretçinin işi. */
@media (max-width: 480px) {
  .today-row-meta {
    flex-wrap: wrap;
    overflow: visible;
    row-gap: var(--sp-1);
  }
  .today-row-meta > * { flex: none; }
  .today-row-meta > .truncate { flex: 0 1 auto; min-width: 0; }
  .today-row-meta .dot-sep { display: none; }
}

/* --- Satırda dokunma hedefleri ----------------------------------------
   Eskiden satırın tamamı tek bir bağlantıydı (`.today-row-link`) ve parmak
   nereye değerse kayda gidiyordu. Meta şeridi popover düğmeleri taşımaya
   başlayınca o bağlantı bölünmek zorunda kaldı — HTML bağlantı içinde
   düğme yasaklar — ve geriye 20 piksellik bir başlık satırı kaldı.

   Çözüm "gerilmiş bağlantı": başlığın görünmeyen bir ardılı, adın ve
   altındaki meta şeridinin durduğu alanı kaplar; gerçekten tıklanabilir
   olan öğeler (popover tetikleyicileri) onun üstüne çıkar.

   Kapsayıcı blok **satır değil `.today-row-body`** (Faz 15). Satırın
   tamamı kaplanınca tıklama alanı gereğinden büyüyordu: onay kutusunun
   çevresindeki boşluk, sağdaki tarih hücresi ve satırın 16 piksellik yatay
   dolgusu da "kaydı aç" sayılıyordu — tamamlamak isteyip tike yarım piksel
   ıskalayan kullanıcı kendini görev ayrıntısında buluyordu. Şimdi hedef
   tam olarak okunan alan kadar. */
.today-row { position: relative; }
.today-row-title::after {
  content: "";
  position: absolute;
  inset: 0;
}
.today-check,
.today-row-aside .quick-pop,
.today-row-meta .quick-pop { position: relative; z-index: 1; }

@media (pointer: coarse) {
  /* Satır telefonda **iki banda** ayrılır ve ikisi de tam 44 pikseldir:
     üstte kaydın adı (dokununca kayıt açılır), altta değer çipleri
     (dokununca düzenleme popover'ı açılır).

     Ölçülerek bulundu. Önce satırın kendi dikey dolgusu korunmuş, çipe
     `::after` ile 44 piksellik görünmez alan verilmişti; satır 77 piksel
     oluyor ve o 44 piksel ortadan kesince başlığa kesintisiz 26 piksel
     kalıyordu. Yani sayfanın **asıl** eylemi (kaydı aç) ikincil eylemden
     küçük hedefe düşmüştü. İki 44 yan yana ancak 88 piksele sığar; satırın
     kendi dolgusu kalkar, yerini bantların dolgusu alır.

     Görünen çip yine büyütülmez — büyütülseydi satır "sürekli açık kutu"
     görünümüne geri dönerdi (aynı çözüm satır menüsünde de var).

     Sarmalanan meta satırları arasındaki boşluk da bu yüzden açılır: iki
     görünmez 44 piksellik alan üst üste binmemeli. */
  .today-row { align-items: stretch; padding-top: 0; padding-bottom: 0; }
  .today-row-body { gap: 0; }
  /* Faz 25 — **çakışmanın kökü**: burada `display: flex` yazılıydı ve o
     satır, başlığın `.clamp-2` sınıfını sessizce iptal ediyordu. İki satır
     kırpması `display: -webkit-box` ister; kap flex'e dönünce
     `-webkit-line-clamp` hükümsüz kalıyor, `overflow: hidden` ise yerinde
     duruyordu. Sonuç: uzun bir görev adı iki satırda durmak yerine üç-dört
     satıra yayılıyor, sabit yükseklikli kabın içinde kırpılıyor ve sağdaki
     tarih hücresiyle aynı bandı paylaşan meta şeridinin üstüne biniyordu.

     Kırpma geri geliyor, 44 piksellik dokunma hedefi de duruyor: hedefi
     artık `display` değil `min-height` + dikey dolgu veriyor. Metin
     kutunun üstünden başlıyor ve sağdaki tarih de `align-self: flex-start`
     ile üstte — iki sütunun ilk satırı aynı yatayda. */
  .today-row-title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    min-height: var(--tap);
    padding-block: var(--sp-3);
  }
  /* Onay halkası da **ilk banda** yaslanır (tarih hücresiyle aynı kural).
     Esnemeye bırakıldığında satırın tamamı kadar uzuyor ve ortasında
     duruyordu: iki satırlık bir kayıtta halka, adın değil meta şeridinin
     hizasına düşüyor, "hangi satırı tamamlıyorum" sorusu doğuyordu. */
  .today-check {
    margin-top: 0;
    align-self: flex-start;
    min-height: var(--tap);
    display: flex;
    align-items: center;
  }
  .today-row-meta {
    /* Dokunmatikte çipler kırpılmaz, alt satıra iner: her biri kendi
       popover'ını açan bir hedef ve kırpılmış bir hedef dokunulamaz. */
    flex-wrap: wrap;
    overflow: visible;
    gap: var(--sp-5) var(--sp-2);
    padding: var(--sp-3) 0;
  }
  /* Faz 19 — **çakışmanın kökü**: masaüstünde şerit `overflow: hidden`, yani
     esneyip içeriğinden dar kalan bir çip kırpılıyordu. Dokunmatikte taşma
     `visible` (popover'lar dışarı çıkabilsin diye) ve aynı daralma bu kez
     kırpılmıyor, **üstüne biniyordu**: "Devam ediyor" çipi yanındaki iş
     adının üzerine yazılıyordu. Sarma kuralı da devreye girmiyordu, çünkü
     iş adı `min-width: 0` ile sıfıra kadar inebildiği için satır "sığıyor"
     sayılıyordu.

     Kural: çipler **daralmaz** (`flex: none`), yalnız iş adı daralır. Yer
     kalmadığında satır sarar — durum ile bağlı iş alt alta iner, hiçbiri
     diğerinin üstüne binmez. */
  .today-row-meta > * { flex: none; }
  .today-row-meta > .truncate { flex: 0 1 auto; min-width: 0; }
  /* Sarma açıkken ayırıcı nokta bir önceki satırın sonunda tek başına
     kalıyor ("Devam ediyor ·" / "Marmara Diş Kliniği…"). Satır atlaması
     ayrımı zaten yapıyor; nokta yalnız yan yana dizilen bir şeritte iş
     görür. */
  .today-row-meta .dot-sep { display: none; }
  /* Tarih satırın **sağ üstünde**: iki satırlık bir başlıkta ortalanmış
     tarih, başlığın ikinci satırıyla aynı hizaya düşüp "bu tarih hangi
     satırın?" sorusunu doğuruyordu. Üste sabitlenince her satırda başlığın
     ilk satırıyla aynı yatayda duruyor. */
  .today-row-aside { align-self: flex-start; min-height: var(--tap); }
  .quick-pop-btn::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: var(--tap);
    transform: translateY(-50%);
  }
}

/* Akıştaki boş grup: ortalanmış, 56 piksellik ikonlu büyük boş durum kalıbı
   burada çalışmıyor — boş bir çalışma alanında üçü alt alta gelip 500
   pikselden fazla yer kaplıyor ve hiçbiri bilgi taşımıyordu. Aynı metinler
   tek satırlık bir nota iner. */
/* Faz 6: aynı kompakt biçim `.dash-card-body`nin doğrudan çocuğu olan boş duruma da
   uygulanır. "Bugün" bölümünün iki sütununda liste boşken `.today-flow` kabı
   hiç çizilmiyor (kap boş bir çerçeve bırakırdı) ve boş durum tam boyuna
   dönüyordu: iki satırlık bir listenin yerini, ortalanmış büyük ikonlu bir
   blok alıyor ve yanındaki dolu sütunla dengesizleşiyordu. */
.today-flow .empty-state,
.dash-card-body > .empty-state {
  flex-direction: row;
  align-items: center;
  text-align: left;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
}
.today-flow .empty-icon,
.dash-card-body > .empty-state .empty-icon {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
}
.today-flow .empty-icon .icon,
.dash-card-body > .empty-state .empty-icon .icon { width: 18px; height: 18px; }
.today-flow .empty-state h3,
.dash-card-body > .empty-state h3 { font-size: var(--fs-sm); }
.today-flow .empty-state p,
.dash-card-body > .empty-state p { font-size: var(--fs-sm); max-width: none; }

/* (`.metric*` silindi: özet şeridinin üç satırı, panonun ikinci satırındaki
   dört sayaca (`.dash-stat`) dönüştü. Şerit dar bir rayda tek kolon olmak
   üzere tasarlanmıştı; ray kalkınca dayanağı da kalktı.) */

/* (Faz 6 — rayın içindeki dönem formu için yazılan sıkıştırmalar silindi;
   dönem seçici artık rayda değil, sayfa başlığının sağındaki açılırda ve
   orada genişliği `.filter-pop-panel` belirliyor.) */


/* --- Değeri düzenleyen popover ----------------------------------------
   Panoda her kaydın altında sürekli açık iki alan (durum seçici + tarih
   kutusu) duruyordu. Üç kayıtlık bir ekran bile form gibi okunuyordu; göz
   önce kutuları, sonra veriyi görüyordu. Oysa panoda yapılan işin çoğu
   okumaktır.

   Alan kaldırılmadı, ertelendi: satırda **değerin kendisi** yazar, değere
   dokununca aynı `_quick` formu popover içinde açılır. Kalıp yeni değil —
   liste satırlarının mobil üç nokta menüsü hızlı alanları zaten böyle
   taşıyor (`.row-menu-panel`); `[data-menu]` davranışı, `Escape`, dışarı
   tıklama ve odak dönüşü ortaktır. */
.quick-pop { position: relative; display: inline-flex; min-width: 0; }

.quick-pop-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-width: 0;
  max-width: 100%;
  /* Negatif kenar boşluğu, dolgunun metni komşularından kaydırmasını
     engeller: düğme olmayan bir kardeşiyle ("· 3 gün gecikti") aynı
     hizada durmalı. */
  margin: -2px -4px;
  padding: 2px 4px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.quick-pop-btn { transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.quick-pop-btn:hover,
.quick-pop-btn[aria-expanded="true"] {
  border-color: var(--border-input);
  background: var(--surface);
}

/* Tetikleyici bir durum rozetiyse **kapsül düğmenin kendisidir**.

   Eskiden rozet kendi dolgusunu taşıyordu, ok işareti onun dışında kalıyordu:
   renkli hap tam metnin bittiği yerde bitiyor, ok beyaz zeminde yalnız
   duruyordu. Üstüne hover çerçevesi ikisinin birden etrafından geçince ortaya
   iç içe iki kutu çıkıyordu — göz bunu tek bir denetim olarak değil, "hap +
   yanına iliştirilmiş ok" olarak okuyordu. Yarım boyanmış görünüyordu çünkü
   gerçekten yarım boyanmıştı.

   Ton sınıfı artık düğmeye de basılıyor (`_quick.pop_select`, `tone`), yani
   `--st-*` değişkenleri buradan iniyor: dolgu, çerçeve ve mürekkep oku da
   kapsıyor; içteki `.status` yalnız nokta + metin dizilimini veriyor. Sözlük
   tek yerde kalır (bkz. `.status` bloğu), değişen yalnız kabuktur. */
.quick-pop-btn.is-capsule {
  margin: 0;
  padding: 2px var(--sp-2);
  border-radius: var(--r-pill);
  border-color: var(--st-line);
  background: var(--st-fill);
  color: var(--st-ink);
}
/* İçteki rozet dolgusunu ve çerçevesini bırakır — ikisi üst üste binerse
   kapsülün içinde bir gölge hap çiziliyordu. Nokta ve boşluk onun işi olarak
   kalır. */
.quick-pop-btn.is-capsule > .status {
  padding: 0;
  border-color: transparent;
  background: transparent;
}
/* Hover dolguyu değiştirmez, **çerçeveyi koyultur**: dolgu burada süs değil
   veridir (hangi durum), tıklanabilirlik onun üstüne yazılamaz. */
.quick-pop-btn.is-capsule:hover,
.quick-pop-btn.is-capsule[aria-expanded="true"] {
  border-color: var(--st-ink);
  background: var(--st-fill);
}
/* Ok, rozetin mürekkebini alır: kapsülün içinde ayrı bir gri yabancı
   duruyordu. Görünürlük kuralı (`opacity`) değişmez, yalnız renk. */
.quick-pop-btn.is-capsule .quick-pop-caret { color: currentColor; }

/* Ok işareti "burası tıklanabilir" der ama sakin durur: satırla
   ilgilenilene kadar görünmez. Dokunmatikte `:hover` diye bir an olmadığı
   için her zaman açıktır. */
.quick-pop-caret {
  flex: none;
  width: 14px;
  height: 14px;
  color: var(--text-muted);
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.today-row:hover .quick-pop-caret,
.today-row:focus-within .quick-pop-caret,
.quick-pop-btn[aria-expanded="true"] .quick-pop-caret { opacity: 1; }
@media (hover: none) {
  .quick-pop-caret { opacity: 1; }
}

/* `position: fixed` ve konumu `app.js` hesaplar (`data-menu-anchor`):
   panel `.today-flow` içinde duruyor ve o kapta `overflow: hidden` var —
   mutlak konumlanan bir panel kartın kenarında kırpılırdı. */
.quick-pop-panel {
  position: fixed;
  top: auto;
  right: auto;
  z-index: 60;
  min-width: 232px;
}
.quick-pop-panel .quick-form { width: 100%; }
.quick-pop-panel .quick-form .select-shell,
.quick-pop-panel .quick-form .select-sm,
.quick-pop-panel .quick-form .input-sm { width: 100%; max-width: none; }

/* Panel içindeki alan "hayalet" olmaz: kabı zaten bir panel, saklanacak
   gürültü yok. Üstelik panel satırın *dışında* açıldığı için satır hover'ı
   alanı hiç aydınlatmaz — kural olmasa görünmez kutulara dokunmak
   gerekirdi (`.row-menu-panel` ile birebir aynı gerekçe). */
.quick-pop-panel .quick-form .select-btn,
.quick-pop-panel .quick-form .input-sm {
  border-color: var(--border-input);
  background: var(--surface);
}
.quick-pop-panel .quick-form .select-btn .chevron { opacity: 1; }
.quick-pop-panel .quick-form input[type="date"]::-webkit-calendar-picker-indicator { opacity: 1; }

/* --- Seçenek kipi: panelin içi menüdür, ikinci bir seçici değil ---------
   Popover'ın içindeki `<select>` kullanıcıya aynı işi iki kez yaptırıyordu
   (paneli aç → seçiciyi aç). Seçenekler artık doğrudan panelde duran birer
   `submit` düğmesi; görünümleri menü satırının kendisidir
   (`.dropdown-item`), çünkü işlevleri de odur. */
.quick-pop-opts { min-width: 200px; }
.quick-pop-opts .quick-form { display: flex; flex-direction: column; gap: 2px; }
/* Menü satırının dokunma hedefi işaretçiye göre değişir: farede 38 px yeter
   ve dört durumluk bir liste ekranı doldurmaz; parmakta tam hedefe çıkar
   (`.row-menu-panel .dropdown-item` ile birebir aynı ölçü). */
.quick-opt { min-height: 38px; }
.quick-opt .icon { flex: none; }
@media (pointer: coarse) {
  .quick-opt { min-height: var(--tap); }
}

/* --- Tarih kipi: panel değil, takvimin arkasında duran girdi -----------
   Tek alanlık bir iş için başlıklı ve 232 px'lik bir panel, işlemi
   olduğundan karmaşık gösteriyordu. Panel açılır açılmaz tarayıcının kendi
   takvimi açıldığı için (app.js, `data-date-pick`) buradaki yüzeyin tek
   görevi, takvimi kapatan kullanıcıya elle yazacak bir kutu bırakmak. Bu
   yüzden içeriğine göre daralır. */
.quick-pop-date { min-width: 0; width: 10.75rem; padding: var(--sp-2); }
/* Tarih girdisinin kendi doğal genişliği ~208 px: panelin ölçüsünü o
   belirliyordu. Biçim sabit olduğu için (gg.aa.yyyy + takvim simgesi)
   ölçü de sabit verilir. */
.quick-pop-date .quick-form .input-sm { width: 9.5rem; min-width: 0; max-width: none; }
/* Düğme panelin genişliğini **belirlemez**: `width: 100%` yüzde olarak
   çözülemediği yerde (içeriğine göre daralan bir kapta) düğmenin kendi
   en geniş hâli ölçü oluyordu ve panel, tek satırlık bir tarih alanı için
   60 piksel fazla yer kaplıyordu. */
.quick-date-clear { width: auto; margin: var(--sp-1) auto 0; }

/* Betik yokken tetikleyici hiçbir şey yapmaz, bu yüzden hiç çizilmez:
   panel satıra gömülü ve açık gelir. Faz 10 öncesindeki davranışın aynısı,
   yani betiksiz tarayıcıda tek bir düzenleme yeteneği kaybolmaz. */
html:not(.js) .quick-pop-btn { display: none; }
html:not(.js) .quick-pop-panel {
  position: static;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  animation: none;
}
html:not(.js) .quick-pop-panel[hidden] { display: block !important; }
html:not(.js) .quick-pop-panel .dropdown-header { display: none; }


/* --- Form içindeki tarih alanı (`date_field`) --------------------------
   Liste satırındaki `pop_date` tetikleyicisi görünmez durur: orada asıl iş
   okumak, alan ancak dokununca belli olur. Formda denge tersine döner —
   kullanıcı oraya *doldurmaya* gelmiştir, alanın kendini göstermesi
   gerekir. Bu yüzden aynı düğme burada bir rozet gibi çizilir: kenarlıklı
   ama input'tan hafif, yüksekliği satır metniyle uyumlu. */
.date-pick { display: inline-flex; max-width: 100%; }
.date-pick-btn {
  margin: 0;
  padding: var(--sp-1) var(--sp-2);
  gap: var(--sp-2);
  border-color: var(--border-input);
  border-radius: var(--r-md);
  background: var(--surface);
}
.date-pick-btn:hover,
.date-pick-btn[aria-expanded="true"] { border-color: var(--border-strong, var(--border-input)); }
.date-pick-value { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Boş alan veri gibi okunmamalı: tarayıcının "gg.aa.yyyy" ipucunun yerini
   alan, açıkça davet olan soluk bir metin. */
.date-pick-value.is-empty { color: var(--text-muted); }
/* Takvim simgesi burada `quick-pop-caret` sınıfını taşır ama liste
   satırının aksine kalıcı görünür: alanın ne olduğunu söyleyen tek işaret. */
.date-pick-btn .quick-pop-caret { opacity: 1; color: var(--text-secondary); }

.date-pick-panel .input { width: 100%; }
.date-pick-quick {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  margin-top: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--border);
}
.js .date-pick-quick { display: flex; }


/* ==========================================================================
   Takvim — ajanda diline yaklaşma (Faz 10)
   ========================================================================== */

/* Izgara hücresindeki etkinliğin zemini iki kez yer değiştirdi ve ikisinin
   de gerekçesi yazılı kalsın:

   Faz 10'da dolu renkli kutuydu; bir ayda otuz hücre × üç kutu = doksan
   renkli dikdörtgen olduğu için zemin sayfa yüzeyine bırakıldı, tür yalnız
   soldaki 3 px'lik çizgide ve ikonda kaldı.

   Faz 27'de dolgu geri geldi, ama **aynı dolgu değil**: eskisi tür renginin
   kendisiydi (500 basamağı), bugünkü sözlüğün `-fill` rolü (100 basamağı) ve
   üstündeki metin `-ink`. Fark ölçülebilir — eski kutu hücre yüzeyine
   ~2.5:1 ile basıyordu, yenisi 1.15:1 ile oturuyor. Yani doksan
   dikdörtgen yine var, ama artık "doksan renkli kutu" değil doksan tonlu
   satır; tür bir bakışta okunuyor, hücre bir uyarı duvarına dönmüyor.

   Çizgi de kaldı: dolgu tonlu olduğu için 3 piksellik 500 basamağı şerit
   türü *kesin* söyleyen kanal olmayı sürdürüyor. */
.cal-event-task {
  border-left-color: var(--kind-task);
  background: var(--kind-task-fill);
  color: var(--kind-task-ink);
}
.cal-event-project {
  border-left-color: var(--kind-project);
  background: var(--kind-project-fill);
  color: var(--kind-project-ink);
}
.cal-event-company {
  border-left-color: var(--kind-company);
  background: var(--kind-company-fill);
  color: var(--kind-company-ink);
}
/* İkon tür renginde: renk tek kanalda konuşmuyor ama konuştuğu her kanalda
   aynı şeyi söylüyor. */
.cal-event .icon { color: currentColor; }

/* Tamamlanmış görev takvimde kalır ama sesini alçaltır. Üstü çizili metin
   kullanılmıyor: okunmayı zorlaştırır ve satır hâlâ açılabilir bir kayıt.

   Alçaltma `opacity` yerine **renk** ile yapılıyor. Saydamlık metni zeminle
   karıştırıp kontrastı ölçülemez hâle getiriyordu: `.5` saydamlıkta mürekkep
   beyaz üzerinde ~3.3:1'e düşüyor, üstelik hücrenin zemini değişince oran da
   değişiyordu. `--text-muted` ise ölçülmüş bir değer (en kötü zeminde
   4.57:1) ve her yüzeyde aynı kalıyor. */
/* Metin soluklaşır ama **işaret renklenir**: tamamlanmışlık artık petrol
   yeşili (`--success`) taşıyan bir kanaldır. Yalnız soluklaşmak yetmiyordu
   — soluk metin "kapandı" değil "önemsiz" demek ve geciken satırın yanında
   ayırt edilemiyordu. Renk yine tek başına konuşmuyor: şeridin yanındaki
   ikon `check-circle`, satırın kendisi de üstü çizili olmadan okunur kalıyor.

   Şerit ve ikon `is-late`ten sonra yazılır; ikisi aynı özgüllükte olduğu
   için sıra kararı verir (bkz. `.kind-dot.is-done` yanındaki not). */
.cal-event.is-done {
  color: var(--text-muted);
  font-weight: 400;
  border-left-color: var(--success);
  /* Faz 27: petrol yeşili dolgu. Metin **yine soluk** — bu bir çelişki
     değil, iki ayrı cümle: dolgu "bu kapandı" der, soluk metin "artık
     senden bir şey beklemiyor" der. Tamamlanmışlığı renklendirip metni de
     koyulaştırmak, biten işi bekleyen işle aynı sesle konuşturmak olurdu. */
  background: var(--state-done-fill);
}
.cal-event.is-done .icon { color: var(--success); }
.cal-item.is-done { color: var(--text-muted); }

/* Dolgular geldikten sonra hover'ın ayrıca yazılması gerekti: `is-late` ve
   `is-done` de (0,2,0) `.cal-event:hover` ile aynı özgüllükte ve dosyada
   ondan sonra: geciken bir etkinliğin üstüne gelindiğinde hiçbir şey
   olmuyordu. Üç seçici tek kuralda, en sonda. */
.cal-event.is-late:hover,
.cal-event.is-done:hover,
.cal-event:hover { background: var(--selected); }

/* Telefondaki görünüm seçici listenin hemen üstünde, kartın dışında durur:
   kart listenin çerçevesi, seçici ise listeyi değiştiren kontrol. */
.cal-mobile-views { margin-bottom: 0; }

@media (max-width: 899px) {
  /* Ajanda gün başlığı kartın iç kenarına hizalanır; masaüstü listesinde
     --sp-5 doğruydu ama telefon kartında satırlar --sp-4 ile başlıyor. */
  .cal-list-day-head { padding: var(--sp-2) var(--sp-4); }
  /* Gün gezinme başlığı ve tarihe atlama satırı kartın içinde nefes alsın. */
  .cal-day-head { padding: var(--sp-3) var(--sp-4) 0; }
  .cal-jump { padding: var(--sp-3) var(--sp-4); }
}

/* ==========================================================================
   Form sayfası ve çekmecesi (Faz 10)
   ========================================================================== */

/* `.form-narrow` (560 px) tek kolonluk bir form içindi ve iki kolon oraya
   sığmıyordu. Yeni genişlik iki kolona yer açar ama serbest bırakmaz:
   980 px üstünde satır uzunluğu okunabilirliği bozuyor, alan etiketiyle
   değeri arasındaki bağ kopuyordu. */
.form-page { max-width: 980px; }

/* --- Ayar sayfası kolonu -------------------------------------------------
   Profil ve çalışma alanı ayarları "liste" değil "form" sayfalarıdır: içerik
   birkaç kısa alandan ibaret. 1440 px'lik ekranda bunlar tuvalin tamamına
   yayılınca sayfa dolu değil **boş** görünüyordu — solda üç alan, sağda bir
   metre boşluk.

   Bölüm gövdesi (`.form-block`) beyaz karttır: ayrı konular arasına normalde
   boşluk koyarız (§3, "Bölüm ritmi"), çünkü orada bölüm gövdesi zaten bir
   kart ya da liste oluyor. Ayar sayfalarında gövde çıplak form olduğu için
   sayfada hiç yüzey kalmıyor ve ekran "yüklenmemiş" gibi duruyordu. Kart
   kuralı `.form-page .form-col` ile aynı gerekçe, tek fark bölümlü bir
   sayfada her **bölümün** gövdesine uygulanması. */
.form-page.is-narrow { max-width: 760px; }
.form-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  padding: var(--sp-5);
}
/* Kart zaten dar; içindeki form ayrıca daralmaz, yoksa kartın sağında
   ikinci bir boşluk şeridi açılır. */
.form-block > .form-narrow { max-width: none; }
@media (max-width: 599px) {
  .form-block { padding: var(--sp-4); }
}


/* --- Tam sayfa formda her bölüm bir kart --------------------------------

   Alanlar doğrudan tuvalin (#F3F6FB) üstünde duruyordu: beyaz girdi
   kutuları renkli zeminde tek tek yüzen adacıklara dönüşüyor, formun
   nerede başlayıp bittiği yalnız boşluktan okunuyordu. Kolonu bir kart
   yüzeyine almak iki şeyi birden çözüyor — alanlar kendi zeminlerine
   oturuyor ve iki kolon arasındaki kavramsal ayrım (`ne` / `kimde`)
   ayırıcı çizgiyle değil yüzeyle anlatılıyor. İkinci kolonun ayırıcı
   dolgusu da bu yüzden sıfırlanıyor (aşağıdaki medya kuralı): kart
   kenarı zaten o işi yapıyor, üstüne 24 px'lik ayırıcı payı eklenince
   sağdaki kolonun içeriği kartın ortasından başlıyordu.

   Kural `.form-page` ile kapsanır: çekmecedeki form zaten beyaz bir
   yüzeyin içinde ve orada kart, kart içinde kart demek. */
.form-page .form-grid > .form-col {
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
}
@media (min-width: 900px) {
  .form-page .form-grid.is-two > .form-col + .form-col {
    padding-left: var(--sp-5);
    border-left: 1px solid var(--border);
  }
}

/* Kaydet ve vazgeç formun altında sabit bir çubukta.

   Uzun bir formda "Kaydet"i bulmak için sona kadar inmek gerekiyordu.
   Çubuk `sticky`: akışın içinde durur (yani formu kapatmaz) ama gövde
   kayarken görünür kalır. `fixed` olsaydı formun son alanını örterdi ve
   ölçüm turundaki "gönder düğmesi alt çubuğun altında kalıyor" bulgusunu
   biz üretirdik. */
.form-actions.is-sticky {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin-top: var(--sp-2);
  padding: var(--sp-3) 0;
  padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  background: var(--page-bg);
  border-top: 1px solid var(--border);
}

/* Telefonda alt sekme çubuğu ekranın dibinde duruyor; işlem çubuğu onun
   *üstünde* bitmeli, altında değil. Aksi halde "Kaydet" sekme çubuğunun
   arkasına giriyor ve dokunulamıyor. */
@media (max-width: 899px) {
  body.has-tabbar .form-actions.is-sticky { bottom: var(--tabbar-h); }
}

/* --- Taşıma / kopyalama gövdesi (Faz 19) ---

   `.section` flex kolon ve kendi `gap`ini taşıyor; içindeki `<p>` kendi
   varsayılan kenar boşluğunu da ekleyince bölüm içi aralık ikiye
   katlanıyordu. Eski şablon bunu her paragrafa `style="margin: 0"`
   yazarak çözüyordu — sekiz satır içi stil, biri eklenmeyi unutulduğunda
   sessizce bozulan bir düzen. Kural tek yerde. */
.transfer-body p { margin: 0; }
/* Onay kutusu ile uzun etiketi: etiket sarınca kutu ortada kalmasın,
   ilk satırla hizalı dursun. */
.transfer-body .transfer-ack { gap: var(--sp-2); align-items: flex-start; }
.transfer-body .transfer-options { gap: var(--sp-4); }

/* Çekmecedeki form: kabuğun tamamını kaplar, gövdesi tek kaydıran alandır.
   Yalnız baş şeridi sabit; işlem düğmeleri gövdenin içinde kayar. */
.drawer-form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  height: 100%;
}
.drawer-form > .drawer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Yerinde düzenleme düğmesi farede 28 px yeter (satır yüksekliğini
   bozmadan tıklanır) ama parmakta yetmez. Ölçüm turu 360 px'te 29 px
   ölçtü; kural aygıta bağlıdır, tasarım sistemi §7.

   Yükseklik `min-height` ile veriliyor, `padding` ile değil: çok satırlı
   bir açıklama alanında dolgu, metni satırın ortasından kaydırıyordu. */
@media (pointer: coarse) {
  .inline-view {
    min-height: var(--tap);
    padding-top: var(--sp-2);
    padding-bottom: var(--sp-2);
  }
}

/* Satır sonundaki üç nokta menüsü parmakta 34 px kalıyordu (ölçüm turu,
   360 ve 390 px). Görünen kutuyu büyütmek listeyi de büyütürdü: mobil
   kartın yüksekliği artar, ekrana sığan kayıt sayısı azalır ve "liste
   taranabilir olsun" kuralı bozulurdu.

   Bu yüzden büyüyen şey görünen kutu değil **dokunulan alan**:
   `::after` görünmez bir çerçeve olarak 44 px'e tamamlar. Ölçüm turu da
   tam bunu ölçüyor (kutuya değil `elementFromPoint`e bakıyor), yani
   düzeltme sınandığı biçimde yapıldı. */
@media (pointer: coarse) {
  .row-btn { position: relative; }
  .row-btn::after {
    content: "";
    position: absolute;
    inset: calc((var(--tap) - 34px) / -2);
    border-radius: inherit;
  }
}


/* ==========================================================================
   REDESIGN FAZ 3 — Genel Bakış ve Takvim

   Bu blok yalnız iki ekrana ait sınıfları taşır. Ortak bileşenlere (düğme,
   kart, liste, açılır menü, durum noktası) hiç dokunulmadı: ikisi de Faz
   1'de tanımlanan token'ları ve bileşenleri kullanıyor.
   ========================================================================== */

/* --- Tür / durum noktası -------------------------------------------------
   Renk "tek başına bilgi taşımaz" kuralının ölçüsü: nokta hiçbir yerde tek
   başına durmaz, yanında her zaman bir etiket ya da başlık vardır. Bu kural
   Faz 27'de de yerinde; değişen **noktanın tek kanal olması** zorunluluğu.

   Faz 26'da nokta 8 pikseldi ve gerekçesi %88 nötr oranıydı: "kırk kayıtlık
   bir ızgarada kırk dolu kutu o oranı tersine çevirir". Oran bütçesi
   açıldığında nokta artık tek başına taşımak zorunda olmadığı için 9 piksele
   çıktı ve dış halkasını aldı — çünkü bundan sonra **renkli bir dolgunun
   üstünde** de duruyor (rozet, tonlu grup başlığı) ve orada kendi zeminine
   1.2:1 ile karışıyordu. Halka noktayı her yüzeyde kendi zemininden ayırır.

   Renk değerleri artık burada değil: `base.css`teki kayıt renk sözlüğünden
   (`--kind-*`, `--state-*`) okunuyor. Nokta işaret rolünü ister, dolgulu
   yüzeyler `-fill`/`-ink` rolünü; ikisi aynı ada bağlı olduğu için bir
   ekranın mavisi diğerinin mavisiyle aynı kalıyor. */
.kind-dot {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: var(--r-pill);
  background: var(--border-strong);
  /* `currentColor` değil `--dot-ring`: halka zemini taklit eder, metni
     değil. Varsayılan kart yüzeyi; tonlu kapsayıcılar kendi dolgusunu
     buraya yazar (bkz. `.status`, `.today-group-head`). */
  box-shadow: 0 0 0 2px var(--dot-ring, var(--surface));
}
/* Sözlüğün üçüncü rolü: **mürekkep**.

   Nokta ve rozet türü bir *satırda* söyler; bu, türü bir **ekranın**
   kimliği olarak söyler (liste başlığı, kayıt başlığı). Takvim tür
   renklerini konuşuyordu ama liste ve ayrıntı ekranları yalnız durum
   rengini gösteriyordu — "Devam ediyor"un rengi vardı, "bu bir görev"in
   yoktu ve iki soru tek kanaldan okunmaya çalışılıyordu.

   Dolgu ve çerçeve bilerek yok: başlık zaten sayfanın en ağır öğesi,
   yanına ikinci bir kutu koymak onu bastırırdı. Sınıf adı `.kind-task`
   değil `.is-task` — nokta sınıfları `background` yazıyor, aynı adı bir
   `<svg>`ye takmak ikona zemin verirdi. */
.kind-ico { flex: none; }
.kind-ico.is-task { color: var(--kind-task); }
.kind-ico.is-project { color: var(--kind-project); }
.kind-ico.is-company { color: var(--kind-company); }
/* Başlığın önündeki tür ikonu. Satır yüksekliğine `vertical-align` ile
   oturuyor: başlık bir `flex` kabı değil ve öyle yapılsaydı `truncate`
   (taşan başlığın üç noktası) çalışmazdı. */
.title-ico {
  width: 20px;
  height: 20px;
  margin-right: var(--sp-2);
  vertical-align: -3px;
}

.kind-task { background: var(--kind-task); }       /* mineral mavi */
.kind-project { background: var(--kind-project); } /* royal indigo */
.kind-company { background: var(--kind-company); } /* antik altın */

/* --- Durum türü ezer -----------------------------------------------------
   Nokta tek bir soruya cevap verir ve bu yüzden tek renk taşır. Tür (ne
   olduğu) ile durum (nerede durduğu) çakıştığında **durum kazanır**: geciken
   bir görev artık "bir görev" değil, "geciken bir iş"tir; tamamlanmış bir
   görevin türü de kararı değiştirmez, iş kapanmıştır.

   Bu yüzden tür kuralları tek sınıfla (0,1,0), durum kuralları çift sınıfla
   (0,2,0) yazılır — özgüllük sıralamayı garanti eder, dosyadaki yer değil.
   `is-done`, `is-late`ten **sonra** gelir: tamamlanmış bir kayıt geç bitmiş
   olsa da artık alarm vermez, kapanmıştır. */
.kind-dot.is-late { background: var(--state-late); }
.kind-dot.is-done { background: var(--state-done); }
.kind-dot.is-today { background: var(--brand); }
.kind-dot.is-ahead { background: var(--strong-border); }


/* --- Tür rozeti: türlerin karıştığı yerde dolgu --------------------------
   Nokta ile rozet arasındaki seçim bir yoğunluk tercihi değil, **kapsayıcı
   genişliği** sorusudur:

   · Satır içinde, yanında zaten bir başlık varken → nokta. Kırk satırlık
     bir listede kırk rozet, satırın kendi metnini bastırır.
   · Tür bir **kapsayıcıya** ad veriyorsa (grup başlığı, süzgeç seçeneği,
     karışık liste sekmesi) → dolgu. Orada tür satırın bir niteliği değil,
     o bloğun ne olduğu; nokta o işi 9 piksele sığdırmaya çalışıyordu.

   Dolgu tek başına gelmez: rozet ikonunu ve metnini de zorunlu tutar
   (`.kind-badge .icon` her zaman çizilir, boş rozet yok). Renk üçüncü
   kanaldır, birinci değil. */
.kind-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 2px var(--sp-2);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: var(--surface-soft);
  color: var(--text-secondary);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.55;
  white-space: nowrap;
}
.kind-badge .icon { flex: none; }
/* Tür tek sınıf (0,2,0 — `.kind-badge` ile birleşik), durum çift sınıf
   olamaz çünkü ikisi de rozetin üstünde. Bu blokta sıra karar verir ve
   `is-late`/`is-done` bilerek **sonra** yazılır; gerekçe `.kind-dot`
   bloğundakiyle aynı. Ölçüsü `test_faz27_*` içinde. */
.kind-badge.kind-task {
  background: var(--kind-task-fill);
  border-color: var(--kind-task-line);
  color: var(--kind-task-ink);
}
.kind-badge.kind-project {
  background: var(--kind-project-fill);
  border-color: var(--kind-project-line);
  color: var(--kind-project-ink);
}
.kind-badge.kind-company {
  background: var(--kind-company-fill);
  border-color: var(--kind-company-line);
  color: var(--kind-company-ink);
}
.kind-badge.is-late {
  background: var(--state-late-fill);
  border-color: var(--state-late-line);
  color: var(--state-late-ink);
}
.kind-badge.is-done {
  background: var(--state-done-fill);
  border-color: var(--state-done-line);
  color: var(--state-done-ink);
}
/* Rozetin içindeki nokta kendi dolgusuna karışmasın. */
.kind-badge .kind-dot { --dot-ring: transparent; }


/* ==========================================================================
   Genel Bakış — 12 kolonlu ızgara
   --------------------------------------------------------------------------
   Önceki kuşak asimetrikti: solda sabit 360 piksellik bir "bağlam rayı",
   sağda uzayan ana alan. İki sorunu vardı.

   Birincisi **hiza**. Ray 360'ta biterken ana alan kendi içinde ikiye
   bölünüyordu (`.overview-pair`) ve o bölünme rayın çizgisiyle hiçbir yerde
   buluşmuyordu. Sayfada üç ayrı dikey başlangıç çizgisi vardı; hiçbiri
   yanlış değildi ama üçü bir arada "her şey iç içe" hissini üretiyordu.

   İkincisi **ağırlık**. Raydaki iki bölüm ("İşlerin durumu", "Son ekip
   hareketleri") ana içerikle aynı göz ağırlığındaydı: ikisi de başlıklı,
   ikisi de çerçeveli. Bir rayın işi bağlam taşımaktır, yarışmak değil.

   Çözüm tek bir 12 kolonluk taban ızgara. Kartların genişliği artık bir
   tasarım kararı değil, ızgaranın sonucu — hepsi aynı çizgilere oturur:

       1  Başlık · dönem · yeni kayıt                              (12)
       2  Açık iş · Geciken · Bugünkü görev · Bekleyen takip     (3+3+3+3)
       3  Bugünün odağı (8)            |  Bugün (4)
       4  Potansiyel müşteri akışı (6) |  Yaklaşan teslimler (6)
       5  Son ekip hareketleri                                     (12)

   "Yoğun KPI gridi yok" kuralı (tasarım sistemi, Faz 3) çiğnenmiş değil:
   ikinci satırdaki dördü de **tıklanır** ve altındaki kartlarda karşılığı
   olan bir listeye iner. Yasaklanan şey sayı kutusu değil, hiçbir yere
   gitmeyen sayı kutusuydu.
   ========================================================================== */

.dash {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  /* Yatayda --sp-4, dikeyde --sp-5.

     Eskiden ikisi de --sp-4'tü ve gerekçesi sağlamdı: satır başına 8 piksel,
     dört satırda ilk ekrandan 32 piksel götürüyordu. Faz 29'da denge
     değişti, çünkü artık ayrılması gereken şey *kartlar* değil **katmanlar**
     (odak → iş listeleri → özet). Yan yana duran iki kart aynı katmandır ve
     birbirine yakın durmalı; alt alta duranlar farklı katmandır.

     Dört piksellik fark az görünüyor ama yönü doğru: ızgaranın dikey
     çizgileri sıkı, yatay çizgileri gevşek olduğunda göz sayfayı kolon
     kolon değil **satır satır** okuyor — panonun anlatmak istediği sıra da
     bu. Bedeli tek satırda 4 piksel, üç aralıkta 12; ilk ekranda bir liste
     satırı bile etmiyor. */
  gap: var(--sp-5) var(--sp-4);
  /* `stretch`: bir satırdaki iki kart **aynı boyda** biter.

     Eski düzenin kuralı bunun tersiydi ("iki değişken boylu kolon yan yana
     konmaz") ve haklıydı — ama orada kolonlar sayfanın tamamı kadar uzundu;
     kısa olanın yanında kart boyu boşluk kalıyordu. Burada satırlar
     `max-height` ile zaten sınırlı, yani eşitlenen şey en fazla 420 piksel.
     O ölçekte hizalı biten iki kart, alt kenarı birbirini tutmayan iki
     karttan daha derli toplu görünüyor: ızgaranın yatay çizgileri de
     dikeyleri kadar okunur oluyor. */
  align-items: stretch;
}

/* Varsayılan tam genişlik; kolonlar yalnız yer varken bölünür. Tek tek her
   karta `grid-column` yazmak yerine önce hepsine 12 verilir — yeni bir kart
   eklendiğinde kimse bir kuralı yazmayı unutmuş olmaz, en kötü ihtimalle
   kart tam genişlikte durur. */
.dash > * { grid-column: span 12; }

/* Tek kolona inince sıra, ızgaranın soldan sağa okunuşu olmaktan çıkıp
   **öncelik sırası** olur. Kaynak sırası masaüstünün satırlarını anlatıyor
   (odak | huni · bugün | teslimler) ve telefonda bire bir uygulandığında
   potansiyel müşteri hunisi, günün görevlerinin önüne geçiyordu: panoyu
   telefondan açan kişinin ilk sorusu "bugün ne yapacağım", "boru hattı ne
   durumda" değil.

   Kolon düzeni CSS'in işi olduğu için düzeltme de CSS'te: kaynak sırası
   masaüstünün düzenini anlatmaya devam eder, `order` telefonun sırasını
   kurar. Başlık `order: 0` ile başta kalır.

   Faz 25: sayaç şeridi de **sona indi**. Panoyu telefondan açan kişinin
   sorusu sırayla şu: "bugün neye bakayım" (odak) → "ne yapacağım" (bugün) →
   "ne yaklaşıyor" (teslimler) → "müşteri tarafı ne durumda" (huni) → ve en
   son "genel sayılar ne" (şerit). Şerit ikinci sırada dururken ilk ekranın
   yarısını dört rakam yiyor, asıl iş kaydırmanın altında kalıyordu. */
@media (max-width: 999px) {
  .dash-focus { order: 1; }
  .dash-today { order: 2; }
  .dash-due { order: 3; }
  .dash-funnel { order: 4; }
  .dash-stats { order: 5; }
  .dash-team { order: 6; }
}

/* Tek kolon ölçüsü: **8 + 4**, her satırda aynı.

   Kartlar ara bir sarmalayıcıya (`.dash-col`) girmez, doğrudan ızgaranın
   çocuğudur. İki gerekçe:

   1. Aynı satırdaki iki kart üst kenarı tanımı gereği, alt kenarı da
      `align-items: stretch` ile paylaşır. Kolon sarmalayıcısında her kart
      kendi içeriği kadar uzadığı için ikinci satırın kartları farklı
      yükseklikte başlıyordu — sayfa kaymış görünüyordu.
   2. Bütün satırlar aynı iki düşey çizgiyi kullanır. Önceki düzende ilk
      satır 8/4, ikinci satır 6/6'ydı: dört kartın dört ayrı kenarı vardı.

   Satır düzeninin bilinen bedeli — kısa kart, uzun kartın boyuna çekilir ve
   altında beyazlık kalır — yükseklikleri tek ölçüye bağlayarak ödendi:
   ilk satırın iki kartı da aynı sabit boyda (aşağıda `.dash-focus` /
   `.dash-funnel`), ikinci satırın ikisi de aynı `max-height` ile sınırlı.

   Sol sütun günün işini taşır (odak → bugün), sağ sütun boru hattını
   (huni → teslimler); dar sütunda yalnız liste var, odak kartındaki kayıt
   adı 1/3 genişlikte okunmazdı. */
@media (min-width: 1000px) {
  .dash-focus,
  .dash-today { grid-column: span 8; }
  .dash-funnel,
  .dash-due { grid-column: span 4; }
}

/* --- 1. satır: başlık, dönem, yeni kayıt -------------------------------- */

.dash-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  min-width: 0;
}
.dash-head-text { min-width: 0; }
.dash-head .page-title { margin: 0; }
.dash-head-note {
  margin: 4px 0 0;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.dash-head-note .dot-sep { margin: 0 var(--sp-2); color: var(--text-muted); }

.dash-head-tools {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 0 0 auto;
}
/* Düğmeler sıkışmaz ve büyümez: başlık uzadıkça o kırpılır, düğme değil. */
.range-dock { position: relative; flex: 0 0 auto; }

/* Dar ekranda araçlar kendi satırlarına iner ve sağa yaslanır. Yan yana
   durmaları 600 px'in altında iki kötü seçenekten birini dayatıyordu: ya
   dönem düğmesi ikona inip seçili aralığı gizleyecek ya da başlık satırı
   üçe bölünecekti. */
@media (max-width: 639px) {
  .dash-head { flex-wrap: wrap; }
  .dash-head-text { flex: 1 1 100%; }
  .dash-head-tools { margin-left: auto; }
}

/* Panonun kendi "Yeni kayıt" düğmesi artık hiç yok (Faz 48): masaüstünde
   üst çubuktaki "+ Yeni", telefonda alt çubuğun artısı tek merkez. Eskiden
   burada 899 px altında düğmeyi gizleyen bir kural vardı; gizlenecek düğme
   kalmayınca kural da kalktı. */

/* Süzgeçler (dönem, sektör) başlıkta **ikincil** durur: ikisi de çerçeveli,
   ikisi de normal punto, ikisi de sağda. Gerekçe: süzgeç, süzdüğü şeyin önüne geçmemeli — ana
   içeriğin üstünde kendi şeridini (çip dizisi ya da lejant bandı) alsaydı
   sayfanın ilk 48 pikseli bir süzgeç katmanı olurdu. Şeritte durunca hep
   aynı yerde, tek tıkla erişilebilir ve ızgaranın ilk satırından bir piksel
   bile fazla yer istemiyor. */
.dash-head-tools .range-dock + .range-dock { min-width: 0; }
/* Sektör düğmesi daralabilen tek kontrol: dönem düğmesinin metni bir tarih
   aralığı (kırpılırsa okunmaz), sektörünki bir ad ya da bir sayı. */
.dash-head-tools .sector-filter { min-width: 0; flex: 0 1 auto; }
.dash-head-tools .sector-filter .filter-btn-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 420 px altında süzgeçler kendi satırlarına iner ve genişliği paylaşır:
   kırpılmış bir tarih aralığı yerine tam okunan bir tarih aralığı. */
@media (max-width: 419px) {
  .dash-head-tools {
    flex: 1 1 100%;
    min-width: 0;
    margin-left: 0;
    flex-wrap: wrap;
  }
  .dash-head .range-dock { flex: 1 1 160px; min-width: 0; }
  .dash-head .range-dock .filter-btn {
    width: 100%;
    min-height: var(--tap);
    justify-content: flex-start;
  }
  .dash-head .range-dock .filter-btn-text { overflow: hidden; text-overflow: ellipsis; }
}

/* --- 2. satır: sayaç şeridi ----------------------------------------------
   Dört sayaç **tek** yüzeyde, aralarında saç teli çizgi.

   Önceki kuşakta dördü de ayrı karttı: kendi çerçevesi, kendi gölgesi, kendi
   yumuşak renkli ikon karosu. Altlarındaki gerçek kartlarla (odak, bugün,
   huni, teslimler) birebir aynı malzemeyi konuşuyor ama onların taşıdığı
   şeyi — birlikte okunan, birlikte kaydırılan bir veri kümesi —
   taşımıyorlardı. Sayfadaki "kutu içinde kutu" hissinin en görünür kaynağı
   buydu: ekranın üst yarısında dört küçük kart, alt yarısında dört büyük
   kart, hepsi aynı çizgi ve gölgede.

   Şerit bunu bire indiriyor: ızgarada tek bir çocuk, tek bir çerçeve. Dört
   sayı yine dört ayrı hedef (dördü de tıklanır ve bir listeye iner) ama
   artık **bir** nesnenin bölmeleri. Kazanılan şey yalnız sadelik değil, yer
   de: 8 piksellik üç ızgara boşluğu ve üç çift kenarlık düşüyor.

   Yetkisi olmayan kullanıcıya "0" değil "—": ölçülmeyeni sıfır diye sunmak,
   gerçekten sıfır olmasından farksız görünür ve yanıltır. */
.dash-stats {
  display: grid;
  /* Telefonda bile **ikişerli**. Tek kolona inselerdi dördü 516 piksel
     ederdi: ekranın tamamı, dört sayı için. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  /* Bölme çizgileri `gap` + zemin ile değil, bölmelerin kendi
     kenarlıklarıyla çiziliyor (aşağıda): `gap` yaklaşımı köşelerde
     yuvarlatmanın dışına taşan bir zemin bırakıyor ve koyu temada o zemin
     ikinci bir yüzey gibi okunuyordu. Kırpma da bu yüzden: bölmenin hover
     zemini kartın yuvarlak köşesinin dışına çıkmasın. */
  overflow: hidden;
}
@media (min-width: 700px) {
  .dash-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Bölme: solda etiket + açıklama, sağda sayı.

   Sayı sağda, çünkü dört bölmenin rakamları böylece aynı dikey hizaya
   oturuyor ve "hangisi büyük" sorusu tek göz gezdirmeyle cevaplanıyor —
   sola yaslıyken basamak sayısı (7 / 12 / 128) hizayı bozuyordu. */
.dash-stat {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  color: inherit;
  /* Bölme ayırıcıları. Negatif kenar boşluğu yok: şerit `overflow: hidden`
     olduğu için ilk sütunun sol çizgisi ve ilk satırın üst çizgisi zaten
     kırpılmıyor — onlar hiç çizilmiyor (aşağıdaki `:nth-child` kuralları). */
  border-left: 1px solid var(--border-soft);
  border-top: 1px solid var(--border-soft);
  transition: background-color var(--dur-1) var(--ease-out);
}
/* İki kolonlu dizilimde 1. ve 3. bölmenin solunda, 1. ve 2. bölmenin
   üstünde çizgi olmaz — orası şeridin kendi kenarı. */
.dash-stats > :nth-child(2n + 1) { border-left: 0; }
.dash-stats > :nth-child(-n + 2) { border-top: 0; }
@media (min-width: 700px) {
  /* Dört kolonda tek satır: yalnız ilk bölmenin solunda çizgi olmaz, üst
     çizgi hiç olmaz. */
  .dash-stats > * { border-top: 0; border-left: 1px solid var(--border-soft); }
  .dash-stats > :first-child { border-left: 0; }
}
/* Hover'da **yalnız zemin** yumuşar. Şerit tek bir yüzey olduğu için sınır
   ve gölge artık bölmenin değil kabın işi; onları oynatmak dört bölmeden
   birinin kabın dışına taşması demek olurdu. */
a.dash-stat:hover {
  background: var(--surface-soft);
  text-decoration: none;
}

.dash-stat-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-width: 0;
}
/* Etiket koyu ve yarı kalın; ikon **karo değil**, etiketin yanında çıplak ve
   soluk. 36 pikselik yumuşak renkli bir kare, dört bölmede dört ayrı yüzey
   demekti ve şeridin kendi çerçevesiyle birlikte "kutu içinde kutu"nun
   ikinci kaynağıydı. İkon bilgi taşımıyor (etiket aynı şeyi yazıyla
   söylüyor), o yüzden yer de istememeli — `icon()` makrosu zaten
   `aria-hidden` basıyor. */
.dash-stat-label {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-primary);
}
.dash-stat-label .icon {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--text-muted);
}
/* Etiket metni en fazla iki satır, kelime **bütün** kalır. Tek satırlı
   `truncate` dört kolonda ~150 piksele düşen bölmede "Adaydan müşteriye
   dönü…" yazıyordu; üç noktanın yediği kelime etiketin asıl kelimesiydi.
   `overflow-wrap: normal` — kelime ortasından kırılma yok; iki satıra da
   sığmayan (olağanüstü uzun) etiket kırpılır, tam metin bölmenin `title`ında. */
.dash-stat-label-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-width: 0;
  line-height: 1.25;
  overflow-wrap: normal;
  word-break: normal;
}
/* Dar masaüstü (dört kolon ama ~185 px'lik bölmeler): sayı bir kademe
   küçülür ve etikete üç satır tanınır. "Adaydan müşteriye dönüşüm" 100
   piksellik metin kolonunda üç kelime = üç satırdır; iki satırda yine
   son kelime düşüyordu. Açıklama satırı zaten iki satıra sarıyor, bölmenin
   boyu değişmez. */
@media (min-width: 700px) and (max-width: 1099px) {
  .dash-stat-label-text { -webkit-line-clamp: 3; line-clamp: 3; }
  .dash-stat-value { font-size: var(--fs-lg); }
}
/* Geciken sayacında ikon ve sayı aynı dili konuşur. */
.dash-stat-late .dash-stat-label .icon { color: var(--accent); }
.dash-stat-note {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}
.dash-stat-value {
  flex: none;
  /* --fs-xl: sayı bölmenin en büyük öğesi olmaya devam ediyor ama boyu o
     belirlemiyor; --fs-2xl'de rakam, yanındaki iki satırlık metinden uzun
     kalıyor ve bölmeyi tek başına büyütüyordu. */
  font-size: var(--fs-xl);
  font-weight: var(--fw-black);
  letter-spacing: -0.03em;
  line-height: 1.2;
  color: var(--text-primary);
  /* Rakamlar eşit genişlikte: dört bölmenin sayısı sağa dayandığı için
     orantısız "1"ler hizayı tırtıklı gösterirdi. */
  font-variant-numeric: tabular-nums;
}

/* Ölçülemeyen değer ("—") sayı gibi görünmemeli. Ayrım artık kesik çizgili
   bir ikon karosunda değil, doğrudan metinde: hem ikon hem sayı soluk. */
.dash-stat.is-quiet .dash-stat-label,
.dash-stat.is-quiet .dash-stat-label .icon,
.dash-stat.is-quiet .dash-stat-value { color: var(--text-muted); }
/* Geciken sayacı sıfırdan büyükse sayı yanık mercana döner. Dolu kırmızı bir
   kutu değil: sayı zaten küçük bir yüzey ve renk orada yeterince yüksek
   sesle konuşuyor. Sıfırken sınıf hiç basılmaz (bkz. şablon) — "0 geciken iş"
   kırmızı yazılırsa iyi haber kötü haber gibi okunur. */
.dash-stat-late .dash-stat-value { color: var(--accent-solid); }

/* --- Sayaç: telefon (<= 479 px) -----------------------------------------
   Bölme iki **satıra** dönüyor: üstte etiket, altta sayı. 360 pikselde bir
   bölmeye ~170 piksel düşüyor ve yan yana düzende etikete kalan pay ~90 px —
   "Bugün yapılacak" iki-üç parçaya bölünüyordu.

   Açıklama ("hedef tarihi geçmiş") gizlenir ve bölmenin `title`ına iner.
   Bilgi kaybı değil, yer değiştirme: açıklama zaten sayının *ne* olduğunu
   söylüyor ve o cevap etiketin kendisinde de var. */
@media (max-width: 479px) {
  .dash-stat {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    gap: 2px;
    padding: var(--sp-3);
  }
  .dash-stat-label { font-size: var(--fs-sm); line-height: 1.25; }
  .dash-stat-note { display: none; }
  .dash-stat-value { font-size: var(--fs-lg); }
}

/* --- Kart ---------------------------------------------------------------
   Üçüncü satırdan itibaren her bölüm bir kart: beyaz yüzey, ince çerçeve,
   içeride başlık şeridi ve kendi kayan gövdesi.

   Bu, tasarım sistemi §3'ün "her bölümü karta koyma" uyarısıyla çelişmiyor:
   buradaki kartların hepsi **birlikte okunan ve birlikte kaydırılan bir veri
   kümesi** taşıyor (bir liste, bir huni, bir kayıt). Çelişen şey, kartın
   içine ikinci bir çerçeve koymaktı — aşağıdaki son kural onu engelliyor. */
.dash-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* Kartın zemini **bir kez** burada adlandırılır. Gövdedeki kaydırma
     gölgesi (`.dash-card-body`) dört katmanlı bir gradient ve ilk ikisi
     "yüzeyin kendisi"nden başlayıp saydama gidiyor; o değer sabit
     `--surface` yazıldığında, zemini değişen bir kart (aşağıda `.is-quiet`)
     gövdesinin üstünde beyaz bir sis tabakası taşıyordu. */
  --dash-surface: var(--surface);
  background: var(--dash-surface);
  /* Çizgi ve gölge `.card` ile birebir aynı: panodaki kart ile listedeki
     kart aynı yüzeydir, farklı yerde duruyor olmaları onları iki ayrı
     malzeme yapmaz. */
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

/* --- Faz 29: kartın üç katmanı -----------------------------------------
   Panodaki dört kart aynı malzemeden (beyaz + 1 px çizgi + aynı gölge)
   yapılmıştı ve bu, "hepsi eşit derecede önemli" demekti. Ekranda öyle
   okunuyordu da: göz nereden başlayacağını bilmiyor, dört kutu arasında
   gezinip duruyordu. Hiyerarşi yalnız *sıralamayla* (hangisi üstte) değil,
   **malzemeyle** de kurulur.

   Üç katman, üç malzeme — ve her katmanın sayfada kaç tane olabileceği
   belli:

     Katman 1 · yükseltilmiş  — sayfada **tek**. Odak kartı: bugünün tek
       sorusu. Daha büyük yarıçap, `--shadow-raised`, çizgi yumuşar (gölge
       zaten ayırıyor; ikisi birden "hem yüzüyor hem çerçeveli" demek olur).
     Katman 2 · akışta        — iş listeleri (Bugün · Yaklaşan teslimler).
       Değişmedi: beyaz, çizgi, `--shadow-card`. Sayfanın taban malzemesi.
     Katman 3 · sakin         — özet/bağlam (huni). Tuvale gömülür: yumuşak
       yüzey, gölge yok. Okunmayı bekleyen bir iş değil, arka plandaki bir
       ölçü; malzemesi de öyle söylesin.

   Bir katmanı "biraz daha koyu bir gri" yaparak ayırmak yerine üç *fiziksel*
   durum seçildi (yüzen · duran · gömülü), çünkü kullanıcı ton farkını
   sıralayamaz ama yükseltiyi anında okur. */
.dash-card.is-lifted {
  border-radius: var(--r-xl);
  border-color: var(--border-soft);
  box-shadow: var(--shadow-raised);
}
.dash-card.is-quiet {
  --dash-surface: var(--surface-soft);
  box-shadow: none;
}
.dash-card-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
  /* 42 px: başlık 15 px/600, tek satır. 48'de şerit kartın kendisinden çok
     yer istiyordu — beş kartta 30 piksel, ilk ekranın bir liste satırı. */
  min-height: 42px;
  padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--border-soft);
}
/* "Tümünü gör" başlık şeridini şişirmesin: `.card-link` 32 piksel taban
   yükseklik istiyor (8 + 32 + 8 = 48) ve bağlantısı olan kart, olmayandan
   yedi piksel uzun oluyordu — aynı satırdaki iki kartın başlık çizgisi
   tutmuyordu. Yalnız fare için: dokunmatikte bağlantı `--tap` kalır. */
@media (pointer: fine) {
  .dash-card-head > .card-link { min-height: 26px; }
}

.dash-card-title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  /* Kart başlığı her yerde aynı ölçüde: 15 px. 13 px + 700, başlığı
     "küçük ama bağıran" bir etikete çeviriyor ve altındaki liste
     satırlarıyla aynı puntoda kalıyordu.

     Faz 29: ağırlık 600 → **800**, aralık -0.005 → -0.02em. Punto yerinde
     kaldı, yani ilk ekrandan tek piksel gitmiyor; değişen tek şey başlığın
     *yoğunluğu*. Gerekçe: kart başlığı (15/600) ile kayıt adı (13/600) aynı
     ağırlıktaydı ve aradaki iki piksel, "bu bir bölüm adı, şu bir kayıt"
     demeye yetmiyordu — göz kartın neresinin başlık olduğunu her seferinde
     yeniden çözüyordu. Manrope'un 800 ekseni tam bu iş için var: başlığı
     tok yapan şey büyüklük değil siyahlık (bkz. `base.css`, h1-h4).
     Sıkışan harf aralığı da aynı kararın parçası — 800 ağırlıkta gevşek
     aralık, kelimeyi şişman gösterir, tok değil. */
  font-size: var(--fs-base);
  font-weight: var(--fw-black);
  letter-spacing: -0.02em;
  color: var(--text-primary);
}
.dash-card-title .icon { color: var(--text-muted); }
/* --- Başlıktaki sayı yuvası --------------------------------------------
   Kart başlığının üç yuvasından ikincisi: **ad · sayı · eylem**.

   Önceki kuşakta bu yuva üç kartta üç ayrı şeydi — "Bugün"de soluk bir
   `.muted small`, huninin başlığında "4 açık" cümlesi, teslimlerin
   başlığında çizgi + yüzde + pay üçlüsü. Üçü de aynı soruya cevap veriyordu
   ("bu kartta kaç şey var") ve hiçbiri diğerine benzemiyordu; göz her kartta
   hiyerarşiyi yeniden öğrenmek zorundaydı.

   Hap değil düz sayı: dolu zeminli küçük bir rozet, kart adının yanında ondan
   daha çok yer kaplıyordu. Okunacak şey rakamın kendisi, taşıdığı kap değil.
   Aynı sınıf "Bugün" kartının grup başlıklarında da kullanılıyor — kartın
   sayısı ile grubun sayısı aynı ölçüde konuşmalı. */
.dash-count {
  flex: none;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: 0;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* --- Gövdedeki ölçü satırı ("Yaklaşan teslimler") ----------------------
   Tamamlanma oranı bir zamanlar bir cümleydi ("açık işlerde 14/23 görev
   %61"), sonra **başlık şeridinde** üç parçalı bir ölçüye dönüştü: 56
   piksellik bir çizgi + koyu yüzde + soluk pay.

   Geniş ekranda çalışıyordu. Telefonda beş parça (ad · çizgi · yüzde · pay ·
   "Tümünü gör") tek şeride sığmıyor ve hiçbiri daralamadığı için (`nowrap`,
   sabit genişlikte çizgi) **üst üste biniyordu**. Sarma kuralları eklendikçe
   şerit iki, üç satıra çıkıyor ve kartın başlığı kartın kendisinden yer
   istiyordu; bir de dar sütunda çizgiyi gizleyen ayrı bir kırılım gerekiyordu.

   Ölçü gövdenin ilk satırına indi: tam genişlikte, kendi çizgisiyle,
   kimseyle yer paylaşmadan. Başlık şeridinde geriye sayfanın her yerinde
   geçerli olan üçlü kalıyor. Bağlam (`açık işlerde … görev`) `title`da. */
.dash-meter {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  /* Gövde kendi içinde kayıyor (`.dash-card-body`); ölçü kayıp gitmesin.
     Yapışkan olmasaydı üç iş kaydırıldığında kartın oranı ekrandan
     düşerdi — başlıktan çıkarmanın amacı onu görünür kılmaktı, gizlemek
     değil. Zemin opak: altından geçen satırlar okunmamalı. */
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface-sunken);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
}
.dash-meter-label {
  flex: none;
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
}
/* Çizgi satırın artan payını alır: sabit genişlik, eski ölçünün telefonda
   taşmasının sebebiydi. */
.dash-meter-bar { flex: 1 1 auto; min-width: 24px; }
.dash-meter-value {
  flex: none;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
/* 360 pikselin altında etiket düşer, ölçü kalır: çizgi ile yüzde birlikte
   zaten "ne kadarı bitti" diyor, başlığı kartın konusu söylüyor. */
@media (max-width: 359px) {
  .dash-meter-label { display: none; }
}

/* Dar ekranda başlık şeridi sarabilsin: kart adı uzun, "Tümünü gör" sabit.
   Ölçü artık burada olmadığı için sarma yalnız bir güvenlik ağı. */
@media (max-width: 640px) {
  .dash-card-head {
    flex-wrap: wrap;
    padding-top: var(--sp-2);
    padding-bottom: var(--sp-2);
  }
  .dash-card-title { min-width: 0; }
}

.dash-card-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Kart içindeki kaydırma sayfayı sürüklemesin: liste dibine gelince
     sayfanın kaymaya başlaması, kartın kendi kaydırmasını fark edilmez
     kılıyordu. */
  overscroll-behavior: contain;

  /* Çubuk gizlenir. Masaüstü Windows'ta kaydırma çubuğu *durağan* çizilir:
     panoda dört-beş kart yan yana durduğunda ekranın sağına dört-beş dikey
     gri şerit iniyor ve ızgara, içeriğinden çok kendi kaplarını gösteriyordu.

     Yerine kaydırma gölgesi geçiyor (`.filter-pop-body` ile aynı teknik):
     altta içerik kaldıkça soluk bir geçiş çizilir, liste bitince
     `background-attachment: local` sayesinde kendiliğinden kaybolur. Yani
     "aşağıda daha var" işareti duruyor, onu taşıyan gri şerit gitti. */
  scrollbar-width: none;
  background:
    linear-gradient(var(--dash-surface, var(--surface)) 30%, transparent) top / 100% 18px,
    linear-gradient(transparent, var(--dash-surface, var(--surface)) 70%) bottom / 100% 18px,
    radial-gradient(farthest-side at 50% 0, var(--scroll-shadow), transparent) top / 100% 8px,
    radial-gradient(farthest-side at 50% 100%, var(--scroll-shadow), transparent) bottom / 100% 8px;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
}
.dash-card-body::-webkit-scrollbar { width: 0; height: 0; }

/* Kartın içindeki listeler kendi çerçevesini çizmez: kartın kenarlığı zaten
   orada ve iç içe iki çerçeve tasarım sisteminin §3'te yasakladığı şeyin ta
   kendisi. */
.dash-card .list,
.dash-card .today-flow { border: 0; border-radius: 0; }

/* --- Kart içi satırlar: panoda daha sıkı ---------------------------------
   Liste ekranındaki satır 56 piksel yüksek ve 20 piksel yanlıklıdır; orada
   satır **ekranın konusu**. Panoda ise bir kartın içinde üç-beş satır var ve
   kart, yanındaki kartla aynı ekranı paylaşıyor: aynı ölçü burada kartı iki
   katına çıkarıyor ve ilk ekrandan bir kart eksiltiyordu. */
.dash-card .list-row {
  min-height: 46px;
  padding: var(--sp-2) var(--sp-4);
}

/* Huni satırı tek satır: aşama adı · çubuk · sayı.
   Çubuk eskiden `width: 100%` ile kendi satırına iniyordu — dört aşama 336
   piksel ediyor, kart kendi içinde kayıyordu. Oysa huninin okunma biçimi
   "hangisi uzun": çubuklar alt alta ve **aynı hizada** başlayınca bu soru
   tek bakışta cevaplanıyor, üstelik dördü de ekranda kalıyor. */
.dash-funnel .list-row-main {
  /* Flex değil **grid**: aşama adları farklı uzunlukta ("Yeni" ile "Teklif
     gönderildi" arasında 80 piksel var) ve flex'te çubuk, adın bittiği yerden
     başlıyordu — altı çubuğun altı ayrı başlangıcı oluyor, "hangisi uzun"
     sorusu gözle cevaplanamıyordu. Karşılaştırılan şey uzunlukken ortak bir
     sıfır noktası şart.

     Ad kolonu sabit (132 px, en uzun etikete göre): çubuklar aynı çizgide
     başlayıp aynı çizgide bitiyor, yani boyları doğrudan oranı okutuyor. */
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  align-items: center;
  gap: var(--sp-3);
}
.dash-funnel .list-row-title { min-width: 0; }
.dash-funnel .progress { min-width: 32px; }

/* Odak kartı: başlık --fs-lg, gövde --sp-4.
   --fs-2xl (28 px) + --sp-6 (24 px) kartı 300 pikselin sınırına dayıyordu;
   iki satıra kırılan tek bir uzun kayıt adı kartı kaydırılır hâle
   getiriyordu. Faz 25'te dolgu bir basamak daha indi (--sp-5 → --sp-4):
   kart tek bir kaydı gösteriyor, dört kenarında 20'şer piksel beyazlık
   bilgi değil yükseklik demekti. Kayıt adı hâlâ ekranın en büyük metni. */
.dash-focus .focus-body {
  gap: var(--sp-2);
  padding: var(--sp-4);
}

/* Masaüstünde gövde dört değil **üç** satır: tür/bağlam ile gecikme bilgisi
   aynı satırı paylaşır (biri solda, biri sağda).

   Alt alta dizildiklerinde kart 323 piksele çıkıyor ve "Bugün" kartının
   büyük kısmı ilk ekranın dışında kalıyordu. İkisi de **meta** bilgi (ne tür
   kayıt · ne kadar geç kaldı), ölçüleri de küçük — aynı satırda okunmaları
   sırayı bozmuyor, ikisi arasında 777 piksellik boşluk zaten vardı.
   Telefonda kural yok: orada satır 390 piksel ve ikisi üst üste binerdi. */
@media (min-width: 1000px) {
  .dash-focus .focus-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: var(--sp-2) var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
  }
  .dash-focus .focus-kicker { grid-column: 1; grid-row: 1; }
  /* Satır **açıkça** birinci: `grid-row` yazılmazsa gecikme, kendinden önce
     gelen ve iki kolonu birden kaplayan başlığın altına düşüyor (otomatik
     yerleştirme geriye dönmez) — kazanılan satır geri veriliyordu. */
  .dash-focus .focus-late { grid-column: 2; grid-row: 1; justify-self: end; }
  .dash-focus .focus-title,
  .dash-focus .focus-sub,
  .dash-focus .focus-actions { grid-column: 1 / -1; }
  .dash-focus .focus-actions { margin-top: 0; }

  /* Rota çizgisi de daralıyor: ray ile durak arasındaki 16 piksel, üç
     durağın hiçbirine bilgi katmıyordu. Üstündeki 8 piksellik boşluk da
     düştü; yerine `margin-top: auto` geldi. İkisi aynı şeyin iki yüzü:
     çizginin kendi `border-top`u ayrımı zaten yapıyor, sabit boşluk onu
     ikinci kez söylüyordu — buna karşılık satır huniden dolayı içerikten
     uzun kaldığında çizgi kartın tabanına oturuyor ve ortada askıda kalmış
     bir boşluk kalmıyor. */
  .dash-focus .focus-route {
    margin-top: auto;
    /* Yatay dolgu gövdeyle aynı (--sp-4): rotanın ilk durağı, üstündeki
       kicker ve kayıt adıyla aynı düşey çizgiden başlamalı. */
    padding: var(--sp-2) var(--sp-4);
  }
  /* Durağın üst dolgusu **daraltılmaz**: nokta 12 piksel yüksekliğinde ve
     mutlak konumda (`top: 0`), etiket ise dolgunun bittiği yerden başlıyor.
     8 piksel verildiğinde "BAŞLANGIÇ / PLAN / HEDEF" noktanın ve rayın
     içine 4 piksel giriyordu — ekranda üst üste binmiş iki katman. Ana
     kuraldaki 16 piksel (12 + 4 nefes) burada da geçerli; kazanılan 8
     piksel zaten `margin-top: auto` sayesinde kartın tabanından geliyor. */
}

/* Yükseklik sınırı — ekranın asıl ölçüsü.
   "İlk ekran kaydırmadan okunabilsin" isteği, kartların boyunun içeriğe
   bırakılamayacağı anlamına geliyor: sekiz gecikmiş iş, "Bugün" kartını
   ekranın iki katına çıkarıyordu. Sınır konunca uzayan şey sayfa değil
   **kart** oluyor ve dördüncü satır hep aynı yerde başlıyor.

   Telefonda sınır yok: orada zaten tek kolon var ve dikey kaydırma okumanın
   doğal biçimi — kart içi kaydırma yalnız bir engel olurdu. */
@media (min-width: 1000px) {
  /* İlk satır: iki kart da **aynı sabit boyda**. `max-height` yetmezdi —
     sınır yalnız uzayanı keser, kısa kalanı uzatmaz; odak 323, huni 327
     piksel ölçülüyor ve aradaki dört piksel iki kartın alt kenarını
     ayırıyordu. Sabit boyda ikisi de aynı çizgide bitiyor ve altlarındaki
     "Bugün" / "Yaklaşan teslimler" aynı yerde başlıyor.

     256 bir **taban**, tavan değil: `height` yazılsaydı iki satıra kırılan
     tek bir uzun kayıt adı odak kartını kaydırılır hâle getirirdi. Taban
     olunca ızgara satırı içeriğe göre uzuyor ve iki kart birlikte uzuyor
     (`align-items: stretch`) — hizayı sabit sayı değil ızgara koruyor.

     Faz 25: **taban kalktı.** Gerekçesi ("iki kart aynı çizgide bitsin")
     hâlâ geçerli ama artık onu `align-items: stretch` tek başına
     sağlıyor — satırın boyunu, satırdaki en uzun içerik (huninin altı
     aşaması) belirliyor ve odak kartı ona uyuyor. Sabit taban, huni
     kısaldığında bile odağı 256 pikselde tutuyordu; kartın "gereksiz
     yüksekliği" tam olarak oydu. Odak içeriği de sıkıştırıldı (gövde
     dolgusu bir basamak, rota çizgisi tek satır), yani satır artık
     ~212 pikselde bitiyor. */

  /* Huni satırı sıkışır: içerik tek satır (aşama adı · çubuk · sayı) ve 46
     pikselin 12'si boşluktu. Altı aşamanın tamamı ekranda kalmalı —
     kaydırılan bir huni, kaydırıldığı fark edilmeyen bir aşamayı siler. */
  .dash-funnel .list-row { min-height: 32px; padding-block: 3px; }

  /* İkincisi ve sonrası: değişken boylu listeler kendi içlerinde kayar,
     sayfayı uzatmaz. İkisi aynı satırda olduğu için sınır da aynı. */
  .dash-today,
  .dash-due { max-height: 340px; }
}

/* --- Bugünün odağı: ekranın tek renkli yüzeyi ---------------------------

   Zemin **indigo ailesinden** ve düz değil, yukarıdan aşağı sönen bir
   geçiş.

   Eski hâli düz mineral maviydi (`--strong-soft`, #e6eff6). İki sorunu
   vardı. Birincisi aile: mineral mavi bu ekranda başka hiçbir yerde
   geçmiyor — sayfanın geri kalanı (düğmeler, etkin menü satırı, ilerleme
   çizgileri, bağlantılar) indigo konuşurken kartın kendisi üçüncü bir mavi
   söylüyor ve göz onu "vurgulu" değil **yabancı** okuyordu. İkincisi
   düzlük: 420 piksel yüksekliğinde tek tonda doldurulmuş bir dikdörtgen,
   kartın alt yarısında rengin sebebini kaybediyordu.

   Geçiş üstte doygun, ortada beyaza dönüyor: renk "önce buraya bak" demeyi
   başlıkta yapıyor, gövde okunurken çekiliyor. İçerideki çağrı da artık
   birincil indigo düğme (`.btn-primary`) — eskiden lacivertti, çünkü mavi
   bir zeminde indigo düğme ikinci bir mavi oluyordu; zemin indigoya
   geçince o gerekçe düştü ve sayfada "asıl eylem" tek bir renk konuşuyor.

   Gölge yok: `--shadow-float` sayfada bir-iki modüle ayrılmıştır ve bu
   ekranda zaten yükselen tek yüzey bu.

   İkinci bir renkli kart yok ve olmamalı: renkli yüzeyin işi "önce buraya
   bak" demek ve iki kişi aynı anda bunu söyleyemez. */
/* Faz 18: renkli zemin ve geçiş **kalktı**.

   İki kural aynı anda çiğneniyordu. Biri tasarım sisteminin kendi yasağı
   (§1: "Yasak: gradient"). Öteki mor bütçesi: mor bu arayüzde etkin menü,
   bağlantı, grafik ve birincil eylem demek — kartın zemini bunların hiçbiri
   değil. Panoda aynı anda mor bir kart zemini, mor bir etkin menü satırı ve
   mor bir birincil düğme duruyordu; üçü aynı rengi konuşunca düğme kartın
   dokusu gibi okunuyordu.

   "Önce buraya bak" iddiası kaybolmuyor, **kanal değiştiriyor**: yükselti
   artık renkle değil gölgeyle anlatılıyor (`--shadow-float`, tasarım
   sisteminin sayfada bir-iki modüle ayırdığı değer) ve sınır bir basamak
   güçleniyor. İkisi de nötr, ikisi de iki temada aynı çalışıyor — eski
   geçişin koyu temada zaten yarısı görünmüyordu.

   İkinci bir öne çıkan kart yok ve olmamalı: "önce buraya bak"ı iki kişi
   aynı anda söyleyemez. */
.dash-focus {
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-float);
}
.dash-focus .dash-card-head { border-bottom-color: var(--border); }

/* Odak yokken aynı yüzey sakinleşir: "bugün acil bir şey yok" bir uyarı
   değil, iyi haber — ve iyi haber sayfanın en çok yükselen yüzeyini hak
   etmiyor. Kart sıradan kartların arasına geri iner. */
.dash-focus.is-clear {
  background: var(--surface);
  border-color: var(--border-soft);
  box-shadow: var(--shadow-card);
}
.dash-focus.is-clear .dash-card-head { border-bottom-color: var(--border-soft); }

/* `.focus` kendi çerçevesini ve zeminini kartın içinde bırakır: rengi artık
   kart taşıyor. */
.dash-focus .focus,
.dash-focus .focus.is-clear {
  border: 0;
  border-radius: 0;
  background: transparent;
}

/* Rota çizgisi eskiden `margin-top: auto` ile kartın tabanına itiliyordu.
   Gerekçe ızgaraydı: odak kartı yanındaki "Bugün" ile aynı satır
   yüksekliğini paylaşıyor, içeriği kısa kalınca altında yüz piksellik
   beyazlık oluyordu — çizgi o boşluğu en azından dolduruyordu.

   Faz 20'de kart yine bir ızgara satırını paylaşıyor (huni ile) ve o
   gerekçe geri geldi: itme masaüstünde `margin-top: auto` olarak yukarıdaki
   sıkıştırma bloğunda yaşıyor. Telefonda itme yok — orada kart içeriği kadar
   uzun ve çizgi kaydın hemen altında durmalı. */
.dash-focus .dash-card-body { display: flex; }
.dash-focus .focus {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.dash-focus .focus-route { margin-top: var(--sp-2); }

/* --- Dönem seçici (pano) ------------------------------------------------
   Kabuk liste ekranlarının süzgeç açılırıyla ortak (`.filter-pop`); burada
   yalnız içindeki iki grup biçimlenir. */

/* Hazır dönemler: çip değil sade satır. Gerçek bağlantı oldukları için tek
   tıkla uygulanırlar; panelin "Uygula" düğmesi yalnız özel aralık içindir. */
.range-presets { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.range-preset {
  display: flex;
  align-items: center;
  min-height: 34px;
  padding: 0 var(--sp-2);
  border-radius: var(--r-md);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 500;
}
.range-preset:hover {
  background: var(--surface-soft);
  color: var(--text);
  text-decoration: none;
}
.range-preset.is-active {
  background: var(--selected);
  color: var(--text-primary);
  font-weight: 600;
}

/* İki tarih alanı yan yana; dar panelde alt alta. */
.range-fields { display: flex; flex-wrap: wrap; gap: var(--sp-3); min-width: 0; }
.range-fields .field { flex: 1 1 140px; min-width: 0; margin: 0; }
.range-fields .field > label {
  display: block;
  margin-bottom: 4px;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
}
.range-fields .input { width: 100%; }

/* Düğmedeki seçili değer ("Sektör **Tümü**" / "Dönem **1–15 Eyl**"):
   etiketten ayrışsın diye koyu ve biraz daha kalın. */
.filter-btn-value { color: var(--text-primary); font-weight: 600; }

/* Sektör yuvası — içeriğini `app.js` doldurur; boşken yer kaplamamalı. */
.sector-dock { flex: 0 0 auto; min-width: 0; }
.sector-dock:empty { display: none; }


/* --- Bugünün odağı -------------------------------------------------------
   Sayfanın tek "öne çıkan modülü". Zemin açık mineral mavi; çerçeve aynı
   ailenin bir ton koyusu. Gölge yok: `--shadow-float` sayfada bir-iki modüle
   ayrılmıştır ve bu ekranda zaten yükselen tek yüzey bu — zemin farkı
   yeterli işaret. */
.focus {
  border: 1px solid var(--strong-border);
  border-radius: var(--r-lg);
  background: var(--strong-soft);
  overflow: hidden;
}
/* Odak yokken aynı yüzey sakinleşir: "bugün acil bir şey yok" bir uyarı
   değil, iyi haber. */
.focus.is-clear {
  background: var(--surface-soft);
  border-color: var(--border);
}

.focus-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-6);
}

.focus-kicker {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  /* Anlam token'i: zemin `--strong-soft` koyu temada koyulastigi icin
     paletten sabitlenen lacivert metin koyu-ustunde-koyu kaliyordu. */
  color: var(--text-secondary);
}
.focus-kicker .dot-sep { color: var(--text-muted); }

.focus-title {
  margin: 0;
  /* 18 px / 700. Kart başlığı ("Bugünün odağı") her yerde 15 px; kayıt adı
     28 pikselken kartın **kendi başlığının iki katı** oluyordu ve bölüm
     başlığı, içindeki tek satırın altında kalıyordu — okuyan kişi hangisinin
     kapsayıcı olduğunu tipografiden çıkaramıyordu. 18 px farkı koruyor
     (kayıt adı hâlâ kartın en iri metni) ama hiyerarşiyi ters çevirmiyor.
     Bir basamak: 15 (başlık/liste satırı) → 18 (odaktaki ad). */
  font-size: var(--fs-lg);
  line-height: 1.25;
  /* Sıkı aralık iri puntonun işiydi; 18 pikselde harfleri birbirine
     yapıştırıyordu. */
  letter-spacing: -0.012em;
  /* Anlam token'i, kimlik rengi değil. `--navy-active` koyu temada palet
     tarafından **koyulaştırılıyor** (`--p-navy-900`), zemin `--strong-soft`
     de koyu: başlık koyu-üstünde-koyu kalıyordu. Aynı düzeltme hemen
     aşağıdaki `.focus-kicker`da yapılmış, başlıkta atlanmıştı.

     Lacivert zaten buraya ait değildi: tasarım sistemi §1'e göre lacivert
     **kimlik**tir (logo, hero metni) ve bu satır bir kayıt adı. */
  color: var(--text-primary);
}
.focus-title a { color: inherit; }
.focus-title a:hover { text-decoration: underline; }
/* Odak kartının adı, panonun **en önemli hedefi**: kartın konusu olan kayda
   giden bağlantı odur. Ölçüm turu onu 156×30 piksel buldu; başlık satırının
   kendi yüksekliği parmağın gerektirdiğinin altında kalıyor.

   Çözüm dolgu değil sözde öğe: `padding` başlığın altındaki alt satırla
   arasını açıp kartın dikey ritmini bozardı. Hedef adın satırına ortalanıp
   `--tap`e çıkıyor, çizim yerinde kalıyor. */
.focus-title { position: relative; }
.focus-title a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--tap);
  transform: translateY(-50%);
}

.focus-sub {
  margin: 0;
  max-width: 56ch;
  color: var(--text-secondary);
}

/* Gecikme: arka plansız yanık mercan metin. Dolu kırmızı bir kutu, ilgisini
   zaten çekmiş bir kullanıcıya bağırmak olurdu (tasarım sistemi §1). */
/* Faz 32: renk `--accent`ten (mercan 600) sözlüğün `-ink` rolüne (700)
   geçti. İki sebep, ikisi de ölçü: (1) kart yüzeyinde 600 AA'nın altında
   kalıyordu — 4.46:1, `.is-alert` bloğunda yazılı olan tam bu sayı; (2)
   gecikme artık her yüzeyde tek jetondan okunuyor (`.due`, `.is-alert`,
   sade durum rozeti), tek istisna bu satır kalmıştı. */
.focus-late {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--state-late-ink);
}
.focus-late .icon { width: 16px; height: 16px; }

.focus-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-1);
}
/* Hızlı alanlar düğmenin yanında ve **değer** olarak durur; kutu ancak
   dokununca gelir (`_quick.pop_*`). */
.focus-quick {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  font-size: var(--fs-sm);
}
.focus-quick .quick-pop-caret { opacity: 1; }

/* Rota çizgisi: üç durak, aralarında tek ince çizgi. Dekoratif değil —
   "başlangıç, plan, hedef" üçlüsü yan yana durunca kalan yol tek bakışta
   okunuyor. Çizgi noktaların arkasından geçer, üstünden değil.

   Çizginin **dolu payı** artık gerçek bir ölçü: işin biten görev yüzdesi
   (`routes._focus_route` → `Plan` adımının `percent`i). Eskiden bu sayı
   üretiliyor ama hiç basılmıyordu; çizgi her kayıtta aynı gri duruyordu ve
   üç durak sadece üç etiketten ibaretti.

   Duraklar eşit aralıklı olduğu için konumları %0 / %50 / %100'dür; her
   durağın kendisinden sonraki parçasının dolu oranını şablon `--dolu`
   olarak yazar. Geçilen durak `is-done` alır — dolgunun nerede durduğu
   renkten bağımsız, ikinci bir kanaldan da okunur. */
.focus-route {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-2);
  margin: 0;
  /* Faz 25: dolgu 16/24/20'den 12/16/14'e indi. Rota kartın **dipnotu**;
     kaydın adı ve eylemi kadar yer istemesi için bir sebep yok ve odak
     kartının "gereksiz yüksekliği" diye okunan şeyin yarısı buradaydı. */
  padding: var(--sp-3) var(--sp-4) 14px;
  list-style: none;
  border-top: 1px solid var(--brand-border);
  background: var(--surface-soft);
}
.focus-stop {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* 16 piksel taban: nokta 12 piksel yüksekliğinde ve mutlak konumda
     (`top: 0`), etiket dolgunun bittiği yerden başlıyor. Daha azı, etiketi
     noktanın ve rayın içine sokuyor. */
  padding-top: var(--sp-4);
  min-width: 0;
}
/* Bağlantı çizgisi durağın **noktasının ortasından** başlar (6px = 12px'lik
   noktanın yarısı) ve bir sonrakine uzanır. Son duraktan sonra çizgi yok:
   rota orada bitiyor, boşluğa doğru devam etmiyor. */
/* Ray kolonun sağ kenarını 8 piksel aşar (`--sp-2`, ızgaranın boşluğu):
   eskiden kolonun kenarında bitiyordu ve iki durak arasında kopuk bir
   çizgi kalıyordu. Kesintisiz ray, dolgunun nerede durduğunu ölçülebilir
   kılıyor — kopuk bir rayda %50 ile %60 aynı görünüyordu. */
.focus-stop::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 6px;
  right: calc(var(--sp-2) * -1);
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--border);
}
/* Dolu pay. Ayrı bir katman, çünkü boş ray her zaman görünmeli: tek bir
   öğeyi kısaltmak "ilerleme %20" ile "rota burada bitiyor"u aynı resme
   çevirirdi. `--dolu` yoksa (yüzde ölçülemiyor) genişlik sıfır kalır ve
   çizgi eski sade hâlindedir.

   `--dolu` **birimsiz** yazılır (0–100). CSS `calc()` bir uzunluğu yüzdeyle
   çarpamaz ya da yüzdeye bölemez; birimsiz sayıyla çarpıp 100'e bölmek
   aynı hesabın geçerli yazımı. */
.focus-stop::after {
  content: "";
  position: absolute;
  top: 5px;
  left: 6px;
  width: 0;
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--brand);
  transition: width var(--dur-3) var(--ease-out);
}
.focus-route.has-meter .focus-stop::after {
  width: calc((100% + var(--sp-2) - 6px) * var(--dolu, 0) / 100);
}
.focus-stop:last-child::before,
.focus-stop:last-child::after { display: none; }
.focus-stop-mark {
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 2px solid var(--border-strong);
  transition: background-color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out);
}
/* Geçilen durak dolu indigo; hedef her zaman işaretli (rotanın nerede
   bittiği ölçülemeyen kayıtlarda da okunmalı). Hedefe *ulaşılmışsa* iki
   kural da aynı rengi verir, çakışma yok. */
.focus-route.has-meter .focus-stop.is-done .focus-stop-mark {
  background: var(--brand);
  border-color: var(--brand);
}
.focus-stop.is-target .focus-stop-mark {
  background: var(--surface);
  border-color: var(--brand);
}
.focus-route.has-meter .focus-stop.is-target.is-done .focus-stop-mark {
  background: var(--brand);
}
.focus-stop-label {
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
  opacity: 0.75;
}
.focus-stop-value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  /* Anlam token'ı, kimlik rengi değil: `--navy-active` koyu temada
     koyulaşıyor ve koyu zeminde okunmuyordu (aynı düzeltme `.focus-title`
     ve `.focus-kicker`da yapılmıştı, burada atlanmıştı). */
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
/* Yüzde, değerin yanında küçük bir hap: "14/23 görev" payı, "%61" oranı
   söyler ve ikisi aynı puntoda dururken hangisinin ölçü olduğu
   okunmuyordu. */
/* Sayının yerine geçen açıklama ("İşin kapanışı bekleniyor"). Değerin
   altında ve bir basamak sessiz: okunacak şey üstteki cümle, bu onun
   gerekçesi. Yüzde rozetiyle birlikte hiç görünmez — biri varsa öteki yok
   (bkz. `dashboard.html`, rota çizgisi). */
.focus-stop-note {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
}
/* Faz 25: hap zemini kalktı. Yüzde bir **ölçü**, bir etiket değil; dolu
   zeminli küçük bir kutu onu rozete çeviriyor ve rota çizgisinin üstünde
   ikinci bir renkli yüzey üretiyordu (çizginin dolu payı zaten aynı sayıyı
   söylüyor). Marka rengi ve kalın ağırlık, ayrımı yapmaya yetiyor. */
.focus-stop-pct {
  flex: none;
  color: var(--brand);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}
.focus.is-clear .focus-route { border-top-color: var(--border); }

/* Hareketi kapatan kullanıcıda çizgi olduğu yerde belirir. */
@media (prefers-reduced-motion: reduce) {
  .focus-stop::after { transition: none; }
}

/* Odak dışında kalan gecikmiş işler. Başlık küçük ve çizgisiz: bunlar
   "Bugünün odağı" bölümünün devamı, ayrı bir bölüm değil. */
/* (`.focus-more*` silindi: odak kartının altındaki "Gecikmiş diğer işler"
   listesi kaldırıldı. Aynı bilgi ikinci satırdaki "Gecikenler" sayacında ve
   o sayaç hepsini içeren liste ekranına iniyor; kartın içinde ikinci bir
   liste tutmak hem tekrardı hem de kartı ekranın iki katına çıkarıyordu.) */

@media (max-width: 599px) {
  .focus-body { padding: var(--sp-4); }
  /* Rota telefonda da **yatay**: üç durak, tek satır.

     Alt alta dizilen üç madde 171 piksel yer istiyordu (kartın 435 pikselinin
     %39'u) ve karşılığında hiçbir şey kazandırmıyordu — üstelik dikey
     listede ray ile dolu pay anlamını yitirdiği için ilerleme çizgisi de
     düşüyordu. Üç sütunda her durağa ~114 piksel kalıyor: "BAŞLANGIÇ" ve
     "14 Eyl 2026" ikisi de tek satıra sığan ölçüler.

     Dar sütunda değer sarabilir; sarması kabul, ekranın beşte birini bir
     zaman çizgisine vermek değil. */
  .focus-route { padding: var(--sp-4) var(--sp-4) var(--sp-5); gap: var(--sp-2); }
}


/* (`.panel*` ve `.overview-pair` silindi: panoyu kartsız bölümlere ayıran
   o düzen, 12 kolonluk ızgarayla birlikte `.dash-card`a devredildi. Kayıt
   çekmecesindeki aynı adlı sınıflar `.panel-shell` ile kapsanmış durumda ve
   bu silmeden etkilenmiyor — bkz. bu dosyanın 2317 satırı civarı.) */

/* (Faz 6 — `.rhythm*` silindi. "İşlerin ritmi" paneli, "Bugün" bölümünün
   kendisiyle aynı şeyi söylüyordu: biri kaydı gösteriyor, diğeri kaydın
   sayısını.) */


/* (`.ratio*` silindi: tamamlanma oranı kendi bloğunu kaybetti ve "Yaklaşan
   teslimler" kartının başlığına tek satır olarak girdi. O karttaki her işin
   zaten kendi ilerleme çizgisi var; oran onların toplamı, ayrı bir gösterge
   değil.) */


/* --- Ekipteki son hareketler --------------------------------------------
   Vurgusuz bir kronoloji: bu bir yapılacaklar listesi değil, "ben yokken ne
   oldu" sorusunun kısa cevabı. Bu yüzden rayın en altında ve en sessiz
   tipografiyle durur. */
.feed-mini { margin: 0; padding: 0; list-style: none; }
.feed-mini-row {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border-soft);
}
.feed-mini-row:last-child { border-bottom: 0; }
.feed-mini-mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--r-pill);
  background: var(--surface-soft);
  border: 1px solid var(--border-soft);
  color: var(--text-secondary);
}
.feed-mini-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.feed-mini-title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}
.feed-mini-title:hover { text-decoration: underline; }
.feed-mini-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-width: 0;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
}
.feed-mini-meta + .feed-mini-meta { color: var(--text-muted); }

/* Panoda üç hareket **yan yana**. Kart tam genişlikte (12 kolon) ve alt alta
   dizilseydi ekranın dibinde 120 piksel, taşıdığı bilgiye göre fazla yer
   kaplardı. Ayraç alt çizgi değil sağ çizgi: satırlar artık yan yana.

   900 pikselin altında eski hâline döner — üç kolonda başlık tek kelimeye
   iner ve "ben yokken ne oldu" sorusunu cevaplayamaz. */
.feed-mini-grid { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) {
  .feed-mini-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .feed-mini-grid > .feed-mini-row {
    border-bottom: 0;
    border-right: 1px solid var(--border-soft);
  }
  .feed-mini-grid > .feed-mini-row:last-child { border-right: 0; }
}


/* ==========================================================================
   Takvim — redesign Faz 3
   ========================================================================== */

/* --- Tür şeridi: hem lejant hem süzgeç ----------------------------------
   İki işi tek öğe yapar. Ayrı bir lejant + ayrı bir süzgeç paneli, aynı üç
   kelimeyi ekranda iki kez yazmak olurdu.

   Faz 25: üç ayrı **hap** yerine tek bir segmented control.

   Eskiden her tür kendi çerçevesini, kendi yuvarlak köşelerini ve kendi
   zeminini taşıyordu. Takvimin üst şeridinde zaten iki grup daha var —
   görünüm sekmeleri (`.tabs-soft`, o da bir hap dizisi) ve dönem
   gezinmesi — yani 900 pikselin sağında yan yana yedi-sekiz yuvarlak
   nesne duruyor, hiçbiri diğerinden daha az "tıkla beni" demiyordu.
   Şeridin kendisi, ayarladığı ızgaradan daha yoğundu.

   Üçü tek bir kaba girdi: dışarıda bir çerçeve, içeride saç teli ayırıcı.
   Kazanç yalnız sadelik değil, **anlam**: yan yana duran ve bir kapsayıcıyı
   paylaşan üç seçenek, birbiriyle ilişkili bir küme olduklarını biçimle
   söylüyor — ayrı haplar üç bağımsız düğme gibi okunuyordu. */
.cal-kinds {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-4);
  min-width: 0;
}
/* Şeridin ne olduğunu söyleyen tek kelime. Süzgeçler "Filtreler" düğmesinin
   arkasındayken etiket gereksizdi; ortada duran üç seçenek ise neyi
   süzdüğünü kendi başına söylemiyor. */
.cal-kinds-label {
  flex: none;
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-muted);
}
.cal-kind-set {
  display: flex;
  align-items: stretch;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}
.cal-kind {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 30px;
  padding: 0 var(--sp-3);
  /* Ayırıcı **iç** çizgi; dış çerçeveyi kap çiziyor. */
  border-left: 1px solid var(--border-soft);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text);
  white-space: nowrap;
  transition: background-color var(--dur-1) var(--ease-out);
}
.cal-kind:first-child { border-left: 0; }
/* Açık tür kendi tonunu taşır (Faz 27).

   Bu üçlü, uygulamanın **fiilî renk efsanesi**: "görev mavi, teslim mor,
   takip amber" cümlesi başka hiçbir ekranda bir arada yazılı değil. Nokta
   bunu 9 piksele sığdırmaya çalışıyordu; seçeneğin kendisi zaten adını
   taşıdığı için dolgunun eklediği tek şey renk oluyor — yani efsanenin
   asıl bilgisi.

   Kurallar `:hover` ve `.is-off`ten **önce** yazılıyor: üçü de aynı
   özgüllükte (0,2,0) ve sonra gelen kazanır. İmlece cevap verme ile "bu tür
   kapalı" bilgisinin tür renginden önemli olması bilinçli — sönük bir
   seçenek tür rengini taşımaz, taşısa kapalı olduğu okunmaz. */
.cal-kind-task {
  background: var(--kind-task-fill);
  color: var(--kind-task-ink);
  --dot-ring: var(--kind-task-fill);
}
.cal-kind-project {
  background: var(--kind-project-fill);
  color: var(--kind-project-ink);
  --dot-ring: var(--kind-project-fill);
}
.cal-kind-company {
  background: var(--kind-company-fill);
  color: var(--kind-company-ink);
  --dot-ring: var(--kind-company-fill);
}
/* "Tümü" — türü olmayan seçenek, o yüzden rengi de yok. Nötr durması
   bilinçli: üç tür renkleriyle dururken dördüncü bir renk uydurmak,
   şeridin efsane olarak okunmasını bozardı. Seçili olduğunda rengiyle
   değil **çizgisiyle** öne çıkar. */
.cal-kind-all { color: var(--text-secondary); }
.cal-kind-all.is-focus {
  background: var(--surface-sunken);
  color: var(--text);
  box-shadow: inset 0 0 0 1.5px var(--border-strong);
}
.cal-kind:hover { text-decoration: none; background: var(--surface-soft); }
/* Seçilmeyen tür silinmez, **söner**: hangi türlerin var olduğu süzgeç
   açıkken de görünmeli, yoksa kullanıcı geri dönmek için neyi arayacağını
   bilemez. Tek seçime geçince sönmenin anlamı da netleşti — "bunu kapattın"
   değil, "şu an ekranda yalnız öteki var". Bu yüzden sönme ancak bir tür
   seçiliyken uygulanır; "Tümü" seçiliyken üçü de kendi rengindedir.

   Sönme iki kanalda: metin soluklaşır ve nokta **içi boşalır**. Tek kanal
   (opaklık) yetmiyordu — %45 opaklıktaki bir etiket, koyu temada zaten
   soluk olan ikincil metinden ayırt edilemiyordu. */
.cal-kind.is-off { color: var(--text-muted); background: var(--surface-sunken); }
.cal-kind.is-off .kind-dot {
  background: radial-gradient(circle at 50% 50%, var(--surface) 0 2px, var(--border-strong) 2px);
}
/* Kapalı türün de hover'ı olmalı: `.cal-kind.is-off` ile `.cal-kind:hover`
   aynı özgüllükte ve `.is-off` dosyada sonra geliyor, yani zemin kuralını
   yutuyordu — üç seçenekten ikisi imlece cevap verip biri vermiyordu.
   Sönük öğe hover'da bir basamak canlanır ama açık olanla eşitlenmez. */
.cal-kind.is-off:hover { background: var(--surface-soft); color: var(--text-secondary); }
/* Seçili tür: şeritte **her zaman tam bir tane** vurgulu olur ("Tümü" de
   bir seçimdir). Vurgu tür renginin kendi çizgisiyle (`--kind-*-line`)
   yapılıyor: ızgaradaki olay kutuları da aynı üç rengi taşıyor, yani
   "seçtiğim tür" ile "ekranda kalan kutular" aynı rengi konuşuyor.

   Kurallar `.is-off` ve `:hover`ten **sonra**: üçü de (0,2,0) özgüllükte ve
   sonra gelen kazanır. */
.cal-kind-task.is-focus {
  background: var(--kind-task-fill);
  color: var(--kind-task-ink);
  box-shadow: inset 0 0 0 1.5px var(--kind-task-line);
}
.cal-kind-project.is-focus {
  background: var(--kind-project-fill);
  color: var(--kind-project-ink);
  box-shadow: inset 0 0 0 1.5px var(--kind-project-line);
}
.cal-kind-company.is-focus {
  background: var(--kind-company-fill);
  color: var(--kind-company-ink);
  box-shadow: inset 0 0 0 1.5px var(--kind-company-line);
}
/* Seçili çip imlece **kendi rengiyle** cevap verir; yüzeyin griye dönmesi
   "tıklarsan sönecek" izlenimi verirdi — oysa seçili bir çipe tekrar basmak
   hiçbir şeyi değiştirmez, hepsine dönüş "Tümü" ile olur. */
.cal-kind.is-focus:hover { text-decoration: none; filter: saturate(1.2); }
/* Sıfırlama çip değil düz metin: eylem, seçeneklerle aynı ağırlıkta
   görünmemeli. */
.cal-kind-clear {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--brand);
}
.cal-kind-check { margin-left: auto; color: var(--brand); }
/* Sorumlu süzgeci — tür şeridinin yanında, onunla aynı satırda.
   Kendi çerçevesi yok: şeritte üçüncü bir kutu, ay ızgarasından önce
   sayılacak sınır sayısını artırırdı. Etiket tür şeridiyle aynı
   (`.cal-kinds-label`), çünkü ikisi de aynı cinsten bir kontrolün adı. */
.cal-person {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
/* Ekip büyüdükçe isim uzar; şerit yine de tek satırda kalmalı. */
.cal-person-select {
  max-width: 200px;
  min-width: 0;
}
.dropdown-item .kind-dot { margin-right: var(--sp-1); }


/* --- Etkinlik önizleme popover'ı ----------------------------------------
   Kabuk `[data-menu]`; panel `position: fixed` ve konumunu `app.js`
   hesaplar (`data-menu-anchor`) — ızgara hücresi ve kart kırpıyor.

   `display: contents`: kabuk `<span>` ızgara hücresinde ve liste satırında
   **yer tutmamalı**; tetikleyicinin kendisi (`.cal-event` / `.list-row`)
   doğrudan kabın çocuğu gibi yerleşsin. Aksi halde satır düzeni sarmalayıcı
   yüzünden bozulurdu. */
.cal-pop { display: contents; }
/* `position: fixed` + `top/right: auto` — `.row-menu-panel` ve
   `.quick-pop-panel` ile birebir aynı kalıp. `.dropdown` öntanımlı olarak
   `absolute` ve `top: calc(100% + 8px)`; `display: contents` taşıyan bir
   kabın içinde bu, paneli ızgara hücresine göre konumlandırıp hücrenin
   `overflow`una kurban ederdi. Konumu `app.js` hesaplar. */
.cal-pop-panel {
  position: fixed;
  top: auto;
  right: auto;
  z-index: 60;
  width: min(300px, calc(100vw - 32px));
  min-width: 0;
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.cal-pop-panel[hidden] { display: none; }
.cal-pop-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
}
.cal-pop-title {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  line-height: 1.3;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}
.cal-pop-meta {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: 0;
  font-size: var(--fs-sm);
}
.cal-pop-meta > div { display: flex; align-items: flex-start; gap: var(--sp-2); }
.cal-pop-meta dt { flex: none; margin: 0; color: var(--text-muted); line-height: 1.5; }
.cal-pop-meta dt .icon { width: 16px; height: 16px; display: block; }
.cal-pop-meta dd { margin: 0; min-width: 0; color: var(--text-secondary); }
.cal-pop-meta .dot-sep { margin: 0 var(--sp-1); color: var(--text-muted); }
.cal-pop-foot {
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border-soft);
}
.cal-pop-foot .btn { width: 100%; }


/* --- Ajanda satırının tür rengi -----------------------------------------
   Renk **tek kanalda**: satırın başındaki nokta (`.kind-dot`).

   Faz 25'e kadar iki kanal vardı — noktanın yanında, satırın sol kenarında
   3 piksellik renkli bir çizgi daha. İkisi aynı şeyi söylüyordu ve bedeli
   ölçekte görünüyordu: yoğun bir günde on satır, ekranın sol kenarında
   boydan boya renkli bir şerit demek. Ajanda o noktada bir kayıt listesi
   değil renk kartelası gibi okunuyor, satırlar arasındaki gerçek ayrım
   (başlık, saat, gecikme) çizginin altında kalıyordu.

   Kural: renk yalnız **türü ayırt edecek kadar**. Nokta zaten bunu yapıyor
   ve aynı işaret liste ekranlarında, panoda ve önizleme popover'ında da
   aynı anlama geliyor — ikinci bir kanal yeni bir şey söylemiyordu.
   Gecikme (`.due`) ve tamamlanmışlık (`.is-done`) yerinde: ikisi de tür
   değil **durum** anlatıyor ve ikisi de tek tek satırlarda beliriyor. */
.cal-item { position: relative; }


/* --- Günün özeti: ızgara hücresinden açılan panel -----------------------
   Kabuk ve konumlama etkinlik önizlemesiyle birebir aynı (`[data-menu]` +
   `data-menu-anchor`); farkı içeriği: tek kayıt değil, günün tamamı.

   Neden var: ay ızgarası bir hücrede üç, hafta ızgarası altı etkinlik
   gösteriyor ve fazlası "+N daha"ya düşüyordu. O bağlantı kullanıcıyı tam
   sayfa bir gezinmeye (gün görünümü) yolluyordu — oysa aynı soru tek bir
   etkinlik için sorulduğunda ekranda kalıp küçük bir kart açılıyor. İki
   ölçek, iki ayrı davranış. Artık ikisi de panel açıyor; gezinme kaybolmadı,
   panelin altındaki düğmeye indi. */
.cal-day-pop {
  position: fixed;
  top: auto;
  right: auto;
  z-index: 60;
  width: 300px;
  /* Dar ekranda da kenar payı kalsın: `app.js` konumu 8 pikselle
     sınırlıyor, genişliği CSS. */
  max-width: calc(100vw - var(--sp-4));
  /* Tavan: pencerenin boyu. Asıl sınırı `app.js` yazıyor (tetikleyicinin
     üstünde ya da altında kalan yere göre), bu yalnız taban emniyeti —
     betik henüz ölçmeden panel bir kare boyunca kendi doğal boyunda
     çizilir ve on kayıtlı bir gün orada ekranı aşardı. `dvh`, `vh` değil:
     mobil tarayıcı çubuğunun altı sayılmamalı. */
  max-height: calc(100dvh - 2 * var(--sp-4));
  /* Baş ve ayak sabit, **liste** kayar. Panelin tamamı tek parça kaysaydı
     "Gün görünümünde aç" düğmesi kaydırmanın altında kalırdı — panelin
     varlık sebeplerinden biri o düğme. */
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
}
.cal-day-pop-head,
.cal-day-pop-foot { flex: none; }
.cal-day-pop[hidden] { display: none; }
.cal-day-pop-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-sunken);
  font-size: var(--fs-sm);
}
.cal-day-pop-head.is-today { color: var(--brand); }
.cal-day-pop-count {
  flex: none;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Panelin **kendisi** kayar, sayfa değil: on kayıtlı bir gün paneli ekranın
   boyunu aşmamalı. Kaydırma gölgesi `.dash-card-body` ile aynı teknik. */
.cal-day-pop-list {
  margin: 0;
  padding: 0;
  list-style: none;
  /* Kalan yeri alır ve kendi içinde kayar. Sabit bir `46vh` tavanı vardı:
     panelin baş ve ayağıyla toplanınca kısa pencerede yine taşıyordu ve
     `vh` mobilde tarayıcı çubuğunun altını sayıyordu. `min-height: 0`
     flex öğesinin gerçekten kısalabilmesi için gerekli. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.cal-day-pop-row {
  display: grid;
  /* Üç kolon: nokta · ad · saat. Ad **tek** esneyen kolon; saat ve nokta
     sabit kalır, yoksa uzun bir kayıt adı saati satırdan atardı. */
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--fs-sm);
}
.cal-day-pop-row:last-child { border-bottom: 0; }
.cal-day-pop-row:hover { background: var(--surface-soft); }
.cal-day-pop-title {
  min-width: 0;
  color: var(--brand);
  font-weight: 600;
  /* İki satır: paneldeki liste kırpılmış adlar için açılıyor, kırpılmış ad
     göstermek için değil. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.cal-day-pop-meta { font-size: var(--fs-xs); color: var(--text-muted); }
/* Tamamlanmış görev panelden **düşmez**, sakinleşir: "bugün ne yaptım"
   sorusunun cevabı da takvimdedir (aynı kural `.cal-event.is-done`da). */
.cal-day-pop-row.is-done .cal-day-pop-title { color: var(--text-muted); font-weight: 400; }
.cal-day-pop-foot {
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border);
}
.cal-day-pop-foot .btn { width: 100%; }

/* Açık tetikleyici: gün numarası ve "+N daha" panel açıkken işaretli kalır —
   hangi hücrenin panelinin açık olduğu, panelin kendisinden başka bir yerde
   de okunmalı. */
.cal-cell-date[aria-expanded="true"] { background: var(--selected); }
.cal-more[aria-expanded="true"] { color: var(--brand); }

/* --- Kırpılmış etkinlik adının ipucu balonu ----------------------------
   Izgara hücresi dar ve etkinlik adı tek satırda kesiliyor; hafta
   görünümünde "Marmara Diş Kliniği ile…" satırın ne olduğunu söylemiyor.

   Balon `app.js` tarafından **tek bir öğe** olarak gövdeye ekleniyor ve
   `position: fixed` ile konumlanıyor. İki gerekçe:

   1. Izgara (`.cal-grid`) yuvarlak köşeleri için `overflow: hidden` taşıyor.
      Hücrenin içinde mutlak konumlu bir balon, son sütunda ve son satırda
      kırpılırdı — yani tam olarak en çok kırpılan adların yanında.
   2. `title` özniteliği yalnız **fareyle** çalışır; klavyeyle gezen
      kullanıcıya hiçbir şey göstermez. Balon `focus-visible`da da çıkıyor.

   Betik yoksa öznitelik yerinde kalır ve tarayıcının kendi ipucu devreye
   girer — bilgi hiçbir durumda kaybolmuyor. */
.cal-tip {
  position: fixed;
  z-index: 80;
  max-width: 280px;
  padding: 5px var(--sp-2);
  border-radius: var(--r-xs);
  /* Renk `.tip` ile birebir aynı (bkz. `base.css`): ipucu iki temada da
     zeminin tersi olmalı. `--text-primary` aydınlıkta koyu, koyuda açık;
     `--surface` tam tersi. Paletten sabitlenmiş bir renk koyu temada
     beyaz-üstünde-beyaz çıkardı. */
  background: var(--text-primary);
  color: var(--surface);
  font-weight: 600;
  font-size: var(--fs-xs);
  line-height: 1.4;
  pointer-events: none;
  overflow-wrap: anywhere;
  box-shadow: var(--shadow-lg);
}
.cal-tip[hidden] { display: none; }


/* --- Masaüstü gün görünümü ---------------------------------------------- */
.cal-day-shell { overflow: hidden; }
.cal-day-banner {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
  background: var(--app-bg);
}
.cal-day-banner.is-today { background: var(--brand-softer); }
.cal-day-num {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-black);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.cal-day-banner.is-today .cal-day-num { color: var(--brand); }
.cal-day-text { display: flex; flex-direction: column; }


/* --- Boş gün ------------------------------------------------------------
   Tek satır mesaj ve tek bağlantı. Büyük bir illüstrasyonlu kart, boşluğu
   bilgi gibi gösterirdi: ekranın yarısını "burada bir şey yok" demeye
   harcamak, orada bir şey varmış izlenimi bırakıyor. */
.cal-empty {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-5);
}
.cal-empty-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  min-width: 0;
  font-size: var(--fs-sm);
}
.cal-empty-text strong { font-size: var(--fs-base); color: var(--text-primary); }


/* --- Telefon: başparmak çubuğu ------------------------------------------
   Tarih değiştirme, süzgeç ve yeni kayıt ekranın altında toplandı. Yapışkan
   ve alt sekme çubuğunun **üstünde** biter — `fixed` olsaydı listenin son
   satırını örterdi (form çubuklarındaki kuralın aynısı, tasarım sistemi
   §12). */
.cal-thumb {
  position: sticky;
  bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--sp-2));
  z-index: 20;
  display: flex;
  align-items: center;
  /* Çubuk beş kontrol taşıyor ve dördü esnemez (iki ok, "Bugün", süzgeç,
     yeni kayıt); esneyen tek öğe tarih alanı ve onun içinde bir native
     `<input type="date">` var — tarayıcının kendi asgari genişliğinin
     altına inmiyor. 320–360 pikselde toplam, kabı yatayda taşırıyordu ve
     `overflow` da yoktu, yani taşan kontrol tümüyle erişilemez oluyordu.
     Sarma o durumda ikinci satıra iniyor; sığdığı her ölçüde tek satır
     kalıyor. */
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--sp-1);
  margin-top: var(--sp-3);
  padding: var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.cal-thumb .cal-jump {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0;
}
/* Oklar **bitişik**: tek bir işin iki yönü, tek bir grup.

   Eskiden aralarında "Bugün" düğmesi ve tarih alanı vardı — yani ekranın
   iki ucunda duran iki ok. Bir çift ok ayrıldığında "ileri git" düğmesi,
   yanındaki tarih alanının bir parçası gibi okunuyor ve "geri git"in eşi
   olduğu ancak ikon şeklinden anlaşılıyordu. */
.cal-thumb-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
}
.cal-thumb-step { flex: none; }
/* "Bugün" tarih alanının **sağında**: seçicinin değerini sıfırlayan düğme,
   sıfırladığı alandan önce gelmemeli. Okuma yönünde önce nerede olduğun,
   sonra geri dönme yolun. */
.cal-thumb-today { flex: none; }
.cal-thumb-filter { position: relative; flex: none; }
/* Süzgeç paneli de anchor'lu: çubuk yapışkan ve dar, panel onun dışına
   taşmalı. */
.cal-thumb-filter .dropdown {
  position: fixed;
  top: auto;
  right: auto;
  z-index: 60;
  min-width: 200px;
}
/* Süzgeç açıkken düğmenin üstünde küçük bir nokta: "bu ekranda gizli bir
   kural var" bilgisi, panel kapalıyken de görünmeli. */
.cal-filter-dot {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill);
  background: var(--accent-solid);
  border: 2px solid var(--surface);
  pointer-events: none;
}
.cal-thumb-filter .icon-btn.is-on { color: var(--brand); }
.cal-thumb-new {
  flex: none;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border-radius: var(--r-pill);
}

@media (max-width: 899px) {
  /* Mobil kabukta gezinme başlığı artık yalnız tarih yazar; oklar aşağıda. */
  .cal-day-head { justify-content: center; }
  .cal-empty { padding: var(--sp-4); }
}


/* =========================================================================
   REDESIGN FAZ 4 — İş, görev ve firma ayrıntısı; notlar ve yorumlar
   =========================================================================

   Üç ayrıntı ekranı aynı iskeleti paylaşır:

     [ rec-head  ]  ad · durum · sorumlu · tarih · gecikme   [Düzenle] [⋯]
     [ rec-strip ]  ilerleme / süreç çizgisi / kompakt güncelleme
     [ tabs      ]  Görevler · Bilgiler · Aktivite
     [ içerik    ]

   Ortak kural: **durum, tarih ve öncelik renkli kapsülde gösterilmez.**
   Liste ekranlarının Faz 2'de kurduğu dil (küçük nokta + düz metin)
   ayrıntıya da taşındı; ayrıntı ekranı listeden farklı konuşmamalı.
   ===================================================================== */

/* --- Kayıt başlığı ---------------------------------------------------- */

/* Faz 17: başlık artık ince bir çizginin üstünde duran serbest bir satır
   değil, **kendi yüzeyi olan kompakt bir künye**. Ad, durum, sorumlu,
   tarih ve eylemler aynı çerçevenin içinde durur; altındaki şerit
   (ilerleme ya da süreç çizgisi) aynı yüzeyin alt bandı olur.

   Önceki hâlde yedi bilgi ile iki düğme arasında yalnız boşluk vardı:
   "başlık nerede bitti" sorusu tuvalin rengiyle yanıtlanıyordu ve şerit,
   ait olduğu kayıttan bağımsız ikinci bir nesne gibi okunuyordu. */
.rec-head {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4);
  margin-bottom: var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
/* Alt bant varken künyenin alt köşeleri kare: ikisi tek yüzeydir.
   `:has()` desteklenmeyen bir tarayıcıda kaybedilen tek şey iki yuvarlak
   köşedir — düzen ayakta kalır, bant yine yapışık durur. */
.rec-head:has(+ .rec-band) {
  margin-bottom: 0;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.rec-head-text {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  flex: 1 1 320px;
  min-width: 0;
}
/* Kayıt adı `page_title`dan bir punto büyük değil, bir punto **tok**:
   ekranın konusu bu addır ve altındaki meta satırından net ayrılmalı.
   Faz 17'de punto 2xl → xl'e indi: künye bir yüzeyin içine girince ad
   zaten çerçeveyle ayrılıyor, 30 piksellik bir başlık kendi kutusunun
   yarısını harcıyordu. */
.rec-title {
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: var(--fw-black);
  letter-spacing: -0.022em;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.rec-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  min-width: 0;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.rec-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
/* Ayraç CSS'te: şablonlar elle "·" bastığında koşullu bir öğe düştüğünde
   satırın başında ya da sonunda öksüz nokta kalıyordu. */
.rec-meta-item + .rec-meta-item::before {
  content: "·";
  margin-right: var(--sp-2);
  color: var(--text-muted);
}
.rec-meta-owner .truncate { max-width: 22ch; }
.rec-meta .status { font-weight: 600; color: var(--text-primary); }
.avatar-xs { width: 22px; height: 22px; font-size: 10px; }

.rec-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
  margin-left: auto;
}

/* Silme kipinin gerçek tetikleyicisi: menüdeki öğe ona `form` özniteliğiyle
   bağlandığı için görünmesi gerekmiyor. `display: none` — `visually-hidden`
   olsaydı sekme sırasında görünmez bir "Sil" düğmesi kalırdı. */
.rec-hidden-trigger { display: none; }

.rec-menu { position: relative; flex: none; }
.rec-menu-panel { min-width: 210px; }
.rec-menu-panel .dropdown-item { min-height: 38px; }
.rec-menu-panel .dropdown-item.is-danger { color: var(--danger); }
.rec-menu-panel .dropdown-item.is-danger .icon { color: var(--danger); }
.rec-menu-panel .dropdown-item.is-danger:hover { background: var(--danger-bg); }
@media (pointer: coarse) {
  .rec-menu-panel .dropdown-item { min-height: var(--tap); }
}

/* Betik yoksa menü açılamaz; o yüzden tetikleyici gizlenir ve öğeler
   başlığın altına satır içi düğmeler olarak iner. Liste ekranındaki
   `.over-menu` ile aynı geri dönüş. */
html:not(.js) .rec-menu > .btn { display: none; }
html:not(.js) .rec-menu {
  flex: 1 1 100%;
}
html:not(.js) .rec-menu-panel,
html:not(.js) .rec-menu-panel[hidden] {
  display: flex !important;
  position: static;
  flex-wrap: wrap;
  gap: var(--sp-1);
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  animation: none;
}
html:not(.js) .rec-menu-panel .dropdown-item { width: auto; }
html:not(.js) .rec-menu-panel .dropdown-header { display: none; }

/* --- Başlık altı şerit: ilerleme, süreç, kompakt güncelleme ------------ */

/* `.rec-strip` yalnız yerleşimdir (yan yana duran birkaç öğe). Görünümü
   iki modifiye verir ve ikisi **farklı soruları** yanıtlar:

     `.rec-band`  — künyenin alt bandı: okunan bilgi (ilerleme, süreç).
     `.rec-quick` — kontrol kartı: değiştirilen alanlar.

   Tek sınıfken firma ayrıntısında süreç çizgisi ile hızlı güncelleme aynı
   görünüyordu; biri gösterge, öbürü form olduğu hâlde ikisi de aynı
   ağırlıkta duruyordu. */
.rec-strip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-4);
}

/* Künyenin alt bandı. Birleştirme tekniği `.section-head-attached + .card`
   ile aynı: negatif kenar boşluğu yerine burada kare üst köşe + paylaşılan
   sınır yeter, çünkü bant künyenin doğrudan kardeşi. */
.rec-band {
  margin-top: 0;
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-top-color: var(--border-soft);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  background: var(--surface-soft);
  box-shadow: var(--shadow-card);
}

/* Hızlı güncelleme: yatay, kompakt bir kontrol kartı.

   Alanlar tuvalin üstünde tek tek yüzen beyaz kutular değil, çökük bir
   yüzeyin üstünde tek satır. Böylece "okunan yüzey" ile "değiştirilen
   yüzey" bakışta ayrılır: sayfanın geri kalanı beyaz, burası sakin gri.
   Etiketler de bir punto iner — kutunun içindeki etiket, bölüm başlığıyla
   aynı ağırlıkta olmamalı. */
/* Kart **sayfanın tamamına yayılmaz**. Tam genişlikken dört alan 1100
   pikselin içine dağılıyor, "Bekleme nedeni" kutusu ekranın yarısını
   alıyordu: kompakt olması gereken bir denetim, sayfanın en büyük nesnesi
   oluyordu. Tavan ölçü, dört alan + düğmenin tek satırda durabildiği en
   dar genişlik — `fit-content` denendi ve elendi: sarma açıkken kabuk
   düğmeyi alt satıra atacak bir genişlikte duruyordu. */
.rec-quick {
  align-items: flex-end;
  gap: var(--sp-3);
  width: 100%;
  max-width: 860px;
  margin-bottom: 0;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
.rec-quick .field { flex: 1 1 150px; min-width: 0; margin: 0; }
.rec-quick .field-label { font-size: var(--fs-xs); }
.rec-quick > .btn { flex: none; }
/* İlerleme çubuğu sayfanın **tamamına** yayılmıyor.

   `flex: 1 1 260px` çubuğu 700 px'e kadar uzatıyor, "%100" etiketini
   ekranın ortasına, hemen yanındaki durum güncellemesini de en sağ kenara
   itiyordu: aralarında yüz piksellik boşluk olan üç ayrı nesne, tek bir
   şerit gibi okunmuyordu. Çubuk artık okunabilir bir ölçüde durur ve
   güncelleme onun **yanında** kalır. */
.rec-progress { flex: 0 1 360px; min-width: 0; }
.rec-progress-line { display: flex; align-items: center; gap: var(--sp-3); }
/* Yüzde **başlıktır**, sayım onun künyesi.

   Önceki hâlde "8 / 12" tok, "%67" yanında soluk ve altında bir de
   "Görev bazlı hesaplanır." notu duruyordu: üç satırlık bir blok, tek bir
   sayıyı söylemek için. Göz önce hangi sayının okunacağını çözmek
   zorundaydı. Artık tek güçlü sayı ve onu doğrulayan küçük bir oran var;
   "görev" sözcüğü oranın içinde geçtiği için ayrı not gerekmiyor. */
.rec-progress-count {
  flex: none;
  font-size: var(--fs-lg);
  font-weight: var(--fw-black);
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.rec-progress-sub {
  flex: none;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.rec-progress-note {
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.rec-strip-form { display: flex; align-items: flex-end; gap: var(--sp-2); flex: none; }
.rec-strip-form .field { margin: 0; }
/* Bandın sağı kullanılır: ilerleme solda okunur, durum güncellemesi sağ
   uçta durur. İkisi ortada yan yana dururken aralarındaki boşluk "aynı
   grup mu, ayrı mı" sorusunu açık bırakıyordu. */
.rec-band > .rec-strip-form:last-child { margin-left: auto; }

/* Şerit tek başına dururken alt boşluğu kendisi taşır (yukarıdaki
   `margin-bottom`). Bir bölümün son öğesiyse taşımamalı: bölümler arası
   aralığı `stack-lg` zaten veriyor, iki boşluk üst üste binince başlık ile
   bir sonraki bölüm arasında gereksiz bir delik açılıyordu. */
.section > .rec-strip:last-child { margin-bottom: 0; }

/* Görev ayrıntısının hızlı güncellemesi: dört alan + bir düğme, tek şerit.
   Alanlar eşit esner; 720 px altında ikişerli sarar. */
.rec-update { align-items: flex-end; gap: var(--sp-3); }
.rec-update .field { flex: 1 1 150px; min-width: 0; margin: 0; }
.rec-update > .btn { flex: none; }

/* --- Süreç çizgisi (firma) --------------------------------------------- */

/* Dolu renkli aşama kutuları yerine ince çizgi ve küçük noktalar: beş
   aşamanın beşi birden renkli olduğunda "şu an neredeyim" sorusu ancak
   okunarak yanıtlanıyordu. */
.pipe {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1 1 100%;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.pipe::-webkit-scrollbar { display: none; }
.pipe-stop {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  flex: 1 1 0;
  /* `min-content` = durağın en uzun kelimesi. Sabit 84 px iken telefonda
     "Görüşülüyor" kutuya sığmıyor ve `overflow-wrap: anywhere` onu ortadan
     ("Görüşü / lüyor") bölüyordu — heceye değil rastgele yere. Ölçüyü
     kelimeye bağlamak bölünmeyi gereksiz kılar: durak kelimeden dar
     olamaz, o yüzden kelime de kırılmak zorunda kalmaz. */
  min-width: min-content;
  padding-right: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
/* Son durağın sağındaki boşluk çizgiye değil ekrana bakıyordu: 12 px'lik
   payı geri vermek, dar ekranda son durağın tam görünmesiyle kırpılması
   arasındaki fark. */
.pipe-stop:last-child { padding-right: 0; }
/* Çizgi durağın **kendi** parçasıdır: soldaki noktadan sağdaki durağa
   uzanır. Son durakta noktanın hizasında biter, boşluğa uzanmaz. */
.pipe-stop::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 4px;
  height: 1px;
  background: var(--border);
}
.pipe-stop:last-child::before { right: auto; width: 9px; }
.pipe-dot {
  position: relative;
  width: 9px;
  height: 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border-strong);
  background: var(--surface);
}
/* Durak adı **bölünmez**. Bir aşama adı ("Görüşülüyor", "Teklif verildi")
   okunmak için değil tanınmak için oradadır; ortasından kırılan kelime
   tanınmaz. Satır aralarına düşer, kelimenin içine değil. */
.pipe-label { overflow-wrap: normal; word-break: keep-all; hyphens: none; }
.pipe-stop.is-done::before { background: var(--brand); }
.pipe-stop.is-done .pipe-dot { background: var(--brand); border-color: var(--brand); }
.pipe-stop.is-done .pipe-label { color: var(--text-secondary); }
.pipe-stop.is-now .pipe-dot {
  background: var(--brand);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.pipe-stop.is-now .pipe-label { color: var(--text-primary); font-weight: 700; }

/* --- Süreç çizgisi: telefon ---------------------------------------------
   Beş durak (müşteriye dönmüş firmada altı) 360 px'e hiçbir ölçekte sığmaz;
   çizgi bu yüzden kayar. Sorun kaymanın kendisi değil, **kaydığının
   görünmemesiydi**: kaydırma çubuğu gizli olduğu için son durak ekranın
   kenarında kesiliyor ve "bozuk" okunuyordu.

   Üç ayar birlikte düzeltir:
   1. Punto bir tık küçülür ve duraklar arası pay daralır — çoğu firmada
      beş durak böylece kaymadan sığar.
   2. Kaydırma **gölgesi**: kenarda içerik kaldıkça soluk bir geçiş çizilir.
      `background-attachment: local` ile içerikle kayar, son durağa
      gelindiğinde kendiliğinden kaybolur (aynı teknik `.filter-pop-body`).
   3. Durak başına yaslanma (`scroll-snap`): parmakla itince çizgi durağın
      ortasında durmaz. */
@media (max-width: 719px) {
  .pipe {
    scroll-snap-type: x proximity;
    background:
      linear-gradient(to right, var(--surface-soft) 40%, transparent) left / 20px 100%,
      linear-gradient(to left, var(--surface-soft) 40%, transparent) right / 20px 100%,
      radial-gradient(farthest-side at 0 50%, var(--scroll-shadow), transparent) left / 7px 100%,
      radial-gradient(farthest-side at 100% 50%, var(--scroll-shadow), transparent) right / 7px 100%;
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
  }
  .pipe-stop {
    scroll-snap-align: start;
    padding-right: var(--sp-2);
    /* 11 px: `--fs-xs`in bir altı. Jeton açılmıyor — bu tek yerde,
       tek gerekçeyle geçerli bir ölçü. */
    font-size: 0.6875rem;
  }
}

/* 360 px — en dar cihaz. Müşteriye dönmüş firmada çizgide altı durak var ve
   ölçülen açık: 310 px'lik çizgi 294 px'lik banda giriyor, son durak
   ("Müşteri") 16 piksel kalarak kesiliyordu. Duraklar arası payı yarıya
   indirmek bu 16 pikseli fazlasıyla geri veriyor; punto ve etiketler
   olduğu gibi kalıyor. 390 px'te zaten sığdığı için kural oraya uzanmaz. */
@media (max-width: 374px) {
  .pipe-stop { padding-right: 4px; }
}

/* --- Bilgi grupları ---------------------------------------------------- */

/* Üç dar kolon yerine iki geniş kolon.

   270 px'lik alt sınır, ayrıntı sayfasının 1100 px'lik kolonunda üç sütun
   üretiyordu: her sütun kendi içinde dar (etiket + değer 150 px'e sıkışıp
   "16 Ağustos 2026 (30 gün gecikti)" iki satıra kırılıyor), sütunlar
   arasındaki mesafe ise büyük. Göz sayfada üç kez soldan sağa gidip
   geliyor ve bilgi, boşluğun içinde dağılmış görünüyordu.

   İki sütunda değer sığar, satır kırılmaz ve grup sınırı belirgin kalır. */
/* Faz 17: kolonlar **eşit** ve sayıları sabit. `auto-fit` kap genişliğine
   göre bir, iki ya da üç kolon üretiyordu: aynı ekran, iki farklı kayıtta
   iki farklı düzen gösteriyor ve göz her sayfada hizalama çizgisini
   yeniden arıyordu. İki eşit kolon, üç gruplu bir sayfada ikinci satırda
   tek grup bıraksa bile öngörülebilir. */
.info-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5) var(--sp-6);
  align-items: start;
}
@media (min-width: 900px) {
  .info-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.info-group { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.info-group-title {
  margin: 0;
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-secondary);
}
.info-list { display: flex; flex-direction: column; margin: 0; }
/* Etiket kolonu **sabit**. Yüzdeyken her grup kendi genişliğine göre
   farklı bir kolon üretiyordu: "Müşteri → değer" ile "Başlangıç → değer"
   arasındaki mesafe göz kararı farklı çıkıyor, sayfada tek bir hizalama
   çizgisi kalmıyordu.

   Faz 17: satırlar arasındaki boşluk (sp-3) yerini saç teli bir çizgiye
   bıraktı — firma ayrıntısındaki iletişim satırlarıyla (`.contact-row`)
   aynı dil. Boşlukla ayrılan satırlar, değerlerden biri iki satıra
   sardığında hangi etiketin hangi değere ait olduğunu söyleyemiyordu.
   Ortak taban yükseklik de satır ritmini eşitler. */
.info-row {
  display: grid;
  grid-template-columns: minmax(0, 132px) minmax(0, 1fr);
  gap: var(--sp-3);
  align-items: baseline;
  min-height: 34px;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--border-soft);
  min-width: 0;
}
.info-row:last-child { border-bottom: 0; }
.info-row dt { color: var(--text-secondary); font-size: var(--fs-sm); }
.info-row dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: var(--fw-medium);
}
.pre-wrap { white-space: pre-wrap; }

/* --- İletişim satırları (firma) ---------------------------------------- */

.contact-list { display: flex; flex-direction: column; }
.contact-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 40px;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--border-soft);
  min-width: 0;
}
.contact-row:last-child { border-bottom: 0; }
.contact-icon { flex: none; display: inline-flex; color: var(--text-muted); }
.contact-label { flex: none; width: 84px; color: var(--text-secondary); font-size: var(--fs-sm); }
/* Değer büyümez: büyüdüğünde yanındaki not ("Var, eski/yenilenmeli")
   satırın en sağına fırlıyor ve neye ait olduğu okunmaz oluyordu. Not
   değerin hemen yanında durur. */
.contact-value { flex: 0 1 auto; min-width: 0; }
/* Telefon ve e-posta gerçek bağlantı (`tel:`, `mailto:`) ve telefonda asıl
   kullanım biçimi dokunmak; ölçüm turu hedefi 105×21 buldu.

   Sözde öğeyle büyütme burada **işe yaramaz**: `.contact-value` üzerinde
   `.truncate` var, yani `overflow: hidden` — satır kutusundan taşan her
   şey kırpılıyor (aynı tuzağa `.uye-ad`da da düşülmüştü). Onun yerine
   bağlantının kendisi blok olup satır yüksekliğini alıyor: kırpma
   bozulmuyor, satır 40'tan 44'e çıkıyor, yani büyüme dört piksel.

   Yalnız kaba işaretçide: farede 21 piksellik bir hedef zaten sorun
   değil ve satırı herkes için uzatmak listeyi gereksiz seyreltirdi. */
@media (pointer: coarse) {
  .contact-row { min-height: var(--tap); }
  .contact-value > a {
    display: block;
    min-height: var(--tap);
    line-height: var(--tap);
  }
}
.contact-aside { flex: 0 1 auto; min-width: 0; color: var(--text-muted); }

/* --- Hızlı ekleme ------------------------------------------------------ */

/* Tek alan, tek düğme. Alan büyür, düğmeler büyümez: "Ekle" 360 px'te de
   1440 px'te de aynı genişlikte kalmalı. */
.quick-add { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2); }
.quick-add .input,
.quick-add .select { flex: 1 1 240px; min-width: 0; }
.quick-add > .btn { flex: none; }

/* --- Görev satırının meta şeridi --------------------------------------- */

.task-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.task-meta .is-wait { color: var(--warn); font-weight: 600; }

/* Gecikme metni: yanık mercan. `.status.is-alert` ile aynı kural, ama artık
   `.status` taşımayan düz metinler de kullanıyor.

   Faz 27: renk `--accent` (600) yerine sözlüğün `-ink` rolünden geliyor.
   Neden bir basamak koyusu: bu sınıf iki ayrı zeminde çalışıyor — düz kart
   yüzeyinde (detay meta satırı) ve mercan **dolgunun** üstünde (`.status`
   rozeti, `.due`). 600 ikincisinde 4.46:1 ile AA'nın altında kalıyordu;
   700 ikisinde de geçiyor (5.46 ve 6.27). Tek sınıf, tek değer.

   Dolgu bu sınıfa **verilmiyor**: `.is-alert` bir `<p>` üstünde de
   kullanılıyor (firma detayındaki takip notu) ve orada hap geometrisi
   paragrafı kutuya sokardı. Dolgu, kısa ve tek parça olan yüzeylerin
   işi: `.due` ve durum rozeti. */
.is-alert { color: var(--state-late-ink); font-weight: 600; }
.is-alert .icon { color: var(--state-late-ink); }

/* --- Gerektiğinde açılan alanlar --------------------------------------- */

.more-fields { border-top: 1px solid var(--border-soft); padding-top: var(--sp-3); }
.more-fields > summary {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  /* Dokunma hedefi: özet gerçek bir düğmedir, ölçüm turu onu da ölçer. */
  min-height: 36px;
  cursor: pointer;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 600;
  list-style: none;
}
.more-fields > summary::-webkit-details-marker { display: none; }
.more-fields > summary::before {
  content: "";
  flex: none;
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform var(--dur-2) var(--ease-out);
}
.more-fields[open] > summary::before { transform: rotate(90deg); }
@media (pointer: coarse) { .more-fields > summary { min-height: var(--tap); } }
.more-fields > summary:focus-visible { box-shadow: var(--focus-ring); border-radius: var(--r-sm); }
/* Özet kapalıyken de bilgi verir: kutuyu "tekrar var mı" diye açmak
   gerekmemeli. Açıldığında tekrar yazmasın diye gizlenir. */
.more-fields[open] > summary .more-fields-sum { display: none; }
.more-fields .info-list { padding-top: var(--sp-3); }

/* --- Aktivite akışı ---------------------------------------------------- */

/* Faz 10'da akışın işaretlemesi yazıldı ama satırların kendi kuralı hiç
   olmadı: `.feed-item` biçimlendirilmemiş bir liste öğesiydi ve avatar,
   zaman, görünürlük aynı satırda eziliyordu. */
/* Akışın kendi okuma genişliği var. Tam sayfa ayrıntıda liste 1200 piksele
   kadar uzuyordu: cümle solda bitiyor, saat sağ kenarda duruyordu ve göz
   ikisini birleştirmek için yarım ekran kat ediyordu. Sınır, sağa yaslı
   saat sütununu cümlenin okunur mesafesinde tutar. */
.feed-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; max-width: 860px; }
/* Satır ayırıcı yatay çizgiler kalktı, yerine **tek** dikey eksen geldi.
   On yedi hareketin on yedi çizgiyle bölünmesi, listeyi bir tabloya
   benzetiyordu: her satır kendi kutusunda, hiçbiri diğeriyle ilişkili
   değil. Oysa akış bir zaman ekseni — çizgi satırları ayırmak için değil,
   onları birbirine bağlamak için var.

   Eksen **satırın kendi** sözde öğesidir, listenin değil: tek uzun çizgi
   çizilseydi gün ayraçlarının arkasından da geçerdi ve onu kesmek için
   ayraca opak bir zemin vermek gerekirdi — zemin rengi ise panelde,
   kartta ve tam sayfada aynı değil. Satır başına çizgi bu varsayımı
   tümden ortadan kaldırır: ayracın hizasında zaten satır yoktur.

   Çizgi avatar sütununun ortasından geçer (15px ≈ 32px avatarın yarısı)
   ve avatarın/nişanın opak zemini onu keser; boncuk etkisi ayrı bir
   maske istemez. */
.feed-item {
  position: relative;
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  min-width: 0;
}
.feed-item::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 0;
  bottom: 0;
  width: 1px;
  /* `--border-soft` değil: akış çoğu ekranda sunken bir zeminde duruyor ve
     yumuşak çizgi orada tamamen kayboluyordu — çizilen ama görünmeyen bir
     eksen, hiç olmayan eksenden beterdir (yer kaplar, iş görmez). */
  background: var(--border);
}
/* Eksenin uçları avatarın merkezinde başlar ve biter — havada başlayan
   bir çizgi, kırpılmış bir liste izlenimi verirdi. */
.feed-day + .feed-item::before { top: 18px; }
.feed-list > .feed-item:first-child::before { top: 18px; }
.feed-list > .feed-item:last-child::before { bottom: auto; height: 18px; }
/* Gün ayracı: tarih satırdan çıkıp buraya toplandı. Listeyi okunur
   kümelere böler — on yedi satırlık tek yığın, "bugün ne oldu" sorusunu
   kullanıcıya saydırıyordu. */
.feed-day {
  margin: var(--sp-4) 0 var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}
.feed-day:first-child { margin-top: 0; }
/* Süzgeç açıkken ayraçlar kalkar: gizlenen satırlarla birlikte altı boş
   bir gün başlığı kalabilirdi ve CSS onu göremez. Aynı gerekçe blok
   gruplamasında da geçerli (aşağıda). */
.feed:not(:has(#suz-hepsi:checked)) .feed-day { display: none; }
.feed-avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-pill);
  /* Zemin sayfanınkiyle aynı olamaz: akış çoğu ekranda `--surface-sunken`
     üstünde duruyor ve avatar orada tamamen eriyordu — geriye eksen
     çizgisinin üstünde asılı iki harf kalıyordu. Beyaz yüzey + ince
     çerçeve hem daireyi geri veriyor hem çizgiyi temiz kesiyor. */
  background: var(--surface);
  border: 1px solid var(--border-soft);
  color: var(--text-secondary);
  font-size: var(--fs-xs);
  font-weight: 700;
}
/* Değişiklik satırının nişanı: avatarın yerini tutar ama avatar değildir.
   Baş harf dairesi "bunu bir insan yazdı" der; durum değişikliğini yazan
   ise sistemdir. Aynı 32 piksellik yuvada durur (eksen hizası bozulmasın)
   fakat halkası küçük ve zemini sayfayla aynı — listede bir boncuk, bir
   kişi değil. */
.feed-mark {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
}
.feed-mark::before {
  content: "";
  position: absolute;
  width: 22px;
  height: 22px;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--border-soft);
}
.feed-mark .icon { position: relative; width: 13px; height: 13px; color: var(--text-muted); }
.feed-body { display: flex; flex-direction: column; gap: var(--sp-1); flex: 1 1 auto; min-width: 0; }
/* Faz 17: künye satırı **tek basamak geriye** çekildi (xs, ikincil renk) ve
   içinde yalnız bir şey öne çıkar: kim yazdı. Önceki hâlde ad, tür ve
   zaman aynı puntodaydı; üç bilgi aynı ağırlıkta olunca satır bir cümle
   değil bir etiket dizisi gibi okunuyor, asıl içerik onların altında
   kayboluyordu. */
.feed-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.feed-author {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--text-primary);
}
.feed-head .strong { color: var(--text-primary); }
.feed-kind { display: inline-flex; align-items: center; gap: 5px; }
.feed-kind .icon { width: 14px; height: 14px; color: var(--text-muted); }
/* Akışın kendi sessiz kaydı — tür sözlüğünden **ayrı** (Faz 27, ikinci tur).

   Dört giriş türü (iletişim, not, yorum, değişiklik) aynı gri ikonla
   çiziliyordu: bir müşteri görüşmesiyle bir alan güncellemesi ekranda aynı
   ağırlıktaydı, ayrım yalnız ikonun biçimindeydi ve 14 pikselde biçim tek
   başına taşımıyor.

   Renk neden `--kind-*`ten gelmiyor: bunlar kayıt **türü** değil, bir
   kaydın *içindeki* giriş türü. Aynı sözlüğü ödünç almak, az önce
   sökülen tür/durum kısa devresini bir basamak aşağıda tekrar kurardı —
   akıştaki mavi bir ikon "bu bir görev" diye okunurdu. Bu yüzden ayrı
   kanal, ayrı register: **yalnız mürekkep**, dolgu ve çerçeve yok. Akış
   satırı hiçbir zaman rozet gibi görünmez, yalnız ikonu renklenir.

   Sıra bir hiyerarşidir, süs değil: dışarıyla konuşma (iletişim) en sıcak,
   makinenin yazdığı satır (değişiklik) en sessiz. */
.feed-item[data-tur="contact"] .feed-kind .icon { color: var(--warn); }
.feed-item[data-tur="note"] .feed-kind .icon { color: var(--neutral-accent); }
.feed-item[data-tur="comment"] .feed-kind .icon { color: var(--info); }
/* Değişikliğin ikonu künyede değil nişanda (`.feed-mark`) ve bilerek
   `--text-muted`te kalır: sistemin kendi kaydıdır, kimse onu "okumaya"
   gelmez — listede zemin gürültüsü olmalı. */
/* Ardışık aynı kişi + aynı tür = tek blok (bkz. `_activity_feed.html`).
   Avatar `visibility` ile gizlenir, `display: none` ile değil: yerini
   koruması gerekiyor, yoksa süregelen satırlar sola kayıp blok bir
   merdivene dönüşür. Ad ekranda gizlenir ama ekran okuyucuda kalır —
   satırı tek başına duyan kullanıcı kimin yaptığını yine bilir. */
#suz-hepsi:checked ~ .feed-list > .feed-item.is-cont > .feed-avatar { visibility: hidden; }
#suz-hepsi:checked ~ .feed-list > .feed-item.is-cont .feed-author {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Blok içi satırlar birbirine yapışır: aralarındaki nefes, blokları
   ayıran boşluktan küçük olmalı — yoksa gruplama gözle görülmez. */
#suz-hepsi:checked ~ .feed-list > .feed-item.is-cont { padding-top: 0; }

/* Kırpma uyarısı: listenin parçası değil, dipnotu. */
.feed-more {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

/* Görünürlük satırın sonunda: okunan şey içerik, görünürlük onun künyesi.
   Yalnız kısıtlı girişlerde çizilir, o yüzden seyrek — bir istisna
   işareti olarak okunabilsin diye. */
.feed-vis {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-muted);
  font-size: var(--fs-xs);
}
.feed-vis .icon { width: 14px; height: 14px; }
/* Saat en sağda, kendi sütununda. Rakamlar `tabular-nums` ile eşit
   genişlikte: alt alta gelen saatlerin basamakları hizalanmazsa sütun
   sütun olmaktan çıkar, on iki satırda on iki farklı yerde titrer. */
.feed-time {
  margin-left: auto;
  flex: none;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}
/* İçerik künyeden bir basamak **önde**: okunacak şey budur. */
.feed-text {
  margin: 0;
  color: var(--text-primary);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.feed-text.muted { color: var(--text-secondary); }
.feed-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
  margin-top: var(--sp-1);
}
/* Araçlar durur ama bağırmaz.

   Önce yalnız kontrast düşürülmüştü ve gerekçesi doğruydu: `display: none`
   klavye ile dokunmatik kullanıcısından erişimi tümden alır. Ama dört
   düğmelik bir çubuk her notun altında **yer kaplamaya** devam ediyordu ve
   akışta okunacak şey notun kendisi.

   Çözüm ikisinin ortası: yalnız **gerçek imleci olan** ekranda (`hover:
   hover`) saydamlaşır, `visibility` değil `opacity` ile — yani düzen
   sabit kalır, satırlar imleç gezdikçe zıplamaz. Odak içeri girdiği anda
   (Tab) geri gelir; dokunmatikte hiç gizlenmez. */
.feed-tools .btn { color: var(--text-muted); }
.feed-item:hover .feed-tools .btn,
.feed-tools:focus-within .btn { color: var(--text-secondary); }
@media (hover: hover) {
  /* Saydam olmak yetmedi: görünmeyen çubuk **yerini** koruduğu için her
     notun altında otuz piksellik bir delik kalıyordu. Çubuk künye
     satırının boş sağ tarafına taşındı — orada zaten kimse oturmuyor
     (ad solda, saat en sağda) ve satır hiç uzamıyor.

     `display: none` yine seçilmedi; taşınan çubuk odak alınca geri gelir,
     dokunmatikte (hover yok) hiç kaybolmaz ve düzenleme formu açıkken
     akışa dönüp yerini alır — açık bir formun üstünde yüzen bir araç
     çubuğu, formun kime ait olduğunu belirsizleştirirdi. */
  .feed-tools {
    position: absolute;
    top: 0;
    right: 52px;
    margin-top: 0;
    padding: 2px var(--sp-1);
    border-radius: var(--r-pill);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
    opacity: 0;
    transition: opacity var(--dur-1) var(--ease-out);
  }
  .feed-item:hover .feed-tools,
  .feed-tools:focus-within { opacity: 1; }
  .feed-body:has(.feed-tools details[open]) .feed-tools {
    position: static;
    opacity: 1;
    margin-top: var(--sp-1);
    padding: 0;
    background: none;
    box-shadow: none;
  }
}
.feed-tools form { margin: 0; }
.feed-tools > details { flex: 0 0 auto; }
.feed-tools > details[open] { flex: 1 1 100%; }
.feed-tools > details > summary { list-style: none; }
.feed-tools > details > summary::-webkit-details-marker { display: none; }

/* --- Ekleme alanı: segmented control ----------------------------------- */

/* Üç kip bir şerit değil, tek bir denetim: çökük bir yol ve üstünde kayan
   beyaz bir kapsül. Önceki hâlde seçili kip yalnız açık indigo bir zemindi
   ve "sekmeler" ile "süzgeç çipleri" aynı ekranda birbirine benziyordu. */
.composer-tabs {
  gap: 2px;
  width: fit-content;
  max-width: calc(100% - var(--sp-4));
  margin: var(--sp-3) var(--sp-3) 0;
  padding: 3px;
  border-bottom: 0;
  border-radius: var(--r-md);
  background: var(--surface-sunken);
}
.composer-tab { border-radius: 7px; }
.composer-tab .icon { width: 15px; height: 15px; }
#kip-note:checked ~ .composer-tabs [for="kip-note"],
#kip-comment:checked ~ .composer-tabs [for="kip-comment"],
#kip-contact:checked ~ .composer-tabs [for="kip-contact"] {
  background: var(--surface);
  color: var(--text-primary);
  box-shadow: var(--shadow-sm);
}

/* --- Dar ekran --------------------------------------------------------- */

@media (max-width: 719px) {
  .rec-head { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  /* Kap dikey eksene dönünce `.rec-head-text` üzerindeki `flex: 1 1 320px`
     taban ölçüsü **yüksekliğe** çevriliyordu: flex-basis her zaman ana
     eksende ölçülür. Başlık ile eylemler arasında ~250 px boş alan
     açılıyordu; dar ekranda taban içeriğe bırakılır. */
  .rec-head-text { flex: 0 1 auto; }
  .rec-title { font-size: var(--fs-xl); }
  .rec-actions { margin-left: 0; }
  /* Başlıktaki birincil eylem telefonda tam genişlik; menü düğmesi değil. */
  .rec-actions > .btn { flex: 1 1 auto; justify-content: center; }
  .rec-menu > .btn { flex: none; }
  /* Eylem satırı **sarar**. `flex: none` + sarmalamasız hâlinde üç eylem
     (Düzenle · İletişim kaydet · ⋯) 360 px'te 381 piksel istiyor ve
     sonuncusu künyenin dışında kalıyordu: ekranda yarım kesilmiş bir üç
     nokta. Kesilen düğme, olmayan düğmeden kötüdür. */
  .rec-actions { flex-wrap: wrap; }
  /* Sardıktan sonra satırın sağında boşluk kalmasın: etiketli düğme taşıyan
     menü (asıl eylem) esner, üç nokta esnemez. `:has()` desteklenmeyen
     tarayıcıda kaybedilen tek şey sağdaki boşluktur; düzen ayakta kalır. */
  .rec-actions > .rec-menu:not(:has(> .btn-icon)) { flex: 1 1 auto; min-width: 0; }
  .rec-actions > .rec-menu:not(:has(> .btn-icon)) > .btn {
    flex: 1 1 auto;
    width: 100%;
    justify-content: center;
  }
  .info-row { grid-template-columns: 1fr; gap: 2px; }
  .contact-label { width: 76px; }
  .rec-update .field { flex: 1 1 100%; }

  /* Bant ve kontrol kartı telefonda **sola yaslanır**.

     Masaüstünde ilerleme solda, durum formu sağda duruyor
     (`.rec-band > .rec-strip-form:last-child { margin-left: auto }`). Dar
     ekranda form kendi satırına iniyor ama `auto` kenar boşluğu orada da
     iş görmeye devam ediyor: iki alanlık bir form, satırın ortasında asılı
     kalıyordu. Sayfadaki her şey sol kenardan hizalıyken tek bir denetimin
     ortada durması, onu bir şeyin "altına ait" değil bağımsız bir kutu
     gibi gösteriyor. */
  .rec-band > .rec-strip-form:last-child { margin-left: 0; }
  .rec-band .rec-progress { flex: 1 1 100%; }
  .rec-quick { justify-content: flex-start; padding: var(--sp-3); }
}


/* --- Formda kademeli açılım: "Daha fazla bilgi" gövdesi (Faz 5) ---------

   `.more-fields` kuralı Faz 4'te ayrıntı ekranı için yazıldı; formda
   gövdenin kendi boşluğu da gerekiyor, yoksa açılan alanlar özet satırına
   yapışıyor ve bölüm "açıldı mı" belli olmuyordu. */

/* Alan aralığı `.form-col` ile **aynı** (sp-4): açılan alanlar üsttekilerden
   daha sıkışık dururken bölüm, formun devamı değil formun içine sıkıştırılmış
   ikinci bir form gibi okunuyordu. */
.more-fields-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding-top: var(--sp-4);
}
.more-fields-title { color: var(--text-secondary); }


/* --- Tema seçimi (Faz 5) -----------------------------------------------

   Üç seçenek radyo grubudur ama görünümü satır listesi: seçenekler aynı
   anda görünür ve hangisinin etkin olduğu tek bakışta okunur. Açılır kutu
   denendi ve "Sistem"in ne demek olduğunu açıklayacak yer bırakmıyordu;
   açıklama, seçimin kendisi kadar önemli.

   Radyo girdisi gizlenmez, **görsel olarak kaldırılır** (`.visually-hidden`
   ile aynı iş): klavye odağı girdide kalır, odak halkası gövdeye çizilir.
   `display: none` verilseydi grup klavyeyle hiç gezilemezdi. */

.tema-secim {
  display: grid;
  gap: var(--sp-2);
}
.tema-sec { display: block; cursor: pointer; }
.tema-sec-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.tema-sec-govde {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--tap);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  transition: border-color var(--dur-1) var(--ease-out),
              background var(--dur-1) var(--ease-out);
}
.tema-sec:hover .tema-sec-govde { border-color: var(--border-strong); }
.tema-sec-input:focus-visible + .tema-sec-govde { box-shadow: var(--focus-ring); }
.tema-sec-input:checked + .tema-sec-govde {
  border-color: var(--brand-border);
  background: var(--brand-softer);
}
.tema-sec-ikon {
  display: inline-flex;
  flex: none;
  color: var(--text-secondary);
}
.tema-sec-input:checked + .tema-sec-govde .tema-sec-ikon { color: var(--brand); }
.tema-sec-metin { display: grid; gap: 2px; flex: 1; min-width: 0; }
.tema-sec-ad { font-weight: var(--fw-semibold); }
/* Onay işareti yalnız seçilide görünür: seçili olmayanın yanında soluk bir
   tik, "bu da mı seçili?" sorusunu üretiyordu. */
.tema-sec-isaret { flex: none; color: var(--brand); visibility: hidden; }
.tema-sec-input:checked + .tema-sec-govde .tema-sec-isaret { visibility: visible; }


/* ==========================================================================
   2. YARDIMCI SAYFALAR  →  components.css
   ========================================================================== */

/* --- Bildirim kutusu ---------------------------------------------------- */

/* Okunmamış satırın işareti: satır başında küçük indigo nokta + kalın
   başlık. Dolu zemin (`--selected`) kaldırıldı — okunmamışların çoğunlukta
   olduğu bir kutuda "işaretli" satır listenin kendisi oluyor, işaret de
   hiçbir şey söylemiyordu. */
.notif-mark {
  flex: none;
  align-self: center;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--brand);
}
.timeline-item.is-unread .notif-title { font-weight: var(--fw-bold); }

/* Okunmuşta ikon kutusu geri çekilir. Ayrımı tek başına taşımaz (nokta ve
   görünmez "Okunmadı" etiketi de var); yalnız gözün okunmamışları tarayıp
   geçmesini kolaylaştırır. */
.timeline-item:not(.is-unread) .timeline-icon {
  background: var(--surface-soft);
  color: var(--text-muted);
}

/* "3 kez" bir durum değil bir ölçü: dolu indigo hap olmaktan çıkıp sessiz
   meta basamağına indi (§1, üçüncü metin basamağı). Rakam taşıdığı için
   tabular. */
.notif-repeat {
  flex: none;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}

/* --- "Diğer" listesi ----------------------------------------------------- */

/* Satır sonundaki sayaç (okunmamış bildirim adedi). Antik altın rozet,
   listedeki tek renkli kutu olarak "Bildirimler"i öne çıkarıyor ve komşu
   satırları sönük bırakıyordu; sayı sessiz kalır, satırı zaten ismi
   anlatıyor. */
.list-row > .count {
  flex: none;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

/* --- Çöp kutusu ---------------------------------------------------------- */

/* Sekmedeki sessiz sayı. `.count` bu şeritte hiçbir kurala düşmüyordu ve
   sekme metniyle aynı puntoda, aynı ağırlıkta okunuyordu: "Firmalar 12"
   tek bir başlık gibi görünüyordu.

   Faz 46'da bütün görünüm sekmelerine yayıldı (Potansiyel müşteriler ·
   Müşteriler, İşler · Tüm Görevler, Liste · Akış, ayrıntı sekmeleri) ve
   kademesi Faz 45'in ikincil bilgi kuralına çekildi: bir basamak küçük
   (`--fs-xs`), normal ağırlık, `--text-muted`. Kapsül ya da dolgu **yok** —
   renkli rozet "bak buraya" der, oysa sayı yalnız "orada kaç kayıt var"
   sorusuna sekmeyi tıklamadan cevap verir. Etkin sekmede bir ton koyulaşır,
   yoksa etkin adın yanında soluk rakam silik kalıyordu. */
.tab-link .count,
.seg-btn .count {
  margin-left: var(--sp-1);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}
.tab-link.is-active .count,
.seg-btn.is-active .count { color: var(--text-secondary); }

/* Satır sonundaki "Geri yükle / Kalıcı sil" ikilisi. Masaüstünde sağa
   yaslı tek satır, telefonda satırın altında tam genişlik. Üç ölçü de
   şablonda satır içi `style` ile yazılıydı (`gap`, `justify-content`,
   `width`) ve masaüstü ile telefon kopyaları birbirinden habersizdi. */
.trash-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
}
.trash-actions.is-stacked {
  width: 100%;
  justify-content: stretch;
}
/* Telefonda bu iki düğme satırın asıl eylemleri: `btn-sm`in 36 px'i
   dokunma hedefinin (§7) altında kalıyordu. Masaüstü tablosundaki aynı
   düğmeler küçük kalır — orada fare var ve satır yoğunluğu değerli. */
.trash-actions.is-stacked .btn { min-height: var(--tap); }

/* Mobil kayıt satırı: ad + meta üstte, düğmeler altta. */
.trash-row { flex-wrap: wrap; }

/* --- Boş durumun altındaki çıkış yolu ------------------------------------ */

/* `empty_state` gövde almaz; "Genel Bakış'a dön" düğmesi kardeş olarak
   gelir ve hizasını buradan alır. Boş durumun kendi dikey dolgusu zaten
   büyük olduğu için üstten yalnız küçük bir pay verilir. */
.empty-actions {
  display: flex;
  justify-content: center;
  margin-top: calc(-1 * var(--sp-4));
}


/* ==========================================================================
   AİT OLDUĞU BÖLÜM: app/static/css/components.css
   → "Toplu ekleme sihirbazı (Faz 6.1)" bloğunun içine / yerine
     (şu an ~862–1001 satırlar: .stepper … button.tab-link).

   Redesign Faz 5 — toplu firma ekleme sihirbazının yüzeyi.

   BİRLEŞTİRİRKEN SİLİNECEK (artık ölü kural):
     - `.note-text` ve `.note-text .icon`  → yerine `.row-reason`
     - `.row-note td { background: var(--warn-bg); }` → aşağıdaki sessiz hâli
   Her ikisinin de tek tüketicisi `main/company_bulk.html` idi; başka şablon
   bu sınıfları kullanmıyor.
   ========================================================================== */


/* --------------------------------------------------------------------------
   Adım göstergesi — gelecek adım

   `.is-active` ve `.is-done` zaten vardı, "gelecek adım" ise yalnız varsayılan
   görünümdü. Üç durumun üçünü de sınıfla yazmak, birinin rengi değiştiğinde
   ötekinin sessizce kaymasını engelliyor.
   -------------------------------------------------------------------------- */
.stepper-item.is-todo {
  color: var(--text-muted);
  font-weight: 600;
}
.stepper-item.is-todo .stepper-num {
  background: transparent;
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
}

/* Tamamlanan adımda numara yerine onay imi: "3 adımdan 1'i bitti" bilgisini
   saymadan veren tek işaret. Numara kayboluyor ama sırayı konum söylüyor. */
.stepper-item.is-done .stepper-num .icon {
  width: 14px;
  height: 14px;
}

/* Etkin adım gerçekten *vurgulu* olmalı; eskiden yalnız metin koyulaşıyordu ve
   dairenin indigo dolgusu ile "tamamlandı" dolgusu uzaktan ayırt edilemiyordu. */
.stepper-item.is-active .stepper-label { font-weight: var(--fw-bold); }


/* --------------------------------------------------------------------------
   Veri kaynağı sekmeleri

   Gizleme `hidden` özniteliğiyle işaretlemede değil, burada: betik
   yüklenmezse iki panel de açık kalır ve kullanıcı özelliği tamamen
   kaybetmez — yalnız sekmeyle daralan görünümü kaybeder. (Bölüm 6.2'deki
   toplu seçim çubuğuyla aynı kural.) `html.js` `<head>` içinde takıldığı
   için açılışta iki panelin birden görünüp kaybolduğu titreme olmuyor.
   -------------------------------------------------------------------------- */
html.js [data-tab-panel]:not(.is-active) { display: none; }


/* --------------------------------------------------------------------------
   Satır işareti — kapsül yerine nokta

   Önizlemede her satıra `.badge` koymak, 500 satırlık bir tabloyu renkli
   kapsül yağmuruna çeviriyordu: "Hazır" rozeti hiçbir şey söylemiyor, asıl
   bilgiyi (hangi satır neden eklenemiyor) gürültüye gömüyordu. Artık yalnız
   sorunlu satır satır başında küçük bir nokta taşır; gerekçe altta yazılı.

   Renk tek taşıyıcı değil: `row_flag()` makrosu noktanın yanına görünmez bir
   metin etiketi koyuyor, gerekçe de zaten okunabilir metin.
   -------------------------------------------------------------------------- */
.row-flag {
  display: inline-block;
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--text-muted);
}
.row-flag.is-warn { background: var(--warn); }
.row-flag.is-error { background: var(--danger); }

/* Numara hücresi: işaret + numara tek hizada, sütun dar kalsın.
   Gerekçe satırının boş numara hücresi de aynı genişliği tutar, böylece
   metin firma adı kolonunun altında başlar. */
td.row-num,
th.row-num {
  width: 1%;
  white-space: nowrap;
  padding-right: var(--sp-2);
}
td.row-num {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.row-flag + * { margin-left: var(--sp-2); }

/* Mobil listede işaret numara dairesinin yanında durur. */
.list-row > .row-num {
  display: inline-flex;
  align-items: center;
  flex: none;
}


/* --------------------------------------------------------------------------
   Gerekçe — alanın altında, düz metin

   Eskiden gerekçe satırı `--warn-bg` ile boyanıyor ve her cümlenin başına bir
   uyarı üçgeni konuyordu; art arda gelen beş uyarı ekranda sarı bir duvar
   yapıyordu. Sessiz hâl: dolgu yok, sol kenarda ince bir renk çizgisi, metin
   ikincil renkte. Hata satırında çizgi kırmızıya döner — ton bilgiyi
   *güçlendirir*, tek başına taşımaz.
   -------------------------------------------------------------------------- */
.row-note td {
  padding-top: 0;
  border-top: 0;
  background: transparent;
}
.row-note td:not(.row-num) {
  border-left: 2px solid var(--warn-border);
  padding-left: var(--sp-3);
}
.row-note.is-error td:not(.row-num) { border-left-color: var(--danger-border); }

/* Mobil listede gerekçe bir `<span>`; tablo hücresi yok, kenar çizgisini
   kendisi taşır. */
.list-row .row-note {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
  padding-left: var(--sp-3);
  border-left: 2px solid var(--warn-border);
}
.list-row .row-note.is-error { border-left-color: var(--danger-border); }

.row-reason {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--fs-sm);
}
.row-note.is-error .row-reason { color: var(--danger); }
.row-reason a { color: inherit; text-decoration: underline; }


/* --------------------------------------------------------------------------
   "Bu satır için" seçimi

   Etiket artık `.field-label` olduğu için tablo içinde gereğinden çok yer
   kaplıyordu; küçültülüyor ama gizlenmiyor — seçicinin ne yaptığını yalnız
   seçenek metninden çıkarmak gerekiyordu.
   -------------------------------------------------------------------------- */
.row-action .field-label {
  font-size: var(--fs-xs);
  color: var(--text-muted);
}


/* --------------------------------------------------------------------------
   Atlanacak satır

   `.is-muted` satırı soluklaştırıyor ama gerekçe okunur kalmalı: kullanıcı
   satırı *neden* atladığını görmeden "atla"yı geri alamaz.
   -------------------------------------------------------------------------- */
tr.is-muted + .row-note .row-reason,
.list-row.is-muted .row-reason { color: var(--text-secondary); }


/* ==========================================================================
   REDESIGN FAZ 5 — üyeler ve yetkiler
   `app/static/css/components.css` sonuna eklenecek blok.
   ========================================================================== */

/* --- Ekip listesi ----------------------------------------------------- */

/* Kişi hücresi: avatar + (ad / e-posta). Ayrı bir sarmalayıcı, hizalama
   için değil kırpma için var — `truncate` çalışsın diye ad ile e-postayı
   taşıyan kolonun `min-width: 0` olması gerekiyor; doğrudan `<td>`ye
   konsaydı uzun bir e-posta kolonu kendi genişliğine zorluyor ve tablo
   yatay kaydırmaya düşüyordu. */
.uye-kisi {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}
.uye-kisi-metin {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.uye-ad {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  min-width: 0;
}
/* Telefonda ad, kartın **ana** hedefi: üyeyi açan bağlantı odur. Ölçüm
   turu onu 67×23 piksel buldu — `--tap`in yarısı. Hedef `::after` ile
   büyütülüyor, çizim değil: adın kendisi hâlâ satır aralığını bozmadan
   duruyor, dokunulan alan ad **ve** e-postanın bloğu kadar oluyor.

   Kabuk `.uye-kisi-metin`, `.uye-ad` değil: `.uye-ad` üzerinde `.truncate`
   var ve o `overflow: hidden` demek — satır kutusundan taşan her hedef
   büyütmesi oracıkta kırpılıyordu. İlk deneme tam olarak buna takıldı ve
   ölçüm hiç değişmedi.

   Satırın tamamı da kaplanmıyor: kartta ikinci bir eylem ("Düzenle") var
   ve iki hedef üst üste binerse yanlış olan açılır. */
@media (max-width: 899px) {
  .uye-kisi-metin { position: relative; }
  .uye-ad > a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    /* Ad bloğun **ilk** satırı; `inset: 0` hedefi e-postanın üstüne yayıp
       adın hizasından kaydırıyordu ve ölçüm turunun 22 piksellik üst
       probu hâlâ kartın kendisine düşüyordu. Kutu adın satırına
       ortalanıyor ve gerektiği kadar yukarı taşıyor — `.uye-kisi-metin`de
       `overflow` yok, taşma kırpılmıyor. */
    top: -10px;
    height: var(--tap);
  }
}

/* Rol düz metindir (rozet değil); "Sistem admini" notu altına iner. */
.uye-rol { display: flex; flex-direction: column; gap: 2px; }
.uye-rol-ad { font-weight: 600; color: var(--text-primary); }

/* İletişim görünürlüğü: ikon + metin. Renk tek başına bilgi taşımaz, bu
   yüzden "görmez" hâli griye inmez — yalnız ikonu değişir ve metni ikinci
   basamağa düşer; göz kolonu tararken açık/kapalı ayrımını ikondan yapar. */
.uye-izin {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
.uye-izin .icon { flex: none; color: var(--text-secondary); }
.uye-izin.is-off { color: var(--text-secondary); }
.uye-izin.is-off .icon { color: var(--text-muted); }

/* İşlem hücresi: davet yenileme (yalnız ikon) ve "Düzenle" yan yana. */
.uye-islemler {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
}

/* Tabloda kolon payları: kullanıcı kolonu esner, geri kalanı içeriğine göre
   dar kalır. Eşit paylaşımda "Rol" kolonu tek kelimelik içeriği için
   ekranın altıda birini alıyor, kullanıcı adı ise kırpılıyordu. */
.uye-tablo th:first-child,
.uye-tablo td:first-child { width: 34%; }

/* --- Telefon kartı ---------------------------------------------------- */

/* `.list-row` öntanımlı olarak tek satırdır; üye kartında ad, dört etiketli
   değer ve işlem şeridi alt alta durur. Sarma `trash.html`te satır içi
   `style` ile veriliyordu — burada sınıfa alındı. */
.uye-karti {
  flex-wrap: wrap;
  align-items: flex-start;
  padding-top: var(--sp-4);
  padding-bottom: var(--sp-4);
}
.uye-karti .list-row-main { display: flex; flex-direction: column; gap: var(--sp-3); }

/* Kartta etiket kolonu tablodaki başlığın karşılığı: değer tek başına
   ("Yalnızca ilgili oldukları") hangi sorunun cevabı olduğunu söylemiyor.

   Ama etiket **kendi satırında** duruyordu ve dört alan sekiz satır
   ediyordu: altı üyelik bir ekip, 360 pikselde 2.400 piksellik bir kaydırma
   demekti ve liste, satırları okunan bir liste değil form yığını gibi
   görünüyordu. Etiket artık değerin **solunda**, küçük ve sessiz; kart
   yarıya iniyor ve sorunun cevabı hâlâ yanında duruyor.

   `auto` kolon: etiketler farklı uzunlukta ("Rol" ile "İletişim
   görünürlüğü") ve sabit bir kolon ya birini iki satıra böler ya da
   ötekinin yanında boşluk bırakır. Dört satır aynı karttaki komşularıyla
   hizalanmasa da okunur — burada hiza değil yoğunluk sorun. */
.uye-ozet { gap: var(--sp-1); }
.uye-ozet .detail-row {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--sp-2);
}
.uye-ozet .detail-label {
  font-size: var(--eyebrow-size);
  text-transform: uppercase;
  letter-spacing: var(--eyebrow-tracking);
  white-space: nowrap;
  color: var(--text-muted);
}
.uye-ozet dd { margin: 0; font-size: var(--fs-sm); }

/* --- Rol seçenekleri (üye düzenleme ve davet) -------------------------- */

/* Kartlar tek kolon: rol açıklamaları iki satırlık cümleler ve yan yana
   iki kolonda farklı yükseklikte kutular üretiyordu. Geniş ekranda bile
   dar kalması istenen bir liste — `form-narrow` zaten sınırlıyor. */
.rol-secenekleri { gap: var(--sp-2); }

/* `.more-fields-body` kuralı bu dosyada **yok**: aynı fazda form paketi de
   yazdı ve orada aralık `.form-col` ile eşitlendi (sp-4). İkinci bir tanım,
   hangisinin sonra yüklendiğine bakan bir boşluk demekti. */


/* ==========================================================================
   Liste ekranı — tek kart, tek şerit (redesign)

   İşler, Görevler, Potansiyel müşteriler, Müşteriler, Üyeler ve Çöp kutusu
   aynı iskeleti kullanıyor ama ekranda üç ayrı yüzey gibi duruyorlardı:
   sayfa başlığı, altında serbest duran "PROJELER 1" şeridi, onun altında
   kart. Şerit kartın **dışında** olduğu için sayfada üç yatay çizgi ve iki
   farklı dikey hiza vardı; hangi başlığın hangi listeye ait olduğu
   ancak boşluk ölçerek anlaşılıyordu.

   Şerit artık kartın üst bandı: aynı çerçeve, aynı yarıçap, altında ince
   ayırıcı. Kayıt sayısı ve (seçim varsa) toplu seçim durumu da o bandın
   içinde — "liste başlığı" tek satır.
   ========================================================================== */

.section-head-attached {
  min-height: 42px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--border);
  border-bottom-color: var(--border-soft);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
/* `.section` kardeşleri arasına --sp-4 koyuyor; bant ile kart tek yüzey
   olduğu için o boşluk burada geri alınır. Negatif kenar boşluğu, kuralı
   `:has()` ile kabına yazmaktan ucuz: seçicinin desteklenmediği bir
   tarayıcıda düzen bozulmaz, yalnız boşluk kalır. */
.section-head-attached + .card,
.section-head-attached + .table-wrap,
.section-head-attached + .list {
  margin-top: calc(-1 * var(--sp-4));
  border-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
/* Kartın üst köşeleri artık kare: tablo başlığının köşeyi izleyen kuralı
   (bkz. `.card .table thead tr:first-child`) burada köşeyi yuvarlarsa
   bandın altında iki piksellik bir çentik kalıyordu. */
.section-head-attached + .card .table thead tr:first-child th:first-child,
.section-head-attached + .card .table thead tr:first-child th:last-child {
  border-radius: 0;
}

/* Bandın sağ ucu: sayım, seçim durumu, "Tümünü seç" gibi ikincil bilgi. */
.section-head-attached .section-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}

/* --- Toplu işlem çubuğu: seçim varken tablonun üstünde asılı kalır -------
   Çubuk zaten araç çubuğunun yerinde beliriyor (ekran zıplamasın diye).
   Eksik olan şuydu: yirmi satırlık bir listede aşağı inip on beşinci satırı
   seçtiğinizde çubuk yukarıda, görüş alanının dışında kalıyordu — seçimi
   uygulamak için sayfanın başına dönmek gerekiyordu.

   Sınıf kabukta (`is-selecting`, `app.js` yazar), çubukta değil: yapışması
   gereken kabuğun kendisi. Telefonda kural yok — orada çubuk zaten ekranın
   altına, başparmağın altına yapışıyor. */
@media (min-width: 900px) {
  .filters-shell.is-selecting {
    position: sticky;
    top: var(--topbar-h, 54px);
    z-index: 30;
  }
  /* Yapışan çubuğun altından satırlar geçiyor: zemin opak olmalı, yoksa
     kayan metin çubuğun içinden okunuyor. */
  .filters-shell.is-selecting > .bulk-bar {
    box-shadow: var(--shadow-card-hover);
  }
}

/* --- Kademeli sütun gizleme ---------------------------------------------
   `.hide-compact` tek bant (900-1100) için yazılmıştı; aradaki genişlikler
   (1100-1280) yedi sütunu taşıyamıyor ama hiçbir sütunu da düşürmüyordu:
   orada sütunlar birbirine giriyor, iş adı iki satıra kırılıyordu.

   Üç kademe: önce en az acil sütun (`hide-lg`), sonra ikincisi
   (`hide-md`), en sonda mevcut `hide-compact`. Sınıf `th` ve `td`ye
   **birlikte** konur, yoksa satır kayar. */
/* `hide-xl` en erken düşen kademedir (Faz 25). Aday listesi "Ekleyen"
   sütunuyla birlikte 1440 px'in altında tam doluyor: bir sütun düşmezse
   tablo yatay kayıyor. Düşen "son iletişim" tarihi oldu — o bilgi kartta,
   detayda ve görüşme geçmişinde de var; kaydı kimin girdiği ise başka
   hiçbir listede yok. */
@media (max-width: 1439px) { .hide-xl { display: none !important; } }
@media (max-width: 1279px) { .hide-lg { display: none !important; } }
@media (max-width: 1139px) { .hide-md { display: none !important; } }

/* --- Süzgeç paneli: kart ve form diliyle aynı ---------------------------
   Panel `--shadow-lg` taşıyordu: sayfadaki hiçbir kartın taşımadığı bir
   yükseklik. Açıldığında ekrandan kopuk, "sistem menüsü" gibi duruyordu.
   Artık kartların gölgesi (bir basamak güçlüsü, çünkü gerçekten üstte
   duruyor) ve kartların kenarlığı. Koyu temada zemin `--surface` üzerinden
   geldiği için ayrıca kural gerekmiyor — jeton zaten temayla dönüyor. */
.filter-pop-panel {
  box-shadow: var(--shadow-pop, var(--shadow-card-hover));
  border-color: var(--border);
}
/* Panel içindeki gruplar arası ayırıcı: başlıklar aynı puntoda olduğu için
   üç grup tek uzun liste gibi okunuyordu. */
.filter-pop-body .filter-group + .filter-group {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border-soft);
}
.filter-pop-foot {
  border-top: 1px solid var(--border);
  background: var(--surface-soft);
}


/* --- Araç çubuğu: tek parça arama + dengeli iki uç -----------------------
   "Ara" düğmesi arama alanının bir parçası, ayrı bir eylem değil: aralarında
   --sp-3 boşluk varken çubukta dört ayrı ada (arama, Ara, Filtreler, Yeni
   kayıt) oluyor ve hangisinin hangisiyle çalıştığı belirsizleşiyordu.
   Bitişik çizilince çubuk iki uca ayrılıyor: solda arama, sağda süzgeç ve
   yeni kayıt (aradaki `.toolbar-gap` ikisini ayırır).

   `:has()` yalnız köşe yuvarlaması için: desteklenmeyen tarayıcıda alan
   yuvarlak kalır, düzen bozulmaz. */
@media (min-width: 900px) {
  .toolbar .search-field + .btn {
    /* `.toolbar` bir `gap` uyguluyor ve bitişiklik yalnız `-1px` ile
       kurulmaya çalışılmıştı: sonuç, aralarında 8 px boşluk olan **iki
       kare kenar** oluyordu — kutu ortasından kesilmiş gibi görünüyor ve
       "iki alanın sınırı üst üste binmiş" diye okunuyordu. Negatif kenar
       boşluğu önce `gap`i geri alır, sonra kenarlıkları üst üste bindirir;
       ikisi tek parça olur. Değer `gap` ile bağlı, elle 9 px yazılmadı:
       aralık değişirse seam kendiliğinden doğru kalsın. */
    margin-left: calc(-1 * var(--sp-2) - 1px);
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
  .toolbar .search-field:has(+ .btn) .input {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
  }
  /* Kenarlıklar üst üste bindiği için odak halkası düğmenin altında
     kalıyordu: klavyeyle gezen kullanıcı alanın sağ kenarında halkanın
     kesildiğini görüyordu. Odaklanan alan bir kat öne çıkar. */
  .toolbar .search-field:has(+ .btn) .input-wrap:focus-within {
    position: relative;
    z-index: 1;
  }
  /* Sekme şeridi masaüstünde dokunma hedefi kadar yüksek olmak zorunda
     değil: 44 px, başlık ile araç çubuğu arasına üçüncü bir kat ekliyordu.
     Telefonda kural yok — orada parmak ölçüsü geçerli. */
  .tab-link { min-height: 38px; }
}


/* --- Takvim üst şeridi: üç grup tek satırda -----------------------------
   Görünüm sekmeleri solda, tür süzgeci onların yanında, dönem gezinmesi
   sağ uçta. Tür şeridi eskiden kendi satırındaydı; aynı soruyu ayarlayan
   üç kontrolün üç ayrı kata dağılması, ızgarayı ilk ekranın dışına
   itiyordu. */
.cal-toolbar { justify-content: flex-start; gap: var(--sp-3) var(--sp-4); }
.cal-toolbar .tabs { margin-bottom: 0; flex: 0 0 auto; }
.cal-toolbar .cal-kinds { margin: 0; flex: 0 1 auto; }
.cal-toolbar .cal-person { flex: 0 1 auto; }
/* Gezinme sağ uca: ay adı ile okların yeri ekrandan ekrana değişmemeli. */
.cal-toolbar .cal-nav { margin-left: auto; flex: 0 0 auto; }

/* Takvim kartı: ızgara kartın **tamamı**, iç boşluk yok. Kart dolgusu
   olsaydı hücre çizgileri kenarlıktan içeride biter, ızgara kartın içinde
   yüzen ikinci bir çerçeve gibi okunurdu. */
.cal-grid-month,
.cal-grid-week { border-radius: calc(var(--r-lg) - 1px); }
.card > .cal-grid { margin: -1px; }

/* Etkinlik metni tek satır: iki satıra kırılan bir başlık, hücredeki
   üçüncü etkinliği "+1 daha"ya düşürüyordu. */
.cal-event-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-event .icon { width: 14px; height: 14px; }

/* Bandın canlı seçim sayacı: başlığın parçası ama onun ağırlığında değil —
   sayım rozeti (`.count`) kaydın toplamını söyler, bu ise geçici bir durum. */
.section-live {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  text-transform: none;
  color: var(--brand);
}
.section-live[hidden] { display: none; }


/* ==========================================================================
   Faz 20 — Ayrıntı ekranlarının yoğunluğu

   Firma, iş ve görev ayrıntısı Faz 17'de aynı sözlüğü konuşmaya başladı
   ama aynı **ölçüyü** konuşmuyordu: künye altındaki şerit üç ekranda üç
   farklı yükseklikte, bilgi grupları arasındaki delikler kayıttan kayda
   değişen büyüklükte, kontrol kartı bir ekranda 860 pikselde durup
   yanında boş tuval bırakırken diğerinde sayfayı kaplıyordu.

   Bu blok üç ekranın ortak ölçüsüdür. Yeni bir bileşen tanıtmıyor;
   var olanların boşluk, genişlik ve hiyerarşi ayarlarını tek yerde
   topluyor — ölçü üç şablona dağıldığında biri değişince diğer ikisi
   sessizce eskiyordu.
   ========================================================================== */

/* --- 1. Sayfa ritmi ---------------------------------------------------- */

/* Ayrıntı sayfasının gövdesi. `stack-lg` (20 px) liste ekranları için
   doğru: orada bölümler birbirinden bağımsız konulardır. Ayrıntıda
   bölümlerin hepsi **aynı kaydı** anlatıyor ve 20 px, sekme şeridi ile
   ilk kartın arasında kaydın parçalandığı bir delik açıyordu. 16 px,
   `.section`ın kendi iç aralığıyla (sp-4) aynı: sayfa tek ritimde akar. */
.rec-page { display: flex; flex-direction: column; gap: var(--sp-4); }

/* --- 2. Kontrol kartı tek genişlikte ----------------------------------- */

/* Faz 17'nin 860 pikselik tavanı kalktı. Tavan, "kompakt olması gereken
   denetim sayfanın en büyük nesnesi olmasın" diye konmuştu; ama tavanın
   kendisi başka bir sorun üretti: firma ayrıntısında kartın içinde iki
   küçük form, sağında 240 piksel boş tuval ve altında tam genişlikte
   kartlar vardı — sayfadaki tek hizasız nesne oydu.

   Çözüm tavan değil **dağıtım**: kart sayfadaki diğer kartlarla aynı
   genişlikte durur, alanlar satırı eşit paylaşır ve büyümeleri 280
   pikselde durur. Kalan pay düğmenin soluna gider, yani "Bekleme nedeni"
   kutusu ekranın yarısını alamaz. */
.rec-quick { max-width: none; }
.rec-quick .field { flex: 1 1 160px; max-width: 280px; }
.rec-quick > .btn { margin-left: auto; }
/* Firma ayrıntısı kartı iki ayrı formdan oluşuyor (durum ve takip iki ayrı
   uca gider). Formlar da satırı paylaşır, yoksa `flex: none` ikisini sola
   yığıyordu. */
.rec-quick > .rec-strip-form { flex: 1 1 200px; max-width: 320px; }
.rec-quick > .rec-strip-form .field { max-width: none; }
.rec-quick > .rec-strip-form > .btn { flex: none; }

/* --- 3. Bilgi grupları: delik yerine paketleme ------------------------- */

/* İki eşit ızgara kolonu (Faz 17) öngörülebilirdi ama üç gruplu bir
   sayfada ikinci satırda bir grup ve yanında **grup boyunda bir delik**
   bırakıyordu: iş ayrıntısının "Bilgiler" sekmesinde ekranın sağ alt
   çeyreği boş kalıyordu.

   Çok kolon (`columns`) aynı iki kolonu kurar ama grupları dikeyde
   paketler: kolonların yüksekliği dengelenir, delik kapanır. Izgaranın
   verdiği "aynı satırdaki iki grup aynı hizada başlar" güvencesi burada
   zaten bir şey söylemiyordu — gruplar farklı uzunlukta. */
@media (min-width: 900px) {
  .info-grid {
    display: block;
    columns: 2;
    column-gap: var(--sp-6);
  }
  .info-group {
    break-inside: avoid;
    /* `display: flex` çok kolonda kırılmayı bozuyor; grup zaten dikey bir
       yığın, blok akışı yeter. Başlık ile liste arasındaki boşluk aşağıda. */
    display: block;
    margin-bottom: var(--sp-5);
  }
  .info-group > .info-list,
  .info-group > .contact-list { margin-top: var(--sp-2); }
  /* Son grubun alt boşluğu kolonun dibinde asılı kalmasın. */
  .info-grid > .info-group:last-child { margin-bottom: 0; }
}

/* Satır yoğunluğu: 34 → 30 px taban, dolgu 8 → 6. Yirmi satırlık bir
   sayfada kazanılan 80 piksel, "Bilgiler" sekmesini kaydırmasız okunur
   hâle getiriyor. Çizgi ritmi korunuyor — asıl okunurluğu o taşıyor. */
.info-row { min-height: 30px; padding: 6px 0; }
.contact-row { min-height: 36px; padding: 6px 0; }

/* --- 4. Özellik satırları (renkli çip değil) --------------------------- */

/* İşin kapsamı — Uygulama, Web sitesi, Sosyal medya, Ek işler — çip
   dizisiydi. Çip **seçimdir** (bkz. `.chip` gerekçesi): kaldırılabilir ya
   da çoklu bir giriş alanının parçası. Salt okunur bir bilgi, kenarlıklı
   dört kapsül olarak çizildiğinde satırdaki en gürültülü nesne oluyor ve
   yanındaki "Açıklama" metnini bastırıyordu.

   İkon + metin: aynı bilgi, çerçevesiz. İkon türü söyler, metin adı. */
.feat-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-4);
  min-width: 0;
}
.feat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-weight: var(--fw-medium);
}
.feat .icon { flex: none; color: var(--text-muted); }

/* Katılımcılar da öyle: baş harf + ad, kapsül değil. */
.who-list { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); }
.who { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }

/* --- 5. Alt görevin ana göreve bağı ------------------------------------ */

/* Girinti + zemin, alt görevin **bir alt basamak** olduğunu söylüyordu
   ama hangi göreve ait olduğunu söylemiyordu: arka arkaya iki ana görev
   ve aralarına serpilmiş alt görevlerde satırlar tek bir düz liste gibi
   okunuyor, ayırıcı çizgiler de her yerde aynı ağırlıkta duruyordu.

   Ray, ana görevin tamamlama düğmesinin **tam altından** iner (x = 32 px:
   16 dolgu + 16 yarıçap) ve her alt göreve bir dirsekle bağlanır. Zemin
   kalktı: hiyerarşiyi çizgi anlatıyor, ikinci bir işaret gürültü olurdu. */
.task-row.is-subtask {
  position: relative;
  background: none;
  border-top-color: transparent;
}
.task-row.is-subtask:hover { background: var(--surface-soft); }
.task-row.is-subtask::before,
.task-row.is-subtask::after {
  content: "";
  position: absolute;
  background: var(--border);
  pointer-events: none;
}
/* Dikey ray. */
.task-row.is-subtask::before {
  left: 32px;
  top: 0;
  bottom: 0;
  width: 1px;
}
/* Son alt görevde ray dirseğin hizasında biter: liste orada kapanıyor. */
.task-row.is-subtask:not(:has(+ .task-row.is-subtask))::before {
  bottom: auto;
  height: 28px;
}
/* Dirsek: raydan alt görevin düğmesine. */
.task-row.is-subtask::after {
  left: 32px;
  top: 28px;
  width: 8px;
  height: 1px;
}
/* Ana görev ile alt görevleri arasında ayırıcı yok — ikisi tek öbek.
   Yeni bir ana görev başlarken çizgi geri gelir ve **belirgin** olur:
   öbek sınırı, satır sınırından daha güçlü bir sınırdır. */
.task-row.is-subtask + .task-row:not(.is-subtask) { border-top-color: var(--border); }
@media (max-width: 899px) {
  .task-row.is-subtask::before,
  .task-row.is-subtask::after { left: 30px; }
  .task-row.is-subtask::after { top: 30px; }
  .task-row.is-subtask:not(:has(+ .task-row.is-subtask))::before { height: 30px; }
}

/* --- 6. Telefonda künye eylemleri -------------------------------------- */

/* 360 pikselde üç düğme (Düzenle - İletişim kaydet - üç nokta) sarıyordu
   ve üçüncüsü tek başına alt satıra düşüyordu: sayfanın en üstünde,
   hiçbir şeye bitişik olmayan bir kare. Şablon telefonda "Düzenle"yi
   menüye indiriyor (`hide-mobile` / `hide-desktop`); burada kalan
   eylemler satırı paylaşıyor — birincil eylem büyür, menü kendi
   ölçüsünde kalır. */
@media (max-width: 599px) {
  .rec-actions {
    width: 100%;
    margin-left: 0;
    gap: var(--sp-2);
  }
  .rec-actions > .btn,
  .rec-actions > .rec-menu { flex: 1 1 auto; min-width: 0; }
  .rec-actions > .rec-menu > .btn { width: 100%; }
  /* "Diğer işlemler" büyümez: ikon düğmesidir, ölçüsü sabittir.

     Seçici `:last-child` **değil**: silme kipi başlıkta menünün ardından
     basılıyor (`confirm_form` → gizli tetikleyici formu + `hidden` perde),
     yani menü sonuncu çocuk olmuyor ve kural sessizce hiç uygulanmıyordu.
     Ayırt edici şey konum değil, tetikleyicinin türü. */
  .rec-actions > .rec-menu:has(> .btn-icon) { flex: 0 0 auto; }
  .rec-actions > .rec-menu:has(> .btn-icon) > .btn { width: auto; }
}

/* --- 7. Kip içi giriş metni -------------------------------------------- */

/* Kipin ilk satırı "bu kip ne yapacak"ı söyler; alanlardan bir nefes
   uzakta durur ama kendi kutusunu açmaz. */
.kip-lead { margin: 0; }

/* --- 8. İlerleme bandı: ortadaki delik ---------------------------------- */

/* Çubuk 360 pikselde duruyor, güncelleme formu `margin-left: auto` ile sağ
   uca yapışıyordu: 1100 piksellik bir kolonda ikisinin arasında üç yüz
   piksellik bir boşluk kalıyor ve bant "tek şerit" değil "iki ayrı nesne"
   gibi okunuyordu. Çubuk artık boşluğu yiyor; tavan 640 px, çünkü ondan
   sonrası yüzdeyi okunur kılmıyor, yalnız uzatıyor. */
.rec-band > .rec-progress { flex: 1 1 360px; max-width: 640px; }

/* --- 9. Akışın yoğunluğu ------------------------------------------------ */

/* "Aktivite" sekmesi diğer sekmelerden seyrekti: bilgi satırları 30 px'lik
   bir ritimde akarken akış 16 px aralık + 12 px dolguyla ilerliyordu ve
   sekmeler arasında geçen kullanıcı, aynı kaydın iki farklı yoğunlukta
   çizildiğini görüyordu. Yapı korunuyor (yazma alanı, süzgeç şeridi,
   kronoloji) — yalnız aralıklar diğer sekmelerle aynı ölçüye bağlanıyor. */
.feed { gap: var(--sp-3); }
.feed-item { padding: 10px 0; }


/* ==========================================================================
   Görev kart panosu — iş ayrıntısı (Faz 28)
   --------------------------------------------------------------------------
   İş ayrıntısındaki görev listesi, bölüm bandına yapışık tek bir yüzey
   olmaktan çıkıp **tek sütunlu kompakt kartlara** döndü. Faz 17'nin kararı
   (bant + tek yüzey) görev ayrıntısında duruyor ve doğru: orada beş ayrı
   bölüm var ve her biri kendi başlığıyla ayrılmalı. Burada tek bir liste
   vardı ve ayrılması gereken şey bölümler değil **kayıtlardı**. Kırk satır
   arasındaki 1 piksellik çizgi, gözün "nerede bitti" sorusuna verdiği en
   zayıf yanıttır; boşluk en güçlüsü.

   Ölçü sözleşmesi — bozulursa liste "kompakt" olmaktan çıkar:

   · kart yüksekliği 64–76 px (iki satır yazı + 12 px dolgu),
   · kartlar arası 8 px,
   · meta satırı **sarmaz** (`nowrap`): sarsaydı kart üçüncü satıra taşar,
     bir ekrana sığan görev sayısı yarıya inerdi. Sığmayan bilgi kırpılır
     ve kırpılan ilk şey sorumlunun adıdır (tek `min-width: 0` orada).

   Taban gölgesi **yok**. Tasarım sistemi her karta `--shadow-card` verir ve
   bu kural oradaki tek istisna: 8 piksel arayla dizilmiş kırk yumuşak gölge
   üst üste binip kartların arasını gri bir banda çeviriyordu. Ayıran şey 1
   px sınır + beyaz yüzeyin tuvalden farkı; gölge yalnız hover'da ve
   sürüklenirken, yani "bu kart şu an elimde" derken var.
   ========================================================================== */

.task-board { display: flex; flex-direction: column; gap: var(--sp-3); }

/* Sürükleme sırasında metin seçilmesin: parmak/fare kartı taşırken
   tarayıcı başlıkları maviye boyuyordu. */
.task-board.is-sorting { user-select: none; }

/* --- 1. Durum grupları ------------------------------------------------- */

/* `<details>`/`<summary>`: açılıp kapanma tarayıcının işi, betiğin değil.
   İki kazanç bedavaya geliyor — betik yüklenmese de çalışır ve tarayıcının
   "sayfada bul" davranışı kapalı bir gruptaki eşleşmeyi bulunca grubu
   kendiliğinden açar (`hidden="until-found"` ile aynı sonuç, kod yazmadan).

   Boş grup **kapalı** doğar (şablon `open`u yalnız dolu gruba basar): bir
   başlık satırından fazla yer kaplamaz ama kaybolmaz da — "Devam ediyor"
   başlığının boş durması, o işte şu an yürüyen bir şey olmadığını söyleyen
   bir bilgidir. */
.task-group-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 30px;
  padding: 4px var(--sp-2);
  border-radius: var(--r-sm);
  color: var(--text-secondary);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  text-transform: uppercase;
  cursor: pointer;
  list-style: none;
}
.task-group-head::marker { content: ""; }
.task-group-head::-webkit-details-marker { display: none; }
.task-group-head:hover { background: var(--surface-soft); color: var(--text-primary); }

.task-group-name { min-width: 0; }
.task-group-count { color: var(--text-muted); font-weight: 600; letter-spacing: 0; }

.task-group-caret {
  color: var(--text-muted);
  transition: transform var(--dur-2) var(--ease-out);
}
.task-group[open] > .task-group-head .task-group-caret { transform: rotate(90deg); }

/* Kartlar arası 8 px — panonun tek ritmi. */
.task-group-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-2) 0 var(--sp-1);
}
.task-group-empty {
  margin: 0;
  padding: var(--sp-2) var(--sp-3);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* Sürüklenen birim: üst görev **ve** alt görevleri. Alt görev tek başına
   taşınmaz; üstünden koparmak bir sıralama değil taşıma kararıdır. */
.task-item { display: flex; flex-direction: column; gap: var(--sp-1); }

/* --- 2. Kartın kendisi -------------------------------------------------- */

.task-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 64px;
  padding: var(--sp-3) var(--sp-2) var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  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);
}
.task-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-card);
}
/* Tıklama alanı kartın tamamı (`.task-card-title::after`), imleç de bunu
   söylemeli: denetimde "yalnızca başlık bağlantı" diye okundu, çünkü kartın
   gövdesi ok imleciyle duruyordu — alan vardı, davet yoktu. Klavyede de
   aynı: odak başlıktayken halka **kartın** çevresinde belirir. */
.task-card { cursor: pointer; }
.task-card:focus-within { border-color: var(--brand); box-shadow: var(--shadow-card); }
/* Paneli açık olan kart işaretli kalır (`app.js`, `satirinda`): kullanıcı
   panelde bir alanı değiştirdiğinde hangi kartı düzenlediğini görmeli. */
.task-card.is-open { border-color: var(--brand); box-shadow: var(--shadow-card); }

/* Tamamlama kutusu ve sağ uçtaki araçlar, başlığın kartı kaplayan tıklama
   alanının (`::after`) **üstünde** durur.

   İkisi aynı sonucu iki farklı yoldan alıyor ve bu bilinçli:

   · Kutu başlıktan **önce** geliyor, yani ağaç sırası onu altta bırakırdı;
     `z-index` şart. İçinde yüzen bir yüzey olmadığı için burada yığın
     bağlamı açmanın bedeli yok.
   · Araçlar başlıktan **sonra** geliyor; konumlanmış olmaları ağaç sırasıyla
     zaten üste çıkmalarına yetiyor. `z-index` **bilerek yazılmıyor**: bir
     yığın bağlamı açardı ve içindeki üç nokta menüsü (`.row-menu-panel`,
     `position: fixed; z-index: 60`) o bağlamın 1'ine hapsolurdu — menü üst
     çubuğun ya da alt çubuğun altında açılırdı. */
.task-card-check { flex: none; margin: 0; position: relative; z-index: 1; }
.task-card-tools {
  flex: none;
  display: flex;
  align-items: center;
  gap: 2px;
  position: relative;
}
.task-card-menu { display: inline-flex; }

.task-card-body {
  min-width: 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.task-card-title {
  font-weight: 600;
  font-size: var(--fs-base);
  line-height: 1.4;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Tıklama alanı kartın tamamı: "kart tıklanınca hızlı görev detayı açılır"
   kuralı tek bir sözde öğeyle kuruluyor. İkinci bir sarmalayıcı bağlantı
   açmak, içindeki formu (tamamlama kutusu) geçersiz HTML yapardı — bağlantı
   içinde form bulunamaz. */
.task-card-title::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
/* Klavye odağı (Faz 34).

   Bağlantı zaten odaklanabilir ve `Enter` onu açar — eksik olan **halkanın
   nereyi gösterdiğiydi**: varsayılan `:focus-visible` metnin kutusunu
   çiziyordu (ölçümde 206×21), oysa tıklanan alan kartın tamamı (358×76).
   Klavyeyle gezen kullanıcı, fareyle gezenin gördüğü hedefi görmüyordu.

   Halka bu yüzden kartı kaplayan sözde öğeye taşındı: çizilen kutu ile
   tıklanan kutu artık aynı. Kartın kendisine `tabindex` verilmedi — ikinci
   bir odak durağı, `Tab` sırasına her kart için boş bir adım eklerdi. */
.task-card-title:focus-visible { outline: none; }
.task-card-title:focus-visible::after {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--r-md);
}

.task-card-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  min-height: 18px;
  /* Sarmaz ve taşmaz: kartın yüksekliği sözleşmenin parçası. */
  flex-wrap: nowrap;
  overflow: hidden;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.task-card-meta > * { flex: none; }

/* Durum noktası: 8 px, etiketsiz. `--st-fill` burada tanımlanıyor çünkü
   başlamamış durumun "içi boş halka" biçimi (`.status-neutral .dot-mark`)
   deliğin rengini bu değişkenden okuyor; `.status` kabuğunun dışındayız. */
.task-dot { --st-fill: var(--surface); display: inline-flex; align-items: center; }
.task-dot .dot-mark {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--text-muted);
}

/* Sığmayan ilk şey sorumlunun adı: durum, tarih ve önem kalır. */
.task-who {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: 0 1 auto;
}
.task-who .avatar { flex: none; }

.task-due { white-space: nowrap; }

/* Önem düz **metin**: renkli hap değil. Normal önem hiç basılmıyor (varsayılan
   bir bilgi değildir), düşük önem sessiz gri, yüksek amber, acil mercan. */
.task-flag { font-weight: 600; color: var(--text-secondary); }
.task-flag.tone-neutral { color: var(--text-muted); font-weight: 400; }
.task-flag.tone-warn { color: var(--warn); }
.task-flag.tone-accent { color: var(--state-late-ink); }

/* Geciken kartta "Yüksek" altın kalmaz, nötre iner. İki gerekçe aynı yere
   çıkıyor:

   · Ölçüm: altın mürekkep (`--warn`) gecikme zemininin (`--state-late-fill`)
     üstünde 4.48 karşıtlık veriyordu — eşiğin (4.5) kıl payı altı
     (`tools/tema_audit.py`). Jetonu koyulaştırmak ya da buraya tek kullanımlık
     bir hex yazmak, tasarım sistemi §1'in "hex yalnız palette" kuralını
     delerdi.
   · Tasarım: kart zaten mercan konuşuyor. Aynı yüzeyde ikinci bir renkli
     sinyal, §1'in "%88 nötr / %12 vurgu" disiplininde üçüncü blok demek —
     ikisinden biri gereksiz ve gereksiz olan, gecikmenin yanında önem.

   "Acil" (`tone-accent`) mercan kalmayı sürdürüyor: o, kartın kendi
   uyarısıyla **aynı** şeyi söylüyor, onunla yarışmıyor. */
.task-card.is-late .task-flag.tone-warn { color: var(--text-secondary); }

.task-subs { display: inline-flex; align-items: center; gap: 4px; color: var(--text-muted); }
.task-subs .icon { width: 14px; height: 14px; }
.task-wait { color: var(--warn); font-weight: 600; }

/* --- 3. İki durum, iki zemin -------------------------------------------- */

/* Geciken kart: çok hafif mercan ton. Okunan işaret yine **tarih** (mercan
   mürekkep, `.is-alert`); zemin onu yalnız uzaktan taranabilir kılıyor.
   Dolgu bir tondur, blok değil — yüzeye 1.5:1'in altında oturur (Faz 27). */
.task-card.is-late {
  background: var(--state-late-fill);
  border-color: var(--state-late-line);
}
.task-card.is-late .task-dot { --st-fill: var(--state-late-fill); }

/* Tamamlanan kart soluklaşır ve başlığı üstü çizilir. İki kanal birden:
   renk körlüğünde de okunur. Tamamlama kutusu soluklaşmaz — yanlışlıkla
   işaretlenen bir görevi geri almanın yolu odur. */
.task-card.is-done { background: var(--surface-soft); border-color: var(--border-soft); }
.task-card.is-done .task-card-body { opacity: 0.66; }
.task-card.is-done .task-card-title,
.task-card-title.task-done {
  color: var(--text-muted);
  text-decoration: line-through;
}
.task-card.is-done .task-dot { --st-fill: var(--surface-soft); }

/* --- 4. Alt görev kartı ------------------------------------------------- */

/* Bir basamak içeride, bir tık küçük ve zemini çukur: "bu, üstündekinin
   parçası" cümlesi üç kanalla birden kuruluyor. Bağlantı çizgisi nötr —
   renkli sol şerit değil (tasarım sistemi §1 yasak listesi). */
.task-card.is-sub {
  margin-left: var(--sp-6);
  min-height: 48px;
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3);
  background: var(--surface-soft);
  border-color: var(--border-soft);
}
.task-card.is-sub .task-card-title { font-size: var(--fs-sm); font-weight: 500; }
.task-card.is-sub::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--sp-4));
  top: calc(-1 * var(--sp-1) - 1px);
  bottom: 50%;
  width: var(--sp-3);
  border-left: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  border-bottom-left-radius: var(--r-xs);
  pointer-events: none;
}

/* --- 5. Sürükleme tutamağı ---------------------------------------------- */

/* `touch-action: none` şart: dokunmatikte tarayıcı ilk hareketi kaydırma
   sayıp işaretçi olaylarını kesiyor ve kart hiç kalkmıyordu. Yalnız
   tutamağa veriliyor, karta değil — kartın üstünde parmakla kaydırmak
   çalışmayı sürdürmeli. */
.task-grip {
  width: 34px;
  height: 34px;
  color: var(--text-muted);
  cursor: grab;
  touch-action: none;
}
.task-grip:active { cursor: grabbing; }

/* Farede sessiz dur, ihtiyaç anında görün — `.row-btn` ile aynı gerekçe.
   Dokunmatikte `:hover` diye bir an yok, orada hep açık (aşağıda). */
@media (hover: hover) {
  .task-grip { opacity: 0; transition: opacity var(--dur-1) var(--ease-out); }
  .task-card:hover .task-grip,
  .task-card:focus-within .task-grip,
  .task-grip:focus-visible { opacity: 1; }
}

/* Elde duran kart: gölge bir kademe yukarı, sınır marka rengine döner ve
   kart imlecin altında kalsın diye yığının üstüne çıkar. */
.task-item.is-dragging { position: relative; z-index: 20; }
.task-item.is-dragging .task-card {
  border-color: var(--brand);
  box-shadow: var(--shadow-lg);
}
.task-item.is-dragging .task-card-title::after { display: none; }

/* --- 6. Hızlı ekleme ve boş durum --------------------------------------- */

/* Ekleme alanı panonun son kartı: kesik çizgi "burası bir kayıt değil, bir
   davet" der (dosya yükleme yüzeyiyle aynı dil, Faz 17). */
/* Hızlı ekleme Faz 33'te panonun **dışına**, bölümün altına çıktı: artık iki
   görünüme birden hizmet ediyor (pano ve liste), ikisinin de içinde
   olamazdı. Seçici bu yüzden kapsayıcıdan bağımsız. */
.task-add.quick-add {
  margin: var(--sp-1) 0 0;
  padding: var(--sp-3);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface);
}
.task-board-empty {
  border: 1px dashed var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}

/* ==========================================================================
   Kanban panosu (Faz 33)

   Görev takibi sütunlar arasında ilerleyen bir akıştır; dikey liste bunu
   ancak dolaylı anlatıyordu. Pano **varsayılan** görünüm, liste ikinci.

   Sütunun kendisi bir kart değil bir **oluk**: zemini tuvalden bir ton
   çukur, kenarlığı yok. Dört kartlı bir çerçeve çizmek, içindeki gerçek
   kartlarla yarışan ikinci bir kutu katmanı yaratırdı.
   ========================================================================== */

/* --- 1. Araç çubuğu: görünüm + kişi ------------------------------------- */

.board-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}

/* Segment seçici: iki seçenek, tek hap. Açılır kutu olsaydı iki seçenek
   için bir tıklama fazladan isterdi ve hangisinde olduğun kapalı kalırdı. */
.seg {
  display: inline-flex;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-soft);
}
.seg-btn {
  padding: 4px var(--sp-3);
  border-radius: calc(var(--r-md) - 3px);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dur-1) var(--ease-out),
    color var(--dur-1) var(--ease-out);
}
.seg-btn:hover { color: var(--text-primary); }

/* Dokunmatikte görünüm anahtarı parmağa açılır (tasarım sistemi §7).
   Masaüstünde 28 px doğru ölçü — araç çubuğu düğmesi, metin yüksekliğinde.
   Telefonda aynı 28 px, `tools/ui_audit.py` ölçümünde 360 ve 390'da küçük
   hedef olarak rapor ediliyordu: "Pano / Liste" panonun en üstteki ve en
   sık kullanılan kontrolü, dokunulamıyor olması panonun kendisine
   ulaşılamaması demekti. Kabın dolgusu da düşüyor, yoksa şerit iki kat
   yükselirdi. */
@media (pointer: coarse) {
  .seg { padding: 0; }
  .seg-btn { min-height: var(--tap); }
}
.seg-btn.is-active {
  background: var(--surface);
  color: var(--text-primary);
  box-shadow: var(--shadow-card);
}

.board-person { display: inline-flex; align-items: center; gap: var(--sp-2); }
.board-person select { max-width: 15rem; }

/* --- 2. Öneri ve kilit bandı -------------------------------------------- */

/* Öneri bir **soru**, uyarı değil: zemini sakin, ikonu bilgi. Amber ya da
   mercan kullanmak, kullanıcının yanlış bir şey yaptığını ima ederdi. */
.board-suggest,
.board-lock {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-soft);
  font-size: var(--fs-sm);
}
.board-suggest .icon,
.board-lock .icon { color: var(--text-muted); flex: none; }
.board-suggest-text { flex: 1 1 12rem; min-width: 0; color: var(--text-secondary); }
.board-lock span { flex: 1 1 12rem; color: var(--text-secondary); }
.board-lock form { margin: 0; }

/* --- 3. Sütunlar --------------------------------------------------------- */

/* Dört eşit sütun. `minmax(0, 1fr)`: sıfır taban olmadan uzun bir görev
   başlığı sütunu şişirir ve dördü eşitliğini kaybederdi. */
.kanban {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-3);
  align-items: start;
}
.kanban.is-sorting { user-select: none; }

/* Telefondaki sütun seçici (Faz 5). Masaüstünde hiç çizilmez: dört sütun
   yan yana dururken bir de sekme çubuğu koymak, aynı seçimi iki kez
   sormaktı. Grid'in tam satırını kaplar, yoksa ilk sütunun hücresine
   sıkışırdı. */
.kanban-tabs {
  display: none;
  grid-column: 1 / -1;
  gap: var(--sp-1);
  margin-bottom: var(--sp-1);
  /* Yatay kaydırma (Faz 34).

     Eskiden dört sekme genişliği eşit paylaşıyordu (`flex: 1 1 0`) ve
     360-390 pikselde her birine ~44 px ad yeri kalıyordu: ölçümde dördü de
     kırpılmıştı — "Yapıl…", "Deva…", "Bekli…", "Tam…". Kırpılan şey
     durumun **adı**ydı, yani sekmenin taşıdığı tek bilgi; kullanıcı
     seçeceği sütunu tahmin ediyordu.

     Ad artık kırpılmıyor, şerit kaydırılıyor. Son sekmenin yarım görünmesi
     bir kayıp değil, "devamı var" işaretidir; dördünü 2×2 sarmak ise
     telefonda 100 pikseli yalnız seçiciye verirdi. */
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  /* Şerit tek satır; çubuk çizilseydi 48 px'lik hedefin altından yer
     yiyordu. Kaydırma yine parmakla ve `Tab`la (odak sekmeyi görünür kılar)
     yapılabiliyor. */
  scrollbar-width: none;
}
.kanban-tabs::-webkit-scrollbar { display: none; }
/* Kaydırılabildiğini **göster**. Yarım görünen son sekme tek başına yeterli
   bir işaret değildi: ölçümde şerit çoğu telefonda son sekmenin tam sınırına
   denk geliyor ve dördüncü durum ekranda hiç yokmuş gibi duruyordu. Sağ
   kenardaki solma "burada bir şey kesiliyor" der; okla anlatmıyoruz, çünkü
   ok bir **düğme** vaadi taşır ve dokunulacak bir şey değil.

   Sınıfı JS koyuyor (`data-scroll-hint`): sığıp sığmadığı yazı tipine, dile
   ve ekran genişliğine bağlı, CSS bunu soramaz. Koşulsuz uygulansaydı şeridin
   sığdığı ekranda son sekmeyi boşuna soldururduk. Sona gelince işaret kalkar
   — "devamı var" demeyi sürdürmek yalan olurdu. */
.kanban-tabs.is-scrollable {
  -webkit-mask-image: linear-gradient(to left, transparent 0, #000 var(--sp-6));
  mask-image: linear-gradient(to left, transparent 0, #000 var(--sp-6));
}
.kanban-tabs.is-scrollable.is-end {
  -webkit-mask-image: none;
  mask-image: none;
}

/* Hızlı güncellemenin tek formu: iki alan + tek düğme + onay rozeti.
   Alanlar yan yana, düğme sonda; dar ekranda sarar ve düğme tam satır olur —
   "kaydet" hiçbir ölçüde ekranın dışında kalmamalı. */
.rec-quick-form {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.rec-quick-form > .field { min-width: 0; }
.rec-quick-form [data-dirty-submit]:disabled { opacity: 0.55; cursor: default; }
/* Onay rozeti: yeşil, küçük, kendi zemini yok. Faz 46'dan beri hızlı
   güncellemede bildirim şeridinin **yerine** geçer (app.js `RotaSavedMark`):
   gözün zaten baktığı yerde, üç saniye duran kısa söz. Betik ekler; girişte
   hafifçe belirir, kalkarken animasyon yok (kaybolan şeyi izletmeye gerek
   yok). */
.quick-saved {
  align-self: center;
  color: var(--success);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
  animation: quick-saved-in var(--dur-2, 160ms) var(--ease-out, ease-out);
}
/* Yalnız saydamlık: yerinde düzenlemedeki konum `transform` ile kuruluyor,
   aynı özelliği animasyonla ezmek rozeti bitişte zıplatırdı. */
@keyframes quick-saved-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .quick-saved { animation: none; }
}
/* Yerinde düzenlenen alanda rozet kutunun sağ kenarına biner: satır
   eklemek üç saniyeliğine bütün paneli aşağı iterdi. Zemin, altındaki
   metnin ucunu örter. */
.inline-edit { position: relative; }
.inline-edit > .quick-saved {
  position: absolute;
  right: var(--sp-2);
  top: 50%;
  transform: translateY(-50%);
  padding-left: var(--sp-2);
  background: var(--surface);
}
/* Sunucunun `saved` şeridi (`base.html`): betik gönderen alanı bulunca
   şeridi kaldırıp rozeti gösterir; bulamazsa sınıfı düşürür ve şerit
   sıradan bildirim olarak görünür. Betiksiz tarayıcıda `.js` yok, şerit
   hep görünür. */
.js .flash-local { display: none; }

/* Kapatılabilir açıklamanın çarpısı (`_macros.dismissible_note`). Kutunun
   içinde, metnin sağında; kendi zemini yok — nötr bir simge düğmesi. */
.notice-close {
  flex: none;
  /* Çerçeve **düğmeye** göre konumlanır: kutuya göre konumlansaydı iki
     satırlık bir açıklamada hedef metnin ortasına kayardı. */
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: -4px -6px -4px 0;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-muted);
  cursor: pointer;
}
.notice-close:hover { color: var(--text); background: var(--surface-soft); }
.notice-close:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Görünen kutu 32 kalır, dokunulan alan 44 olur — kart tamamlama düğmesiyle
   aynı sözleşme. Komşusu olmadığı için görünmez çerçeve burada güvenli. */
@media (max-width: 899px), (pointer: coarse) {
  .notice-close::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}
.kanban-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  /* Eşit paylaşım değil, **ad kadar** yer: kırpmanın kaynağı `1 1 0`dı. */
  flex: 0 0 auto;
  scroll-snap-align: start;
  /* Dokunma hedefi sözleşmesi: `--tap` (44 px, dokunmatikte 48). */
  min-height: var(--tap);
  padding: 0 var(--sp-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}
/* Ad **kırpılmaz**. Telefonda sütun başlığı (`.kanban-head`) hiç
   çizilmediği için durumu söyleyen tek yer burası; kısaltmak bilgiyi
   ekrandan tamamen silmekti. Sığmayan şerit kayar (yukarıda). */
.kanban-tab-name { white-space: nowrap; }

/* Sekme şeridinin altındaki tek cümlelik yol tarifi. Varsayılanı gizli:
   sürüklemenin çalıştığı yüzeyde ikinci bir yol anlatmak, kullanıcıyı
   daha uzun olana yönlendirirdi. Sekmeler hangi kırılımda açılıyorsa
   (719 px) cümle de orada açılır — ikisi aynı kararın iki yüzü. */
.kanban-tip {
  display: none;
  /* Sekme şeridiyle aynı gerekçe: grid'in tam satırını kaplar, yoksa ilk
     sütunun hücresine sıkışırdı. */
  grid-column: 1 / -1;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 var(--sp-3);
}
.kanban-tip .icon { color: var(--text-muted); }
.kanban-tab-count { flex: none; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* Seçili sekme dolgu değil **çerçeve** alır — durum şeridiyle (Faz 31)
   aynı ayrım: renk durumun (nokta), çerçeve kullanıcının seçiminin. */
.kanban-tab-input:checked + .kanban-tab {
  border-color: var(--border-strong);
  background: var(--surface);
  color: var(--text-primary);
}
.kanban-tab-input:focus-visible + .kanban-tab {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.kanban-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
  padding: var(--sp-2);
  border-radius: var(--r-lg);
  background: var(--surface-soft);
}

.kanban-head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-secondary);
}
.kanban-name { min-width: 0; flex: 1 1 auto; }

/* Sayı bir rozet değil sessiz bir rakam: sütun başlığı zaten bir başlık,
   üstüne renkli hap koymak dört kez bağırmak olurdu. */
.kanban-count {
  flex: none;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Durum rengi **nokta**, şerit değil. İlk sürümde başlığın solunda 3
   piksellik dikey bir bant vardı; dört sütun yan yana dizilince ekranın
   üstünde dört renkli çubuk oluyordu ve bu, tasarım sistemi §1'in yasak
   listesindeki "renkli sol şerit" kalıbının ta kendisiydi
   (`test_faz27…serit_hala_yok` aynı kuralı kartlarda koruyor).

   Rengi burada **yazmıyoruz**: nokta `.status-*` sözlüğünden geçiyor, yani
   listedeki, şeritteki ve panodaki aynı durum aynı tonu alıyor. Pano bir
   süre kendi eşlemesini tuttu ve o kopyada "Devam ediyor" `--brand`
   oluyordu — tasarım sistemi §1'de `--brand` **eylem** rengi (birincil
   düğme, bağlantı, odak) ve "başka hiçbir şey"; durum rengi `--info`.
   Sözlüğü paylaşmak bu sapmanın tekrarını imkânsız kılıyor.

   Sözlük ayrıca biçim kanalını da taşıyor: başlamamış durumun noktası içi
   boş halkadır (`.status-neutral`), yani renk tek başına konuşmuyor.
   `--st-fill` halkanın içi; `.status` kapsülünün dışında kullandığımız için
   varsayılanını burada veriyoruz. */
.kanban-dot {
  display: inline-flex;
  flex: none;
  --st-fill: var(--surface-soft);
}
.kanban-dot .dot-mark {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

/* Oluk: kartların dizildiği yer. Boşken de yüksekliği var — sürüklenen
   kartın bırakılabileceği bir hedef görünmeden durmalı. */
.kanban-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-height: 72px;
}

/* Sürükleme sırasında hedef oluk belli olsun: kesik kenarlık + hafif
   vurgu. Yalnız zemin değişseydi, hangi sütunun hedef olduğu aynı tonda
   duran komşusundan ayırt edilemezdi. */
.kanban-body.is-over {
  outline: 2px dashed var(--brand);
  outline-offset: 4px;
  border-radius: var(--r-md);
}

/* "Süzgeç boş döndü" — "hiç görev yok"tan ayrı ve daha sessiz bir cümle:
   biri davet, öteki sonuç. Boş durum kutusu çizmek, üç görevi olan bir işte
   "İlk görevi ekleyin" demek olurdu. */
.board-filter-empty {
  margin: var(--sp-3) 0 0;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* Tamamlanmış kartta tarih bir uyarı değil bir kayıttır: ne mercan ne amber,
   sessiz gri. Metnin kendisi de değişir (`Task.completion_note`) — ölçü
   bugün değil tamamlanma günüdür. */
.task-due.is-done-note { color: var(--text-muted); }

/* Dolu sütunda cümle düşer. Kural burada, sunucuda değil: sürükleyerek
   boşalan bir sütun sunucuya sormadan da doğru cümleyi göstermeli. */
.kanban-body:has([data-task-item]) .kanban-empty { display: none; }

.kanban-empty {
  margin: 0;
  padding: var(--sp-2);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* Sütun başına ekleme: sınırsız bir alan değil, kartlarla aynı genişlikte
   tek satır. `Enter` gönderir; ayrı bir düğme, dört sütunda dört düğme
   demekti. */
.kanban-add { margin: 0; }
.kanban-add .input { width: 100%; }

/* "Bekliyor" sütunundaki neden seçimi yalnız **yazarken** açılır.
   Sürekli açık dururken sütun boşken bile iki alan kaplıyordu: hiç görevi
   olmayan bir sütunun en görünür şeyi, henüz var olmayan bir görevin
   nedenini soran bir açılır kutuydu. Kural CSS'te ve `:focus-within` ile —
   betik yokken de doğru çalışır, klavyeyle gelen kullanıcı alana girer
   girmez seçimi görür. */
.kanban-add select { display: none; margin-top: var(--sp-1); width: 100%; }
.kanban-add:focus-within select { display: block; }

/* Panodaki kart: dikey liste kartından iki farkı var — durum noktası yok
   (sütun söylüyor) ve başlık **iki satıra** kadar sarabilir. Listedeki tek
   satır kuralı orada hizalanacak bir kolon olduğu içindi; sütunda kolon yok
   ve dar bir kartta tek satır, uzun görev adlarını okunmaz kılardı. */
.kanban .task-card {
  align-items: flex-start;
  gap: var(--sp-2);
  padding: var(--sp-3);
}
.kanban .task-card-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
}
.kanban .task-card-meta { flex-wrap: wrap; row-gap: 4px; }
/* İkincil cümleler ("12 gün gecikmeyle tamamlandı", bekleme nedeni) panoda
   kendi satırını alır ve **iki satıra** kadar sarar. Liste kartındaki
   `nowrap` + `flex: none` burada metni kartın kenarında kelime ortasından
   kesiyordu — üç nokta bile yok, çünkü kırpan meta satırının `overflow`u.
   Kelime bütün kalır (`overflow-wrap: normal`); iki satıra sığmayan kırpılır
   ve tam metin `title` balonunda durur. */
.kanban .task-card-meta .task-card-text {
  flex: 1 1 100%;
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
  overflow-wrap: normal;
  word-break: normal;
  text-overflow: clip;
  line-height: 1.3;
}

/* İptal edilmiş işin panosu: sessizleşir ve kontrolleri düşer. Solukluk
   tek başına bırakılmadı — kilit bandı nedeni yazıyla da söylüyor. */
.kanban.is-locked { opacity: 0.72; }

/* --- 8. Aday akışı kartı (Faz 40) --------------------------------------
   Görev kartı yeniden kullanılmadı: o kart tamamlama kutusu, önem bayrağı
   ve alt görev yığını etrafında kurulu — üçü de adayda yok. Ortak olan
   **kabuk** (`.kanban*`, `.task-item`) zaten paylaşılıyor; kartın kendisi
   taşıdığı üç bilgiye göre ayrı: firma, sorumlu, sonraki takip. */
.lead-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  transition: border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}
.lead-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-card); }
.lead-card:focus-within { border-color: var(--brand); box-shadow: var(--shadow-card); }

.lead-card-head {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-1);
}
.lead-card-title {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}
.lead-card-title:hover { text-decoration: underline; }
/* Faz 45: sektör kartın **son** satırı ve soluk — ikincil bilgi; meta
   satırı (`.rec-line`, ortak sözlük) başlığın hemen altında "kimde — ne
   zaman" diye okunur. Kart hâlâ üç satır: yükseklik değişmedi, sıra değişti. */
.lead-card-sector { margin: 0; }
.lead-card-meta { min-height: 20px; }
/* Takibi gelmiş kayıt kartın tek uyarısı; `is-alert` (ortak sözlük) renk
   **ve** kalınlık verir, çünkü tek başına renk daltonik kullanıcıya hiçbir
   şey söylemez. Takipsiz kart eğik yazıyla "Takip yok" der. */
.lead-due.is-empty { font-style: italic; }

/* Tutamak görev kartındakiyle aynı düğme; görünürlük kuralı kart
   seçicisine bağlı olduğu için burada tekrarlanır. */
@media (hover: hover) {
  .lead-card:hover .task-grip,
  .lead-card:focus-within .task-grip { opacity: 1; }
}
.task-item.is-dragging .lead-card {
  border-color: var(--brand);
  box-shadow: var(--shadow-lg);
}

/* --- 4. Yaklaşan teslim -------------------------------------------------- */

/* Geciken tarih mercan (`.is-alert`), yaklaşan tarih amber. İkisi bilerek
   birbirini dışlar (`Task.is_due_soon`); kart zemini ise yalnız gecikmede
   tonlanır — "yaklaşıyor" bir uyarı değil bir hatırlatmadır. */
.task-due.is-soon { color: var(--warn); font-weight: 600; }

/* --- 5. Bekleme nedeni penceresi ---------------------------------------- */

/* Kart "Bekliyor" sütununa bırakıldığında açılır. Küçük ve tek soruluk:
   nedensiz bekleyen görev sessizce ölür, ama neden sormak da bir formu
   doldurtmak olmamalı. */
.wait-modal {
  width: min(24rem, calc(100vw - 2 * var(--sp-4)));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--text-primary);
  box-shadow: var(--shadow-card);
}
.wait-modal::backdrop { background: rgb(0 0 0 / 0.32); }
.wait-modal-form {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin: 0;
  padding: var(--sp-4);
}
.wait-modal-title { margin: 0; font-size: var(--fs-md); font-weight: 600; }
.wait-modal-list { display: flex; flex-direction: column; gap: var(--sp-1); }
.wait-modal-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.wait-modal-foot { display: flex; justify-content: flex-end; gap: var(--sp-2); }

/* --- 6. Dar ekranda pano ------------------------------------------------- */

/* Tablette iki sütun, telefonda tek. Dört sütunu yatay kaydırmaya
   sıkıştırmak, `.docs/ToDo.md`deki "mobilde masaüstü tablosu küçültülmez"
   kuralının pano hâli olurdu: görünen ama kullanılamayan bir düzen. Tek
   sütuna düşen pano, başlıklarıyla birlikte okunabilir bir yığın olur. */
/* Masaüstü ve tablet: dört sütun **hep dört**, ama sütunun bir alt sınırı
   var (15rem). Pencere daraldığında sütunlar okunamaz hâle gelene kadar
   sıkışmaz; kap kaydırılır. Önceki çözüm 1200 pikselin altında iki sütuna
   düşürüyordu ve o an pano olmaktan çıkıyordu: "Bekliyor" ile "Tamamlandı"
   alt satıra inince akış soldan sağa okunmayı bırakıyordu.

   Kaydırma **kontrollü**: yakalama noktaları sütun başlarında, yani parmak
   bıraktığında pano iki sütun ortasında durmaz. */
@media (min-width: 720px) {
  .kanban {
    grid-template-columns: repeat(4, minmax(15rem, 1fr));
    overflow-x: auto;
    /* Kaydırma çubuğu belirdiğinde pano bir anda daralmasın: oluk hep ayrılı
       durur. Yükleme sırasında (kartlar geldikçe kap kaydırılabilir olur)
       görünen sıçrama tam olarak buydu. */
    scrollbar-gutter: stable;
    scroll-snap-type: x proximity;
    /* Sürükleme sırasında hedef oluğun kesik çerçevesi (`outline-offset: 4px`)
       kabın kenarında kırpılmasın. */
    padding: 4px;
    margin: -4px;
  }
  .kanban-col { scroll-snap-align: start; }
}

/* Telefon: tek sütun ve yatay kaydırma **yok**. Hangi sütunun okunduğuna
   üstteki sekme çubuğu karar verir; seçilmeyen sütunlar hiç çizilmez.
   Sütunları alt alta yığmak da denenebilirdi ama dört başlık + dört boş
   durum cümlesi, üç görevlik bir işte ekranın tamamını doldurup asıl
   içeriği katlanmış gibi gösteriyordu. */
@media (max-width: 719px) {
  .kanban { grid-template-columns: minmax(0, 1fr); }
  .kanban-tabs { display: flex; }
  .kanban-tip { display: flex; }
  .kanban-col { display: none; }
  .kanban:has(#kanban-tab-todo:checked) .kanban-col[data-col="todo"],
  .kanban:has(#kanban-tab-in_progress:checked) .kanban-col[data-col="in_progress"],
  .kanban:has(#kanban-tab-blocked:checked) .kanban-col[data-col="blocked"],
  .kanban:has(#kanban-tab-done:checked) .kanban-col[data-col="done"],
  /* Aday akışının dört basamağı (`company_list.html`, `FLOW_STATUSES`). */
  .kanban:has(#kanban-tab-new:checked) .kanban-col[data-col="new"],
  .kanban:has(#kanban-tab-awaiting_reply:checked) .kanban-col[data-col="awaiting_reply"],
  .kanban:has(#kanban-tab-in_talks:checked) .kanban-col[data-col="in_talks"],
  .kanban:has(#kanban-tab-proposal_sent:checked) .kanban-col[data-col="proposal_sent"] {
    display: flex;
  }
  /* Sütun adı sekmede zaten yazıyor; başlıkta ikinci kez tekrar etmesi
     360 pikselde bir satır israfıydı. Sayı da orada. */
  .kanban-head { display: none; }
  .board-bar { flex-direction: column; align-items: stretch; }
  .board-person select { max-width: none; flex: 1 1 auto; }
  /* Sütun içi ekleme alanı da dokunma hedefi. */
  .kanban-add .input,
  .kanban-add select { min-height: var(--tap); }
}

/* --- 7. Telefon ve dokunmatik ------------------------------------------- */

@media (max-width: 899px) {
  /* Kart tam genişlikte; iç dolgu ve köşe biraz büyür, başlık bir satırda
     kalmayı sürdürür (iki satıra izin vermek yükseklik sözleşmesini
     bozardı — uzun ad panelde tam okunuyor). */
  .task-card {
    min-height: 72px;
    padding: var(--sp-3);
    border-radius: var(--r-lg);
  }
  .task-card.is-sub { margin-left: var(--sp-5); min-height: 56px; }
  .task-card.is-sub::before { left: calc(-1 * var(--sp-4)); }
  /* Telefonda sorumlunun adı yerine yalnız avatarı kalır: 360 pikselde ad,
     tarihi ve önemi kartın dışına itiyordu. */
  .task-who > .truncate { display: none; }
}

@media (pointer: coarse) {
  .task-card { min-height: 76px; }
  /* Tutamak hep açık: dokunmatikte `:hover` diye bir an yok. */
  .task-grip { opacity: 1; }

  .task-group-head { min-height: var(--tap); }
}

/* Faz 34 — mobil görev kartının dokunma hedefleri: 44 px.

   Sorgu iki kanallı (dokunmatik aygıt **veya** mobil kart düzeni).
   Faz 8.5'in "genişliğe değil işaretleme aygıtına bak" kuralı hâlâ doğru
   ama tek başına yetmiyordu: kart düzeni 900 px'in altında çiziliyor ve
   orada fareyle bakıldığında hedefler varsayılanlarına düşüyordu —
   tamamlama 32, tutamak ve üç nokta 34. Aynı düzenin aynı düğmesi yalnız
   hangi aygıtla bakıldığına göre iki farklı boyut alıyordu; ölçen de
   sözleşmenin tutulmadığını görüyordu.

   Sağ uçtaki iki hedef için eski gerekçe ("tutamağı büyütmek üç noktayla
   üst üste bindiriyordu") doğruydu ama yanlış sonuca varıyordu: görünmez
   `::after` çerçeveleriyle büyütülen iki komşu hedef gerçekten çakışır.
   Çözüm çakışmayı yönetmek değil, **görünen kutuyu** büyütmek: yan yana
   iki gerçek kutu üst üste binemez ve `elementFromPoint` ikisini de 44
   okur. Bedeli başlığa kalan ~14 piksel; başlık zaten tek satır ve
   kırpılıyor, tam adı panel veriyor.

   Tamamlama kutusu bunun tersi: **görünen** dairesi 32 kalmalı (bir tik
   kutusunu 44 çizmek kartın sol ucunu şişirirdi) ve yanında büyüyecek bir
   komşu yok — solunda kartın kenarı var. Orada görünmez çerçeve doğru
   araç, çakışacak bir şey yok.

   `--tap` (dokunmatikte 48) değil düz 44: 48+48 sağ ucu 100 piksele
   çıkarıp 360 px'lik ekranda başlığı okunmaz yapıyor, soldaki 48'lik
   çerçeve de başlığın tıklama katmanına 8 piksel taşıyordu. 44 sözleşmenin
   kendisi, 48 onun rahat hâli. */
@media (max-width: 899px), (pointer: coarse) {
  .task-card-tools .task-grip,
  .task-card-tools .row-btn {
    width: 44px;
    height: 44px;
  }
  /* Kutular zaten 44 olduğu için görünmez büyütme yalnız zarar verir:
     `.row-btn::after` (-7 px) yanındaki tutamağın üstüne taşardı. */
  .task-card-tools .row-btn::after { content: none; }

  /* Tamamlama: görünen daire 32, dokunulan alan 44. `.task-card-check`
     zaten `position: relative; z-index: 1` — çerçeve başlığın kartı
     kaplayan tıklama katmanının (`.task-card-title::after`) üstünde kalır,
     yoksa kutunun kıyısına dokunmak görevi açardı. */
  .task-card-check .task-check { position: relative; }
  .task-card-check .task-check::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* ==========================================================================
   Durum şeridi — "İşlerin durumu" (Faz 31)

   Listenin üstünde tek satır: beş durum, her biri nokta + ad + sayı; sağda
   üç kısayol (Geciken · Bu hafta bitecek · Sorumlusu olmayan).

   Neden kart değil şerit: aynı bilgiyi beş istatistik kartıyla vermek
   ekranın ilk 120 pikselini yiyordu ve liste ekranının asıl vaadi liste.
   Ölçü sözleşmesi tek cümle: **şerit bir satır yüksekliğindedir** (~34 px)
   ve içindeki hiçbir öğe kendi zeminini boyamaz. Renk yalnız noktadadır —
   nokta sözlüğü `.status-*` kurallarından gelir, burada yeniden yazılmaz;
   yazılsaydı aynı durum listede ve şeritte iki farklı renk alabilirdi.

   Seçili basamak dolgu değil **çerçeve** alır. İki kanal ayrı tutuluyor:
   renk durumun (nokta), çerçeve kullanıcının seçiminin. Seçimi de renkle
   anlatsaydık şeritte iki ayrı şey aynı dili konuşurdu — hangi basamağın
   renkli olduğu "hangi durum" mu "hangi seçim" mi belirsiz kalırdı.
   ========================================================================== */

.status-strip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  margin-bottom: var(--sp-4);
  min-width: 0;
}
.status-strip-items {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  flex-wrap: wrap;
  gap: var(--sp-1);
  min-width: 0;
}
.status-strip-label {
  margin-right: var(--sp-1);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  white-space: nowrap;
}
.status-strip-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 1px var(--sp-2);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: var(--text);
  text-decoration: none;
}
/* Sayı, durumun adından bir tık geride: satırda önce "hangi durum" okunur,
   sonra "kaç tane". Sekmeli rakam (`base.css`) sayıların aynı genişlikte
   kalmasını sağlıyor — şerit, sayaç değiştikçe yatay oynamıyor. */
.status-strip-item .count {
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.status-strip-item:hover,
.status-strip-item:focus-visible { border-color: var(--border); }
.status-strip-item.is-active {
  border-color: var(--border-strong);
  background: var(--surface-soft);
}
.status-strip-item.is-active .count { color: var(--text); }

/* Kısayollar düz metin bağlantısıdır: üçü de listeyi daraltır ama bir
   *durum* değildir, o yüzden noktaları ve sayıları yoktur. Seçiliyken
   şeridin sol yarısıyla aynı dili konuşur (çerçeve + hafif zemin). */
.status-strip-quick {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  flex-wrap: wrap;
  gap: var(--sp-1);
}
.strip-link {
  padding: 1px var(--sp-2);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  text-decoration: none;
  white-space: nowrap;
}
.strip-link:hover,
.strip-link:focus-visible { border-color: var(--border); color: var(--text); }
.strip-link.is-active {
  border-color: var(--border-strong);
  background: var(--surface-soft);
  color: var(--text);
}

/* Telefonda şerit sarmalanmaz, **kaydırılır**: beş durum + üç kısayol dar
   ekranda üç sıraya yayılıp listeyi aşağı itiyordu — etkin süzgeç satırında
   çözülen sorunun aynısı, aynı çözümle. */
/* Ölçü notu (1440 px, kenar çubuğu açık): şerit tam 1176 pikselin 835'ini
   basamaklara, 325'ini kısayollara veriyor — tek satır. 1280 pikselde
   kısayollar kendi satırına iniyor (30 px → 62 px). Başlığı orada gizleyip
   tek satırı zorlamak denendi ve **geri alındı**: kazanılan 110 piksel
   yetmiyor (eksik ~50 px daha var), yani şerit yine iki satır oluyor ve
   üstüne bir de adını kaybediyordu. İki sıra dar masaüstünde kabul; asıl
   kısıt "listeden önce kaç piksel" ve 62 px hâlâ tek bir kart satırının
   altında. */

/* Telefonda başlık düşer: orada şerit yatay kayıyor ve satırın önündeki
   sabit metin, kaydırılacak yerin üçte birini yiyordu. */
@media (max-width: 899px) {
  .status-strip-label { display: none; }
}

@media (max-width: 719px) {
  .status-strip {
    flex-wrap: nowrap;
    gap: var(--sp-3);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .status-strip::-webkit-scrollbar { display: none; }
  /* İki grup da **doğal genişliğinde** kalır. `flex: 1 1 auto` telefonda
     tam tersini yapıyordu: kısayol bloğu esnemediği için basamaklar 21
     piksele eziliyor, şerit "beş durum" yerine tek bir kırpılmış nokta
     gösteriyordu (ölçüm: itemsEn 21 px, içerik 593 px). Kaydırma kabı
     şeridin kendisi; içindekilerin büzülmesi gerekmiyor. */
  .status-strip-items,
  .status-strip-quick {
    flex: 0 0 auto;
    flex-wrap: nowrap;
  }
}

/* Dokunmatikte her basamak bir hedeftir. */
@media (pointer: coarse) {
  .status-strip-item,
  .strip-link { min-height: 32px; }
}

/* ===========================================================================
   İş künyesi bandı, takipçiler ve durum yardımı — Faz 32
   =========================================================================== */

/* İki bant art arda geldiğinde (durum/takipçi + ilerleme) künyeyle birlikte
   **tek yüzey** olurlar: aradaki yuvarlak köşe ve boşluk, ikisini iki ayrı
   kutu gibi okutuyordu. */
.rec-band:has(+ .rec-band) {
  margin-bottom: 0;
  border-radius: 0;
  border-bottom: 0;
}

.job-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3) var(--sp-6);
}
.job-band-group {
  display: flex;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  min-width: 0;
}
/* Takipçi grubu sağa yaslı: sol uç işin **durumu** (bu ekranın kararı), sağ
   uç kimin izlediği (bu ekranın çevresi). Ortada tek bir boşluk var, iki
   grup birbirine karışmıyor. */
.job-band-group + .job-band-group { margin-left: auto; }
.job-band-label {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
.job-band-body {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
.job-status-form {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

/* Takipçi avatarları bindirmeli: üç yüz yan yana 90 pikselken, bindirmeli
   dizide 56 piksel. Bant tek satırda kalmalı. */
.rec-watchers {
  display: inline-flex;
  align-items: center;
}
.rec-watchers > .avatar + .avatar {
  margin-left: -6px;
  box-shadow: 0 0 0 2px var(--surface-soft);
}

/* "Takip et" künyedeki diğer eylemlerle aynı hizada durur; açıkken düğme
   **dolmaz**, yalnız mürekkebi koyulaşır: takip etmek birincil bir eylem
   değil, bir tercihtir (§1 — renk dar payda iş yapar). */
.rec-watch-form { display: inline-flex; }
.rec-watch-form .btn.is-on { color: var(--text); }

/* --- Durum yardımı (bilgi simgesi + kapalı panel) ------------------------ */

.hint {
  position: relative;
  display: inline-flex;
}
.hint-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-pill, 999px);
  color: var(--text-muted);
  cursor: pointer;
  list-style: none;
}
.hint-toggle::-webkit-details-marker { display: none; }

/* Dokunmatikte 28 px'lik soru işareti nişan alınamıyordu (§7). Kutunun
   kendisi büyümüyor, yalnız dokunma alanı: görsel ölçü 28 px kalır,
   `::after` ile şeffaf bir hedef serilir. Kutuyu 48'e çıkarmak, yanındaki
   başlığı ikinci satıra itiyordu. */
@media (pointer: coarse) {
  .hint-toggle { position: relative; }
  .hint-toggle::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--tap);
    height: var(--tap);
    transform: translate(-50%, -50%);
  }
}
.hint-toggle:hover,
.hint[open] > .hint-toggle {
  background: var(--surface-sunken, var(--surface-soft));
  color: var(--text);
}
.hint-toggle:focus-visible {
  outline: 2px solid var(--focus, var(--accent));
  outline-offset: 2px;
}

/* Masaüstü: simgenin altına açılan küçük kutu. */
.hint-panel {
  position: absolute;
  z-index: 40;
  top: calc(100% + var(--sp-2));
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: min(340px, calc(100vw - var(--sp-6)));
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}
.hint-head {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.hint-list { margin: 0; }
.hint-row {
  display: grid;
  grid-template-columns: minmax(96px, auto) 1fr;
  gap: var(--sp-1) var(--sp-3);
  align-items: baseline;
  font-size: var(--fs-sm);
}
.hint-row + .hint-row { margin-top: var(--sp-2); }
.hint-term { margin: 0; }
.hint-desc {
  margin: 0;
  color: var(--text-secondary, var(--text-muted));
}

/* Telefon: alt panel. Açılır kutu 360 pikselde dokunulan simgenin üstünü
   örtüyor ve sayfayı yatay kaydırıyordu; alt panel parmağın geldiği yerde
   durur ve genişliği ekranın kendisidir. */
@media (max-width: 720px) {
  .hint-panel {
    position: fixed;
    top: auto;
    bottom: 0;
    left: 0;
    transform: none;
    width: 100%;
    max-width: none;
    padding: var(--sp-4) var(--sp-4) var(--sp-6);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: var(--shadow-lg);
  }
  .job-band-group + .job-band-group { margin-left: 0; }
}

/* ==========================================================================
   İstatistikler (Faz 41) — `main/insights.html`
   ==========================================================================
   Panonun ızgarası ve kartları olduğu gibi; burada yalnız kolon payları ve
   tabloların sayısal sütunları var. Kolon ölçüsü panonunkiyle aynı (8 + 4):
   tablo geniş sütunda, "neden" listeleri dar sütunda. Sabit boy yok —
   panodaki kartların boyu "ilk ekran" için sınırlıydı, bu sayfa okunmak
   için kaydırılır. */
@media (min-width: 1000px) {
  .insights .insight-owners,
  .insights .insight-dwell { grid-column: span 8; }
  .insights .insight-reasons,
  .insights .insight-overdue { grid-column: span 4; }
}

/* Tanım cümlesi şeridin hemen altında, kart değil metin: bir ölçünün
   tanımı ölçünün yanında durur, ayrı bir yardım sayfasında değil. */
.insights .insight-note {
  margin: 0;
  max-width: 72ch;
}
.insights .dash-card-body .insight-note {
  padding: var(--sp-3) var(--sp-4) var(--sp-4);
}

/* Sayısal sütunlar sağa yaslı: "hangisi büyük" tek göz gezdirmeyle
   okunsun (sayaç şeridindeki gerekçenin aynısı). */
.insight-table th.num,
.insight-table td.num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.insight-table tbody tr.is-muted td { color: var(--text-secondary); }

/* Oran hücresi: küçük bir çubuk + yüzde. Çubuk sayıyı tekrar etmiyor,
   satırlar arasında hizayı sağlıyor — on satırlık tabloda göz yüzdeleri
   okumadan sırayı görüyor. */
.insight-rate {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.insight-rate .progress { width: 56px; flex: 0 0 auto; }

/* Neden listesi: huni satırıyla aynı düzen ve aynı gerekçe (`.dash-funnel
   .list-row-main`): ad kolonu sabit ki çubuklar ortak sıfırdan başlasın.
   152 px en uzun nedene göre ("Zamanlama uygun değil"). */
.insight-reasons .list-row-main {
  display: grid;
  grid-template-columns: 152px minmax(0, 1fr);
  align-items: center;
  gap: var(--sp-3);
}
.insight-reasons .list-row-title { min-width: 0; }
.insight-reasons .progress { min-width: 32px; }
.insight-reasons .list-row-aside { display: inline-flex; gap: var(--sp-2); align-items: baseline; }

.text-accent { color: var(--accent); }

/* Kart başlığındaki eksen seçici: başlık satırının boyunu büyütmesin. */
.dash-card-head .seg-sm .seg-btn { padding: 2px var(--sp-2); font-size: var(--fs-xs); }

/* Telefonda sıra belge sırasıdır: tarih süzgeci → dört özet kartı →
   açıklama → kişi tablosu → olumsuzluk nedeni → basamakta bekleme →
   geciken takipler. Pano `.dash-stats`i beşinci sıraya iter (orada odak ve
   bugün kartları önce gelir); istatistikte sayılar ilk sorudur, o miras
   burada sıfırlanır. */
@media (max-width: 999px) {
  .insights .dash-stats { order: 0; }
}

/* Geniş tablolar kartı ve sayfayı genişletmesin: ızgara hücresi ve kart
   `min-width: 0` alır, tablo kendi sarmalayıcısında (`.table-wrap`) yatay
   kayar. `.dash-card-body` dikey kaydırma için `overflow-y: auto`
   taşıyor; yatayda taşan şey sarmalayıcıda kalır. */
.insights .dash-card,
.insights .dash-card-body { min-width: 0; }
.insights .dash-card-body { overflow-x: hidden; }
.insights .table-wrap { max-width: 100%; }

/* 360–390 piksel: neden satırında 152 piksellik sabit başlık sütunu
   çubuğu ezip iki basamaklı sayıyı sıkıştırıyordu; başlık ve çubuk alt
   alta iner. */
@media (max-width: 479px) {
  .insight-reasons .list-row-main { grid-template-columns: minmax(0, 1fr); gap: var(--sp-1); }
  /* Kişi ekseni seçici (Sorumlu / Ekleyen) başlığın altına iner; 360'ta
     başlıkla yan yana sığmıyor ve başlık üç harfe kırpılıyordu. */
  .insights .insight-owners .dash-card-head { flex-wrap: wrap; }
  .insights .insight-owners .dash-card-head .seg-sm { flex: 1 1 100%; }
}

/* --- Rol tablosu (Faz 43) ----------------------------------------------

   "Hangi rol neyi yapabilir" karşılaştırması (`main/_role_matrix.html`).
   Üç yerde çizilir: ekip sayfası (kart altı), davet çekmecesi ve üye paneli
   (rol kartlarının altı). Çekmece 480 px'tir; beş sütunun oraya sığması
   için hücre dolgusu ve satır yüksekliği `.table`ın varsayılanından
   sıkıdır — bu bir veri listesi değil, tek bakışta taranan bir referans.
   Sütun başlıkları `.table th`ın büyük harfi ve gölgesi ile aynı dilde,
   satır başlığı (`th[scope=row]`) ise düz metin: sol sütun bir etiket
   listesi, ikinci bir başlık şeridi değil. */
.rol-matrisi .table-wrap { border: 1px solid var(--border-soft); border-radius: var(--r-sm); }
.rol-matrisi-tablo { font-size: var(--fs-sm); }
.rol-matrisi-tablo th,
.rol-matrisi-tablo td { padding: var(--sp-2) var(--sp-3); }
.rol-matrisi-tablo tbody tr { height: auto; }
.rol-matrisi-tablo tbody th {
  text-transform: none;
  letter-spacing: 0;
  font-size: inherit;
  font-weight: 400;
  color: var(--text);
  background: transparent;
  white-space: normal;
  border-bottom: 1px solid var(--border-soft);
}
.rol-matrisi-tablo tbody tr:last-child th { border-bottom: 0; }
/* Sütun başlıkları kartın yapışkan başlığını devralmasın: tablo bir
   `<details>` içinde, kaydırma bağlamı kendi kutusudur. */
.card .rol-matrisi-tablo thead th { position: static; }
.rol-matrisi-tablo thead th.text-center { white-space: normal; min-width: 72px; }
/* "Evet" onay yeşil, "hayır" tire soluk: hücreyi okumak yerine tarayınca
   yeşilin sağa doğru artması rol sırasını da anlatıyor. */
.rol-hucre.is-evet .icon { color: var(--state-done-ink); }
.rol-hucre.is-anahtar .icon { color: var(--text-secondary); }
.rol-hucre.is-kendi { color: var(--text-secondary); white-space: nowrap; }
/* Dipnotlar akan metin, flex değil: `<strong>` ayrı bir flex öğesi olunca
   telefonda "kendi kaydı:" tek başına bir sütuna düşüyordu. */
.rol-matrisi-notlar { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.rol-matrisi-notlar li { display: block; }
.rol-matrisi-notlar .icon { vertical-align: -2px; margin-right: var(--sp-1); }
.rol-matrisi-gorunurluk .detail-row { grid-template-columns: 180px minmax(0, 1fr); }
@media (max-width: 639px) {
  /* Telefonda tablo yatay kayar (`.table-wrap`); sol sütun dar kolona
     sıkışıp dört satıra kırılmasın diye alt sınırı var — "Süreci yürütme:
     durum değiştirme…" yedi satıra bölününce tablo taranamıyordu. */
  .rol-matrisi-tablo tbody th { min-width: 200px; }
  .rol-matrisi-tablo thead th.text-center { white-space: nowrap; }
  .rol-matrisi-gorunurluk .detail-row { grid-template-columns: 1fr; gap: 0; }
}


/* ==========================================================================
   Firma ayrıntısı — iki kolon (`.rec-split`)
   --------------------------------------------------------------------------
   Masaüstünde sayfa ikiye bölünür: solda **akan** şeyler (aktivite, işler,
   görevler — sekmeli), sağda **özet** (durum + sonraki takip formu, iletişim
   bilgileri, süreç/firma künyesi, kişiler). Eskiden üçü de sekmeydi ve
   kullanıcı telefon numarasına bakmak için akıştan çıkıp "Bilgiler"e
   gidiyordu; şimdi özet her sekmede yanında durur.

   Oran ~66/34: sağ kolon `minmax(300px, 34%)`. 300 piksel, "Sonraki takip"
   satırının tarih + yakın-tarih parantezini tek satırda taşıyabildiği en
   dar ölçü. Sol kolon `minmax(0, 1fr)` — `0` şart, yoksa uzun bir görev
   başlığı ızgara hücresini genişletip sağ kolonu ekran dışına itiyor.

   Sağ kolon **yapışkan**: sayfa kaydırılırken özet yerinde kalır. Boyu
   pencereye kırpılır ve kendi içinde kaydırılır; yoksa uzun bir rehber
   (çok kişili firma) yapışkan kolonun altını erişilmez bırakırdı. İçindeki
   açılır paneller (durum seçici, tarih) `position: fixed` çalıştığı için
   kırpma onları kesmez.

   Telefonda (899 px ve altı) üç kap da `display: contents`: çocuklar
   doğrudan `.rec-page` sütununa akar ve sayfa Faz 20'deki tek kolonlu
   hâliyle birebir aynı kalır — hızlı güncelleme en üstte (`order: -1`),
   ardından sekmeler, ardından seçili sekmenin içeriği. "Bilgiler" telefonda
   sekme olarak yaşamaya devam eder; masaüstünde sekme gizlenir (içeriği
   zaten sağda) ve ilk sekme "İşler ve görevler" olur.

   İş ayrıntısı ve görev ayrıntısı bu sınıfı **kullanmaz**; iş panosu
   (Kanban) tam genişlikte kalır.
   ========================================================================== */
.rec-split,
.rec-split-main,
.rec-split-side { display: contents; }
/* Kolonların içindeki iki sarmal (sol liste, sağ bilgi) gerçek kutu: biri
   `hide-mobile` taşıyabiliyor ve `display: none` ancak bir kutuya işler.
   Aralık `.rec-page` ile aynı (sp-4), ritim kolon içinde de bozulmaz. */
.rec-split-list,
.rec-split-info { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }

@media (max-width: 899px) {
  .rec-split-notice { order: -2; }
  .rec-split-quick { order: -1; }
}

@media (min-width: 900px) {
  .rec-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(300px, 34%);
    gap: var(--sp-5);
    align-items: start;
  }
  .rec-split-main,
  .rec-split-side {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    min-width: 0;
  }
  .rec-split-side {
    position: sticky;
    top: calc(var(--topbar-h) + var(--sp-4));
    max-height: calc(100vh - var(--topbar-h) - var(--sp-4) * 2);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    /* Kaydırma çubuğu içeriğe yapışmasın; sağdaki pay ızgara boşluğundan
       düşülür ki kolonun dış ölçüsü değişmesin. */
    padding-right: var(--sp-1);
    margin-right: calc(-1 * var(--sp-1));
  }
  /* Masaüstünde "Bilgiler" sekmesi yok (`hide-desktop`): içeriği sağ kolonda.
     Sekme URL'si `bilgiler` iken sol kolon "İşler ve görevler"i gösterir;
     etkin çizgi de onun altında olmalı. Sınıf `is-active` ile aynı görünüm,
     yalnız bu genişlikte anlamlı. */
  .rec-split .tab-link.is-active-desktop {
    color: var(--text-primary);
    font-weight: var(--fw-bold);
    border-bottom-color: var(--brand);
  }
  .rec-split .tab-link.is-active-desktop .count { color: var(--text-secondary); }

  /* --- Sağ kolonun içi: dar genişliğe göre yeniden dizilir --- */

  /* Hızlı güncelleme: yatay şerit dikey yığına döner. Alanlar tam genişlik,
     düğme altta sola; `.rec-quick .field { max-width: 280px }` tavanı
     kolonun kendisi zaten dar olduğu için kalkar. */
  .rec-split-side .rec-quick { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .rec-split-side .rec-quick > .rec-strip-form {
    flex: 0 0 auto;
    flex-direction: column;
    align-items: stretch;
    max-width: none;
  }
  /* `flex: 1 1 160px` yatay şerit içindi; sütun yönünde 160 piksel **boy**
     olur ve her alanın altında koca bir boşluk açılır. */
  .rec-split-side .rec-quick .field { flex: 0 0 auto; max-width: none; }
  .rec-split-side .rec-quick > .rec-strip-form > .btn { align-self: flex-start; }
  .rec-split-side .rec-quick .quick-saved { align-self: flex-start; }
  .rec-split-side .rec-quick > .revert-block { flex: 1 1 auto; margin-left: 0; }
  .rec-split-side .rec-quick > .revert-block[open] { border-top: 1px solid var(--border); padding-top: var(--sp-3); }

  /* Bilgi grupları tek kolon: iki kolonlu paketleme (`columns: 2`) geniş
     sayfa içindi; 300–420 piksellik kolonda her grup tam genişlik alır. */
  .rec-split-side .info-grid { columns: 1; }
  .rec-split-side .info-grid > .info-group { margin-bottom: var(--sp-5); }
  .rec-split-side .info-grid > .info-group:last-child { margin-bottom: 0; }

  /* Rehber başlığında "Kişi ekle" ikon + etiketle dar kolona sığar; başlık
     sarınca düğme ikinci satıra düşüyordu. */
  .rec-split-side .person-summary { flex-wrap: wrap; }
}
