/* ============================================================
 * features/chat.css — sohbet ekranı (balonlar + canlı gösterge + girdi)
 * (JS karşılığı: js/features/chat/)
 * Kimlik her balonun yanındaki avatar'da, canlı SSE durumu göstergede
 * (.live-ind). Eski METİN başlığı 2026-07-12'de silindi; 2026-07-13'te
 * yerine bar pill'inin tepedeki EŞİ geldi (.chat-headzone: geri[mobil]
 * + avatar + hafıza-temizle + karakter adı, içerik kadar geniş — aşağıda).
 * ============================================================ */

/* ── ORTAK DEĞİŞKENLER — chat ekranının TEK kontrol noktası ────
   TEK-SINIF + ORTAK VAR mimarisi (kullanıcı 2026-07-15, PROJE KURALI):
   her öğe TEK spesifik sınıf taşır; o öğeyle ilgili TÜM CSS o sınıfın
   bloğunda yaşar; ortaklık ORTAK SINIFLA DEĞİL buradaki var'larla
   sağlanır ("cb-pill ch-pill ch-pill--nav" tarzı sınıf yığması YASAK —
   birine müdahale hepsine dokunuyordu). Reçeteyi değiştirmek = bu blok;
   bir öğeyi değiştirmek = yalnız kendi bloğu. :root'ta: composer
   harness'te de (#view-chat'siz) aynı kaynaktan çalışır. */
:root {
  --chat-circle: var(--circle-xl);  /* TEK daire boyu (avatar/buton/ikon dairesi) */
  --chat-chip-gap: 6px;       /* canlı gösterge daireleri arası boşluk */
  --chat-row-gap: 6px;        /* pill içi öğe aralığı */
  /* pill kapsül reçetesi — SABİT 32px, r-full DEĞİL: 999→32 radius
     geçişi chip satırı açılınca son karede oturuyordu (2026-07-12) */
  --chat-pill-r: 32px;
  --chat-pill-bg: var(--surface-3);                     /* pill cam zemini (ortak seçim) */
  --chat-pill-blur: var(--glass-blur);                  /* pill buzlu camı */
}

/* ── Sohbet değişiminde soft geçiş (chat/index.js open()) ─────
   .chat-veil eklenince YALNIZ mesaj akışı söner (150ms), yeni sohbet
   gizliyken render edilip görünür medya hazır olunca sınıf kalkar →
   YAVAŞ aydınlanma (450ms). Header/bar pill'leri fade katmanının
   DIŞINDA — anında boyanırlar (kullanıcı 2026-07-15: "pill
   arkaplanları sonradan yükleniyor"; opacity animasyonlu atanın
   altındaki backdrop-filter geçiş bitene dek çizilmiyordu). */
#view-chat { position: relative; }
#view-chat .chat-msgs { transition: opacity 450ms cubic-bezier(.4, 0, .2, 1); }
#view-chat.chat-veil { pointer-events: none; }
#view-chat.chat-veil .chat-msgs { opacity: 0; transition-duration: 150ms; }

/* Veil bekleme nabzı (kullanıcı 2026-07-12): yükleme uzarsa ekran kör
   karanlık kalmasın — .main ortasında SİLİK menekşe halka. Spinner
   view'İN İÇİNE konamaz (veil = tüm view'da opacity:0, çocuğu da
   söndürür) → :has ile kardeş katmandan çizilir; :has'siz eski
   tarayıcıda hiçbir şey görünmez = bugünkü davranış, kırılma yok.
   0.45s gecikme: hızlı geçişlerde hiç belirmez, flaş olmaz. */
.main:has(> #view-chat.active.chat-veil)::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 28px; height: 28px; margin: -14px 0 0 -14px;
  border-radius: 50%; pointer-events: none; z-index: 7;
  border: 2px solid var(--accent-soft);
  border-top-color: rgba(var(--accent-bright-rgb), .55);
  opacity: 0;
  animation: veil-spin .85s linear infinite, veil-in .4s ease .45s forwards;
}
@keyframes veil-spin { to { transform: rotate(1turn); } }
@keyframes veil-in { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .main:has(> #view-chat.active.chat-veil)::after { animation: veil-in .4s ease .45s forwards; }
}

/* ── Üst/alt gölge perdesi (scrim) — yüzen pill'ler zeminden
   ayrışsın, mesajlar ekran kenarında yumuşak sönsün diye kenardan
   ortaya kararma. z=4: msgs üstü, header/bar (z=6) altı; tıklamayı
   yutmaz. Kullanıcı 2026-07-14: koyu renk %80'e koyulaştı.
   Kullanıcı 2026-07-18: perde YALNIZ MOBİL (07-14'teki "hem PC hem
   mobil" kararı tersine döndü) + 130→220px ve EASED çok-duraklı
   gradyan: düz iki-duraklı gradyanın bitiş çizgisi gözle seçiliyordu
   ("geçiş çok hissediliyor") — duraklar ease-out eğrisinde, perde
   ortalara doğru homojen açılır, sert kenar yok. color-mix yüzdesi
   --chat-scrim'in kendi alfasını çarpar (tek reçete). */
#view-chat { --chat-scrim: rgb(0 0 0 / 80%); }
@media (max-width: 860px) {
  #view-chat::before, #view-chat::after {
    content: ""; position: absolute; left: 0; right: 0; z-index: 4;
    height: 220px; pointer-events: none;
  }
  #view-chat::before {
    top: 0;
    background: linear-gradient(to bottom,
      var(--chat-scrim) 0,
      color-mix(in srgb, var(--chat-scrim) 87%, transparent) 10%,
      color-mix(in srgb, var(--chat-scrim) 70%, transparent) 22%,
      color-mix(in srgb, var(--chat-scrim) 52%, transparent) 34%,
      color-mix(in srgb, var(--chat-scrim) 36%, transparent) 46%,
      color-mix(in srgb, var(--chat-scrim) 22%, transparent) 58%,
      color-mix(in srgb, var(--chat-scrim) 12%, transparent) 70%,
      color-mix(in srgb, var(--chat-scrim) 5%, transparent) 82%,
      color-mix(in srgb, var(--chat-scrim) 1.5%, transparent) 91%,
      transparent 100%);
  }
  #view-chat::after {
    bottom: 0;
    background: linear-gradient(to top,
      var(--chat-scrim) 0,
      color-mix(in srgb, var(--chat-scrim) 87%, transparent) 10%,
      color-mix(in srgb, var(--chat-scrim) 70%, transparent) 22%,
      color-mix(in srgb, var(--chat-scrim) 52%, transparent) 34%,
      color-mix(in srgb, var(--chat-scrim) 36%, transparent) 46%,
      color-mix(in srgb, var(--chat-scrim) 22%, transparent) 58%,
      color-mix(in srgb, var(--chat-scrim) 12%, transparent) 70%,
      color-mix(in srgb, var(--chat-scrim) 5%, transparent) 82%,
      color-mix(in srgb, var(--chat-scrim) 1.5%, transparent) 91%,
      transparent 100%);
  }
}

/* ── CHAT HEADER (2026-07-13, v3) — İKİ pill, iki uca yaslı:
   SOLDA gezinme (geri[yalnız mobil] + kırmızı hafıza-temizle),
   SAĞDA kimlik (avatar 48px + karakter ADI ellipsis'li — uzun ad
   pill'i BÜYÜTMEZ, görsel taşma yok). Pill'ler bar pill'inin tepedeki
   eşleri, İÇERİK KADAR geniş. Aradaki boşluk tıklamayı YUTMAZ
   (headzone pointer-events:none, pill'ler auto). */
.chat-headzone {
  position: absolute; left: 12px; right: 12px;
  top: calc(16px + var(--safe-top));    /* barzone'un ayna simetriği */
  z-index: 6;
  display: flex; justify-content: space-between;
  /* center: soldaki çıplak daireler (.ch-nav) sağdaki kimlik pill'inin
     8px kapsül padding'i kadar YUKARIDA kalıyordu — daire merkezleri
     avatarın merkeziyle aynı hizada olacak (kullanıcı 2026-07-20) */
  align-items: center; gap: 10px;
  pointer-events: none;
}
/* ── SOL: GEZİNME KABI (.ch-nav) — CAM KAPSÜL (kullanıcı 2026-07-25):
   eski "görünmez kap, daireler kendi camıyla yüzer" düzeni bitti;
   ch-nav artık .ch-id / .nsp-pill ile AYNI mimari: TEK dış cam
   kapsül (reçete --chat-pill-*), içindeki daireler ZEMİNSİZ ikon
   butonları (dış cam katman doktrini — iç öğeye arkaplan verme, yalnız
   hover durumu). Böylece iki uçtaki (.ch-nav / .ch-id) ve bardaki
   (.nsp-pill) kapsüller görünüş + mimari olarak eş.
   8px padding = kapsül çerçevesi: daire merkezi .ch-id / .nsp-pill
   dairelerinin merkeziyle AYNI hizada. */
/* 2026-07-16: görevsiz .ch-nav-row ara katmanı öldü — kap flex
   satırının kendisi (CSS_GOLDEN_RULE.md K6). */
.ch-nav {
  width: fit-content; max-width: 100%; pointer-events: auto;
  display: flex; align-items: center; gap: var(--chat-row-gap);
  padding: 8px;
  border-radius: var(--chat-pill-r);
  background: var(--chat-pill-bg);
  backdrop-filter: var(--chat-pill-blur); -webkit-backdrop-filter: var(--chat-pill-blur);
}

/* geri (yalnız mobil — masaüstü kuralı media bloğunda); zeminsiz ikon
   butonu, kapsülün camı üstünde durur — hover'da hafif zemin belirir */
.ch-back {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  background: transparent; color: var(--text-2);
  transition: background var(--tr-fast), color var(--tr-fast), filter var(--tr-fast);
}
.ch-back:hover { background: var(--surface-3); color: var(--text); }

/* hafıza temizle — kırmızı ikon; zeminsiz, hover'da kırmızı cam zemin */
.ch-reset {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  background: transparent; color: var(--danger);
  transition: background var(--tr-fast), color var(--tr-fast), filter var(--tr-fast);
}
.ch-reset:hover { background: var(--danger-soft); color: var(--danger); }

/* ── SAĞ: KİMLİK PILL'İ (.ch-id) — cam kapsül: avatar + ad ──
   4px padding = kapsül çerçevesi; gölge aynı gün silindi — pill'ler
   gölgesiz düz cam (kullanıcı 2026-07-16). */
/* 2026-07-16: görevsiz .ch-id-row ara katmanı öldü — kapsül flex
   satırının kendisi (CSS_GOLDEN_RULE.md K6). */
.ch-id {
  width: fit-content; max-width: 100%; pointer-events: auto;
  min-width: 0; flex-shrink: 1;    /* ad ellipsis'i flex içinde de çalışsın */
  display: flex; align-items: center; gap: var(--chat-row-gap);
  padding: 8px;
  border-radius: var(--chat-pill-r);
  background: var(--chat-pill-bg);
  backdrop-filter: var(--chat-pill-blur); -webkit-backdrop-filter: var(--chat-pill-blur);
}
/* header avatarı — tek-sınıf: .avatar primitifinden 2026-07-16'da
   bağımsızlaştı (reçetesi burada; foto çemberi mutlak doldurur —
   grid/intrinsic boyut oyunlarına kapalı, tam ortalı kırpım) */
.ch-av {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center; overflow: hidden;
  background: var(--surface-3); color: var(--text-2);
  font-weight: 700; font-size: 15px; user-select: none;
  cursor: pointer;
}
.ch-av img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; max-width: none;
  object-fit: cover; object-position: center;
  border-radius: inherit;
}
.ch-av:hover { filter: brightness(1.1); }
/* karakter adı — SINIRLI genişlik + ellipsis (uzun ad taşmaz/pill'i
   şişirmez); kırpılınca tamamı title tooltip'inde (chat/index.js) */
.ch-name {
  max-width: min(46vw, 240px);
  padding: 0 12px 0 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 14.5px; font-weight: 650; letter-spacing: -.01em;
  color: var(--text);
}
/* .btn-back sohbette artık yok ama astro detayının geri tuşu bu
   reçeteyi paylaşır (astro/detail.js) — SİLME. */
.btn-back { display: none; }

.chat-msgs {
  flex: 1; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
  /* Kök kilidi terfi kırıcısı — mekanizmanın anlatısı token'ın başında
     (tokens.css --rootlock-inset): ICB'yi TAM dolduran scroller kök
     scroller'a terfi edip URL bar'ını oynatır; bu pay doluluğu bozar.
     Üst scrim'in (110px) altında görünmez. SİLME! (Kabuk sekmelerinde
     aynı payı .side-pages yer — shell.css mobil.) */
  margin-top: var(--rootlock-inset);
  /* Üstte header pill'i, altta yüzen bar (ikisi de 64px + boşluk) —
     ilk/son balon cam altında BAŞLAMASIN, kaydırınca altından geçsin
     diye iki uçta SİMETRİK 100px pay (kullanıcı 2026-07-13: "alttaki
     boşluğun aynısını üste de ekle"). Statik --safe-bottom/--safe-top:
     canlı env scroll sırasında scrollHeight'ı oynatıp mesajları
     zıplatabiliyordu (2026-07-12). */
  padding: calc(100px + var(--safe-top)) 16px calc(100px + var(--safe-bottom));
  /* 3px → 8px: aynı yazarın ardışık balonları birleşik görünüyordu
     (kullanıcı 2026-07-12) */
  display: flex; flex-direction: column; gap: 8px;
  /* Scrollbar GİZLİ (kullanıcı 2026-07-15): kaydırma çalışır, çubuk
     çizilmez — sağ kenardaki "şey" ve alttaki yatay eşi de gitti
     (overflow-x:hidden yukarıda: taşan dalga çubukları bar üretmesin). */
  scrollbar-width: none;
}
.chat-msgs::-webkit-scrollbar { width: 0; height: 0; }
/* Yükleme spinner'ı ve boş-durum kartı kutuda ortalanır (pill payları
   padding'de olduğundan margin:auto görünür alanın ortasına oturur) */
.chat-loading { align-self: center; margin: auto; }
.chat-msgs .empty { margin: auto; }
/* Yazar değişince grup arası ekstra nefes (ts araya girmişse onun
   alt marjı zaten ayırıyor — bu seçiciler ts'siz iyimser balonlar
   ve çoklu-balon RP akışı için; canlı gösterge de bir --bot satırı) */
.msg-row--user + .msg-row--bot,
.msg-row--bot + .msg-row--user { margin-top: 8px; }

/* ── Balon satırı: her balonun yanında yazar pp'si (başlık silindi
   2026-07-12 — kimlik balonun kendisinde). Avatar boyu = --chat-circle
   (chat ekranının TEK daire boyu; kullanıcı 2026-07-15 simetri
   kararı); satır yapısı balon ARALARINA
   ek boşluk koymaz (dikey ritim .chat-msgs gap'inde).
   Kullanıcı satırı aynanın karşısı: avatar sağda. ── */
.msg-row {
  display: flex; align-items: flex-start; gap: 8px;
  /* balon sınırı (min(78%,620px)) + avatar sütunu (daire+8) */
  max-width: calc(min(78%, 620px) + var(--chat-circle) + 8px);
}
.msg-row--bot { align-self: flex-start; }
.msg-row--user { align-self: flex-end; flex-direction: row-reverse; }
.msg-row > .msg { max-width: none; min-width: 0; }
.msg-av { width: var(--chat-circle); height: var(--chat-circle); font-size: 15px; }
.msg-row--bot .avatar { cursor: pointer; }   /* tık → karakter paneli */
/* KRİTİK: column-flex kaydırma kabında çocuklar varsayılan
   flex-shrink:1 ile birbirini EZİYORDU (medya/ses balonları
   yüksekliğini alamıyordu). Hiçbir balon küçülmez — taşan
   içerik kabın scroll'una gider (fix 2026-07-06). */
.chat-msgs > * { flex: 0 0 auto; }
.msg {
  max-width: min(78%, 620px);
  padding: 10px 15px; border-radius: 20px;
  font-size: 14.5px; line-height: 1.5;
  word-wrap: break-word; white-space: pre-wrap;
  animation: pop-in var(--tr-med);
}
.msg--user {
  /* satır avatarla flex-start hizalanır; flex-end balonu avatardan
     aşağı düşürüyordu (--bot zaten flex-start, iyi hizalıydı) */
  align-self: flex-start;
  background: var(--accent-strong); color: var(--bubble-user-text);
  border-bottom-right-radius: 8px;
}
.msg--bot {
  align-self: flex-start;
  background: var(--bubble-bot); color: var(--bubble-bot-text);
  border-bottom-left-radius: 8px;
}
.msg--err {
  align-self: center; max-width: 92%;
  background: var(--danger-soft); color: var(--danger);
  border-radius: var(--r-md); font-size: 13px; text-align: center;
}
/* ── WhatsApp tarzı özel ses oynatıcı (voice-player.js) ──
   Gerçek dalga formu + parmakla kaydırma. Çoklu-dosya balonunda
   .mb-audios içinde yığılır (aşağıya bak). */

/* Dalga renkleri — marka ailesi (menekşe); track/fill balon
   başına var'la verilir. */
.vp {
  display: flex; align-items: center; gap: 12px;
  width: 250px; max-width: 66vw;   /* SABİT genişlik — width:100% balonu 14px'e çökertiyor */
  --vp-track: rgba(255, 255, 255, .24);   /* çalınmamış çubuklar (nötr açık gri) */
  --vp-fill: var(--accent-bright);          /* çalınan çubuklar — ailenin açık tonu */
  --vp-btn-bg: var(--accent-grad);
  --vp-btn-fg: #fff;
  --vp-time: var(--text-2);
}
/* Kullanıcı balonu mor gradient → dalga beyaz okunur */
.msg--user .vp {
  --vp-track: rgba(255, 255, 255, .42);
  --vp-fill: #fff;
  --vp-btn-bg: rgba(255, 255, 255, .95);
  --vp-btn-fg: var(--accent-strong);
  --vp-time: rgba(255, 255, 255, .9);
}
.vp-btn {
  flex: 0 0 auto; width: var(--circle-sm); height: var(--circle-sm); border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; border: 0; padding: 0;
  background: var(--vp-btn-bg); color: var(--vp-btn-fg);
  box-shadow: 0 3px 10px rgba(0, 0, 0, .18);
  transition: transform var(--tr-fast), filter var(--tr-fast);
}
.vp-btn:hover { filter: brightness(1.06); }
.vp-btn:active { transform: scale(.94); }

.vp-wave {
  position: relative; flex: 1 1 auto; height: 32px; min-width: 0;
  cursor: pointer; touch-action: none; outline: none;
  /* KIRP: 44 çubuğun min-width'i (2px + gap) dar alanda kutudan taşıp
     komşu ikonların ÜSTÜNE biniyordu ve chat'te yatay scrollbar
     doğuruyordu (mobil, 2026-07-15) — taşan çubuk çizilmez. */
  overflow: hidden;
}
.vp-bars {
  position: absolute; inset: 0;
  display: flex; align-items: center; gap: 2px;
}
.vp-bars span {
  flex: 1 1 0; min-width: 2px; border-radius: 2px;
  background: var(--vp-track);
  transition: height var(--tr-fast);
}
/* İlerleyen kısım: aynı çubuklar mor/beyaz, playhead'e kadar kırpılır */
.vp-bars--play { clip-path: inset(0 calc(100% - var(--p, 0%)) 0 0); }
.vp-bars--play span { background: var(--vp-fill); }

.vp-thumb {
  position: absolute; top: 50%; left: var(--p, 0%);
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--vp-fill);
  transform: translate(-50%, -50%);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
  pointer-events: none; opacity: 0;
  transition: opacity var(--tr-fast);
}
.vp.is-active .vp-thumb,
.vp.is-dragging .vp-thumb,
.vp-wave:hover .vp-thumb,
.vp-wave:focus-visible .vp-thumb { opacity: 1; }

.vp-time {
  flex: 0 0 auto; min-width: 30px; text-align: right;
  font-size: 11.5px; font-variant-numeric: tabular-nums;
  color: var(--vp-time);
}
.vp.is-loading .vp-bars--track span { animation: vp-pulse 1.1s ease-in-out infinite; }
@keyframes vp-pulse { 0%, 100% { opacity: .5; } 50% { opacity: .9; } }

/* ── Çoklu-dosya medya balonu (media-bubble.js) ──────────────
   Tek turn'ün ardışık medya part'ları TEK balonda: foto albümü +
   video + ses yığını + belge listesi. TÜM bölümler aynı --mw
   genişliğinde (yoksa boyutlar tutmuyor). white-space:normal ŞART:
   .msg base'i pre-wrap; HTML girinti boşlukları album üstüne büyük
   boşluk koyuyordu. */
.msg--files { --mw: min(72vw, 260px); padding: 3px; overflow: hidden; white-space: normal; }
.msg--files > * + * { margin-top: 3px; }
.mb-album, .mb-docs, .mb-audios, .mb-video { width: var(--mw); }

/* Foto albümü — container'a aspect-ratio, hücreler doldurur */
.mb-album { display: grid; gap: 2px; border-radius: 15px; overflow: hidden; }
.mb-cell { position: relative; overflow: hidden; background: var(--surface-2); cursor: pointer; }
.mb-cell .mb-ph { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mb-cell:hover .mb-ph { filter: brightness(1.06); }
/* Tek görsel: kırpma yok — doğal oran (mw genişlik / 360px yükseklik sınırı) */
.mb-album--1 { width: auto; max-width: var(--mw); display: block; }
.mb-album--1 img { display: block; width: auto; height: auto; max-width: 100%; max-height: 360px; border-radius: 15px; cursor: pointer; }
.mb-album--2 { grid-template-columns: 1fr 1fr; aspect-ratio: 2 / 1; }
.mb-album--3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; aspect-ratio: 3 / 2; }
.mb-album--3 .mb-cell:first-child { grid-row: 1 / span 2; }
.mb-album--4, .mb-album--many { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; aspect-ratio: 1 / 1; }
.mb-more { position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(6, 6, 12, .5); backdrop-filter: blur(1px); color: #fff; font-size: 22px; font-weight: 600; }

/* Video */
.mb-video video { display: block; width: 100%; border-radius: 13px; background: #000; }

/* Belge listesi (geçmişte dosya adı yok → mime'dan etiket) */
.mb-docs { display: flex; flex-direction: column; }
.mb-doc { display: flex; align-items: center; gap: 10px; padding: 7px; border-radius: 11px;
  cursor: pointer; transition: background var(--tr-fast); }
.mb-doc:hover { background: var(--surface); }
.mb-doc-ic { width: 40px; height: 40px; border-radius: 11px; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 17px; background: var(--accent-soft); color: var(--accent); }
.mb-doc--pdf   .mb-doc-ic { background: var(--danger-soft); color: var(--danger); }
.mb-doc--sheet .mb-doc-ic { background: var(--ok-soft); color: var(--ok); }
.mb-doc--zip   .mb-doc-ic { background: var(--warn-soft); color: var(--warn); }
.mb-doc-body { min-width: 0; flex: 1; }
.mb-doc-name { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mb-doc-sub { font-size: 11px; color: var(--text-3); margin-top: 1px; }
.mb-doc-dl { margin-left: auto; width: var(--circle-sm); height: var(--circle-sm); border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 11px; color: var(--text-2); background: var(--surface-2);
  transition: background var(--tr-fast), color var(--tr-fast); }
.mb-doc:hover .mb-doc-dl { background: var(--accent-soft); color: var(--accent); }

/* Türe özel JSON kartı (json-view registry `card` → media-bubble
   toJsonCard): İSKELET burada — renk/gradient türün feature
   css'indedir (ör. astro.css .mb-json--astro). Hover = kalk +
   parla + ikon eğil + ok kay; dokunmada :active aynı his. */
.mb-json {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 13px;
  width: var(--mw); padding: 15px 16px; border-radius: 14px;
  cursor: pointer;
  background: var(--surface); box-shadow: var(--glass-edge);
  transition: transform var(--tr-fast), filter var(--tr-fast), box-shadow var(--tr-fast);
}
.mb-json:hover, .mb-json:active { transform: translateY(-1px); filter: brightness(1.1); }
.mb-json-ic {
  width: 44px; height: 44px; border-radius: 13px; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 19px;
  background: var(--accent-soft); color: var(--accent);
  transition: transform var(--tr-med);
}
.mb-json:hover .mb-json-ic, .mb-json:active .mb-json-ic { transform: rotate(-8deg) scale(1.08); }
.mb-json-body { min-width: 0; flex: 1; }
.mb-json-title { font-size: 14px; font-weight: 650; letter-spacing: -.01em; }
.mb-json-cta {
  display: flex; align-items: center; gap: 5px; margin-top: 2px;
  font-size: 12px; font-weight: 600; color: var(--accent);
}
.mb-json-cta i { font-size: 9px; transition: transform var(--tr-fast); }
.mb-json:hover .mb-json-cta i, .mb-json:active .mb-json-cta i { transform: translateX(3px); }

/* Çoklu ses — voice-player.js yığını */
.mb-audios { display: flex; flex-direction: column; }
.mb-audios .vp { width: 100%; max-width: none; gap: 11px; padding: 6px 3px; }
.mb-audios .vp + .vp { border-top: 1px solid var(--border); }

/* Kullanıcı balonu (mor gradient) — belge/liste beyaza yaklaşır */
.msg--user .mb-doc-name { color: #fff; }
.msg--user .mb-doc-sub { color: rgba(255, 255, 255, .72); }
.msg--user .mb-doc-ic { background: rgba(255, 255, 255, .18); color: #fff; }
.msg--user .mb-doc:hover { background: rgba(255, 255, 255, .12); }
.msg--user .mb-doc-dl { background: rgba(255, 255, 255, .18); color: #fff; }
.msg--user .mb-audios .vp + .vp { border-top-color: rgba(255, 255, 255, .22); }

.msg-ts {
  /* Negatif üst marj: 8px'lik genel gap ts'i kendi turn'ünden
     koparıyordu — üstte 4px'e çek, altta grup arasını genişlet.
     Yan pay 62px = avatar sütunu (48+8) + eski 6px → ts balonun
     altına hizalanır, avatarın değil. */
  font-size: 10.5px; color: var(--text-3);
  margin: -4px 6px 6px calc(var(--chat-circle) + 14px);   /* daire + 8 gap + 6 */
  align-self: flex-start;
}
.msg-ts--user { align-self: flex-end; margin: -4px calc(var(--chat-circle) + 14px) 6px 6px; }

/* ── Canlı gösterge (live-indicator.js) — typing'in yerini aldı
   (2026-07-12): gönderim boyunca karakter avatarı nabız halkasıyla
   nefes alır, BALON YOK; workflow node duyuruları avatar yanında
   İKON DAİRELERİ olarak belirir/söner (2026-07-15: metin çipleri
   SİLİNDİ — node metinleri tek dilliydi, i18n çözümü ikon; daire
   boyu avatarla AYNI 48px, yazı yok, duyuru metni yalnız title
   tooltip'inde). Beliriş/gidiş YAVAŞTIR (şak diye değil). */
.live-ind { min-height: var(--chat-circle); animation: pop-in var(--tr-med); }
/* Nabız SİSTEMİN TEK pulse'ından (.pulse-attn, components.css) —
   eski live-radar kopyası öldü (kullanıcı 2026-07-24: cn-ic / balance
   ile AYNI pulse; halka sistem geneli accent). .live-av daire yapılır
   ki pulse-attn'in box-shadow halkası (border-radius: inherit) çember
   çıksın. */
.live-av { position: relative; flex: 0 0 auto; width: var(--chat-circle); height: var(--chat-circle); border-radius: 50%; }
.live-av .avatar { width: var(--chat-circle); height: var(--chat-circle); font-size: 15px; }
.live-chips {
  /* gap YOK — daireler arası boşluk her dairenin KENDİ sağ marjında:
     daire silinirken marj da 0'a iner, komşular PAT DİYE KAYMAZ,
     yumuşakça yer kapanır (gap tek tek animasyonlanamıyor). */
  display: flex; flex-wrap: wrap;
  align-self: center; align-items: center; min-width: 0;
}
/* Node ikonu dairesi: avatar dairesinin eşi, içinde yalnız node'un
   emoji ikonu; N>1 paralel çağrı köşe rozetinde.
   Giriş/çıkış TEK mekanizma = transition (animasyon DEĞİL: fill'li
   giriş animasyonu cascade'de transition'ı ezip sönmeyi pat diye
   yapıyordu — 2026-07-15). Beliriş = genişlik 0→daire + hafif yaylı
   büyüme (komşuları yumuşakça iter); siliniş = ters yönde sönerek
   büzülme, boşalan yer akıcı kapanır. Eğriler yön başına ayrı:
   varış durumunun transition'ı geçerli olduğundan giriş eğrisi .in
   bloğunda, çıkış eğrisi taban blokta yaşar. box-shadow YOK
   (kullanıcı 2026-07-15). */
.live-chip {
  position: relative; flex: 0 0 auto;
  width: 0; height: var(--chat-circle); margin-right: 0;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bubble-bot);
  opacity: 0; transform: scale(.4);
  /* ÇIKIŞ eğrisi (JS OUT_MS=450 ile eş) */
  transition: width .45s cubic-bezier(.4, 0, .2, 1),
              margin .45s cubic-bezier(.4, 0, .2, 1),
              opacity .4s ease,
              transform .4s cubic-bezier(.4, 0, 1, 1);
}
.live-chip.in {
  width: var(--chat-circle); margin-right: var(--chat-chip-gap);
  opacity: 1; transform: none;
  /* GİRİŞ eğrisi — hafif yaylı oturma */
  transition: width .45s cubic-bezier(.2, .9, .3, 1),
              margin .45s cubic-bezier(.2, .9, .3, 1),
              opacity .45s ease,
              transform .5s cubic-bezier(.3, 1.4, .45, 1);
}
.lc-e { font-size: 20px; line-height: 1; }
.lc-n {
  position: absolute; top: -2px; right: -2px;
  min-width: 18px; height: 18px; border-radius: var(--r-full);
  display: grid; place-items: center; padding: 0 4px;
  background: var(--accent-grad); color: var(--on-accent);
  font-size: 10.5px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 2px 8px rgba(var(--accent-rgb), .5);
}

/* ════════════════════════════════════════════════════════════
 * PILL CHAT BAR (composer.js) — design-tests/chatbar-pill.html
 * Yüzen tam-radius pill (başlık pill'inin eşi): solda "+", ortada
 * şifre-silindiri yazı alanı, sağda mic ↔ gönder morph'u. Bar
 * yüksekliği SABİT (56px) — asla büyümez; yazı pill'in üstüne,
 * sohbetin üzerine taşar ve maske ile şeffaflaşır.
 * ════════════════════════════════════════════════════════════ */
.chat-barzone {
  position: absolute; left: 12px; right: 12px;
  /* çıplak env YASAK — canlı değişip pill'i zıplatır; statik
     --safe-bottom token'ı (tokens.css, kök kilidi mimarisi 2026-07-12) */
  bottom: calc(16px + var(--safe-bottom));
  z-index: 6;
  /* stateful node ikonu (state-popup.js) bar SAĞINA flex kardeş olarak
     doğar (2026-07-24 yer değişimi); ikon etiketi kapanınca bar boşalan
     alana kendiliğinden geri genişler (flex). 2026-07-16: ara .cb-host
     katmanı öldü — composer
     doğrudan buraya kurulur, .cb-pop'un çıpası .cb-bar'ın kendisi
     (aynı kutu, aynı geometri; CSS_GOLDEN_RULE.md K6). */
  display: flex; align-items: flex-end; gap: 8px;
}

/* ── COMPOSER BAR PILL'İ (.cb-bar) — tek-sınıf: eski "cb-pill cb-bar"
   yığını ÖLDÜ, bar'ın tüm kapsül CSS'i BURADA (reçete değerleri dosya
   başındaki --chat-pill-* var'larından). 4px padding = kapsül çerçevesi,
   .ch-id'nin ikizi; gölge + focus halkası aynı gün silindi — pill'ler
   gölgesiz düz cam (kullanıcı 2026-07-16). is-rec bar parıltısı da
   öldü (kullanıcı 2026-07-19: kayıt geri bildirimi yalnız butonun
   radar pulse'ı — bar gölgesiz kalır). */
.cb-bar {
  position: relative; z-index: 2;
  flex: 1 1 auto; min-width: 0;   /* barzone payı (eski .cb-host'tan, 2026-07-16) */
  display: flex; flex-direction: column; gap: 12px;
  padding: 8px;
  border-radius: var(--chat-pill-r);
  background: var(--chat-pill-bg);
  backdrop-filter: var(--chat-pill-blur); -webkit-backdrop-filter: var(--chat-pill-blur);
}
/* bar'ın buton satırı (eski ortak .cb-prow'un bar'a özel hâli) —
   flex-end: girdi alanı uzarken daireler altta hizalı kalır */
.cb-bar-row { position: relative; display: flex; align-items: flex-end; gap: var(--chat-row-gap); }

/* + butonu — tek-sınıf (eski "cb-btn cb-plus" öldü) */
.cb-plus {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  color: var(--text-2); background: var(--surface-2);
  transition: background var(--tr-fast), color var(--tr-fast),
              transform var(--tr-med), filter var(--tr-fast);
}
.cb-plus:hover { background: var(--surface-3); color: var(--text); }
.cb-plus i { transition: transform var(--tr-med); }
/* popover açıkken gradient + 45° dönüş (× hissi) */
.cb-plus.is-open { background: var(--accent-grad); color: var(--on-accent); }
.cb-plus.is-open i { transform: rotate(45deg); }

/* orta alan — SABİT yükseklik: bar asla büyümez, düzen bozulmaz */
.cb-mid { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; min-height: var(--chat-circle); }

/* ── ŞİFRE SİLİNDİRİ ──────────────────────────────────────────
   Yazı alanı pill akışında DEĞİL: prow'a mutlak bağlı, alta sabit.
   autogrow (composer.js) yükseltince pill'in ÜSTÜNE, sohbetin
   üzerine taşar; odaktan (alt satır/imleç) uzaklaşan her satır px
   maskesiyle giderek şeffaflaşır — pill aydınlık odak bandı. Tavan
   min(38svh,320px) (svh = statik, bar animasyonunda değişmez);
   sonrası parmak/teker ile iç scroll (bar gizli,
   kaydırma-düzenleme serbest). */
.cb-ta {
  position: absolute; left: 54px; right: 54px; bottom: 0;
  height: 48px; max-height: min(38svh, 320px);
  padding: 13px 4px;
  background: none; border: 0; outline: none; resize: none;
  font: inherit; font-size: 14.5px; line-height: 1.45; color: var(--text);
  overflow-y: auto; scrollbar-width: none;
  caret-color: var(--accent);
  -webkit-mask-image: linear-gradient(to top, #000 0, #000 48px, transparent 340px);
          mask-image: linear-gradient(to top, #000 0, #000 48px, transparent 340px);
}
.cb-ta::-webkit-scrollbar { display: none; }
.cb-ta::placeholder { color: var(--text-3); }
.cb-bar.no-plus .cb-ta { left: 14px; }   /* "+" gizliyse (aile yok) */

/* ── EK ŞERİDİ (dosya seçilince) — pill'in üst satırı ─────────
   Çok dosyada bar ekranı yemesin, fazlası şeridin İÇİNDE kayar
   (kullanıcı 2026-07-12: "pek çok kutu dizilince bar uzayıp
   bozuluyor"). GRID: masaüstü 4 eşit kolon, mobil tek kolon
   (kullanıcı 2026-07-18) — minmax(0,1fr) ki ad ellipsis'i kolonu
   patlatmasın. Scrollbar GİZLİ (radius'lu kapsülü bozuyordu).
   Tavanlar SATIRA TAM oturur (kullanıcı 2026-07-18 "tam sığsın";
   satır 52 = 44 önizleme + 4+4 chip pad, gap 6, pad 8 üst + 4 alt):
   masaüstü 3 TAM satır = 8+52×3+6×2+4 = 180px, mobil 4 TAM satır =
   8+52×4+6×3+4 = 238px — kesik-satır işareti bilinçli yok, fazlası
   sessizce içeride kayar. (Üst/alt scrim gölgesi denendi ve GERİ
   ALINDI, kullanıcı 2026-07-18 — .attach-wrap sarmalayıcısıyla
   geri gelir.) */
.attach-strip {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px; padding: 8px 10px 4px;
  max-height: 180px; overflow-y: auto;
  background: var(--surface);
  border-radius: var(--chat-pill-r);
  scrollbar-width: none;
}
.attach-strip::-webkit-scrollbar { display: none; }
.attach-strip[hidden] { display: none; }
/* chip zeminsiz/gölgesiz (kullanıcı 2026-07-18) — şeridin --surface
   zemininde yalnız önizleme + ad + daire ✕ yüzer */
.attach-chip {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 4px 7px 4px 4px; border-radius: 13px;
  font-size: 12px;
}
/* önizleme BÜYÜK (kullanıcı 2026-07-18): görselde küçük avatar
   karesi, diğer ailelerde ikon karesi — aynı boy */
.attach-chip img { width: 44px; height: 44px; border-radius: 12px; object-fit: cover; flex: 0 0 auto; }
.attach-chip .ac-ic {
  width: 44px; height: 44px; border-radius: 12px; flex: 0 0 auto;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); font-size: 17px;
}
/* ad tek satır ellipsis'le SINIRLI; esner → ✕ kolonun sağ kenarına yaslanır */
.attach-chip .ac-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ✕ = daire zeminli mini tuş (kullanıcı 2026-07-18); hover reçetesi
   .ch-reset ikizi (danger-soft) */
.attach-chip button {
  width: var(--circle-xs); height: var(--circle-xs); border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-3);
  transition: background var(--tr-fast), color var(--tr-fast);
}
.attach-chip button:hover { background: var(--danger-soft); color: var(--danger); }

/* kayıt CANLI durumu — yazı alanının yerine (yazısız: nokta + sayaç) */
.cb-rec { display: none; align-items: center; gap: 10px; padding: 13px 4px; font-size: 13.5px; color: var(--text-2); }
.cb-rec.on { display: flex; }
.cb-rec-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--danger); animation: cb-blink 1s ease-in-out infinite; }
@keyframes cb-blink { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.cb-rec-t { font-variant-numeric: tabular-nums; font-weight: 650; color: var(--text); min-width: 38px; }

/* kayıt SONRASI helper = SES MODU KABI (2026-07-15 mimari düzeltme):
   bar'ın iki modu var — yazı modu (.cb-ta) ve ses modu (.cb-voice).
   Ses modunun TÜM parçaları tek kapta yaşar ve .on tek anahtarıyla
   açılır. 2026-07-16 DÜZ hiyerarşi (kullanıcı): .cb-vhost ve .vp kökü
   bar'da YOK — kabın doğrudan çocukları [.vp-btn--bar][.vp-wave]
   [.vp-time][.cb-x] (voice-player mountBarPlayer); dalga renk reçetesi
   ve durum sınıfları (is-loading/is-active/is-dragging) kabın kendisinde. */
.cb-voice {
  display: none; align-items: center; gap: 6px;
  flex: 1 1 auto; min-width: 0; padding: 0 6px 0 0;
  --vp-track: rgba(255, 255, 255, .24);   /* çalınmamış çubuklar */
  --vp-fill: var(--accent-bright);         /* çalınan çubuklar */
  --vp-time: var(--text-2);
}
.cb-voice.on { display: flex; }
/* durum ikizleri — balondaki .vp.is-* kurallarının bar eşleri */
.cb-voice.is-loading .vp-bars--track span { animation: vp-pulse 1.1s ease-in-out infinite; }
.cb-voice.is-active .vp-thumb { opacity: 1; }
.cb-voice.is-dragging .vp-thumb { opacity: 1; }
/* Bar'daki play tuşu (.vp-btn--bar) — voice-player 'bar' rolünün
   KENDİ sınıfı (2026-07-15: .cb-btn kalıtımı SÖKÜLDÜ — bar butonları
   "130 yerden" etkilenmesin, her buton kendi bloğundan yönetilsin).
   Geometri dosya başındaki tek kaynaktan (--chat-circle). ÇIPLAK:
   daire zemini YOK (kullanıcı 2026-07-15 2. tur), yalnız accent glif.
   Balon içindeki 34px .vp-btn hâli TAMAMEN ayrı, ona dokunmaz. */
.vp-btn--bar {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  background: none; color: var(--text-2);   /* ÇIPLAK — zeminsiz, nötr glif (kullanıcı 2026-07-16; accent gitti) */
  transition: color var(--tr-fast), filter var(--tr-fast), transform var(--tr-fast);
}
.vp-btn--bar:hover { color: var(--text); }
.vp-btn--bar:active { transform: scale(.94); }

/* ✕ — sesi sil: ses modu kabının (.cb-voice) içinde yaşar, kap açılınca
   görünür (kendi .on'u YOK). 2026-07-16: zemin de gitti — play tuşunun
   ikizi ÇIPLAK nötr glif (--text-2), hover'da yalnız renk kırmızıya döner. */
.cb-x {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  background: none; color: var(--text-2);
  transition: color var(--tr-fast), transform var(--tr-med);
}
.cb-x:hover { color: var(--danger); }
.cb-x:active { transform: scale(.94); }

/* ── ana buton: mic ↔ gönder morph'u — tek-sınıf (eski "cb-btn cb-main"
   öldü); touch-action:none = mic basılı-tut jesti kaydırmaya dönüşmesin */
.cb-main {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  touch-action: none;
  color: var(--accent); background: var(--accent-soft); overflow: visible;
  transition: background var(--tr-fast), color var(--tr-fast),
              transform var(--tr-med), filter var(--tr-fast);
}
/* hover = yalnız parlaklık: zemin/renk zaten tabandan accent-soft/accent
   (eski hover'daki bg+color tekrarı ÖLÜ koddu — is-send/is-rec kendi
   zeminlerini sonra yazıyor, taban hover'ı yalnız idle'a değiyordu) */
.cb-main:hover { filter: brightness(1.15); }
.cb-main:disabled { opacity: .45; cursor: default; }
.cb-main .cb-ic { position: absolute; inset: 0; display: grid; place-items: center; transition: opacity var(--tr-med), transform var(--tr-med); }
.cb-ic-send { opacity: 0; transform: rotate(-40deg) scale(.55); }
.cb-ic-send i { margin-right: 2px; }   /* paper-plane glifi optik ortalama */
/* GÖNDER hâli = tabanla AYNI görünüm (accent-soft zemin + accent ikon);
   ayrım YALNIZ ikon morph'u (mic → uçak). accent-grad SÖKÜLDÜ (kullanıcı
   2026-07-25: düz accent ailesi doktrini) → is-send'in kendi hover'ı da
   gerekmiyor, taban .cb-main:hover parlaklığı geçerli. */
.cb-main.is-send { background: var(--accent-soft); color: var(--accent); }
.cb-main.is-send .cb-ic-mic { opacity: 0; transform: rotate(40deg) scale(.55); }
.cb-main.is-send .cb-ic-send { opacity: 1; transform: none; }

/* ── KAYIT modu: buton kocaman + radar pulse (kaydırma jesti YOK) ──
   Not (2026-07-16): kayıt sırasında sağ/alt ekran kenarında beliren
   "gri çizgi" radar'ın suçu DEĞİL — halka viewport dışına taşınca kök
   scroll göstergesi flaşlıyordu; düzeltme base.css kök overflow:clip
   (+ shell.css mobil .main clip). Radar kenarı geçse de artık çizgi
   doğurmaz, orijinal genişliğinde kalır. */
.cb-main.is-rec {
  background: var(--accent-strong); color: var(--on-accent);
  transform: scale(1.45);
  box-shadow: 0 0 0 10px rgba(var(--accent-rgb), .18), 0 0 46px rgba(var(--accent-pop-rgb), .55);
  z-index: 5;
}
.cb-ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 2.5px solid rgba(var(--accent-rgb), .75);
  opacity: 0; pointer-events: none; z-index: -1;
}
.cb-main.is-rec .cb-ring { animation: cb-radar 1.9s cubic-bezier(.2, .6, .35, 1) infinite; }
.cb-main.is-rec .cb-r2 { animation-delay: .62s; }
.cb-main.is-rec .cb-r3 { animation-delay: 1.24s; }
@keyframes cb-radar {
  0%   { transform: scale(1);   opacity: .85; border-color: rgba(var(--accent-rgb), .9); }
  100% { transform: scale(3.6); opacity: 0;   border-color: rgba(var(--accent-rgb), 0); }
}

/* ── "+" POPOVER — minimal, +'yı işaret eden ok; yalnız aile adları
   (dosya türü listesi UI'a yazılmaz — kullanıcı kararı 2026-07-12) ── */
.cb-pop {
  position: absolute; z-index: 30;
  left: 2px; bottom: calc(100% + 12px);
  min-width: 172px; padding: 6px;
  border-radius: var(--r-md);
  background: var(--panel-bg);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-edge), var(--shadow-3);
  transform-origin: 26px calc(100% + 8px);
  opacity: 0; transform: scale(.86) translateY(8px);
  pointer-events: none;
  transition: opacity var(--tr-med), transform var(--tr-med);
}
.cb-pop.open { opacity: 1; transform: none; pointer-events: auto; }
.cb-pop::after {              /* +'yı işaret eden ok */
  content: ""; position: absolute; left: 23px; bottom: -6px;
  width: 13px; height: 13px; border-radius: 3px;
  background: var(--panel-bg);
  transform: rotate(45deg);
}
.cb-pop-it {
  width: 100%; display: flex; align-items: center; gap: 11px;
  padding: 8px 14px 8px 8px; border-radius: 11px; text-align: left;
  font-size: 13.5px; font-weight: 600; letter-spacing: -.01em;
  transition: background var(--tr-fast);
}
.cb-pop-it:hover { background: var(--surface-2); }
.cb-pop-ic {
  width: 38px; height: 38px; border-radius: 11px; flex: 0 0 auto;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}

/* Masaüstü — bar + header pill'leri serbest yüzer, ortalı, AYNI
   genişlik reçetesi (kullanıcı 2026-07-12/13) */
@media (min-width: 861px) {
  .chat-barzone {
    left: 0; right: 0; margin: 0 auto;
    width: min(680px, calc(100% - 32px));
    bottom: calc(22px + var(--safe-bottom));
  }
  .chat-headzone {
    left: 0; right: 0; margin: 0 auto;
    width: min(680px, calc(100% - 32px));
    top: calc(22px + var(--safe-top));
  }
  /* masaüstünde geri tuşu GEREKSİZ (kullanıcı 2026-07-13) — sol
     kolon zaten görünür, sohbet kapatma = listeden başka seçim */
  .ch-back { display: none; }
}

/* Mobil */
@media (max-width: 860px) {
  .btn-back { display: inline-flex; }   /* astro detayının geri tuşu */
  .msg { max-width: 86%; }
  .msg-row { max-width: calc(86% + var(--chat-circle) + 8px); }
  /* Kayıt sonrası bar player'ında gri süre sayısı MOBİLDE YOK
     (kullanıcı 2026-07-15) — dar pill'de dalga nefes alsın;
     balon içi oynatıcıların süresi durur. */
  .cb-voice .vp-time { display: none; }
  /* ek şeridi TEK kolon; 32px köşe radius'u chip'leri yemesin diye
     yanlardan içerlek; tavan 4 TAM satır (taban bloktaki geometri
     notu — kullanıcı 2026-07-18) */
  .attach-strip { grid-template-columns: 1fr; padding: 8px 16px 4px; max-height: 238px; }
}

/* ── Stateful node kayıtları ikonu (chat/state-popup.js) ──────
   Chat barının SOLUNDA .cb-btn eşi daire (kendi mini cam pill'inde):
   state tutan node (bugün yalnız astro_chart) kendini doldurmuşsa
   doğar. "Etiketle doğar" + ilk 5 sn halka pulse'ı; etiket çıkışı
   MASAÜSTÜ = silinip kapanma (yazı solar → yer kapanır → bar flex'le
   nazikçe geri genişler), MOBİL = dairenin üstünde ayrı balon (bar
   hiç oynamaz). Etiket gidince kayıt sayısı köşede SABİT 18px
   tam-daire rozete geçer (içerikle uzamaz; N>9 → "9+"). Kapatma tuşu
   yok — saf durum aynası. Seçim: design-tests/astro-icon-designs.html
   v3 (kullanıcı 2026-07-14). */
/* tek-sınıf: eski "cb-pill nsp-pill" yığını ÖLDÜ — mini pill'in tüm
   kapsül CSS'i burada (reçete --chat-pill-* var'larından).
   8px padding = bar kapsülünün (.cb-bar) ikizi: daire merkezi bar
   dairelerinin merkeziyle AYNI hizaya oturur (kullanıcı 2026-07-20;
   gölge de aynı gün silindi — pill'ler gölgesiz düz cam). */
/* .nsp-pill DOĞRUDAN yatay flex satırıdır (kullanıcı 2026-07-25):
   görevsiz .nsp-row sarmalayıcısı öldü — .ch-nav / .ch-id kapsülleriyle
   AYNI mimari (kapsül = flex satırının kendisi, CSS_GOLDEN_RULE.md K6).
   gap SIFIR — daire↔yazı aralığı etiketin sol padding'inde (x-shut onu
   da kapatır); flex gap'i etiket 0'a büzülünce kalıp pill'i daireden
   geniş bırakıyordu (kullanıcı 2026-07-14). Mobil etiket balonu
   (.nsp-chip) absolute → akış dışı, satırı bozmaz. */
.nsp-pill {
  flex: 0 0 auto; position: relative; z-index: 2;
  display: flex; align-items: center; gap: 0;
  padding: 8px;
  border-radius: var(--chat-pill-r);
  background: var(--chat-pill-bg);
  backdrop-filter: var(--chat-pill-blur); -webkit-backdrop-filter: var(--chat-pill-blur);
  animation: nsp-in .45s cubic-bezier(.2, .9, .3, 1.4) both;
}
@keyframes nsp-in { from { opacity: 0; transform: scale(.3); } to { opacity: 1; transform: none; } }
.nsp-pill.nsp-out { animation: nsp-out .28s cubic-bezier(.4, 0, 1, 1) both; }
@keyframes nsp-out { to { opacity: 0; transform: scale(.3); } }

/* stateful kayıtlar butonu — tek-sınıf (eski "cb-btn nsp-btn" öldü).
   Zemin = eski HOVER reçetesi (accent-soft cam): kullanıcı 2026-07-20
   "hover hali daha uyumlu, normal o olsun" — .cb-main deseninin eşi,
   hover yalnız parlar. */
.nsp-btn {
  position: relative; flex: 0 0 auto;
  width: var(--chat-circle); height: var(--chat-circle);
  border-radius: 50%;
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
  background: var(--accent-soft); color: var(--accent);
  transition: background var(--tr-fast), color var(--tr-fast), filter var(--tr-fast);
}
.nsp-btn:hover { filter: brightness(1.15); }

/* halka pulse: doğuşta 4 tur, sonra kendiliğinden durulur */
.nsp--ripple::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  pointer-events: none;
  animation: nsp-ripple 1.25s cubic-bezier(.4, 0, .2, 1) .5s 4;
}
@keyframes nsp-ripple {
  0%   { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), .55); }
  100% { box-shadow: 0 0 0 20px rgba(var(--accent-rgb), 0); }
}

/* kayıt sayısı rozeti — etiket fazında gizli (sayı etikette yazar),
   etiket çıkınca belirir */
.nsp-badge {
  position: absolute; top: -2px; right: -2px;
  width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent-grad); color: var(--on-accent);
  font-size: 10.5px; font-weight: 700; line-height: 1;
  box-shadow: 0 2px 8px rgba(var(--accent-rgb), .5);
  pointer-events: none;
  transition: opacity .3s, transform .3s;
}
.nsp-badge--hid { opacity: 0; transform: scale(.4); }

/* masaüstü etiketi: [daire][yazı]; x-fade = yazı solar (bar durur),
   x-shut = yer kapanır (bar genişler) — state-popup.js zamanlar */
.nsp-lbl {
  max-width: 220px; overflow: hidden; white-space: nowrap;
  padding: 0 12px 0 10px;
  font-size: 13.5px; font-weight: 650; letter-spacing: -.01em;
  transition: max-width .65s cubic-bezier(.4, 0, .2, 1),
              opacity .5s ease,
              padding .65s cubic-bezier(.4, 0, .2, 1);
}
.nsp-lbl.x-fade { opacity: 0; }
.nsp-lbl.x-shut { max-width: 0; padding: 0; }

/* mobil etiketi: dairenin üstünde ayrı balon — bar hiç oynamaz.
   Sağa çapalı (2026-07-24: pill bar SAĞINA taşındı; left:0 balonu
   ekran dışına taşırıyordu → right:0 ile İÇERİ, merkeze doğru büyür). */
.nsp-chip {
  position: absolute; bottom: calc(100% + 10px); right: 0;
  max-width: calc(100vw - 24px); overflow: hidden;
  padding: 9px 13px; border-radius: 13px; white-space: nowrap;
  background: var(--chrome);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-edge), var(--shadow-2);
  font-size: 13px; font-weight: 650; letter-spacing: -.01em;
  animation: nsp-in .4s cubic-bezier(.2, .9, .3, 1.3) both;
  transition: opacity .9s ease, transform .9s ease;
  pointer-events: none;
}
.nsp-chip::after {               /* daireyi işaret eden ok (sağdaki daireye) */
  content: ''; position: absolute; right: 24px; bottom: -5px;
  width: 11px; height: 11px; border-radius: 3px;
  background: var(--chrome); transform: rotate(45deg);
}
.nsp-chip.x-gone { opacity: 0; transform: translateY(-10px); }

/* ── nsp POPUP — TEK popup, otomatik çip sekmeler (10. tur FİNAL,
   2026-07-20; design-tests/nsp-popup-designs.html varyant 4).
   Eski grup-listesi → kayıt-listesi → tek-kayıt zinciri (capop/agv)
   ÖLDÜ. TEK YÜZ (2026-07-24, kullanıcı): nsp motorun STANDART
   sheet'i — mobilde (<720px) alt sayfa, masaüstünde (≥720px) ekran
   ORTASINDA panel. Eski "pill dairesinin köşesinden doğan çapalı
   popover" yüzü (anchor + data-anchored) SİLİNDİ: popup, kendisini
   açan tuşu TAKİP ETMEZ. Burada yalnız nsp'nin BOYUT kararları
   yaşar. Salt izleme. */
.pp[data-pp="nsp"] {
  --pp-h: min(78svh, 700px);
  --pp-body-pad: 0;          /* sekme/pane/return kendi paylarını taşır */
  --pp-body-pt: 12px;        /* desktop nefes payı */
  /* NOT: eski kişi-kartı reçetesi (--nsp-card-*) 2026-07-23'te düştü —
     harita artık features/astro/viewer.js ile çiziliyor (bilet/pencere
     zeminleri astro.css'ten iner). */
}

/* çip sekmeler — dolu kaynaklardan otomatik; vurgu tek jest: soft çip */
.nsp-tabs {
  flex: none; display: flex; gap: 8px; overflow-x: auto;
  scrollbar-width: none; padding: 2px 16px 12px;
}
.nsp-tabs::-webkit-scrollbar { display: none; }
/* sekmeler satırı EŞİT doldurur (2 sekme = %50-%50) */
.nsp-tab {
  flex: 1 1 0; min-width: 0; display: inline-flex; align-items: center;
  justify-content: center; gap: 7px;
  padding: 8px 12px; border-radius: 999px;
  font-size: 13px; font-weight: 650; color: var(--text-3);
  transition: background .22s, color .22s, transform .22s cubic-bezier(.2, .9, .3, 1.25);
}
.nsp-tab.is-act { background: var(--accent-soft); color: var(--accent-bright); transform: scale(1.04); }
.nsp-tabn { font-size: 11px; font-weight: 700; color: var(--text-3); }
.nsp-tab.is-act .nsp-tabn { color: inherit; opacity: .75; }

/* içerik — pane sabit scroll kabı, .nsp-page her sekmede yeniden doğar */
.nsp-pane {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--page-pad);
  scrollbar-width: thin; scrollbar-color: var(--scrollbar) transparent;
}
.nsp-page { animation: nsp-page .26s cubic-bezier(.22, 1, .36, 1) both; }
@keyframes nsp-page { from { opacity: 0; } }

/* footer — yalnız "Sohbete dön" (kaydet yok, salt izleme yüzeyi);
   zemin accent-soft, ikon+yazı accent (kullanıcı 2026-07-20) */
.nsp-return {
  flex: none; align-self: center;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  margin: 8px 16px 14px; padding: 8px 16px; border-radius: 999px;
  background: var(--accent-soft);
  font-size: 13.5px; font-weight: 650; color: var(--accent-bright);
  transition: filter var(--tr-fast), transform var(--tr-fast);
}
.nsp-return:hover { filter: brightness(1.15); }
.nsp-return:active { transform: scale(.96); }
.nsp-return i { transition: transform var(--tr-fast); }
.nsp-return:hover i { transform: translateX(-3px); }
@media (max-width: 719px) {          /* mobil yüz: tam-en geri + safe-area */
  .nsp-return {
    align-self: stretch;
    margin: 8px 16px calc(14px + env(safe-area-inset-bottom)); padding: 12px;
  }
}

/* masaüstü BOYU: PC'de GENİŞ yüzey (kullanıcı 2026-07-20: "büyüsün,
   genişlesin yükselsin") — ekran ortasında, tavana svh korkuluğu;
   doğuş animasyonu iskeletin standart sheet'i (popup.css pp-up) */
@media (min-width: 720px) {
  .pp[data-pp="nsp"] {
    --pp-w: min(660px, 94vw);
    --pp-h: min(800px, 86svh);
    --pp-r: var(--r-lg);
  }
}

/* ── ZAMAN ÇİZELGESİ görseli ORTAK bileşene taşındı (2026-07-23):
   .tl-* sınıfları components.css'te, çizim core/timeline.js'te.
   Sohbet ajandası + harita takvimi + astro sekmesi TEK çelikten
   çizer (eski .nsp-tl/ev/rel bloğu buradaydı; astro sekmesi ayrı
   "kutu" çiziyordu, ikisi ayrışmıştı — artık tek kaynak).
   Popup harita detayı da artık astro çiziciyi (features/astro/viewer.js
   → .ast-tlwrap) kullandığından çizelge components.css defaults'uyla
   çizilir; eski .nsp-cd/.nsp-dt kart-detay reçetesi 2026-07-23'te
   KALDIRILDI (state-popup renderCharts/chartDetail ile birlikte). */

