/* ─────────────────────────────────────────────────────────────────────────
   arsiv — tek dosya, build adımsız. İKİ TEMA, tek token seti:
     gündüz = "Pembe Zarf"     (kâğıt · allık · çakıl-buton · altın mühür) — :root
     gece   = "Gece Penceresi" (cam · gece · lamba)                 — html[data-tema="gece"]
   Tema seçimi index.html head'indeki küçük script'tedir (sistem tercihi;
   localStorage.tema = "gece" | "gunduz" ile elle ezilir). Üslup kararı:
   2026-08-22 owner turu (3 yön × 3 revizyon, held-out eleştirmen ×2).

   Renk kontrast oranları (WCAG 2.1, gerçek relative-luminance hesabıyla
   doğrulandı, 2026-08-22 — küçük metin ≥4.5:1, büyük/dekoratif ≥3:1):

   GÜNDÜZ
     --color-ink / paper                                   → 12.27:1
     --color-ink / surface                                 → 13.69:1
     --color-ink-muted / paper                             →  5.22:1
     --color-ink-muted / surface                           →  5.82:1
     --color-accent / paper                                →  5.26:1
     --color-accent / surface                              →  5.88:1
     --color-accent / surface-sunken                       →  4.63:1
     --color-on-accent / accent                            →  6.09:1
     --color-danger / paper                                →  5.49:1
     --color-on-danger / danger                            →  6.35:1
     --color-live / paper                                  →  5.70:1
     --color-live / live-soft                              →  5.03:1
     --color-ink / peach                                   → 10.59:1
     --color-ink-muted / peach                             →  4.50:1
     --color-accent / peach                                →  4.54:1
     --color-ink / peach-deep (kapı)                       →  8.71:1
     --color-accent-strong / peach-deep (kapı placeholder) →  4.94:1
     --color-gate-error / peach-deep                       →  5.31:1
     --color-border-strong / paper (kutu sınırı, eşik 3)   →  3.48:1

   GECE (cam zeminler alfa-blend ile ölçüldü; en zayıf çift listede)
     --color-ink / paper                                   → 15.46:1
     --color-ink-muted / paper                             →  9.24:1
     --color-accent / paper                                →  9.30:1
     --color-on-accent / accent                            →  8.82:1
     --color-danger / paper                                →  8.38:1
     --color-on-danger / danger                            →  8.14:1
     --color-live / paper                                  → 14.68:1
     --color-cream / night (kapı)                          → 16.43:1
     --color-gate-error / night                            →  8.90:1
     --color-ink-muted / cam-buton (alfa-blend)            →  7.32:1

   Kenarlık/gölge tonları yalnız dekoratif ayraçlardır, metin taşımaz —
   WCAG metin-kontrast kuralına tabi değildir.
   ───────────────────────────────────────────────────────────────────────── */

/* Cormorant Garamond — italic 500 — latin-ext */
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/cormorant-garamond-italic-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Cormorant Garamond — italic 500 — latin */
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/cormorant-garamond-italic-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Cormorant Garamond — normal 500 — latin-ext */
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/cormorant-garamond-normal-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Cormorant Garamond — normal 500 — latin */
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/cormorant-garamond-normal-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Lora — italic 400-700 — latin-ext */
@font-face {
  font-family: 'Lora';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/lora-italic-400-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Lora — italic 400-700 — latin */
@font-face {
  font-family: 'Lora';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/lora-italic-400-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Lora — normal 400-700 — latin-ext */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/lora-normal-400-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Lora — normal 400-700 — latin */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/fonts/lora-normal-400-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Renkler — TEK tanım yeri (gündüz = Pembe Zarf). Gece değerleri dosya
     sonundaki html[data-tema="gece"] bloğunda; aynı adlar, farklı değerler. */
  --color-paper: #f8ece9;
  --color-surface: #fffaf8;
  --color-surface-sunken: #f1dcd8;
  --color-border: #e8cdc8;
  --color-border-strong: #a5726a;
  --color-ink: #3b2430;
  --color-ink-muted: #7a5a66;
  --color-accent: #a83a63;
  --color-accent-strong: #8c2d52;
  --color-accent-soft: #f6dbe3;
  --color-on-accent: #ffffff;
  --color-danger: #a83a2c;
  --color-danger-soft: #f4d9d2;
  --color-on-danger: #ffffff;
  --color-focus: #a83a63;
  --color-progress-track-bg: rgb(255 255 255 / 22%);
  /* canlı / yayında — hata kırmızısından AYRI token (2026-08-22 bulgusu).
     2026-08-23 saha bulgusu (owner): eski #7e5d10 nokta olarak "altın mühür"
     okunuyordu ama rozet ZEMİNİ olunca haki/zeytine düşüyordu. Mum-mühürü
     karminine alındı — zarfın mumu, tema ailesinden; danger #a83a2c (tuğla)
     ve accent #a83a63 (gül) ile karışmaz, üçü ayrı kalır. */
  --color-live: #b31e44;
  --color-live-soft: #f9d9e0;

  /* Tören zeminleri (mektup akışı) + kapı — gündüzde zarfın içi */
  --color-peach: #f3d9d3;
  --color-peach-deep: #e9c2bb;
  --color-night: #2a1a22;
  --color-cream: #f8ece9;
  --color-cream-soft: rgb(248 236 233 / 55%);
  --color-white-warm: #fffaf8;
  --color-ink-line: rgb(59 36 48 / 36%);
  --color-gate-error: #8a2a1e;

  /* Malzeme — kalın kâğıt kenarı, mühür gölgesi, cam (gecede dolar) */
  --kagit-kenar: rgb(59 36 48 / 10%);
  --muhur-golge: rgb(0 0 0 / 18%);
  --muhur-halka: rgb(255 255 255 / 25%);
  --glass-bg: transparent;
  --glass-border: transparent;
  --glass-hi: transparent;
  --glass-shadow: transparent;
  --glass-card-bg: transparent;
  --glass-card-border: transparent;
  --glass-card-hi: transparent;
  --glass-well-bg: transparent;
  --glass-well-shadow: transparent;
  --accent-glow: transparent;
  --accent-glow-hi: transparent;
  --live-halo: transparent;
  --live-glow: transparent;

  /* Işık lekeleri (arka plan, süzülür — index.html .lekeler) */
  --leke-1: rgb(214 120 140 / 16%);
  --leke-2: rgb(240 169 143 / 18%);
  --leke-3: rgb(255 214 190 / 22%);

  /* Tipografi — beş boyut kademesi. `xl` 2026-08-25'te eklendi: müzik arşivi
     başlığının 2rem'i tek-kullanımlık bir BİLEŞEN token'ıydı
     (--font-size-muzik-baslik), gerçek bir kademeye terfi etti. Değer birebir
     aynı; kaçan ölçü artık ölçeğin İÇİNDE, yanında değil. */
  --font-body: "Lora", Georgia, "Times New Roman", serif;
  --font-display: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --font-size-sm: 0.8125rem;
  --font-size-base: 0.9375rem;
  --font-size-md: 1.125rem;
  --font-size-lg: 1.5rem;
  --font-size-xl: 2rem;
  --line-height-base: 1.6;

  /* Aralık skalası */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 18px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Yarıçap skalası */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;

  /* Katmanlama — ince kenarlık + çok hafif gölge, ağır drop-shadow yok */
  --shadow-sm: 0 1px 2px rgb(59 36 48 / 6%), 0 1px 1px rgb(59 36 48 / 4%);
  --shadow-md: 0 6px 18px rgb(59 36 48 / 10%);

  --touch-target: 44px;
  /* Okuma kolonu — metin/liste ağırlıklı ekranların tavanı (mektup ve müzik).
     Takvim/gün/kayıt `.view-root`un 1180px'inde kalır; bu token ikinci ve TEK
     dar ölçüdür. Müzik 2026-08-25'e kadar üçüncü bir değerde (480px) duruyordu. */
  --olcu-okuma: 38rem;
  /* Kart İÇİNDEKİ küçük resmin köşesi — taşıyıcı `--radius-kart`ın (22px)
     orantılı küçüğü (rev2 İ2 ölçümü). Gün listesinde elle yazılıydı; müzik
     kartı 2026-08-25'te aynı malzemeye geçince tek kaynağa bağlandı. */
  --radius-kart-ic: 10px;
  --transition-fast: 120ms ease;
  --transition-base: 180ms ease;

  /* ── Adı-konmuş istisnalar ────────────────────────────────────────────────
     Yukarıdaki skalaların HİÇBİR kademesine oturmayan, ama tek kaynağa
     bağlanmış değerler. 2026-08-25 konsolidasyon turunda dosyanın 3200.
     satırındaki İKİNCİ `:root` bloğundan buraya taşındı — değerler birebir,
     görsel sonuç değişmedi. Token'ın tek evi burasıdır; yeni token yalnız bu
     bloğa (ve gece karşılığı tek gece bloğuna) yazılır.

     --color-danger-night: gece-güvenli tehlike tonu. `.prep-error` içinde
       oturduğu kutu (--color-night) HER İKİ temada da koyu; --color-danger ve
       --color-gate-error ikisi de o zeminde 2:1'in altına düşüyor (elestiri-1
       E5, ölçülü).
     --radius-kart: .session-card--large + .player-media + .video-mikser'in
       elle-yazılmış 22px/20px'lerini tek kaynağa bağlar (elestiri-1 İ4);
       .canli-view > .player-media'nın gündüz+gece eşleri de buraya bağlı.
       `.studyo-iki-pane`nin masaüstü-kilitli 22px'i BİLEREK dışarıda (gece
       varyantı hiç olmadı; bağlamak orada değeri 20px'e düşürürdü).
     --font-size-marka: marka başlığının üç fazda kaçmış 1.25/1.45/1.5rem'i
       tek kaynağa indi; gündüz 1.45 / gece 1.5 görsel sonucu KORUNDU.
     --font-size-muzik-sarki: 1.05rem — base (0.9375) ile md (1.125) ARASINDA,
       hâlâ ölçek-dışı. Bu token drift'i çözmüyor, adını koyup donduruyor;
       md'ye oturtmak GÖRSEL bir karardır ve üslup-hizalama turuna bırakıldı
       (bkz. müzik yüzeyi hizalaması, aşama 3-6). AÇIK ARTIK. */
  --color-danger-night: #ff9d8c;
  --radius-kart: 22px;
  --font-size-marka: 1.45rem;
  --font-size-muzik-sarki: 1.05rem;
}

/* ── Sıfırlama ─────────────────────────────────────────────────────────── */

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

html,
body {
  height: 100%;
  /* Son savunma: bileşen düzeyindeki daralma çitlerinden biri ileride kaçsa
     bile belge yatay bir kaydırma yüzeyi üretmesin. `clip`, `hidden` gibi bir
     scroll container kurmadığı için gelecekteki sticky çocukları da bozmaz. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  display: block;
}

/* `hidden` özniteliği HER ZAMAN kazanır — aksi halde .btn gibi `display`
   ayarlayan bileşen sınıfları (özgüllükleri eşit/daha yüksek olduğu için)
   native `[hidden] { display: none }` UA kuralını ezip elemanı görünür bırakır. */
[hidden] {
  display: none !important;
}

button,
input,
textarea {
  font: inherit;
  color: inherit;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

h1,
h2,
h3,
p {
  margin: 0;
}

a {
  color: var(--color-accent);
}

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

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

.tabular-nums {
  font-variant-numeric: tabular-nums;
}

/* ── Butonlar / form kontrolleri ──────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: 0 var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-size: var(--font-size-base);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast),
    opacity var(--transition-fast);
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

a.btn {
  text-decoration: none;
}

.btn-primary {
  background: var(--color-accent);
  color: var(--color-on-accent);
}

.btn-primary:hover:not(:disabled) {
  background: var(--color-accent-strong);
}

.btn-secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-ink);
}

.btn-secondary:hover:not(:disabled) {
  border-color: var(--color-accent);
}

.btn-ghost {
  background: transparent;
  color: var(--color-ink-muted);
  border-color: transparent;
}

.btn-ghost:hover:not(:disabled) {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.btn-block {
  width: 100%;
}

/* G-b (owner onaylı, 2026-08-21) — "yayın yok" artık tıklamayı ENGELLEMEZ,
   yalnız solgunlaştırır: `.btn:disabled`ın GÖRSELLİĞİ aynen, İŞLEVİ olmadan.
   Sekme tıklanır, `#/canli` kendi dürüst boş-durumunu gösterir. */
.topbar-canli--bos {
  opacity: 0.55;
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

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

.field-hint {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
}

.field-input,
.field-textarea {
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-ink);
}

.field-textarea {
  min-height: calc(var(--touch-target) * 1.6);
  resize: vertical;
}

.field-input:focus,
.field-textarea:focus {
  border-color: var(--color-accent);
}

.field-error {
  font-size: var(--font-size-sm);
  color: var(--color-danger);
}

/* ── Uygulama iskeleti ─────────────────────────────────────────────────── */

.app-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topbar {
  display: flex;
  align-self: stretch;
  align-items: center;
  justify-content: space-between;
  /* Dikey padding kucultuldu: marka linki artik kendi 44px'ini tasiyor,
     eski padding ust bari gereksiz sisirirdi. Gorsel yukseklik ~ayni kalir. */
  padding: var(--space-2) var(--space-5);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  /* 100vw masaüstü scrollbar'ını, width:100% ise yalnız ICB'yi ölçer. Şerit
     flex kabında stretch olur; kök clip çiti belgeyi ayrı bir yatay yüzeye
     dönüştürmez, min-width:0 da şeridin kendi içeriğine göre büyümesini keser. */
  min-width: 0;
}

.topbar-brand {
  color: var(--color-ink);
  text-decoration: none;
  border-radius: var(--radius-sm);
  /* Dokunma yuksekligi: 27px -> 44px. Header'in padding'i linkin kendi
     hit-rect'ine dahil DEGIL - flex align-items:center yalnizca dikeyde ortalar,
     tiklanabilir kutuyu buyutmez (2026-08-19 tasarim denetimi). */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--font-display);
  font-weight: 500;
  text-transform: lowercase;
  letter-spacing: 0.32em;
  /* font-size tek kaynaktan: --font-size-marka (aşağıda, grup-C token bloğu) */
}

.topbar-brand:hover {
  color: var(--color-accent);
}

.view-root {
  flex: 1;
  padding: var(--space-5);
  max-width: 1180px;
  width: 100%;
  margin: 0 auto;
}

/* Stüdyo: tuval kenardan kenara nefes alır — yan padding minimum (8px; sıfır
   değil, çünkü radius'lu tuval viewport kenarına yapışınca kırpık görünür).
   Alt paneller ayrı bir tavana SARILMAZ: player'la aynı genişliği paylaşır —
   tek hiza çizgisi bilinçli karar, ikinci bir grid çizgisi görsel gürültü. */
.view-root--genis {
  max-width: none;
  padding-left: var(--space-2);
  padding-right: var(--space-2);
}

/* ── Ekran başlığı — TEK kalıp (2026-08-25) ───────────────────────────────
   Beş ekranın (takvim · gün · kayıt · canlı · müzik) başlık şeridi buraya
   indi. Kaynak "canlı"nın şeridi: SOL ad / SAĞ not, ad `font-display`
   italik 500 `--font-size-lg`.

   Bu turdan önce şerit DÖRT ayrı kuralda yaşıyordu (.calendar-header /
   .day-view-header / .player-header / .canli-header) ve dördü ikişer
   bildirimde birbirinden kaymıştı: align-items center/center/baseline/
   baseline, margin-bottom space-5/space-5/space-4/space-4. Hangisinin
   doğru olduğu hiçbir yerde yazılı değildi.
     · align-items: center  — ölçülü gerekçesi olan TEK değer (rev2 İ4:
       .back-link'in 44px dokunma kutusu, üstten hizalı başlıkla aynı
       satırda 4,2px kaçıyordu). Takvim ve gün zaten buradaydı.
     · margin-bottom: --space-5 — dört şeritten ikisinde zaten buydu.
   Başlık ADI ise "büyük başlık üçlüsü" olarak zaten üç yerde ayrı ayrı
   yazılıydı (.canli-title, .player-title, .canli-bos-baslik — üçü de
   BİREBİR aynı üç bildirim). Takvim ve gün başlıkları o aileye bu turda
   katıldı (Lora 700 dik -> display italik 500); müzik ilk kez görünür bir
   başlık kazandı. Kalıba yeni ekran eklemek artık iki sınıf adı yazmaktır,
   dosyanın sonuna beşinci bir şerit kuralı eklemek değil. */
.ekran-basligi {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  flex-wrap: wrap;
}

/* Sol yuva birden çok parça taşıdığında: gün ve kayıt ekranlarında geri
   bağlantısı ("‹ Aya dön") başlıkla aynı grupta, sağ yuva serbest kalır. */
.ekran-basligi-sol {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.ekran-basligi-ad {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  font-family: var(--font-display);
  font-size: var(--font-size-lg);
  font-style: italic;
  font-weight: 500;
}

/* Sağ yuva: izleyici sayacı, kapsam satırı — ekranın "notu". */
.ekran-basligi-not {
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
}

.loading-text,
.empty-text,
.error-text {
  color: var(--color-ink-muted);
  padding: var(--space-6) 0;
  text-align: center;
}

.error-text {
  color: var(--color-danger);
}

/* ── Giriş ekranı: .gate — "Mektup akışı — tören ekranları" bölümünde ────── */

/* ── Takvim ────────────────────────────────────────────────────────────── */

.calendar-nav {
  display: flex;
  gap: var(--space-2);
}

.calendar-nav-btn {
  width: var(--touch-target);
  height: var(--touch-target);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  font-size: var(--font-size-md);
  cursor: pointer;
}

.calendar-nav-btn:hover:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.calendar-nav-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  border-color: var(--color-border);
}

.calendar-weekdays {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.calendar-weekday {
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--color-ink-muted);
  text-align: center;
  padding-bottom: var(--space-1);
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-2);
}

.day-cell {
  min-height: 108px;
  border-radius: var(--radius-md);
  padding: var(--space-2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.day-cell--empty {
  background: transparent;
  border-color: transparent;
  color: var(--color-ink-muted);
  opacity: 0.55;
}

.takvim-bosluk {
  display: none; /* yalnız-mobil eleman */
}

.day-cell--filler {
  visibility: hidden;
}

.day-number {
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--color-ink-muted);
}

.day-cell--today .day-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-on-accent);
}

.session-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.session-card {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1);
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid transparent;
  text-align: left;
  cursor: pointer;
  min-height: var(--touch-target);
  width: 100%;
}

.session-card:hover {
  background: var(--color-surface-sunken);
  border-color: var(--color-border);
}

.session-thumb {
  width: 40px;
  height: 24px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunken);
  flex-shrink: 0;
}

.session-meta {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.session-time {
  font-size: var(--font-size-sm);
  font-weight: 600;
}

.session-duration {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
}

.session-flagbadge {
  margin-left: auto;
  font-size: var(--font-size-sm);
  color: var(--color-accent);
  background: var(--color-accent-soft);
  border-radius: 999px;
  padding: 0 var(--space-2);
  flex-shrink: 0;
}

.day-more {
  display: flex;
  align-items: center;
  min-height: var(--touch-target);
  padding: var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--color-accent);
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  width: 100%;
}

.day-more:hover {
  text-decoration: underline;
}

/* Büyük gün-görünümü kartları (#/gun/...) — takvim kartının aynısı, geniş */

.session-card--large {
  padding: var(--space-3);
  border-color: var(--color-border);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  border-radius: var(--radius-md);
}

.session-card--large .session-thumb {
  width: 96px;
  height: 54px;
}


.day-session-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.back-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-target);
  padding: 0 var(--space-2);
  color: var(--color-ink-muted);
  text-decoration: none;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  font-weight: 600;
}

.back-link:hover {
  color: var(--color-accent);
}

/* ── Oynatıcı ──────────────────────────────────────────────────────────── */


.player-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--space-5);
  align-items: start;
}

.player-main {
  min-width: 0;
}

.player-media {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  /* Tuval rolü "gece"dir, "mürekkep" değil: --color-ink gece temasında AÇIK
     renge döner ve letterbox krem parlardı (2026-08-22 faz-2 c-E2′/d-E1 +
     oynat-tasarımı B3, üç bağımsız tanık). --color-night iki temada da koyu.
     .player-media--katilim istisnası aşağıda (kaynak-sırası) aynen çalışır. */
  background: var(--color-night);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.player-media video {
  width: 100%;
  height: 100%;
  display: block;
}

.prep-panel {
  color: var(--color-on-accent);
  width: 100%;
  max-width: 360px;
  padding: var(--space-5);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: center;
}

.prep-phase {
  font-size: var(--font-size-md);
  font-weight: 700;
}

.prep-status {
  font-size: var(--font-size-sm);
  opacity: 0.85;
}

.prep-note {
  font-size: var(--font-size-sm);
  opacity: 0.75;
}

.progress-track {
  width: 100%;
  height: 8px;
  border-radius: 999px;
  background: var(--color-progress-track-bg);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  width: var(--progress-percent, 0%);
  background: var(--color-on-accent);
  border-radius: inherit;
  transition: width var(--transition-base);
}

.prep-error {
  font-size: var(--font-size-base);
}

.player-timeline {
  margin-top: var(--space-3);
}

.timeline-track {
  position: relative;
  height: 20px;
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
}

/* Gorunur isaret 14px, DOKUNMA alani 44px.
   Tik gercek bir <button>: basinca video o ana atliyor. 14x14 dokunma yuzeyi
   gereken alanin ~%10'uydu (2026-08-19 tasarim denetimi) - parmakla guvenilir
   sekilde vurulamiyordu. Kutuyu buyutmek yerine gorunur kareyi ::before'a alip
   butonun KENDISINI 44x44 yaptik: hedef parmagin bekledigi yerde buyudu, tasarim
   ayni kaldi. Sasede saydam kalan alan zaman cizelgesinin ustunde durur ve
   altindaki scrubber'i kapatmasin diye dikeyde ortalanir. */
.timeline-tick {
  position: absolute;
  top: 50%;
  left: var(--tick-pos, 0%);
  transform: translate(-50%, -50%);
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  border-radius: 3px;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.timeline-tick::before {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 3px;
  background: var(--color-accent);
}

.timeline-tick:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 37px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-ink);
  color: var(--color-paper);
  font-size: var(--font-size-sm);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  white-space: nowrap;
  pointer-events: none;
}

.player-sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.sidebar-section {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}

.sidebar-section-title {
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: var(--space-3);
}

.mark-btn {
  margin-bottom: var(--space-3);
}

.flag-form {
  display: flex;
  flex-direction: column;
  margin-bottom: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
}

.flag-form-actions {
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}

.flags-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.flag-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
}

.flag-row:hover {
  background: var(--color-surface-sunken);
}

.flag-row-jump {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  padding: var(--space-1) 0;
  min-height: var(--touch-target);
}

.flag-row-jump:active {
  color: var(--color-accent-strong);
}

.flag-time {
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-accent);
  flex-shrink: 0;
  min-width: 3.5em;
}

.flag-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.flag-label {
  font-size: var(--font-size-base);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flag-sub {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flag-delete-btn {
  width: var(--touch-target);
  height: var(--touch-target);
  flex-shrink: 0;
  border-radius: var(--radius-md);
  border: none;
  background: none;
  color: var(--color-ink-muted);
  cursor: pointer;
}

.flag-delete-btn:hover {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.flags-empty {
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
}

.siblings-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.sibling-row {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--touch-target);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  background: none;
  text-align: left;
  cursor: pointer;
  font-size: var(--font-size-sm);
}

.sibling-row:hover {
  background: var(--color-surface-sunken);
}

.sibling-row--current {
  color: var(--color-accent);
  font-weight: 700;
}

/* ── Canlı ─────────────────────────────────────────────────────────────── */
/* Yerleşim 2026-08-21'den beri STÜDYONUN kardeşidir, oynatıcının değil: tuval
   üstte tam genişlik (.player-media), kontrol satırı hemen altında, widget'lar
   en altta yan yana (.canli-alt-paneller). `.player-layout` / `.player-main` /
   `.player-sidebar` ızgarası burada artık KULLANILMAZ (yalnız `renderPlayer`
   kullanıyor); `.player-media` ve `.sidebar-section` aynen paylaşılır. Burada
   yalnız canlıya ÖZGÜ olan şey tanımlanır (başlık şeridi, yorum akışı). */


.canli-nokta {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-live);
  flex-shrink: 0;
}


/* ── Video-altı mikser (Canlı) ────────────────────────────────────────────
   17-mikser-ses-haritasi §3: video'nun HEMEN ALTINDA, radyo kapalıyken de
   HER ZAMAN görünür — Ortam kanalı gerçek (videoEl.volume), Müzik kanalı
   pasif (bağlanacak sinyal yok). Yüzey/kenarlık/radius tokenları
   .sidebar-section'la aynı — yeni görsel dil açılmadı. */
.video-mikser {
  display: flex;
  gap: var(--space-6);
  margin-top: var(--space-3);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.mikser-kanal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.mikser-kanal--pasif {
  opacity: 0.55;
}

/* İş-1b (2026-08-25, owner kararı) — Ortam (video-altı) + Müzik (radyo
   kartına taşındı) kanalları dikeyden yataya döndü: dikey sürgü + 140px'lik
   rotate(-90deg) kutusu telefonda dikey ekran yiyordu. Modifier sınıfı
   BİLEREK yalnız bu iki kanalı işaretler — kayıt oynatıcısının mikseri
   (`#/kayit`, AYNI `.mikser-kanal`/`.mikser-surgu` tabanını paylaşır) bu
   turun kapsamı DIŞINDA, dikey kalır (kapsam çiti). */
.mikser-kanal--yatay {
  flex-direction: row;
  flex-wrap: wrap;
  width: 100%;
}

.mikser-kanal--yatay .mikser-surgu-kutu {
  width: auto;
  height: auto;
  flex: 1 1 auto;
  min-width: 0;
}

.mikser-kanal--yatay .mikser-yuzde {
  flex: 0 0 auto;
  min-width: 2.5em;
  text-align: right;
}

.mikser-kanal--yatay .mikser-not {
  flex: 1 1 100%;
  text-align: left;
  max-width: none;
}

.mikser-surgu-kutu {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: 140px;
}

/* Standart yatay <input type=range> + rotate(-90deg): deprecated
   `-webkit-appearance: slider-vertical`e yaslanmadan üç tarayıcıda da aynı
   davranan dikey sürgü (17-mikser-ses-haritasi §3'ün önerdiği yol). */
.mikser-surgu {
  width: 140px;
  height: var(--touch-target);
  margin: 0;
  /* .mikser-surgu-kutu bir flex kutusu; flex-shrink varsayılanı (1) olmadan
     beyan edilen 140px atıl kalıp UA'nın input[type=range] içsel min-content
     genişliğine düşüyordu (ölçüldü: 129px, Chromium) — fader tarayıcıdan
     tarayıcıya farklı boyda oturuyordu (M4 review bulgusu). */
  flex-shrink: 0;
  transform: rotate(-90deg);
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

/* İş-1b — yatay varyant: rotate YOK, genişlik kutuyu doldurur (kutu kendisi
   `.mikser-kanal--yatay .mikser-surgu-kutu`da esner). Aynı özgüllük (tek
   class), sonra geldiği için `.mikser-surgu`nun 140px/rotate'ini ezer. */
.mikser-surgu--yatay {
  width: 100%;
  height: var(--touch-target);
  flex-shrink: 1;
  transform: none;
}

.mikser-surgu::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 999px;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
}

.mikser-surgu::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 24px;
  height: 24px;
  margin-top: -9px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 2px solid var(--color-surface);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

.mikser-surgu::-moz-range-track {
  height: 6px;
  border-radius: 999px;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
}

.mikser-surgu::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 2px solid var(--color-surface);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

.mikser-surgu:disabled {
  cursor: not-allowed;
}

.mikser-surgu:disabled::-webkit-slider-thumb {
  background: var(--color-ink-muted);
}

.mikser-surgu:disabled::-moz-range-thumb {
  background: var(--color-ink-muted);
}

.mikser-surgu:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

.mikser-yuzde {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
}

.mikser-etiket {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  font-weight: 600;
}

.mikser-not {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  text-align: center;
  margin: 0;
  max-width: 10em;
}

/* Kayıt oynatıcısının mikseri (2026-08-22 akşam, müzik arşivi): canlı mikserin
   sınıfları birebir, artı üçüncü bir "durum" sütunu — müzik çalıyor mu, bu
   dakikada radyo var mıydı, tarayıcı jest mi bekliyor (iOS autoplay). Sütun
   sürgü değil metin taşıdığı için sola yaslı ve esnek; dar ekranda alta sarar. */
.video-mikser--kayit {
  flex-wrap: wrap;
  align-items: flex-start;
}

.mikser-durum-kutu {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2);
  flex: 1 1 12em;
  min-height: var(--touch-target);
}

.mikser-durum-kutu .mikser-durum {
  text-align: left;
  max-width: none;
}

.mikser-baslat {
  align-self: flex-start;
}

.canli-kenar-satiri {
  display: flex;
  /* Yol 3 madde 3 (12-radyo-sentez.final.md) rozetin ALTINA ikinci bir
     dürüstlük satırı (`.canli-hls-dusus-not`) ekledi — sütuna çevrildi,
     ikisi de sağa hizalı kalır (`align-items`, eski `justify-content:
     flex-end`in yerini alır). Tek çocukken (HLS notu `hidden`) davranış
     BİREBİR eskisi gibi kalır. */
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
  min-height: 28px;
  margin-top: var(--space-2);
}

.canli-kenar-rozeti {
  /* inline-flex + iki eksen ortalaması: aile üyeleri hem <button> hem <span>
     olarak kuruluyor ve min-height'ları değişken (28/44px) — WebKit'te
     min-height'lı button içeriği ortalamaz, metin ÜSTE yapışır (2026-08-23
     saha bulgusu, telefon/iPad). Ortalamayı eleman tipinden bağımsız kıl. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  font-weight: 700;
  line-height: 1;
  cursor: default;
}

.canli-kenar-rozeti:disabled {
  opacity: 1;
}

.canli-kenar-rozeti--geride {
  border-color: var(--color-danger);
  color: var(--color-danger);
  cursor: pointer;
}

.canli-kenar-rozeti--geride:hover {
  background: var(--color-surface-sunken);
}

.canli-kenar-rozeti--duraklatildi {
  font-weight: 600;
}

/* WebRTC ICE/SDP tamamlanana kadar (pc.connectionState !== "connected") —
 * --duraklatildi ile AYNI pasif aile (aynı görsel ağırlık), ayrı sınıf
 * çünkü anlamı farklı: kullanıcı durdurmadı, bağlantı henüz kurulmadı. */
.canli-kenar-rozeti--baglaniyor {
  font-weight: 600;
}

/* Yol 3 madde 3 (12-radyo-sentez.final.md) — HLS-düşüş dürüstlük notu.
   `.radyo-kaset-not`in emsali (fısıltı register, alarm rengi YOK): kaçış-
   kapağı bir arıza değil, bilinen bir yavaş yol — kırmızı/kalın bir dil
   yanlış alarm olurdu. */
.canli-hls-dusus-not {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  text-align: right;
}

/* ── Kalite satırı (2026-08-24) — rozet ailesinin yanında, aynı hap dili.
   Satır `.canli-kenar-satiri`nin çocuğudur: katılım geçişindeki gizlenme
   (birleşme-K6) ve sağa hizalama oradan miras. Pasif üyeler (o yolda
   karşılığı olmayan preset'ler) disabled + soluk — "hayalet kontrol" değil,
   adlı bir yokluk. */
.canli-kalite-satiri {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.canli-kalite-etiket {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  text-transform: lowercase;
  letter-spacing: .02em;
  margin-right: var(--space-1);
}

.canli-kalite-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  font-weight: 600;
  line-height: 1;
  text-transform: lowercase;
  letter-spacing: .02em;
  cursor: pointer;
}

.canli-kalite-btn:hover:not(:disabled) {
  background: var(--color-surface-sunken);
}

.canli-kalite-btn:disabled {
  opacity: .45;
  cursor: default;
}

.canli-kalite-btn--secili {
  border-color: var(--color-accent-strong);
  color: var(--color-accent-strong);
  font-weight: 700;
}

.canli-bos {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
  text-align: center;
}

.canli-bos-baslik {
  font-family: var(--font-display);
  font-size: var(--font-size-lg);
  font-weight: 500;
}

.canli-bos-metin {
  color: var(--color-ink-muted);
  max-width: 34ch;
}

/* ── Canlı: katılım satırı + alt paneller (owner 2026-08-21) ───────────────
   Stüdyonun emsali: kontrol satırı tuvalin hemen altında, widget'lar en altta
   yan yana (.studyo-kontrol-satiri / .studyo-alt-paneller ile aynı ölçüler).
   Kolon sayısı farkı bilinçli — Canlı'da iki kart var (Radyo + Yorumlar),
   stüdyoda üç; kart-içi görsel dil (.sidebar-section) ikisinde de aynı. */
.canli-katil-satiri {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-3);
}

.canli-katil-satiri .btn {
  flex: 1;
  min-width: 160px;
}

.canli-alt-paneller {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
  align-items: start;
  margin-top: var(--space-4);
}

/* Katılım modunda aynı yuva bir video çerçevesi değil, katılımcı tuvalinin
   (izin/uyarı panelleri + kendi kamera + Erdem-ham + alt yönerge) taşıyıcısıdır:
   16/9 çerçeve, siyah zemin ve overflow kırpması buradan kalkar — kırpma
   kalsaydı tuvalin altındaki satırlar görünmezdi. .player-media kuralının
   KENDİSİNE dokunulmadı; player view'ı onu kullanmaya devam ediyor. */
.player-media--katilim {
  display: block;
  aspect-ratio: auto;
  background: transparent;
  border-radius: 0;
  overflow: visible;
}

/* Genişlik tavanı Canlı'da kalktı (view-root--genis); tavansız bir 16/9 tuvalin
   YÜKSEKLİĞİ pencere genişliğiyle doğrusal büyüyor ve 2026-08-21 ölçümünde hem
   1280×800'de hem 1920×1080'de Katıl düğmesini, mikseri, rozeti ve alt panelleri
   fold'un ALTINA düşürdü — yani eylem düğmeleri ekranda yoktu. Tavan genişliğe
   değil yüksekliğe bağlanır: tuval kenardan kenara kalır (tek hiza çizgisi +
   geniş-ekran kararı korunur), yalnız yüksekliği viewport'a bağlanır. Oranı
   bozan clamp'in karşılığı object-fit: contain — kapsam Canlı'nın KENDİ
   yuvasıdır, paylaşılan .player-media / .player-media video kurallarına
   dokunulmaz (#/player aynen kalır). */
.canli-view > .player-media:not(.player-media--katilim) {
  max-height: 62vh;
}

.canli-view > .player-media:not(.player-media--katilim) > video {
  object-fit: contain;
}

/* Katılım yuvası aspect-ratio taşımaz (yüksekliği içeriden gelir) ve
   overflow: visible'dır: aynı tavan DIŞ kutuya konsaydı iç tuval taşar, altındaki
   yönerge satırının üstüne binerdi. Tavan bu yüzden tuvalin kendisine konur —
   tek-düğme kararından (2026-08-21) sonra tuvalin kendi "Katıl"ı yok, korunacak
   düğme tektir: dıştaki "Katılımdan ayrıl" fold üstünde kalır. */
.canli-view > .player-media--katilim .studyo-iki-pane {
  max-height: 62vh;
}

/* 2026-08-21 review B2 — F3 izin paneli bu sütuna masaüstünde 211px,
   mobilde 308px ekliyor; tavan tuvalin KENDİSİNDE olduğu için o yükseklik saf
   ilaveydi ve ölçümde o günün iki düğmesi (tuvalin kendi "Katıl"ı ile dıştaki
   "Katılımdan ayrıl") fold'un altına düşüyordu — yani yukarıdaki yorumun
   koruduğu değişmez, tam onu koruyan dalgada kırılıyordu. Tek-düğme kararından
   sonra korunacak düğme yalnız dıştaki "Katılımdan ayrıl"dır; kural aynen
   geçerli. Panel görünürken tuval tavanı küçülür: izin yokken gösterilecek bir
   görüntü zaten yok, düğme ise ekranda kalmak zorunda.
   Sınıf JS'ten gelir (izinPaneliKur/onGorunurluk) — `:has()` desteğine
   bağlanmaz, çünkü desteklemeyen tarayıcıda kural sessizce kaybolurdu. */
.canli-view > .player-media--katilim > .studyo-katilimci--yonergeli .studyo-iki-pane {
  max-height: 32vh;
}

/* Tuvalin altındaki yönerge satırının boşluğunu eskiden araya giren
   .studyo-kontrol-satiri taşıyordu (margin-top: var(--space-3)); tek-düğme
   kararıyla (2026-08-21) o satır katılımcı tuvalinden silinince yönerge tuvale
   0px yapıştı — .studyo-katilimci'nin taban kuralı yok ve global `p` sıfır
   marjlı. Boşluk artık satırın kendisinde. (.studyo-kontrol-satiri silinmedi:
   yayıncı konsolu onu kullanmaya devam ediyor.) */
.studyo-katilimci > .field-hint {
  margin-top: var(--space-3);
}

/* ── Radyo (Canlı sayfasının "Radyo" kartı) ───────────────────────────── */
/* .sidebar-section aynen kullanılır, burada yalnız radyoya özgü parçalar. */

.canli-radyo-bolumu {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  /* `.canli-alt-paneller` grid'inin doğrudan öğesi. Varsayılan min-width:auto
     kuyruktaki nowrap şarkı adını grid'in içsel minimumu yapıp belgeyi
     viewport dışına büyütebilir; grid item içerikten bağımsız daralabilmeli. */
  min-width: 0;
}

.radyo-ust {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.radyo-ust .sidebar-section-title {
  margin-bottom: 0;
}

.radyo-rozet {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-live);
  flex-shrink: 0;
}

.radyo-rozet-nokta {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-live);
  flex-shrink: 0;
}

.radyo-kapali-not {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
}

/* ── Radyo kartının ÜÇÜNCÜ hâli: `kaset` akışı (2026-08-22 müzik bacağı) ──
   `.radyo-govde`nin İÇİNDE değil KARDEŞİ: owner'ın `acik` beyanından da
   `mod`undan da bağımsız yaşar, tek kapısı akışın canlı olmasıdır (bkz.
   app.js `kartiUygula` — DÜZELTME, review 2026-08-22: bu yorum yanlışlıkla
   var olmayan bir `kasetKartiniUygula` adına işaret ediyordu; gerçek adı
   `radyoKasetOynatici` içindeki `kartiUygula`). Görsel dili `.radyo-sh-kart`ın
   aynısı — ikisi de "radyo şu an şuradan geliyor" diyen kutulardır. */
.radyo-kaset-kart {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunken);
}

/* AYNI oynatıcı "Şu an yayın yok" ekranına da monte ediliyor (radyo bağımsız
   bacaktır — kamera kapalıyken de müzik akabilir). O ekran `align-items:center`
   bir flex kolonudur, yani kart içeriğine göre BÜZÜLÜR ve içindeki `.btn-block`
   düğme komik derecede dar görünürdü. Genişlik oradaki metin bloğunun
   (`.canli-bos-metin`, 34ch) hizasına sabitlenir. */
.canli-bos .radyo-kaset-kart {
  width: 100%;
  max-width: 34ch;
}

/* Ses <audio> elemanı GÖRÜNMEZ: `controls` yok, oynatma/durdurma tek düğmeden
   (radyoKasetBtn) geçer. `display:none` bir <audio>'nun çalmasını ENGELLEMEZ
   (video'nun aksine ses elemanı görünürlükten bağımsızdır) — eleman yalnız
   srcObject taşıyıcısıdır. */
.radyo-kaset-audio {
  display: none;
}

/* Tek satırlık durum notu: "bağlanıyor…", "yayın yok — yeniden deneniyor…",
   "tarayıcı sesi engelledi". Normal (çalan) hâlde GİZLİDİR — sessiz başarı. */
.radyo-kaset-not {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  margin: 0;
}

/* ── Ses seviyesi göstergesi (T2 tanığı, 2026-08-22) — app.js `radyoSesSeviyesiKur`.
   `.radyo-kaset-not`un aksine dinlerken GÖRÜNÜR kalır: bu, "bağlandı" değil
   "akış GERÇEKTEN ses taşıyor" tanığıdır ve `.progress-track`/`.progress-fill`
   ile AYNI mekanizma (JS `--radyo-seviye-oran` özel özelliğini her karede
   yazar) — ayrı bir class çifti çünkü buradaki track kartın AÇIK renkli
   `--color-surface-sunken` zemininde oturuyor, `.progress-track`ın koyu-zemin
   renkleri (`--color-progress-track-bg`/`--color-on-accent`) burada
   görünmezdi. */
.radyo-seviye {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.radyo-seviye-track {
  flex: 1;
  height: 6px;
  min-width: 32px;
  border-radius: 999px;
  background: var(--color-border);
  overflow: hidden;
}

.radyo-seviye-fill {
  height: 100%;
  width: var(--radyo-seviye-oran, 0%);
  background: var(--color-accent);
  border-radius: inherit;
  /* `.progress-fill`in aksine `transition` YOK: burada geçiş 60 fps'te kendi
     karesini çiziyor (bkz. app.js `olcumDongusu`), bir CSS geçişi eklemek onu
     asenkron ikinci bir animasyona bindirip çubuğu titretirdi. */
}

/* Eşik aşıldığında ("ses gelmiyor") metin BİLEREK `--color-danger`/uyarı
   rengine GEÇMEZ (`.radyo-sh-durum--yayinda`'nın aksine): owner müziği
   duraklattığında bu normal bir hâldir, kırmızı/kalın bir "arıza" dili yanlış
   alarm olurdu. Tek fark kalınlık — dikkat çeker ama alarm vermez. */
.radyo-seviye--sessiz .radyo-seviye-not {
  font-weight: 600;
}

.radyo-seviye-not {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  margin: 0;
  min-height: 1em; /* metin boşken de satır zıplamasın */
}

/* Tanınmayan mod notu — `.radyo-kapali-not`un emsali (tek satır, sessiz), ama
   uyarı olduğu için vurgu rengiyle. Sunucu tanımadığı bir `mod` değerini
   olduğu gibi döndürür ve kaset yolunu allow-list'le kapatır; kartın da o anda
   TÜM mutasyon kontrolleri gizlidir (bkz. app.js `radyoModuUygula`), yani bu
   satır çoğu zaman gövdedeki tek içeriktir. */
.radyo-mod-uyari {
  font-size: var(--font-size-sm);
  color: var(--color-danger);
}

/* Yol 3 (12-radyo-sentez.final.md K6) — parça-konum rozeti + gecikme sayısı.
   `.radyo-kaset-not`/`.radyo-seviye-not`in AYNI "fısıltı register"i (Emsal):
   ikisi de K1'in "sağlıklı" satırında GÖRÜNÜR, aksi hâlde `hidden` kalır —
   ayrı sınıflar çünkü anlamları farklı (bağlantı durumu / RMS notu değil,
   bilgilendirme), ama görsel dil BİLEREK aynı: sakin, alarm rengi yok. */
.radyo-konum-rozeti,
.radyo-gecikme-not {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  margin: 0;
}

.radyo-govde {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

.radyo-simdi {
  min-width: 0;
  font-size: var(--font-size-base);
  overflow-wrap: anywhere;
}

/* (2026-08-25: radyo kartının içindeki eski birincil Jam düğmesinin stilleri
   governor kararıyla söküldü; Stationhead kartının link stili de aynı turda
   birlikte gitmişti. UI'nın TEK jam-girişi artık aşağıdaki `.jam-cta`
   şeridi.) */

/* ── Jam CTA şeridi (2026-08-25, #/canli üstü) — burası tuvalin ALTINDA,
   ikincil-vurgulu bir kart (accent kenar + soft zemin), `.btn-primary`in
   dolu-renk birincil-CTA diliyle KARIŞTIRILMASIN — oynat mührü tek birincil
   CTA olarak kalsın diye bilerek daha sessiz (R2). İki tema da
   --color-accent* aile token'larından gelir (bkz. satır 2635 gece forku),
   burada AYRI bir gece kuralı gerekmedi. */
.jam-cta {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-top: var(--space-3);
  padding: var(--space-3);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: var(--color-accent-soft);
  text-decoration: none;
}

.jam-cta:hover {
  background: var(--color-accent-soft);
  filter: brightness(0.97);
}

.jam-cta-metin {
  font-size: var(--font-size-base);
  font-weight: 700;
  color: var(--color-accent-strong);
}

.jam-cta:hover .jam-cta-metin {
  text-decoration: underline;
}

.jam-cta-not {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
}

/* İş-2 (2026-08-25) — giriş ekranındaki aynı `.jam-cta`, `.gate-box`ın
   `align-items:center`i altında içeriğe göre büzülürdü (form/`.gate-input`
   gibi kardeşleri width:100%); şerit onlarla AYNI genişlik ritmine oturur. */
.gate-box .jam-cta {
  align-self: stretch;
  width: 100%;
}

/* `.radyo-kaset-btn` BİLEREK kuralsız: o ikisi kullanıcıyı dışarı yollar (<a>,
   alt çizgisi silinmeli), bu ise sesi BU sekmede açar (<button>) — `.btn` +
   `.btn-block` zaten yeterli, ek bir kural yazmak `width:100%`ü ikinci kez
   söylemek olurdu. Sınıf yalnız ileride ayrışma gerekirse kanca olsun diye
   elemanda duruyor. */

.radyo-arama-form {
  display: flex;
  flex-direction: column;
}

.radyo-sonuc-liste,
.radyo-kuyruk-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.radyo-sonuc-liste {
  max-height: 40vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.radyo-sonuc-satiri,
.radyo-kuyruk-satiri {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-1) 0;
}

.radyo-kapak {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunken);
  flex-shrink: 0;
}

.radyo-kapak--kucuk {
  width: 28px;
  height: 28px;
}

.radyo-sonuc-metin {
  flex: 1;
  min-width: 0;
  font-size: var(--font-size-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.radyo-ekle-btn {
  flex-shrink: 0;
  font-size: var(--font-size-sm);
  padding: 0 var(--space-3);
}

.radyo-bos {
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
}

.radyo-kuyruk-bolumu {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.radyo-kuyruk-baslik {
  margin-bottom: 0;
}

.radyo-yonetim {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-3);
}

.radyo-yonetim > summary {
  cursor: pointer;
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-ink-muted);
  list-style: none;
}

.radyo-yonetim > summary::-webkit-details-marker {
  display: none;
}

.radyo-yonetim > summary::before {
  content: "▸ ";
}

.radyo-yonetim[open] > summary::before {
  content: "▾ ";
}

.radyo-yonetim > summary:hover {
  color: var(--color-ink);
}

.radyo-yonetim-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.radyo-yonetim-satir {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  cursor: pointer;
}

.radyo-yonetim-satir input[type="checkbox"] {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  accent-color: var(--color-accent);
}

.canli-yorum-bolumu {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Akış kendi içinde kayar, sayfa değil: uzun bir yayında yüzlerce satır
   sayfayı sonsuza kadar uzatır ve giriş alanı ekrandan kaçardı. */
.yorum-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-height: 46vh;
  min-height: 120px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.yorum-satiri {
  padding: var(--space-2);
  border-radius: var(--radius-md);
  background: var(--color-surface-sunken);
}

.yorum-bas {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.yorum-ad {
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-accent);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.yorum-zaman {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  flex-shrink: 0;
}

/* Yorum kullanıcının kendi sözüdür ve KIRPILMAZ: uzun bir cümleyi üç noktayla
   kesmek, onu okunamaz kılmanın kibar hali olurdu. */
.yorum-metin {
  font-size: var(--font-size-base);
  overflow-wrap: anywhere;
}

.yorum-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.yorum-gonder-satiri {
  display: flex;
  gap: var(--space-2);
}

.yorum-gonder-satiri .field-input {
  flex: 1;
  min-width: 0;
}

/* ── Stüdyo (tarayıcıdan yayın — Seçenek A, 2026-08-20) ────────────────────
   Yerleşim Canlı'nın kardeşidir, ama `.player-layout` / `.player-main` /
   `.player-sidebar` ızgarası üzerinden DEĞİL: 2026-08-21'den beri ikisi de
   tuval-üstte + panel-altta düzenindedir (.studyo-alt-paneller /
   .canli-alt-paneller). Paylaşılan sınıflar `.player-media` ve
   `.sidebar-section`'dır. .mikser-* (video-mikser, mikser-kanal, mikser-surgu,
   mikser-etiket…) ve .canli-kenar-rozeti burada da yeniden kullanılabilir —
   burada yalnız stüdyoya ÖZGÜ olan sınıflar tanımlanır. */

.studyo-view {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.studyo-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.studyo-title {
  font-family: var(--font-display);
  font-size: var(--font-size-lg);
  font-weight: 500;
}

.studyo-mod-slot {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* ── Stüdyo günlüğü ("Yenilikler" popup'ı) — Ezgi'ye hediye notu ──────────
   Native <dialog>; DOM iskeleti app.js'te (`studyoGunlugunuKur`) sabit
   sınıf adlarıyla üretiliyor, burada yalnız o adlar giydiriliyor. Üslup
   "mektup dili": sıcak kâğıt zemin, Cormorant italik tarih, geniş satır
   aralığı — .mektup/.okuma törenine akraba ama tam-ekran değil, orta boy
   bir panel. */

/* UA'nın <dialog>'a getirdiği border/padding/background/dar max-width
   TAMAMEN ezilir. `padding: 0` PAZARLIKSIZ: app.js'in "panel dışına
   tıklayınca kapat" sözleşmesi `e.target === dialogEl` kontrolüne dayanır
   (bkz. app.js `backdropTikla`) — dialog'un kendi padding'i olsaydı o
   boşluğa tıklamak da `target === dialogEl` verir ama görsel olarak
   panelin İÇİ sayılırdı; padding 0 bu belirsizliği kapatır. Görünür kâğıt
   yüzeyi tamamı `.studyo-gunluk-panel`dedir. Safe-area merkezleme
   kutusunun kendisinde (`inset`) taşınır ki notch'lu cihazda panel köşeye
   yapışmasın. */
dialog.studyo-gunluk {
  position: fixed;
  margin: auto;
  inset: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
    env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  padding: 0;
  border: 0;
  background: transparent;
  max-width: min(34rem, calc(100vw - var(--space-5) * 2));
  max-height: 85vh;
  max-height: 85dvh;
}

/* Düz renk, TOKEN DEĞİL: `::backdrop`ın custom property kalıtımı Safari
   sürümleri arasında güvenilir değil — token yazıp iki temada da aynı
   karartmayı ummak yerine tek, kararlı bir değer kullanılıyor. */
dialog.studyo-gunluk::backdrop {
  background: rgb(0 0 0 / 45%);
}

.studyo-gunluk-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: inherit;
  padding: clamp(var(--space-4), 4vw, var(--space-6));
  background: var(--color-white-warm);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  animation: studyo-gunluk-belir 220ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .studyo-gunluk-panel {
    animation: none;
  }
}

.studyo-gunluk-ust {
  padding-right: var(--touch-target);
}

.studyo-gunluk-baslik {
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* Odak halkası küresel `:focus-visible` kuralından (dosya başı) miras
   gelir — burada ayrıca ezmiyoruz, kare düğme için o dil zaten doğru. */
.studyo-gunluk-kapat {
  position: absolute;
  top: 0;
  right: 0;
  width: var(--touch-target);
  height: var(--touch-target);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-ink-muted);
  cursor: pointer;
  transition: color var(--transition-fast);
}

.studyo-gunluk-kapat:hover {
  color: var(--color-ink);
}

.studyo-gunluk-govde {
  flex: 1 1 auto;
  min-height: 0;
  margin-top: var(--space-4);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.studyo-gunluk-giri + .studyo-gunluk-giri {
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--color-border);
}

.studyo-gunluk-tarih {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--font-size-md);
  color: var(--color-ink);
  margin-bottom: var(--space-4);
}

.studyo-gunluk-paragraf {
  font-family: var(--font-body);
  line-height: 1.9;
  color: var(--color-ink);
  margin-bottom: var(--space-4);
}

.studyo-gunluk-paragraf:last-child {
  margin-bottom: 0;
}

/* Mektup imzası — tarih satırıyla aynı el yazısı (display + italik), sağa
   yaslı. `:last-child` kuralı artık paragrafta değil BURADA bitiyor: imza
   varsa gövdenin son çocuğu odur. */
.studyo-gunluk-imza {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--font-size-md);
  color: var(--color-ink-muted);
  text-align: right;
  margin-top: var(--space-5);
  margin-bottom: 0;
}

@keyframes studyo-gunluk-belir {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* İki kişi tek stüdyo tuvalinde yan yanadır. Yayıncıdaki oran canvas'a da
   gittiği için ayraç, yalnız kozmetik bir bölücü değildir. */
.studyo-iki-pane {
  --studyo-sol-oran: 0.5;
  display: flex;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--color-ink);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.studyo-pane {
  min-width: 0;
  min-height: 0;
  border-radius: 0;
  /* Kontrol şeridinin ENİ, TEK yerden. `.studyo-pane-btn` de bu değişkeni
     okur — düğme eni ile rozetin ayırdığı yer ayrı ayrı yazılsaydı biri
     değişince öteki sessizce bayatlardı (bkz. `.studyo-rozet` max-width). */
  --studyo-pane-btn-eni: 36px;
  --studyo-serit-eni: var(--studyo-pane-btn-eni);
}

/* Şeritte ikinci bir düğme varsa (mute'lu pane) ayrılan yer de büyür.
   `:has()` desteklemeyen bir tarayıcıda bu kural düşer ve davranış bugünkü
   hâline döner — iyileştirme gelmemiş olur, regresyon olmaz. */
.studyo-pane:has(.studyo-pane-kontrol > * + *) {
  --studyo-serit-eni: calc(2 * var(--studyo-pane-btn-eni) + var(--space-1));
}

.studyo-pane--sol {
  flex: var(--studyo-sol-oran) 1 0;
}

.studyo-pane--sag {
  flex: calc(1 - var(--studyo-sol-oran)) 1 0;
}

/* Ezgi yokken yayıncı kendi kamerasını gerçekten tam kare görür; sağ pane ve
   ayraç yalnız ikinci akış geldiğinde geri açılır. */
.studyo-iki-pane--tek .studyo-pane--sol {
  flex: 1 1 0;
}

.studyo-iki-pane--tek .studyo-pane--sag,
.studyo-iki-pane--tek .studyo-ayirac {
  display: none;
}

/* Pointer Events mouse ve touch'u aynı sürükleme yolunda birleştirir. Görsel
   çizgi geniş, gerçek tutamaç daha da geniş olduğundan dokunarak kavranır. */
.studyo-ayirac {
  position: relative;
  z-index: 1;
  flex: 0 0 14px;
  cursor: col-resize;
  touch-action: none;
  background: var(--color-ink);
  outline: none;
}

.studyo-ayirac::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  transform: translateX(-50%);
  background: var(--color-border);
}

.studyo-ayirac:hover::after,
.studyo-ayirac:focus-visible::after {
  background: var(--color-accent);
}

/* Kamera/uzak önizleme videosu .player-media'nın boyutunu kullanır; farklı
   kamera oranları için canvas'taki geometriyle aynı `cover` kırpması uygulanır. */
.studyo-tuval {
  position: relative;
}

.studyo-onizleme {
  object-fit: cover;
}

/* Apple aynası — YALNIZ kendi önizlemen (`--kendi` eki). `.studyo-onizleme`
   tek başına (Ezgi/Erdem paneleri) ayna GÖRMEZ: karşı tarafı aynalamak
   onu aynalamak olurdu (Apple semantiği: kendi önizleme aynalı, karşı taraf
   aynasız). Giden yayın/kayıt bu kuralın kapsamı DIŞINDA — `pipKompozitoruKur`
   içindeki `anaVideo`/`pipVideo` DOM'a hiç eklenmez, yalnız `<canvas>`a
   `drawImage()` ile piksel-kopyalanır; CSS transform'u bu videolara zaten
   uygulanmaz (tuval + WebRTC track'i gerçek yönde kalır). */
.studyo-onizleme--kendi {
  transform: scaleX(-1);
}

/* "Yayına Başla" — ilk girişte ortadaki büyük stream düğmesi (2026-08-26
   owner direktifi). Tuvalin üstünü örten tam-ekran "başlat" durumu; kamera
   alınınca (cihazlariAlVeKur başarısı) `hidden` ile kalkar. İzin SADECE bu
   düğmeye basınca istenir — açılışta getUserMedia YOK. */
.studyo-baslat-ekrani {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: var(--color-ink);
}

.studyo-baslat-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  width: min(200px, 62%);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  border: 1px solid transparent;
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-size: var(--font-size-base);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--transition-fast), transform var(--transition-fast),
    box-shadow var(--transition-fast);
}

.studyo-baslat-btn:hover {
  background: var(--color-accent-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.studyo-baslat-btn:active {
  transform: translateY(0);
}

.studyo-baslat-ikon {
  width: 56px;
  height: 56px;
}

/* Pane üstü kontrol şeridi — owner 2026-08-21: "ekran büyütme ve mute
   kontrolleri olmalı". Konum SOL-ÜST ve gerekçesi üç taraflı: SAĞ-üst
   `.studyo-rozet`in ("yayın kapalı") yeri — tarayıcı turunda fiilen çakıştı;
   ALT-orta/sağ katılımcıdaki yerleşik `controls` çubuğunun yeri; ALT-şerit
   `.studyo-pane-bilgi`nin yeri. Geriye tek boş köşe sol-üst kalıyor.
   Ofset rozetle aynı (`--space-3`) — iki köşe aynı hizada okunsun. */
.studyo-pane-kontrol {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 2;
  display: flex;
  gap: var(--space-1);
}

.studyo-pane-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--studyo-pane-btn-eni, 36px);
  height: var(--studyo-pane-btn-eni, 36px);
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: var(--font-size-base); /* eski 15px bare-px değeri sayısal olarak base ölçeğiyle AYNI çıktı — token'a bağlandı (2026-08-25 review NOT-3) */
  line-height: 1;
  cursor: pointer;
}

.studyo-pane-btn:hover {
  background: var(--color-surface-sunken);
}

.studyo-pane-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Dokunmatikte hover yok ve parmak 36px'e zor basar — hedef 44px'e çıkar.
   Değişken üzerinden: düğme büyüyünce rozetin ayırdığı yer de kendiliğinden
   büyür, iki sayıyı ayrı ayrı güncellemek gerekmez. */
@media (pointer: coarse) {
  .studyo-pane {
    --studyo-pane-btn-eni: 44px;
  }
}

/* Tam ekranda pane tek başına sahnedir: kırpma YOK (cover -> contain), zemin
   mürekkep. `:fullscreen` ve `:-webkit-full-screen` BİLEREK ayrı kurallardır —
   tek listede birleşseler, birini tanımayan tarayıcı kuralın TAMAMINI düşürürdü
   (bu dosyanın `@supports` yorumundaki aynı ders). */
.studyo-pane:fullscreen {
  width: 100%;
  height: 100%;
  background: var(--color-ink);
}

.studyo-pane:-webkit-full-screen {
  width: 100%;
  height: 100%;
  background: var(--color-ink);
}

.studyo-pane:fullscreen .studyo-onizleme {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.studyo-pane:-webkit-full-screen .studyo-onizleme {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.studyo-pane-bilgi {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  left: var(--space-3);
  margin: 0;
  color: var(--color-on-accent);
  font-size: var(--font-size-sm);
  text-align: center;
}

/* Üst kenarın İKİ sakini vardır — sol-üstte `.studyo-pane-kontrol` şeridi,
   sağ-üstte bu rozet — ve ikisi de mutlak konumlu, yani birbirlerini İTMEZLER.
   Dar bir pane'de (ayraç min-oranı 0.20 → ~189px) rozet şeridin üstüne biner;
   şerit `z-index: 2` taşıdığı, rozet taşımadığı için de üste ŞERİT çıkar ve
   rozetin sol kenarını boyar. a7308fc de bu dosyanın kalite-okuma yorumu da
   "üst köşeler çakışmaz"ı OLGU diye devralmıştı; oysa bu bir garanti değil bir
   tesadüftü — 2026-08-22 tarayıcı ölçümü: 189px pane'de bugünkü üretim DOM'u
   (sol pane TEK düğmeli) 0px çakışıyor, ama sol pane'e ikinci bir düğme
   eklendiği an 20px çakışıyor.
   Çözüm rozete şeridin yerini AYIRTAN bir tavan: yer varken hiçbir şey
   değişmez (189px + tek düğme → tavan 121px, rozet 109px — dokunulmaz), yer
   yokken rozet SARAR. Sarma bilerek: kırpmak ("yayın kap…") bir durum
   beyanını yalancı yapardı, alt kenardaki kalite okumasının aynı dersi. */
.studyo-rozet {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  max-width: calc(100% - 2 * var(--space-3) - var(--studyo-serit-eni) - var(--space-2));
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  font-size: var(--font-size-sm);
  font-weight: 700;
  background: var(--color-surface);
  color: var(--color-ink-muted);
  border: 1px solid var(--color-border);
}

.studyo-rozet--acik {
  background: var(--color-danger);
  color: var(--color-on-danger);
  border-color: var(--color-danger);
}

/* Dürüst gösterge (2026-08-22) — giden bitrate + gerçek çözünürlük + varsa
   sınırlama sebebi. Konum ALT-SOL ve gerekçesi çakışma yasağının kendisidir:
   sağ-üst `.studyo-rozet`, sol-üst `.studyo-pane-kontrol` (a7308fc), alt-şerit
   `.studyo-pane-bilgi` — ama sonuncusu YALNIZ sağ pane'e konur, sol pane'in
   alt kenarı boş kalır. (Bu üç köşenin BİRBİRİYLE çakışmaması ayrı bir işti ve
   burada varsayılmıyor: üst kenarın iki sakini için ölçüm ve kural
   `.studyo-rozet`in yorumundadır.) `tabular-nums`: sayı iki saniyede bir değişiyor,
   değişken genişlikli rakamlar okumayı sürekli titretirdi.
   Rozetin AKSİNE kırmızıya çalmaz: bu bir arıza beyanı değil, sürekli bir
   okuma — kırmızı yalnız `--sinirli` halinde, o da uyarı şeridinin
   (accent-soft) diliyle, "arıza OLABİLİR" tonunda.
   SARILIR, KIRPILMAZ (2026-08-22 ölçümü): önce tek satıra kilitliydi
   (`nowrap` + `ellipsis`) ve 375px'te "1.4 Mbps · 960×540 · 24 fps · bant
   genişliği sınırlıyor" cümlesinin TAM SONUNU yiyordu — yani sınırlama
   sebebini, bu göstergenin var oluş nedenini. Sebep dizgenin sonunda durduğu
   için kırpma tam da susturmaya çalıştığımız sessizliği geri getiriyordu.
   Yuvarlaklık 999px'ten `--radius-lg`ye indi: iki satıra sardığında kaza
   gibi değil kasıtlı görünsün. */
.studyo-kalite-okuma {
  position: absolute;
  bottom: var(--space-3);
  left: var(--space-3);
  z-index: 2;
  max-width: calc(100% - 2 * var(--space-3));
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
}

.studyo-kalite-okuma--sinirli {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
  color: var(--color-ink);
}

.studyo-kontrol-satiri {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-3);
}

/* Owner 2026-08-21: yayıncıda yan panel yok — üst sıra yalnız kamera tuvali,
   üç kontrol paneli altta yan yana; .sidebar-section görsel dili aynen kalır. */
.studyo-alt-paneller {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  align-items: start;
  margin-top: var(--space-4);
}

.studyo-kontrol-satiri .btn {
  flex: 1;
  min-width: 160px;
}

.studyo-durum-metin,
.studyo-kulaklik-uyarisi {
  font-size: var(--font-size-sm);
  color: var(--color-ink-muted);
  margin: var(--space-2) 0 0;
}

.studyo-cihaz {
  margin-bottom: var(--space-3);
}

.studyo-kutu-satiri {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  font-size: var(--font-size-sm);
}

/* ── "Gelişmiş ses" katlanırı (2026-08-25, envanter §6 #4) — AEC/NS/AGC
   mühendis-kısaltmaları + varsayılan-kapalı üç anahtar owner'ın gördüğü ilk
   katmandan buraya taşındı. Görsel dil `.radyo-yonetim`in aynısı (▸/▾ ok,
   nötr renk) — yeni bir "katlanır" dili icat etmek yerine zaten var olanı
   tekrar kullanıyor. */
.studyo-gelismis {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-2);
  margin-top: var(--space-2);
}

.studyo-gelismis > summary {
  cursor: pointer;
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-ink-muted);
  list-style: none;
}

.studyo-gelismis > summary::-webkit-details-marker {
  display: none;
}

.studyo-gelismis > summary::before {
  content: "▸ ";
}

.studyo-gelismis[open] > summary::before {
  content: "▾ ";
}

.studyo-gelismis > summary:hover {
  color: var(--color-ink);
}

.studyo-gelismis-govde {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-top: var(--space-2);
}

/* Her checkbox'ın sade Türkçe açıklaması hemen ALTINDA, kutunun (20px,
   .studyo-kutu-satiri input kuralı) + satır boşluğunun hizasına girintili —
   açıklama hangi kutuya ait olduğunu konumla da söylesin, yalnız metinle değil. */
.studyo-gelismis-not {
  margin: 0 0 var(--space-1) calc(20px + var(--space-2));
}

/* F3 — izin/cihaz arızası artık tek kırmızı satır değil, kendini açıklayan bir
   yönerge: durum adı + adımlar + RELOAD'SIZ yeniden deneme düğmesi. Yayıncı ve
   Canlı-katılım AYNI bloğu kurar (izinPaneliKur), o yüzden tek kural yeter.
   Gizleme `[hidden]`ın !important kuralından gelir (yukarıda) — burada ayrıca
   bir `display:none` yazılmaz. */
.studyo-izin-yonerge {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--color-danger);
  border-radius: var(--radius-lg);
  background: var(--color-danger-soft);
}

.studyo-izin-baslik {
  margin: 0;
  font-weight: 600;
  color: var(--color-danger);
}

.studyo-izin-adimlar {
  margin: 0;
  padding-left: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--color-ink);
}

.studyo-izin-not {
  margin: 0;
}

/* Düğme blok değil: yönerge bir form değil, bir çıkış yoludur. */
.studyo-izin-yonerge .btn {
  align-self: flex-start;
}

/* F2 — rozet BAĞLANTIYI anlatır, bu şerit KARENİN kendisini ("rozet YAYINDA
   demek görüntü gidiyor demek değil", 2026-08-21). Kırmızı DEĞİL: bu bir arıza
   beyanı değil, arıza OLABİLİR uyarısıdır — durum düzelince kendiliğinden
   kalkar, kimse elle kapatmaz. */
.studyo-uyari-serit {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-strong);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md);
  background: var(--color-accent-soft);
  color: var(--color-ink);
  font-size: var(--font-size-sm);
}

/* 2026-08-21 review C1 — aynı anda doğru olan sebeplerin HEPSİ yazılır (tek
   satır göstermek `onizleme-siyah`ın sonrakileri maskelemesine yol açıyordu).
   Madde imi YOK: bunlar bir liste değil, aynı arızanın ayrı ayrı cümleleri. */
.studyo-uyari-satiri {
  margin: 0;
}

/* ── Bildirim (toast) ──────────────────────────────────────────────────── */

#toast-region {
  position: fixed;
  bottom: var(--space-5);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  /* Tören katmanlarının (150/170/200) ÜSTÜNDE: takvim tören sırasında arkada
     kurulur ve orada bir hata toast'u doğabilir — z:100'de görünmeden sönüyordu. */
  z-index: 250;
  width: min(420px, calc(100vw - var(--space-6)));
}

.toast {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  background: var(--color-ink);
  color: var(--color-paper);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-md);
}

.toast-message {
  font-size: var(--font-size-base);
}

.toast-action {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--color-accent-soft);
  font-weight: 700;
  cursor: pointer;
  min-height: 36px;
  padding: 0 var(--space-2);
}

.toast-action:hover {
  text-decoration: underline;
}

/* ── Duyarlı kırılımlar ────────────────────────────────────────────────── */

@media (max-width: 980px) {
  .player-layout {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Mobilde ayraç yok: iki önizleme eşit, alt alta ve dokunma kaydırmasını
     engellemeyen normal bloklara döner. */
  .studyo-iki-pane {
    flex-direction: column;
    aspect-ratio: auto;
    gap: var(--space-3);
    overflow: visible;
    background: transparent;
    border-radius: 0;
  }

  .studyo-pane {
    flex: 0 0 auto;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-lg);
  }

  /* Tek-kişi modunun masaüstü flex:1'i kolon-yönünde basis-0'a düşüp pane'i
     sıfır yüksekliğe çökertir — mobilde yükseklik aspect-ratio'dan gelir. */
  .studyo-iki-pane--tek .studyo-pane--sol {
    flex: 0 0 auto;
  }

  .studyo-ayirac {
    display: none;
  }

  .studyo-alt-paneller,
  .canli-alt-paneller {
    /* `1fr`in gizli `auto` minimumu uzun nowrap radyo satırını kolon ölçüsü
       yapıyordu; mobil iz de masaüstü gibi sıfır tabanlı olmalı. */
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 720px) {
  .view-root {
    padding: var(--space-4) var(--space-3);
  }

  .calendar-weekdays {
    display: none;
  }

  .calendar-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .day-cell--filler {
    display: none;
  }

  .day-cell {
    min-height: unset;
    flex-direction: row;
    align-items: center;
    gap: var(--space-3);
  }

  .day-cell--empty {
    padding: var(--space-1) var(--space-2);
  }

  /* Bugün asla katlanmaz — yalnız bugün-olmayan boş hücre gizlenir; koşu
     .takvim-bosluk aralık-satırına iner (JS her ikisini de basar). */
  .day-cell--empty:not(.day-cell--today) {
    display: none;
  }

  .takvim-bosluk {
    display: flex;
    align-items: center;
    /* .day-cell 1px kenar taşır (--empty'de yalnız rengi şeffaf) — kenarsız
       satır 1px sola/2px kısa oturur; şeffaf kenar iç-hizayı eşitler (İ1). */
    border: 1px solid transparent;
    padding: var(--space-1) var(--space-2);
  }

  .takvim-bosluk-etiket {
    min-width: 22px; /* "bugün" rozetiyle aynı hiza — İ1 kuralının kardeşi */
    text-align: center;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-ink-muted);
  }

  .day-cell .session-list {
    flex: 1;
  }

  .session-card--large .session-thumb {
    width: 64px;
    height: 36px;
  }
}

/* ── Azaltılmış hareket ────────────────────────────────────────────────── */

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

/* ── Mektup akışı — tören ekranları ────────────────────────────────────── */

.gate { min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: var(--space-5); background: var(--color-night); }
.gate-box { display: flex; flex-direction: column; align-items: center;
  gap: var(--space-6); width: 100%; max-width: 360px; }
.gate-title { font-family: var(--font-display); font-weight: 500;
  font-size: var(--font-size-lg); color: var(--color-cream);
  text-transform: lowercase; letter-spacing: 0.42em; text-indent: 0.42em; }
.gate-rule { width: 40px; height: 1px; border: 0; margin: 0; background: var(--color-cream-soft); }
.gate-form { display: flex; flex-direction: column; align-items: center;
  gap: var(--space-4); width: 100%; }
.gate-input { width: 100%; min-height: var(--touch-target); background: transparent;
  border: 0; border-bottom: 1px solid var(--color-cream-soft); border-radius: 0;
  color: var(--color-cream); text-align: center; letter-spacing: 0.4em;
  padding: var(--space-2); }
.gate-input::placeholder { color: var(--color-cream-soft); letter-spacing: 0.3em; }
/* outline'ı SÖNDÜRME: klavye odak halkası :focus-visible'dan gelir (rengi
   aşağıda krem'e çevrilir); yalnız alt-çizgi koyulaşması yeterli işaret değildi. */
.gate-input:focus { border-bottom-color: var(--color-cream); }
.gate .field-error { color: var(--color-gate-error); text-align: center; }
.gate :focus-visible { outline-color: var(--color-cream); }
.gate-enter { display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--touch-target); padding: 0 var(--space-6);
  background: transparent; border: 1px solid var(--color-cream-soft);
  border-radius: 999px; color: var(--color-cream); font-weight: 500;
  font-size: var(--font-size-sm); letter-spacing: 0.28em; text-transform: uppercase;
  cursor: pointer; transition: background-color var(--transition-base), color var(--transition-base); }
.gate-enter:hover:not(:disabled) { background: var(--color-cream); color: var(--color-night); }
.gate-enter:disabled { cursor: not-allowed; opacity: 0.55; }

.whiteout { position: fixed; inset: 0; z-index: 200; background: var(--color-white-warm);
  opacity: 0; pointer-events: none; transition: opacity 2.2s ease-in-out; }
.whiteout--on { opacity: 1; pointer-events: auto; }
.whiteout--cikis { transition-duration: 1.8s; }

.jenerik { position: fixed; inset: 0; z-index: 150;
  background: radial-gradient(120% 90% at 50% 42%, var(--color-peach) 55%, var(--color-peach-deep) 100%); }
/* mask'taki black/transparent alfa kanalıdır, palet rengi değil */
.jenerik-pencere { position: absolute; inset: 0; overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 13%, black 84%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, black 13%, black 84%, transparent 100%); }
.jenerik-metin { position: absolute; left: 50%; transform: translate(-50%, 100vh);
  width: min(40rem, 86vw); will-change: transform; }

.mektup p { margin: 0 0 2.1em; font-size: clamp(1.02rem, 2.3vw, 1.28rem);
  line-height: 2.05; color: var(--color-ink); }
.mektup .mektup-imza { margin-top: 2.6em; text-align: right;
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: clamp(1.3rem, 2.8vw, 1.7rem); line-height: 1.5; }

.jenerik-tus { position: fixed; z-index: 160;
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--touch-target); padding: 0 var(--space-5); border-radius: 999px;
  border: 1px solid var(--color-ink-line); background: var(--color-white-warm);
  color: var(--color-ink); font-size: var(--font-size-sm); font-weight: 500;
  letter-spacing: 0.22em; text-transform: uppercase; cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base),
    border-color var(--transition-base); }
.jenerik-tus:hover { background: var(--color-ink); color: var(--color-peach);
  border-color: var(--color-ink); }
.jenerik-tus--sol { left: calc(var(--space-5) + env(safe-area-inset-left, 0px)); }
.jenerik-tus--sag { right: calc(var(--space-5) + env(safe-area-inset-right, 0px)); }
.jenerik-tus--dolgun { background: var(--color-ink); color: var(--color-peach);
  border-color: var(--color-ink); }
.jenerik-tus--dolgun:hover { background: var(--color-night); }

.okuma { position: fixed; inset: 0; z-index: 170; overflow-y: auto;
  background: var(--color-peach); -webkit-overflow-scrolling: touch; }
/* Kap odağı programatik (tabindex=-1, Space kaydırsın diye) — tam-ekran kabın
   çevresine halka çizmek anlamsız; halka gerçek kontrollerde (:focus-visible) kalır. */
.okuma:focus { outline: none; }
.okuma-govde { width: min(38rem, 88vw); margin: 0 auto; padding: 14vh 0 18vh; }
.okuma-kapat { bottom: auto; top: calc(var(--space-4) + env(safe-area-inset-top, 0px));
  right: calc(var(--space-5) + env(safe-area-inset-right, 0px)); }

.mektup-view { max-width: var(--olcu-okuma); margin: 0 auto; padding: var(--space-6) 0 var(--space-8); }

/* ══════════════════════════════════════════════════════════════════════════
   ÜSLUP — Pembe Zarf (gündüz) · Gece Penceresi (gece) — 2026-08-22
   Token ADLARI yukarıdaki :root'ta; burada yalnız biçim / malzeme / ışık /
   tipografi / hareket / süs kuralları. Gece bloğu en sonda, tek kopya,
   html[data-tema="gece"] altında (tema seçimi index.html head script'inde).
   ══════════════════════════════════════════════════════════════════════════ */

/* ── biçim: çakıl (999px) ───────────────────────────────────────────────── */
/* (2026-08-26: .gate-enter ve .jenerik-tus bu listeden çıkarıldı -- ikisi de
   kendi taban bloklarında zaten `border-radius: 999px` taşıyor, burada ikinci
   kez almaları çift-tanım borcuydu. Liste yalnız bu bildirimi taşıdığı için
   üyelikten çıkmakla başka hiçbir kural kaybolmadı -- sekiz geçişin tamamı
   denetlendi.) */
.btn,
.field-input,
.calendar-nav-btn {
  border-radius: 999px;
}
.session-card--large { border-radius: var(--radius-kart); box-shadow: var(--shadow-md); border-color: var(--color-border-strong); }
.toast { border-radius: 999px; padding: var(--space-3) 24px; }

/* ── malzeme: kalın kâğıt — düz dolgu + alt kenar; cam yok ──────────────── */
.btn {
  padding: 0 22px;                      /* çakılda metin-nefesi ≥20px */
  text-transform: lowercase;            /* samimi register — resmiyet kırıcı */
  box-shadow: inset 0 -2px 0 var(--kagit-kenar);
  transition: background-color var(--transition-base), border-color var(--transition-base),
    box-shadow var(--transition-base), transform var(--transition-base);
}
.btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--shadow-md), inset 0 -2px 0 var(--kagit-kenar); }
.btn-ghost { box-shadow: none; }
.btn-ghost:hover:not(:disabled) { transform: none; box-shadow: none; }
.calendar-nav-btn { box-shadow: inset 0 -2px 0 var(--kagit-kenar); }
/* kâğıt dokusu — %9 SVG-noise (renksiz alfa maskesi, palet-bağımsız) */
body {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.09 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
}

/* ── ortak düzeltmeler (2026-08-22 eleştirmen §0 — eski app.css'in de kusurları) ── */
.canli-kenar-rozeti { min-height: var(--touch-target); padding: 0 14px; box-shadow: inset 0 -1px 0 var(--kagit-kenar); }
.field-input::placeholder, .field-textarea::placeholder { color: var(--color-ink-muted); }
.field-input, .field-textarea { border-color: var(--color-border-strong); padding-left: 20px; padding-right: 20px; }
.toast-action { min-height: var(--touch-target); }
.gate-enter, .jenerik-tus { text-transform: lowercase; letter-spacing: .05em; font-family: var(--font-body); font-weight: 600; }
.day-more { color: var(--color-accent-strong); }

/* ── tipografi: marka + büyük kart başlığı italik display ────────────────── */
.topbar-brand { font-style: italic; font-size: var(--font-size-marka); letter-spacing: .3em; }
.session-card--large .session-time { font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 1.2rem; }

/* ── süs: balmumu mühür (canlı işaretleri) + toast'ta "e" damgası + zarf-kapağı ── */
.canli-nokta, .radyo-rozet-nokta {
  background: radial-gradient(circle at 32% 28%,
    color-mix(in srgb, var(--color-live) 35%, white 65%),
    var(--color-live) 55%,
    color-mix(in srgb, var(--color-live) 70%, black 30%) 100%);
  box-shadow: inset 0 -1px 1px var(--muhur-golge), 0 0 0 1px var(--muhur-halka);
}
.toast { position: relative; overflow: visible; animation: zarf-toast-giris 220ms ease-out; }
.toast::after {
  content: "e"; position: absolute; top: -18px; right: 14px;
  font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 1rem;
  color: var(--color-live); transform: rotate(-8deg); pointer-events: none;
}
.mektup-view { border-top: 1px dashed var(--color-ink-line); }

/* ── kapı: zarfın içinde (gece bloğu token'la geceye döner) ─────────────── */
.gate { background: var(--color-peach-deep); }
.gate-title { color: var(--color-ink); }
.gate-rule { background: var(--color-ink-line); }
.gate-input { color: var(--color-ink); border-bottom-color: var(--color-ink-muted); }
.gate-input::placeholder { color: var(--color-accent-strong); }
.gate-input:focus { border-bottom-color: var(--color-ink); }
.gate-enter { color: var(--color-ink); border-color: var(--color-ink-muted); }
.gate-enter:hover:not(:disabled) { background: var(--color-ink); color: var(--color-peach); }
.gate :focus-visible { outline-color: var(--color-accent); }
/* (2026-08-26: buradaki `.gate .field-error { color: ... }` kaldırıldı --
   yukarıdaki tek evinde (aynı token değeriyle, ayrıca text-align ile birlikte)
   zaten tanımlı; bu satır ne değiştiriyor ne tamamlıyordu.) */

/* ── hareket ────────────────────────────────────────────────────────────── */
@keyframes zarf-toast-giris { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

/* ── ışık lekeleri: çok hafif süzülen yuvarlak ışıklar (index.html'de .lekeler) ──
   Hareket transform'la (compositor), 96–118 sn döngü, genlik küçük. */
.lekeler { position: fixed; inset: -20vmax; z-index: 0; pointer-events: none; overflow: hidden; }
.leke { position: absolute; border-radius: 50%; will-change: transform;
  animation: leke-suzul var(--leke-sure, 96s) ease-in-out infinite alternate; }
.leke-1 { width: 70vmax; height: 52vmax; left: -10vmax; top: -6vmax;
  background: radial-gradient(closest-side, var(--leke-1), transparent 70%); --leke-sure: 96s; }
.leke-2 { width: 56vmax; height: 44vmax; right: -8vmax; top: 30vh;
  background: radial-gradient(closest-side, var(--leke-2), transparent 70%); --leke-sure: 118s; animation-delay: -40s; }
.leke-3 { width: 80vmax; height: 60vmax; left: 10vmax; bottom: -24vmax;
  background: radial-gradient(closest-side, var(--leke-3), transparent 70%); --leke-sure: 104s; animation-delay: -70s; }
@keyframes leke-suzul {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(3vmax, -2vmax, 0) scale(1.06); }
  100% { transform: translate3d(-2vmax, 3vmax, 0) scale(0.97); }
}
#app { position: relative; z-index: 1; }   /* içerik lekelerin üstünde; fixed overlay'ler kendi z-index'lerini korur */

@media (prefers-reduced-motion: reduce) {
  .leke, .toast { animation: none; }
  .btn, .calendar-nav-btn { transition: none; }
  .btn:hover:not(:disabled), .calendar-nav-btn:hover:not(:disabled) { transform: none; }
}

/* ══ GECE — "Gece Penceresi": cam · gece · lamba ═══════════════════════════ */
html[data-tema="gece"] {
  --color-paper: #1b1417;
  --color-surface: rgb(255 236 226 / 7%);
  --color-surface-sunken: rgb(255 236 226 / 13%);
  --color-border: rgb(255 240 232 / 14%);
  --color-border-strong: rgb(255 240 232 / 40%);
  --color-ink: #f6ebe4;
  --color-ink-muted: #c9b5af;
  --color-accent: #f0a98f;
  --color-accent-strong: #f7bfa9;
  --color-accent-soft: rgb(240 169 143 / 18%);
  --color-on-accent: #2a1612;
  --color-danger: #ff8fa3;
  --color-danger-soft: rgb(255 143 163 / 16%);
  --color-on-danger: #2a1210;
  --color-focus: #ffd9c7;
  --color-progress-track-bg: rgb(255 236 226 / 18%);
  --color-live: #ffe3c2;
  --color-live-soft: rgb(255 227 194 / 16%);
  --color-peach: #2a1c1f;
  --color-peach-deep: #1b1417;
  --color-night: #120d10;
  --color-cream: #f6ebe4;
  --color-cream-soft: rgb(246 235 228 / 55%);
  --color-white-warm: #251a1e;
  --color-ink-line: rgb(246 235 228 / 30%);
  --color-gate-error: #ff8fa3;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 30%);
  --shadow-md: 0 8px 24px rgb(0 0 0 / 40%);
  --kagit-kenar: transparent;
  --muhur-golge: rgb(0 0 0 / 35%);
  --muhur-halka: rgb(255 255 255 / 18%);
  --glass-bg: rgb(255 236 226 / 9%);
  --glass-border: rgb(255 240 232 / 22%);
  --glass-hi: rgb(255 255 255 / 18%);
  --glass-shadow: rgb(0 0 0 / 22%);
  --glass-card-bg: rgb(255 236 226 / 6%);
  --glass-card-border: rgb(255 240 232 / 12%);
  --glass-card-hi: rgb(255 255 255 / 10%);
  --glass-well-bg: rgb(0 0 0 / 22%);
  --glass-well-shadow: rgb(0 0 0 / 30%);
  --accent-glow: rgb(240 169 143 / 28%);
  --accent-glow-hi: rgb(255 255 255 / 35%);
  --live-halo: rgb(255 227 194 / 18%);
  --live-glow: rgb(255 227 194 / 45%);
  --leke-1: rgb(240 169 143 / 34%);
  --leke-2: rgb(255 227 194 / 22%);
  --leke-3: rgb(176 88 110 / 28%);

  /* Adı-konmuş istisnaların gece karşılıkları — gerekçeleri :root'taki
     kardeş blokta. 2026-08-25'te dosyanın 3216. satırındaki İKİNCİ gece
     token bloğundan buraya taşındı; değerler birebir. */
  --color-danger-night: #ff8fa3;
  --radius-kart: 20px;
  --font-size-marka: 1.5rem;
}
html[data-tema="gece"] body { background-image: none; }   /* kâğıt dokusu gecede yok; lekeler cam için yeter */
/* malzeme: roller ayrı — tıklanan = parlak kenarlı cam; kart = sakin cam; yazılan = çukur; bildirim = opak gece */
html[data-tema="gece"] .btn-secondary,
html[data-tema="gece"] .canli-kenar-rozeti,
html[data-tema="gece"] .calendar-nav-btn {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  box-shadow: inset 0 1px 0 var(--glass-hi), 0 4px 14px var(--glass-shadow);
  backdrop-filter: blur(18px) saturate(150%); -webkit-backdrop-filter: blur(18px) saturate(150%);
}
html[data-tema="gece"] .btn-primary { box-shadow: 0 6px 18px var(--accent-glow), inset 0 1px 0 var(--accent-glow-hi); }
html[data-tema="gece"] .session-card--large { background: var(--glass-card-bg); border: 1px solid var(--glass-card-border); box-shadow: inset 0 1px 0 var(--glass-card-hi); border-radius: var(--radius-kart); }
html[data-tema="gece"] .field-input, html[data-tema="gece"] .field-textarea { background: var(--glass-well-bg); border: 1px solid var(--glass-border); box-shadow: inset 0 2px 6px var(--glass-well-shadow); }
html[data-tema="gece"] .btn-ghost { background: transparent; border-color: transparent; box-shadow: none; }
html[data-tema="gece"] .toast { background: var(--color-night); color: var(--color-cream); border: 1px solid var(--color-cream-soft); border-radius: 18px; box-shadow: var(--shadow-md); }
html[data-tema="gece"] .toast-action { color: var(--color-accent); }
html[data-tema="gece"] .canli-kenar-rozeti--geride { border-color: var(--color-danger); color: var(--color-danger); }
/* ışık: canlı nokta = lamba, nefes alır */
html[data-tema="gece"] .canli-nokta, html[data-tema="gece"] .radyo-rozet-nokta {
  background: var(--color-live);
  box-shadow: 0 0 0 4px var(--live-halo), 0 0 18px var(--live-glow);
  animation: gece-nefes 2.6s ease-in-out infinite;
}
@keyframes gece-nefes { 0%, 100% { opacity: .65; transform: scale(.9); } 50% { opacity: 1; transform: scale(1.08); } }
html[data-tema="gece"] .topbar-brand { letter-spacing: .28em; }
html[data-tema="gece"] .toast::after { color: var(--color-accent); }
html[data-tema="gece"] .jenerik-tus { background: var(--color-white-warm); color: var(--color-ink); }
@media (prefers-reduced-motion: reduce) {
  html[data-tema="gece"] .canli-nokta, html[data-tema="gece"] .radyo-rozet-nokta { animation: none; }
}

/* ===== FAZ-2 ÜSLUP — kalan ekranlar (canlı · takvim/gün · kayıt · stüdyo/mektup) ===== */
/* --- grup a: override.rev2.css --- */
/* ══════════════════════════════════════════════════════════════════════════
   FAZ-2 GRUP A — Canlı ekranı — faz-1 üslubunun (Pembe Zarf / Gece Penceresi)
   sahip olunan bileşenlere taşınması. app.css'in SONUNA eklenir (aynı seçici,
   sonra gelir → kazanır). Yeni token YOK — hepsi mevcut :root / gece paletinden.
   Sahip: .canli-* (rozet/nokta HARİÇ), .katil*, .radyo-* panel (rozet HARİÇ),
   video kutusu + durum satırı, durum hapları.

   REV2 (son revizyon, held-out eleştiri-1'e karşı) — değişen her blok kendi
   yorumunda hangi bulguyu (E#/İ#) ele aldığını adlandırır. Tam gerekçe:
   `../a/notlar.md` "## rev2".
   ══════════════════════════════════════════════════════════════════════════ */

/* ── ekran başlığı: REV2 İ1'in bulduğu ses (font-display, italik, 500, lg)
   2026-08-25'te `.ekran-basligi-ad` kalıbına taşındı ve BEŞ ekranın ortak
   kuralı oldu. Bu blokta ayrı bir .canli-title kuralı YOK. */

/* ── video kutusu: kart diliyle uyumlu köşe + kağıt/cam çerçeve ──────────
   session-card--large'ın köşe yarıçapı (22px gündüz / 20px gece) buraya
   taşınıyor — brief §"video/kanvas kutuları" kuralı. :not(--katilim) ile
   katılım tuvaline (kendi kuralı satır 1309, çerçevesiz/şeffaf) dokunulmaz.

   REV2 E1 (YENİ REGRESYON, düzeltildi): `.player-media`nın TABAN kuralı
   zemini `--color-ink` ile boyuyor — bu bir METİN token'ı, gecede krem
   (#f6ebe4). %12 cam kenar o krem üstünde eziliyordu (hesap ve piksel
   ölçümü aynı: rgb(247,236,228), paper'a karşı 15.59:1 sert halka) ve aynı
   kök neden `object-fit:contain`in 16:9-olmayan kaynaklarda bastığı
   letterbox bantlarını da krem yapıyordu. Kutunun kendi yüzeyi verildi
   (`--color-night`, iki temada da tanımlı — yeni token yok); gecede
   kenarlık artık gerçekten cam zemin üstünde okunuyor.
   REV2 İ6 (ÖLÇÜLDÜ, düzeltildi): gecenin `inset 0 1px 0 --glass-card-hi`
   iç-parlaklığı hiç boyanmıyordu — inset gölge zeminin üstünde ama VİDEO
   içeriğinin (width/height:100%) altında kalıyordu (kenarlığın hemen
   altındaki piksel düz (51,51,51), parlaklık satırı yok). Parlaklık artık
   içeriğin ÜSTÜNDE ayrı bir ::after katmanında. */
.canli-view > .player-media:not(.player-media--katilim) {
  background: var(--color-night);
  border-radius: var(--radius-kart);
  border: 1px solid var(--color-border-strong);
  box-shadow: var(--shadow-md);
}
html[data-tema="gece"] .canli-view > .player-media:not(.player-media--katilim) {
  border-radius: var(--radius-kart);
  border: 1px solid var(--glass-card-border);
  box-shadow: var(--shadow-md);
}
html[data-tema="gece"] .canli-view > .player-media:not(.player-media--katilim)::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 1px 0 var(--glass-card-hi);
}

/* ── durum hapları: .canli-kenar-rozeti ailesi ────────────────────────────
   Temel hap biçimi (999px) ve gece camı (glass-bg/border/backdrop-filter)
   ÜSLUP'ta zaten var (satır 2511, 2651) — .btn'in "küçük-harf etiket"
   kuralını (satır 2516) bu hap ailesine de taşıyoruz: aynı familyanın metni
   aynı registerde konuşmalı.

   REV2 E3 (P5 kapsam çiti, düzeltildi): app.js'te `canliRozet` (bu ekranın
   TEK hap örneği) hep aynı `.canli-kenar-satiri` sarmalayıcısının içinde
   yaşıyor — dört durumu da (plain/--geride/--duraklatildi/--baglaniyor)
   dahil. `#/studyo`daki rozetler (`.canli-kenar-rozeti studyo-rozet*`,
   app.js:5992/6535 vb.) o sarmalayıcının İÇİNDE DEĞİL. Bu revizyondaki HER
   rozet kuralı `.canli-kenar-satiri > .canli-kenar-rozeti` yuvasına
   çıpalandı — grup D'nin ekranına artık hiçbir kural sızmıyor. */
.canli-kenar-satiri > .canli-kenar-rozeti {
  text-transform: lowercase;
  letter-spacing: .02em;
}

/* REV2 E2 (R19 dokunulabilirlik, düzeltildi): ailenin pasif (disabled)
   üyeleri (--duraklatildi, --baglaniyor, "canlı" plain hali — üçü de
   `disabled=true`, app.js `canliRozetiGuncelle`) faz-1'in 44px + cam +
   kağıt-kenarı biçimini ödünç alıyordu; kırpılmış görüntüde `.btn-secondary`
   ile ayırt edilemiyordu. Yalnız `:disabled` seçilerek küçültüldü/şeffaflandı
   — tek TIKLANABİLİR üye (--geride, disabled=false) bu kuraldan doğal
   olarak muaf (aşağıda kendi affordance'ını taşıyor, İ5). */
.canli-kenar-satiri > .canli-kenar-rozeti:disabled {
  min-height: 28px;
  padding: 0 var(--space-1);
  text-transform: none;
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
html[data-tema="gece"] .canli-kenar-satiri > .canli-kenar-rozeti:disabled {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* REV2 İ5 (R1 + brief "canlı ≠ hata", düzeltildi): "12 sn geride" bir arıza
   değil bir senkron durumu; `--color-danger` gerçek hataya (`.radyo-mod-uyari`)
   bırakılıyor. Bu ailenin TEK tıklanabilir üyesi artık rengiyle değil
   `::after` ok işaretiyle ayrışıyor (E2'nin karşı ekseni — dokunmadan önce
   belli olsun). */
.canli-kenar-satiri > .canli-kenar-rozeti--geride {
  border-color: var(--color-border-strong);
  color: var(--color-ink);
}
html[data-tema="gece"] .canli-kenar-satiri > .canli-kenar-rozeti--geride {
  border-color: var(--color-border-strong);
  color: var(--color-ink);
}
.canli-kenar-satiri > .canli-kenar-rozeti--geride::after {
  content: " ↺";
}

/* "Bağlanıyor…" — kullanıcı durdurmadı, bağlantı henüz kurulmadı (app.css
   satır 1252-1257 yorumunun kendi ayrımı).
   REV2 E5 (yön-sadakati + kontrast, YENİ REGRESYON, düzeltildi): eski nefes
   `opacity .6↔1` HAPIN KENDİSİNİ soluklaştırıyordu — gündüzün "kâğıt
   kıpırdamaz" ekseni ihlal ediliyordu VE metin/zemin çifti eşiğin altına
   düşüyordu (gündüz 5.82→2.60:1, gece 7.40→3.63:1, tam bağlantı kurulurken).
   Hap artık hiçbir temada kıpırdamıyor (metin kontrastı sabit kalır);
   "sürüyor" hissi yalnız gecede, yalnız küçük bir noktada, `.canli-nokta`nın
   kendi `gece-nefes` kalıbıyla (satır 2669) — anlam nefes alıyor, metin
   almıyor. */
.canli-kenar-satiri > .canli-kenar-rozeti--baglaniyor {
  animation: none;
}
html[data-tema="gece"] .canli-kenar-satiri > .canli-kenar-rozeti--baglaniyor::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: .45em;
  border-radius: 50%;
  background: var(--color-live);
  animation: gece-nefes 2.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  html[data-tema="gece"] .canli-kenar-satiri > .canli-kenar-rozeti--baglaniyor::before {
    animation: none;
  }
}

/* ── Radyo yönetim açıcısı ("▸ Yönetim") ──────────────────────────────────
   REV2 E4 (brief "dokunma hedefleri ≥ 44px", YENİ — notlar.md'de hiç
   geçmiyordu, düzeltildi): kartın tek kontrolü 13px × 1.6 satır ≈ 21px
   yüksekliğindeydi, dokunma hedefi taşımıyordu. */
.radyo-yonetim > summary {
  display: flex;
  align-items: center;
  min-height: var(--touch-target);
  padding: var(--space-2) 0;
  text-transform: lowercase;
  letter-spacing: .02em;
}

/* ── boş durum ("Şu an yayın yok"): zarf başlığı + sakin gövde ───────────
   .canli-bos-baslik zaten font-display taşıyor (yapısal kural, satır
   1268-1272); session-card--large .session-time'ın italik dokunuşunu
   (satır 2542) buraya da taşıyoruz — ekranın en büyük tek anı, aynı sıcak
   ses. .canli-bos-metin zaten --color-ink-muted'la doğru — dokunulmadı. */
.canli-bos-baslik {
  font-style: italic;
}

/* ── Radyo kartı: taban zaten doğru rolü taşıyor — REV2 İ2/İ3/İ4 ─────────
   rev1 bu iki karta (.radyo-kaset-kart / .radyo-sh-kart) "cam kart" biçimi
   verdi (border-radius 12px, gündüzde inset kağıt-kenar "düğme/çakıl"
   gölgesi, gecede --glass-card-* üçlüsü). Held-out eleştirmen üçünü de
   yanlış buldu:
     İ2 — dış kabı .session-card--large DEĞİL .sidebar-section (radius zaten
          --radius-lg=12px); iç/dış eşmerkezlilik (iç ≈ dış − padding)
          12px→12px ile TERSİNE döndü. Doğru değer zaten app.css'in tabanı:
          --radius-sm (4px).
     İ3 — `inset 0 -1px 0 --kagit-kenar` faz-1'de düğme/çakıl kelimesi
          (.btn, .calendar-nav-btn); bu kartlar PASİF durum kartı, taban
          zaten kenarlıkla (border: 1px solid --color-border) konuşuyor —
          ek bir "basılabilir" sesi kartın çukur zeminiyle (--color-surface-
          -sunken) çelişiyordu.
     İ4 — gecede --glass-card-bg (%6) yerine taban zaten --color-surface-
          -sunken (gece: %13) taşıyordu; kabın (.sidebar-section, %7)
          kendisinden ayrımı rev1 ile kabaca yarıya düşmüştü (Δ≈27→Δ≈12).
   Düzeltme üçü için de AYNI: rev1'in border-radius/box-shadow/gece-arka-plan
   kurallarını KALDIRMAK — app.css'in tabanı (satır 1417-1425, 1540-1548)
   zaten --radius-sm + --color-surface-sunken (iki temada da doğru şekilde
   ayrışan token) taşıyor; üstüne yazacak bir şey yok. Bu yüzden bu dosyada
   .radyo-kaset-kart / .radyo-sh-kart için ARTIK hiçbir kural YOK — REV2'nin
   kendisi "sil" düzeltmesi (same-artifact: fazlalık kaldırıldı, taban
   korundu). */

/* Sessiz durum notları — "henüz bir şey söylenmiyor / şu an bir şey yok"
   hâli, ikisi de aynı sese sahip olmalı. (2026-08-25: bu ailenin üçüncü üyesi
   `.radyo-sh-durum--kapali`, Stationhead kartıyla birlikte söküldü — bkz.
   radyo-durum-metin bölümündeki "fısıltı register" notu; satır-no verilmedi,
   kayar.) */
.radyo-kapali-not,
.radyo-kaset-not {
  font-style: italic;
}

/* Ses seviyesi çubuğu — küçük ölçekte .field-input'in "çukur" (well) rolü:
   gündüzde kağıt kenarı, gecede glass-well oyuğu (satır 2660 emsali). */
.radyo-seviye-track {
  box-shadow: inset 0 1px 2px var(--kagit-kenar);
}
html[data-tema="gece"] .radyo-seviye-track {
  background: var(--glass-well-bg);
  box-shadow: inset 0 1px 3px var(--glass-well-shadow);
}

/* Kapak küçük-resimleri (arama sonucu + kuyruk) — dış kartın radius
   ailesine (radius-lg) değil ama radius-sm(4px)'in bir tık üstüne, satır
   içindeki diğer öğelerle (radyo-istek-satiri: radius-md) aynı kademede. */
.radyo-kapak {
  border-radius: var(--radius-md);
}

/* ── Katıl* ────────────────────────────────────────────────────────────
   .canli-katil-satiri salt yerleşim (gap/flex) — .btn'in kendisi faz-1'de
   bitti, burada tekrarlanacak bir malzeme kuralı yok (bilinçli, notlar.md).
   .player-media--katilim'in KENDİ kuralı (background/radius/overflow) bu
   dosyada EZİLMEZ — o kural "video kutusu" değil, katılımcı tuvalinin
   taşıyıcısı; içerik zaten kırpılmıyor (yukarıdaki :not() ayracı bunu
   koruyor). */

/* REV2 İ7 (ritim/anlam yerleşimi, ÖLÇÜLDÜ, kısmen düzeltildi): hap üstündeki
   mikser kartına 10px, altındaki Radyo kartına 19px uzaktı — video'nun
   durumunu söyleyen hap, SES kartının eki gibi okunuyordu. Tam düzeltme
   (order:-1 ile hapı tuvalin altına çekmek) app.js:2326-2328'in bilinçli
   "tuval → Katıl → mikser → rozet" gerekçesini kırar ve DOM'u değil ama
   görsel akışı yeniden yorumlar — REV2'nin "son revizyon, owner geri dönüşü
   yok" kısıtında bu karar tek başına verilmedi (owner onayı ister,
   notlar.md'de adlandırıldı). Asgari, geri-alınabilir düzeltme uygulandı:
   mikserle bağı netleştirmek için üst boşluk daraltıldı (--space-2→--space-1,
   yani ~8px→~4px, mikserle görsel ilişki güçlendi; Radyo kartıyla ilişki
   değişmedi çünkü DOM sırası aynı kaldı). */
.canli-kenar-satiri {
  margin-top: var(--space-1);
}

/* --- grup b: override.rev2.css --- */
/* ══════════════════════════════════════════════════════════════════════════
   Faz-2 grup B — Takvim + gün listesi — üslubu faz-1'den devralır (2026-08-22)
   Sahip: .calendar* (nav düğmesi HARİÇ), ay/hafta grupları, gün hücreleri,
   gün numarası, '+N daha', .session-card (küçük), .session-thumb/-meta/-time,
   .back-link, .day-view-header/-title. YENİ TOKEN YOK — yalnız faz-1'in
   :root / html[data-tema="gece"] bloklarında zaten tanımlı olan tokenlar
   (--kagit-kenar, --muhur-golge, --muhur-halka, --accent-glow*,
   --glass-card-*, --glass-well-bg, --color-surface-sunken, --color-accent-
   strong, --color-accent-soft) bu bileşenlere uygulanır. Detaylı gerekçe:
   notlar.md (rev1 + "## rev2" bölümü).
   rev2 = rev1'in TAMAMI (aşağıda değişmeden durur) + eleştiri-1'in E2/E3/E4/
   İ1-İ5/İ7/İ8 düzeltmeleri (dosya sonunda, ayrı blok — E1/İ6 kod DEĞİL,
   notlar.md'de gerekçeli bırakıldı).
   ══════════════════════════════════════════════════════════════════════════ */

/* ── gün hücresi = kağıt kart: .calendar-nav-btn'ın (faz-1) taşıdığı aynı
   "kalın kağıt kenarı" malzemesi — border-strong + alt-kenar gölgesi.
   Boş/dolgu hücreler HARİÇ: etkileşimsiz/veri-yok hücre kart görünümü
   ödünç almaz (brief kısıtı). ── */
.day-cell:not(.day-cell--empty):not(.day-cell--filler) {
  border-color: var(--color-border-strong);
  box-shadow: inset 0 -2px 0 var(--kagit-kenar);
}

/* ── "bugün" rozeti = mühür: canli-nokta / radyo-rozet-nokta ile AYNI
   biçimsel rol (küçük dairesel aksan-vurgusu) → AYNI malzeme. ── */
.day-cell--today .day-number {
  background: radial-gradient(circle at 32% 28%,
    color-mix(in srgb, var(--color-accent) 35%, white 65%),
    var(--color-accent) 55%,
    color-mix(in srgb, var(--color-accent) 70%, black 30%) 100%);
  box-shadow: inset 0 -1px 1px var(--muhur-golge), 0 0 0 1px var(--muhur-halka);
}

/* ══ GECE — malzeme rolleri faz-1'in "cam" ayrımını miras alır ══════════════
   gün hücresi = SAKİN kart → .session-card--large ile AYNI glass-card-* rol
   (faz-1, app.css §ÜSLUP). Bugün rozeti = .btn-primary'nin taşıdığı AYNI
   sıcak parlama (--accent-glow*) — canlı-noktanın "nefes" animasyonu
   BİLEREK kopyalanmadı: o hareket --color-live'a özel bir anlam taşır
   (brief: "canlı/yayında işareti --color-live'da... ikisi karışmaz"); bugün
   rozeti --color-accent kullanır, ayrı bir anlam kategorisi — statik parlama
   yeterli, hareket eklemek yanlış bir "canlı" çağrışımı yaratırdı. */
html[data-tema="gece"] .day-cell:not(.day-cell--empty):not(.day-cell--filler) {
  background: var(--glass-card-bg);
  border-color: var(--glass-card-border);
  box-shadow: inset 0 1px 0 var(--glass-card-hi);
}
html[data-tema="gece"] .day-cell--today .day-number {
  box-shadow: 0 0 0 3px var(--accent-glow), 0 0 10px var(--accent-glow-hi);
}

/* ════════════════════════════════════════════════════════════════════════
   rev2 — eleştiri-1 (held-out) düzeltmeleri. Her blok kendi bulgu-kimliğini
   taşır; sıra elestiri-1.md ile aynı. E1 ve İ6 burada YOK — notlar.md'de
   "## rev2" bölümünde gerekçeli bırakıldı (kod değişikliği değiller).
   ════════════════════════════════════════════════════════════════════════ */

/* ── E2 — "bugün" rozeti: rev1'in gradyanı 22px dairede hiç saf accent'e
   ulaşmıyordu (açık uçta kalıyor, gündüz 1,74:1 / gece 4,46:1) + rozet
   .day-cell--empty'nin opacity:.55'ini miras alıyordu (oturumsuz "bugün"
   sabahı). Düz dolgu + halka İ5 ile birlikte aşağıda tek box-shadow'da
   birleştirildi (bkz. İ5 bloğu — bu satır yalnız background'u ve empty-
   izolasyonunu düzeltir, box-shadow'un SON hâli İ5'te). ── */
.day-cell--today { opacity: 1; }                     /* rozeti --empty solmasından çıkar */
.day-cell--today .day-number {
  background: var(--color-accent);                   /* gündüz 6,09:1 · gece 8,82:1 (belgelenmiş taban) */
}

/* ── E3 — boş gün sayıları: opacity:.55 rakamı zeminle karıştırıp 2,23:1
   (gündüz) / 3,64:1 (gece)'e düşürüyordu; ayın 24 hücresi etkileniyordu.
   Geri-çekilme sinyalini opaklıktan boş hücrenin zaten taşıdığı kart/kenar/
   liste YOKLUĞUNA taşı — kart-rengi sabit kalır, yalnız metin tam token. ── */
.day-cell--empty { opacity: 1; }                      /* gündüz 5,22:1 · gece 9,24:1 */

/* ── E4 — .session-card (takvim, küçük): tek gezinme yüzeyi dokunmadan önce
   görünmüyordu (R19 — hover'a bağımlı gösterge, dokunmatikte hover yok).
   İkinci kart açmadan dolgu-kap + basma geri-bildirimi. ── */
.day-cell .session-card { background: var(--color-surface-sunken); border-radius: 10px; }
.day-cell .session-card:hover { background: var(--color-surface); border-color: var(--color-border-strong); }
.day-cell .session-card:active { transform: translateY(1px); }
html[data-tema="gece"] .day-cell .session-card { background: var(--glass-well-bg); }
@media (prefers-reduced-motion: reduce) {
  .day-cell .session-card:active { transform: none; }   /* proje kuralı: basma-ötelemesi de reduced-motion'da kapanır */
}

/* ── İ1 — gün numarası: tek/çift haneli rakamlar farklı x'ten başlayıp
   8,2px tırtıklı sol kenar bırakıyordu (mobil, ≤720px). ── */
@media (max-width: 720px) {
  .day-cell > .day-number {
    min-width: 22px;                 /* "bugün" rozetiyle aynı genişlik → aynı hizada oturur */
    text-align: center;
    flex: 0 0 auto;
  }
}

/* ── İ2 — .session-thumb köşe yarıçapı: 4px (--radius-sm), taşıyıcı kartın
   22px/20px/8px yarıçaplarının dışında kalan tek keskin köşeydi. ── */
.session-card--large .session-thumb { border-radius: var(--radius-kart-ic); }
.day-cell .session-thumb { border-radius: 6px; }

/* ── İ3 — .back-link, üçüncül-metin eylemi olduğu hâlde etkileşimsiz
   .session-duration ile birebir aynı rengi (--color-ink-muted) taşıyordu;
   altı da yalnız hover'da çiziliyordu. ── */
.back-link {
  color: var(--color-accent-strong);          /* gündüz 6,95:1 · gece 11,2:1 */
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.back-link:hover { color: var(--color-ink); }

/* ── İ4 — .back-link'in 44px dokunma kutusu ile başlığın 4,2px kaçıklığı:
   ölçüm `.ekran-basligi`nın `align-items: center` gerekçesi oldu (2026-08-25),
   kalıp bunu beş ekrana birden taşıyor. Burada ayrı kural YOK. */

/* ── İ5 — mühür halkası (gündüz): rgba(255,255,255,.25) kâğıt zemininde
   1,02:1 — hiç render olmuyordu (gecede aynı halka --accent-glow ile
   sorunsuz, dokunulmadı). E2'nin düz-dolgu kararıyla birlikte SON box-
   shadow: gölge aynı kalır, halka ölçülebilir bir accent-türevine döner. ── */
.day-cell--today .day-number {
  box-shadow: inset 0 -1px 1px var(--muhur-golge),
    0 0 0 1px color-mix(in srgb, var(--color-accent) 55%, black);
}

/* ── İ7 — .session-flagbadge: hap biçimi (border-radius:999px + dolgu-
   zemin), etkileşimsiz — R19'un "static chip/pill" yasağının tarifi.
   Önleyici düzeltme; render tanığı mock verisinde flag_count>0 bir oturum
   gerektirir (bkz. notlar.md "## rev2" — tanık borcu bu promptun Write
   kapsamı dışında, mock veri dosyasına dokunulmadı). ── */
.session-flagbadge {
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-accent-strong);
  padding: 0;
}

/* ── İ8 — .calendar-weekday (≥720px, masaüstü Chrome): sütun ortalı
   hizalanmış başlık hiçbir gün-sütununun (sola hizalı) üstüne oturmuyordu;
   Lora + text-transform:none faz-1'in küçük-harf etiket diline katılmıyordu.
   1280px render tanığı bu promptun sabit-viewport render komutunun (420x900)
   dışında — bkz. notlar.md "## rev2". ── */
.calendar-weekday {
  text-align: left;
  padding-left: var(--space-2);
  text-transform: lowercase;
  letter-spacing: .05em;
}

/* --- grup c: override.rev2.css --- */
/* ─────────────────────────────────────────────────────────────────────────
   Faz-2 · Grup C — Kayıt / oynatıcı — biçim geçişi (2026-08-22, rev2 SON)
   rev1 (elestiri-1.md) denetiminin tüm bulgularını kapsar; ayrıntı notlar.md
   "## rev2" bölümünde bulgu→işlem eşlemesiyle. app.css'in SONUNA eklenir.
   Sahip: .player*, .video*, .progress*, .timeline*, .mark*, .prep*,
          .flag*, .flags*, .sibling*, .siblings*, .yorum*
   Dokunulmadı: .btn, .field-input, .toast, .sidebar-section, .mikser-*,
          .canli-*, .back-link (başka grup / faz-1 — kapsam çiti).
   ───────────────────────────────────────────────────────────────────────── */

/* ── E5/İ4 token'ları (--color-danger-night, --radius-kart, --font-size-marka,
   --font-size-muzik-sarki) 2026-08-25 konsolidasyon turunda dosyanın TEK token
   evine — tepedeki `:root` + tek gece bloğuna — taşındı. Gerekçeleri oraya
   birlikte gitti. --font-size-muzik-baslik (2rem) burada ÖLDÜ: bileşen token'ı
   olmaktan çıkıp gerçek bir ölçek kademesine (--font-size-xl) terfi etti.
   Bu turda hiçbir değer değişmedi; tanığı 12 rota×tema computed-style eşitliği. */

/* ── "Büyük başlık üçlüsü" (display italik 500 lg) 2026-08-25'te
   `.ekran-basligi-ad` oldu; kayıt ekranı da o kalıbı kullanıyor. */

/* ── .player-media — elestiri-1 E2: seçici `.player-media`'ydı, ama sınıf
   app.js'te 6 yerde kurulu (Canlı 1958, katılım tuvali 2436, Stüdyo
   6035/6036/6551/6552) — kaynak-sırası özgüllüğüyle `.player-media--katilim`
   (transparent/0 radius, 2026-08-21 kararı) ve `.studyo-pane`'i eziyordu.
   `.player-view` sarmalayıcı (app.js:1096) yalnız kayıt/oynatıcıyı kapsar —
   rota çiti budur, ek `:not()` gerekmez.
   E5 aynı nedenle `.prep-panel`/`.prep-error`'a da uygulanır: o iki sınıf
   da Canlı'nın kendi mediaContainer'ında ikinci kez kuruluyor (app.js:2962) —
   E2'nin scope'u uygulanmazsa Canlı-gece'de --color-cream metni --color-ink
   zemininin üstüne düşer (gece'de ikisi TAM AYNI hex, #f6ebe4 — 1:1).
   `.progress-fill`/`.progress-track` TEK yerde kuruluyor (yalnız kayıt),
   scope gerekmedi.
   İ5: `border` yerine inset box-shadow — border, box-sizing: border-box +
   aspect-ratio: 16/9 ile içerik kutusunu ~2px daraltıyordu, `#/kayit`ta
   object-fit tanımsız (varsayılan fill) olduğu için video esniyordu.
   İ3 (gece): shadow-md koyu zeminde görünmüyordu ve faz-1'in "gecede
   kartlarda drop-shadow YOK" kararına ters düşüyordu — kaldırıldı, yerine
   üst-kenar parlaması (glass-card-hi) kondu. Kenarlık halkası her iki
   temada da AYNI bildirim (--color-border-strong tema-göreli token,
   gündüz 3.89:1 sınıfından, gece ölçümü 3.56:1 — elestiri-1 İ3). */
.player-view .player-media {
  background: var(--color-night);
  border-radius: var(--radius-kart);
  box-shadow: inset 0 0 0 1px var(--color-border-strong), var(--shadow-md);
}

html[data-tema="gece"] .player-view .player-media {
  box-shadow: inset 0 0 0 1px var(--color-border-strong), inset 0 1px 0 var(--glass-card-hi);
}

/* ── .prep* — hazırlık paneli metni "opak gece" çiftinde (--color-cream,
   --color-on-accent zemin --color-accent için tasarlanmıştı, artık zemin
   --color-night). Scope gerekçesi yukarıda (.player-media yorumu). */
.player-view .prep-panel {
  color: var(--color-cream);
}

.progress-fill {
  background: var(--color-cream);
}

/* E5: hata metni önceden .prep-panel'in cream'ini miras alıyordu — normal
   ilerleme kopyasıyla birebir aynı renk, "hata ayrı görünür" kuralını
   (brief: canlı --color-live'da, hata --color-danger'da) ihlal ediyordu.
   --color-danger-night yukarıda tanımlı; kalın da eklendi (küçük-metin
   eşiği: gündüz 8.24:1, gece 8.90:1). */
.player-view .prep-error {
  color: var(--color-danger-night);
  font-weight: 700;
}

/* ── .timeline* — elestiri-1 E6: 999px + glass-well biçimi bu şeridi
   "yazılan" (çukur) ya da "tıklanabilir" (hap düğme) malzemesine
   taşıyordu; şerit kendisi TIKLANAMAZ (yalnız içindeki .timeline-tick
   tıklanır), bir VERİ kanalıdır — progress-track ailesinde kalmalı.
   Tek kural iki temada da yeterli: background/border-color zaten
   tema-göreli token, ayrı gece bloğu gerekmiyor (gece: sayfa zeminine
   karşı kenarlık 3.56:1 — elestiri-1 E6 ölçümü). */
.timeline-track {
  border-radius: 999px;
  background: var(--color-progress-track-bg);
  border-color: var(--color-border-strong);
}

/* İ1: 999px yarıçapla şeridin ilk/son ~10px'i kavis; uçtaki tikler
   `overflow` olmayan şeridin dışına, kâğıdın üstüne taşıyordu. */
.timeline-tick {
  left: clamp(10px, var(--tick-pos, 0%), calc(100% - 10px));
}

/* İ2: ipucu yalnız hover'da açılıyordu — dokunmatikte (mobil-önce ürün)
   hiç görünmez, klavyeyle de açılmazdı. */
.timeline-tick:hover::after,
.timeline-tick:focus-visible::after {
  background: var(--color-night);
  color: var(--color-cream);
}

/* ── .flag-form — elestiri-1 İ7: gece'de --glass-card-bg'ye geçince
   gündüzün çukur (surface-sunken) hissiyle TERS düşüyordu (kabarık cam);
   iki seçenekten biri seçildi (notlar.md'de gerekçeli): gece override
   KALDIRILDI, form her iki temada da app.css'in kendi --color-surface-sunken
   tabanında kalıyor (zaten tema-göreli) — içindeki .field-input/.field-textarea
   AYRICA glass-well aldığı için form'un da well olması iç içe iki çukur
   yaratırdı. */
.flag-form {
  border-radius: var(--radius-lg);
  border-color: var(--color-border-strong);
}

/* ── .flag-row / .sibling-row — elestiri-1 E3: taban yüzey rev1'de
   .sidebar-section'ın zemin token'ıyla AYNIYDI (1.00:1/1.22:1) — satırlar
   dokunmadan önce görünmüyordu (brief: "etkileşimli olan dokunmadan önce
   belli olur"). --color-surface-sunken bir kademe derinlik verir (gündüz
   kenarlık 3.89:1, gece %40 cream 3.43:1); hover bir kademe İLERİ,
   accent-soft/accent'e taşınır (gündüz 5.88:1). */
.flag-row {
  background: var(--color-surface-sunken);
  border-color: var(--color-border-strong);
}

.flag-row:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
}

.sibling-row {
  background: var(--color-surface-sunken);
  border-color: var(--color-border-strong);
}

.sibling-row:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
}

.sibling-row--current {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
}

/* E4: `.sibling-row:hover` özgüllüğü `.sibling-row--current`den yüksekti —
   "buradasın" işareti tam üstüne gelindiğinde kayboluyordu. Kombine seçici
   aynı özgüllükte (0,0,2,0); kaynak sırası (bu kuraldan sonra gelmiyor,
   dosyada .sibling-row:hover'DAN SONRA tanımlı) kazandırır. */
.sibling-row--current:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent-strong);
}

/* ── .video* — kayıt mikseri kartı: video kutusunun hemen altında oturan
   bir "kart", .sidebar-section'ın değil session-card--large'ın radius'unu
   aldı (İ4: artık --radius-kart token'ından, elle yazı yok). Kenarlık
   kağıt-ailesine (border-strong) yükseltildi. İç sürgüler/etiketler
   (.mikser-*) bu grubun kapsamı DIŞINDA — dokunulmadı.
   İ9: notlar.md'deki "kayıt mikseri kartı" tanımı düzeltildi — aynı sınıf
   Canlı (app.js:2132) ve Stüdyo'da (app.js:6080) da kuruluyor; kural üçü
   için de tekdüze olduğundan kırılma yok, yalnız kapsam iddiası yanlıştı. */
.video-mikser {
  border-radius: var(--radius-kart);
  border-color: var(--color-border-strong);
}

html[data-tema="gece"] .video-mikser {
  background: var(--glass-card-bg);
  border-color: var(--glass-card-border);
  box-shadow: inset 0 1px 0 var(--glass-card-hi);
}

/* ── .yorum-satiri gece override'ı — elestiri-1 İ6: gece'de --glass-card-bg'ye
   (%6) düşünce gündüzün çukur (surface-sunken, %13/daha derin) hissiyle
   tersiniyordu, üstelik gece ayrımı gündüzden daha ZAYIFTI. Gece override
   KALDIRILDI; satır app.css'in kendi --color-surface-sunken tabanında
   (tema-göreli, zaten doğru) her iki temada aynı role kalıyor.
   2026-08-26: override kalkınca burada yalnız tabandaki değerin (--radius-md)
   birebir tekrarı kalmıştı -- o da kaldırıldı. Kuralın tek evi yukarıdaki
   `.yorum-satiri` taban bloğudur; bu yorum kararın kaydı olarak duruyor. */

html[data-tema="gece"] .yorum-liste {
  scrollbar-color: var(--color-border-strong) transparent;
}

/* --- grup d: override.rev2.css --- */
/* ══════════════════════════════════════════════════════════════════════════
   FAZ-2 GRUP D — Stüdyo + mektup + genel durumlar — faz-1 üslubunun
   (Pembe Zarf / Gece Penceresi) sahip olunan bileşenlere taşınması.
   REV2 — held-out eleştiri-1'in SON revizyonu (durma kuralı K=2, rev2'den
   sonra dönülmez). Her bulgu ya burada düzeltildi ya da notlar.md'de
   gerekçeyle reddedildi — bkz. "## rev2" bölümü.
   app.css'in SONUNA eklenir (aynı seçici, sonra gelir → kazanır).
   YENİ TOKEN YOK — hepsi mevcut :root / html[data-tema="gece"] paletinden
   (--color-night, --color-live, --color-on-accent, --glass-*, --live-glow,
   --color-ink-muted, --color-border-strong). Gerekçe: notlar.md.
   Sahip: .studyo* (kaydırıcı/tutamak/etiket İÇİ HARİÇ — bkz. .mikser*),
          .mikser-surgu/-etiket/-yuzde/-not (kaydırıcı+tutamak+etiket —
          .video-mikser/.mikser-kanal KUTUSU HARİÇ, grup C'nin "kart" kararı
          zaten global .video-mikser'i kaplıyor), cihaz select'i
          (.studyo-cihaz), onay kutuları (.studyo-kutu-satiri checkbox),
          .okuma* ve .whiteout (mektup zemini — .mektup-view zaten faz-1).
   Dokunulmadı (rev2'de KAPSAM DIŞINA ÇIKARILDI — İ10): .loading-text /
          .empty-text / .error-text — rev1 bunu değiştirmişti ama D'nin
          rotalarında (#/studyo, #/mektup) bu üç sınıf HİÇ oluşmuyor
          (ölçüldü, elestiri-1 İ10); gerçek sahipleri takvim/gün/kayıt/canlı
          ekranları — denetlenmeyen bir kapsamda global değişiklik olurdu.
   Dokunulmadı: .btn (genel kural), .topbar, .sidebar-section(-title),
          .video-mikser/.mikser-kanal (kutu — grup C zaten stiledi),
          .back-link (grup B), .player-media (grup C zaten --color-night'a
          çevirdi — burada TEKRAR tanımlanmaz).
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Stüdyo tuvali: ink→night ─────────────────────────────────────────────
   `.studyo-iki-pane` ve `:fullscreen` hâli `var(--color-ink)`yi zemin
   yapıyordu — bu token GECEDE AYDINLIK bir renge döner (metin-üstü-koyu
   rolü tersine çevrilir). E1 (rev1'de bu kural bir yorum-kapatma hatasıyla
   PARSE EDİLMİYORDU — üstteki başlık yorumunu erken kapatan yıldız+eğik-çizgi ikilisi bu bloğu yutuyordu;
   rev2'de düzeltildi, aşağıdaki `.studyo-ayirac` computed background artık
   gerçekten `--color-night`). İ1 — notlar.md'nin rev1 gerekçesi (bu kuralın
   "parlak kutu"yu düzelttiği iddiası) YANLIŞTI: `.studyo-pane` elemanları
   `.player-media` sınıfını da taşıyor ve grup C'nin `.player-media` gece
   kuralı konteyneri %100 kaplıyor — parlak kutuyu düzelten O. Bu kural
   yine de GEREKLİ: `.studyo-ayirac`ın KENDİ zemini (player-media taşımıyor)
   ve `:fullscreen` hâli (canvas yokken tüm pane) gerçekten bu tokene
   muhtaç — sahiplik doğru, gerekçe yanlıştı, düzeltildi. */
.studyo-iki-pane,
.studyo-ayirac,
.studyo-pane:fullscreen,
.studyo-pane:-webkit-full-screen {
  background: var(--color-night);
}

/* ── Tuval köşesi = kart dili ─────────────────────────────────────────────
   session-card--large'ın 22px radius'u — brief'in "video/kanvas kutuları:
   köşe yarıçapı kart diliyle uyumlu" kuralı. İ2 — rev1 bunu medya-sorgusuz
   yazmıştı: app.css'in `@media(max-width:980px){ .studyo-iki-pane{
   border-radius:0; overflow:visible } }` kararının üstüne, override.css
   dosya SONUNDA olduğu için, GENİŞLİKTEN BAĞIMSIZ biniyordu (420px'te bile
   22px döndüğü ölçüldü, mobil kararı sessizce iptal ediyordu). Masaüstüne
   kilitlendi — mobilde app.css'in kendi kararı (0, kırpmasız) aynen durur. */
@media (min-width: 981px) {
  .studyo-iki-pane {
    border-radius: 22px;
  }
}

/* ── Rozet: "yayın kapalı" / "yayında" ────────────────────────────────────
   İ8 — rev1'in `padding: var(--space-1) 20px` satırı SİLİNDİ: brief'in
   "≥20px yatay nefes" kısıtı hap DÜĞME için yazılmış, rozet düğme değil
   (tıklanmaz — İ9), ve bu satır `.canli-kenar-rozeti`nin paylaşılan 14px'ini
   (app.css "ortak düzeltmeler" bloğu) yalnız stüdyoda 20px'e çeviren bir
   FORK açıyordu (brief DO-NOT: aynı bileşene iki farklı biçim). Override
   kaldırılınca rozet şeffafça paylaşılan 14px'e döner — fork kapandı. */
.studyo-rozet--acik {
  background: var(--color-live);
  color: var(--color-on-accent);
  border-color: var(--color-live);
}
/* E2 — gecede yukarıdaki kural HİÇ uygulanmıyordu: DOM `.canli-kenar-rozeti
   studyo-rozet studyo-rozet--acik` sınıflarını birlikte taşıyor ve app.css'in
   `html[data-tema="gece"] .canli-kenar-rozeti {...}` kuralı (özgüllük 0,2,1)
   `.studyo-rozet--acik`i (0,1,0) eziyordu — ölçülen kontrast 1.02:1 (eşik
   4.5), "YAYINDA" gecede fiilen okunmuyordu. Aynı özgüllükte (0,2,1),
   sonra gelen kural olarak eklendi: gündüz zaten sağlam (6.59:1 — 2026-08-23 karmin token, ayrıca
   dokunulmadı), gece --color-live zemin + --color-on-accent metin ölçüldü
   13.93:1. Cam değil: bu bir durum beyanı, "tıklanan" değil "lamba" dili
   (--live-glow zaten aynı aile, .canli-nokta'nın gece-nefes animasyonuyla). */
html[data-tema="gece"] .studyo-rozet--acik {
  box-shadow: 0 0 14px var(--live-glow);
  background: var(--color-live);
  border-color: var(--color-live);
  color: var(--color-on-accent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* İ9 — R19 (yanlış signifier): "yayın kapalı" hâli (--acik DEĞİL) DOM'da da
   `.canli-kenar-rozeti` taşıyor ve app.css'in gece "tıklanan=cam" kuralı
   (html[data-tema=gece] .canli-kenar-rozeti,.btn-secondary,.calendar-nav-btn
   { background:var(--glass-bg); backdrop-filter:blur(18px)... }) buraya da
   uygulanıyor — rozet tıklanmaz, cam malzemesi yanlış sinyal verir. Daha
   sakin "kart" cam ailesine (glass-card, blur YOK) çekildi; shared sınıfa
   dokunulmadı, yalnız daha özgül `.studyo-rozet` üzerinden. min-height de
   .canli-kenar-rozeti'nin dokunma-hedefi düzeltmesinden (44px, tıklanabilir
   varyantlar --geride/--baglaniyor için doğru) ayrıştırıldı: rozet
   tıklanmadığı için 44px hem gereksiz hem de "burayı ittir" der. */
html[data-tema="gece"] .studyo-rozet:not(.studyo-rozet--acik) {
  background: var(--glass-card-bg);
  border-color: var(--glass-card-border);
  box-shadow: inset 0 1px 0 var(--glass-card-hi);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.studyo-rozet {
  min-height: 28px;
}

/* ── Dürüst gösterge (kalite okuması) = "sakin cam" kart ailesi ──────────
   Gündüzde zaten token'lı (color-surface/border); gecede --color-surface
   düşük-opaklıkta bir ton verir ama blur/kenar-parlaması yok — kart
   ailesine katılır. */
html[data-tema="gece"] .studyo-kalite-okuma {
  background: var(--glass-bg);
  border-color: var(--glass-border);
  box-shadow: inset 0 1px 0 var(--glass-hi), 0 4px 14px var(--glass-shadow);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
}
/* İ13 — rev1 `color-mix(in srgb, var(--color-accent) 22%, var(--glass-bg))`
   kullanıyordu: brief'in "renkler yalnız token'dan" kısıtını ihlal eden,
   hiçbir tokende karşılığı olmayan YENİ bir değer üretiyordu (çift
   tanımlanmadı). Kontrast sorunu YOK (ölçüldü 8.33:1) ama gündüzde zaten
   aynı rol için --color-accent-soft kullanılıyor — gece forku gereksizdi. */
html[data-tema="gece"] .studyo-kalite-okuma--sinirli {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
}

/* ── İzin yönergesi + kare uyarı şeridi ────────────────────────────────────
   İ6 + İ7 + İ15 — rev1 burada gece için "bildirim=opak gece" (--color-night
   zemin, düz renk) bloğu açmıştı. rev2'de o blok TAMAMEN SİLİNDİ, üç ayrı
   ölçülmüş sebeple:
   İ6: opak --color-night, sayfanın kendi --color-paper'ına (#1b1417) çok
       yakın (#120d10) — blok/sayfa aydınlık oranı 1.44→1.06'ya, 1.34→1.06'ya
       düşüyordu, iki uyarı bloğu bir bakışta sayfadan ayrışmıyordu (kamera/
       mikrofon izni yayının önkoşulu — maliyet yüksek).
   İ7: `border-color: var(--color-accent)` DÖRT kenarı birden boyuyordu;
       gündüzün "3 nötr kenar + 4px accent sol bar" imzasını (base app.css
       `.studyo-uyari-serit{border-left:4px solid var(--color-accent)}`)
       gecede tek-tip çerçeveye çeviriyordu (brief DO-NOT: aynı bileşene iki
       farklı biçim).
   İ15: `box-shadow: none` ölü satırdı — `--kagit-kenar` gecede zaten
       transparent, iptal edilecek bir gölge yoktu.
   Üçünün ortak kökü aynı: BAŞTAN gerek YOKTU. Base app.css kuralları
   (`.studyo-izin-yonerge{border:1px solid var(--color-danger);
   background:var(--color-danger-soft)}`, `.studyo-uyari-serit{border:1px
   solid var(--color-border-strong);border-left:4px solid var(--color-accent);
   background:var(--color-accent-soft);color:var(--color-ink)}`,
   `.studyo-izin-baslik{color:var(--color-danger)}`,
   `.studyo-izin-adimlar{color:var(--color-ink)}`) TAMAMEN token-tabanlı —
   her token zaten gece :root bloğunda ayrı (soluk/translucent) bir değer
   taşıyor, üstüne yazmaya hiç gerek yoktu. Metin kontrastı token zaten
   yüksek tutuyor (danger/ink gecede açık renkler); zemin artık soluk
   danger-soft/accent-soft (koyu zemin üstünde translusent, ~1.3-1.4 civarı
   bölge-ayrımı geri gelir — opak gecenin ~1.0'ına karşı). .toast'un opak
   gece malzemesi (dört-rol taksonomisinin "bildirim" ayağı) BURADAN
   etkilenmedi, dokunulmadı. */

/* ── Mikser: kaydırıcı tutamağı ≥28px (brief kısıtı; eskisi 24px) ────────
   Kutu/kanal/durum-satırının KENDİSİ bu grubun kapsamı DIŞINDA (üstteki
   başlık notu) — yalnız sürgü + tutamak + etiket. */
.mikser-surgu::-webkit-slider-thumb {
  width: 28px;
  height: 28px;
  margin-top: -11px;
}
.mikser-surgu::-moz-range-thumb {
  width: 28px;
  height: 28px;
}
/* İ3 — rev1 `::-webkit-slider-thumb, ::-moz-range-thumb`i TEK seçici
   listesinde birleştirmişti: Chrome `-moz-` pseudo-element'i, Firefox
   `-webkit-` olanı TANIMAZ ve CSS Selectors Level 3/4 kuralı gereği
   tanınmayan bir seçici TÜM listeyi geçersiz kılar — sonuç HİÇBİR
   tarayıcıda uygulanmayan bir kural (ölçüm: Chrome'da 17 parse edilen
   kural içinde yok). İki AYRI blokta tekrarlandı — app.css'in kendi
   :fullscreen dersini üç satır sonra ihlal etmemek için. */
html[data-tema="gece"] .mikser-surgu::-webkit-slider-thumb {
  box-shadow: 0 0 0 1px var(--glass-border), var(--shadow-sm);
}
html[data-tema="gece"] .mikser-surgu::-moz-range-thumb {
  box-shadow: 0 0 0 1px var(--glass-border), var(--shadow-sm);
}

/* E3 + İ4 — sürgü OLUĞU (track) dokunulmamıştı: yalnız tutamak vardı, ses
   seviyesinin NEREDE durduğu ekranda görünmüyordu (mikserde okunması
   gereken tek şey bu). Piksel ölçümü: oluk/kutu kontrastı gündüz 1.27:1,
   gece 1.39:1 — brief'in "büyük/dekoratif ≥3:1" tabanının altında.
   `--color-border-strong` HER İKİ temada da yeterli (gece 3.02:1, gündüz
   app.css'in kendi tablosundan 3.48:1) — tek token, gece forku gerekmedi.
   İki AYRI blokta (İ3'ün aynı tuzağı: birleşik seçici = her tarayıcıda ölü). */
.mikser-surgu::-webkit-slider-runnable-track {
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border-strong);
}
.mikser-surgu::-moz-range-track {
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border-strong);
}

/* ── Cihaz seçicileri: pill'e uygun ok + hizası ──────────────────────────
   appearance:none native oku siler, "etkileşimli olan dokunmadan önce
   belli olur" kısıtı için YERİNE token-renkli bir ok konur (yeni DOM öğesi
   değil, background-image). İ12 — rev1'in data-URI'sindeki İKİ SABİT HEX
   (%237a5a66 gündüz, %23c9b5af gece) --color-ink-muted'in bugünkü birebir
   aynasıydı ama token değişince SESSİZCE bayatlardı (CSS `var()` bir
   data-URI içinde okunamıyor — bu yüzden rev1 sabitlemişti). rev2'de
   data-URI TAMAMEN kaldırıldı: iki köşegen linear-gradient ile aynı "ok"
   görünümü, gerçek `var(--color-ink-muted)` okuyarak, TEK kural iki temayı
   birden kapsıyor (gece override'ı da düşer). */
.studyo-cihaz {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 40px;
  background-color: var(--color-surface);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-ink-muted) 50%),
    linear-gradient(-45deg, transparent 50%, var(--color-ink-muted) 50%);
  background-size: 6px 6px, 6px 6px;
  background-position: right 22px center, right 18px center;
  background-repeat: no-repeat;
  margin-left: var(--space-2);
  margin-right: var(--space-4);
  max-width: 100%;
  text-overflow: ellipsis;
}
html[data-tema="gece"] .studyo-cihaz {
  background-color: var(--glass-well-bg);
}
/* E4 — etiket ile select 0px'de bitişiyordu (label.right === select.left,
   420px ve 1200px'te birebir ölçüldü): `.sidebar-section` `display:block`,
   aralarında satır-boşluğu yaratan hiçbir şey yok, iki inline öğe birbirine
   yapışıyordu ("Kamera"nın son harfi select'in kenarına giriyordu). rev1'in
   kendi `padding-right:40px` eklemesi de select'in İÇ payını büyütüp boş
   cihaz listesinde (optCount:0) içerik kutusunu 2px'e düşürüyordu — o kusuru
   büyütmüş, kapatmamıştı. `.field-label`e dokunulmadı (paylaşılan, sahipsiz
   kök — kapsam dışı, bkz. elestiri-1 "Başka grup/sahipsiz"); yalnız select
   tarafında boşluk açıldı ve taşma kırpıldı. (2026-08-26: bu kuralın
   bildirimleri yukarıdaki tek `.studyo-cihaz` bloğuna taşındı — aynı bağlamda
   ikinci bir standalone blok tutmanın gerekçesi yoktu; gerekçe yorumu burada
   kalıyor çünkü açıkladığı margin/max-width kararı hâlâ yürürlükte.) */
/* İ14 — `optCount:0` iken hap hâlâ tıklanabilir görünüyordu (chevron +
   kenarlık + tam yükseklik) üstelik ekranda aynı anda "Cihazlar alınamadı"
   yazıyordu — etkileşimli görünen ama içi boş bir kontrol. `:empty`
   DOM'a dokunmadan, seçeneksiz `<select>`i yakalar. */
.studyo-cihaz:empty {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ── Onay kutuları — native accent-color, iki temada tek satır: token
   zaten --color-accent gece/gündüz için ayrı değer taşıyor, ayrı gece
   kuralı gerekmedi. Kutu, satırın kendisi (44px min-height, mevcut)
   zaten dokunma hedefini karşılıyordu. */
.studyo-kutu-satiri input[type="checkbox"] {
  accent-color: var(--color-accent);
  width: 20px;
  height: 20px;
  cursor: pointer;
}
/* İ5 — `accent-color` YALNIZ işaretli hâli boyar; ekranda üç kutu da
   işaretsizken native UA kutusu (gündüz #767676 kenar + beyaz dolgu) HİÇ
   değişmiyordu — gecede bu, panele karşı 15.2:1 parlayan, keskin köşeli,
   nötr-gri TEK geometriydi, "Gece Penceresi"nin cam/lamba diline hiç
   katılmamış. `color-scheme:dark` UA'nın kendi kutu paletini koyulaştırır
   (canlı test edildi: colorScheme normal→dark), işaretli hâl accent-color'da
   kalır, yeni token gerekmez. */
html[data-tema="gece"] .studyo-kutu-satiri input[type="checkbox"] {
  color-scheme: dark;
}

/* ── Mektup töreni zemini (.okuma/.whiteout) ──────────────────────────────
   Bu iki sınıf zaten faz-1'in "tören ekranları" bölümünde (app.css, .gate'in
   hemen yanında) token-tabanlı tanımlı — lowercase/pill/serif dili girişten
   beri taşıyorlar. Ayrı bir gece bloğu gerekmiyor: `--color-peach` (okuma
   zemini) ve `--color-white-warm` (whiteout) ikisi de gece :root'unda zaten
   koyu değere döner. İ11 — bu turda GERÇEK render'la doğrulandı (rev1'de
   doğrulanamamıştı, bkz. notlar.md "## rev2"): `#/mektup` hash-rotasından
   DEĞİL, girişten HEMEN sonra `mektupToreniyleGir()` bir kez çalışır. */
/* ===== FAZ-2 SON ===== */

/* ===== CANLI OYNAT MÜHRÜ (SEAM_CONTRACT v1, 2026-08-22) ===== */
/* ══════════════════════════════════════════════════════════════════════════
   CANLI — tuval ortasındaki "oynat" mührü            TASLAK · 2026-08-22
   Sözleşme: SEAM_CONTRACT.draft.md · Tasarım: reports/tasarim.md

   YERLEŞTİRME: app.css'in "── Canlı: katılım satırı + alt paneller ──"
   bölümünün SONUNA, `.studyo-katilimci > .field-hint` kuralından hemen önce.
   GECE BLOĞUNA HİÇBİR SATIR EKLENMEZ ve :root'a YENİ TOKEN AÇILMAZ — bileşen
   tema farkını tamamen mevcut token'ların kendi değerlerinden alır:
     --color-accent / --color-on-accent / --color-ink  → renk ve kontrast
     --muhur-halka / --muhur-golge                     → balmumu mührü malzemesi
     --accent-glow                                     → gündüzde `transparent`,
                                                         gecede lamba halesi
   Bu, dosyanın kendi mekanizmasıdır (bkz. :root'taki "gecede dolar" yorumu):
   tek kural yazılır, gündüzde kendini söndürür.
   ══════════════════════════════════════════════════════════════════════════ */

/* Sarmal tüm kareyi kaplar ama TIKLAMAYI GEÇİRİR: `<video controls>`in kendi
   kontrol çubuğu (alt bant) ve tam-ekran düğmesi erişilebilir kalmalı. Tıklamayı
   yalnız diskin kendisi yakalar (aşağıda pointer-events: auto).
   Gizleme küresel `[hidden] { display: none !important }` kuralından gelir —
   app.js sarmalın `hidden` özniteliğini yazar, burada ikinci bir display kuralı
   YOKTUR. */
.canli-oynat {
  --canli-oynat-cap: clamp(64px, 9vw, 88px);
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

/* Emniyet kuralı. Birincil mekanizma ömürdür: `katilimaGec()` mediaContainer'ı
   boşalttığı için sarmal zaten yok olur (SEAM §1). Bu satır, ileride biri
   tuvali boşaltmadan katılım moduna geçerse mührün katılımcı kamerasının
   üstünde asılı kalmasını yapısal olarak imkânsız kılar. */
.player-media--katilim .canli-oynat {
  display: none;
}

/* ── disk: balmumu mührü ────────────────────────────────────────────────────
   Biçim daire, malzeme mühür — `.btn`in hap/kâğıt dili BİLEREK kullanılmadı
   (`.btn` kâğıttır: 999px + lowercase + 0 22px + --kagit-kenar; hepsini ezmek
   tek başına kural yazmaktan uzun olurdu ve `.btn`e daire beklentisi sızdırırdı).
   Emsal `.canli-nokta`dır: aynı --muhur-golge / --muhur-halka ailesi.

   MERKEZLEME `inset: 0 + margin: auto` iledir, `translate(-50%,-50%)` ile DEĞİL:
   böylece `transform` tamamen ölçek animasyonuna kalır ve hover/active kuralları
   merkezlemeyi yeniden yazmak zorunda kalmaz (yeniden yazmayı unutan bir el,
   düğmeyi köşeye fırlatırdı).

   RENK: ilk `background` satırı DÜZ dolgudur ve color-mix/gradyan desteklenmezse
   diskin görünmez kalmasını engeller (mevcut `.canli-nokta`da bu yedek yok —
   ayrı bir iş olarak adlandırıldı). Parıltı ve gölge lekeleri çapın yüzdesiyle
   boyutlandı ki diskin MERKEZİ (▶'nin oturduğu yer) saf --color-accent'te kalsın;
   ölçülen en kötü ▶/zemin kontrastı gündüz 5.31:1, gece ≥8.82:1. */
.canli-oynat-btn {
  position: absolute;
  inset: 0;
  margin: auto;
  width: var(--canli-oynat-cap);
  height: var(--canli-oynat-cap);
  padding: 0;
  border: 0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  pointer-events: auto;
  -webkit-appearance: none;
  appearance: none;
  color: var(--color-on-accent);
  background: var(--color-accent);
  background:
    radial-gradient(circle calc(var(--canli-oynat-cap) * 0.42) at 32% 26%,
      var(--muhur-halka), transparent 100%),
    radial-gradient(circle calc(var(--canli-oynat-cap) * 0.55) at 50% 118%,
      var(--muhur-golge), transparent 100%),
    var(--color-accent);
  /* ÇİFT HALKA — okunurluğun taşıyıcısı. Video karesi DEĞİŞKEN zemindir; kontrast
     kaptan alınamaz (üstelik kabın zemini --color-ink'tir ve gecede KREM'e döner).
     İki halkanın rengi her iki temada da uçlarda durur (gündüz 14.2:1, gece
     14.7:1), dolayısıyla rastgele bir kare rengi için ikisinden en az biri
     ≥3.77:1 ayrışır — dekoratif eşik 3:1 hangi kare gelirse gelsin sağlanır.
     Yarı-saydam --muhur-halka bu iş için KULLANILMAZ: alfa, bilinmeyen kareyle
     karışıp garantiyi yok eder. */
  box-shadow:
    0 0 0 3px var(--color-on-accent),
    0 0 0 4px var(--color-ink),
    0 10px 26px var(--muhur-golge),
    0 0 34px var(--accent-glow);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
  animation: canli-oynat-belir 160ms ease-out;
}

/* ▶ — CSS kenarlık üçgeni. Metin karakteri ("▶") KULLANILMADI: bazı platformlarda
   emoji fontuna düşer ve renkli/farklı boyda çıkar. SVG de kullanılmadı: app.js'in
   `el()` yardımcısı createElement'tir, SVG createElementNS ister.
   translateX: üçgenin ağırlık merkezi solda kalır, optik denge için kaydırılır. */
.canli-oynat-btn::before {
  content: "";
  width: 0;
  height: 0;
  border-top: calc(var(--canli-oynat-cap) * 0.17) solid transparent;
  border-bottom: calc(var(--canli-oynat-cap) * 0.17) solid transparent;
  border-left: calc(var(--canli-oynat-cap) * 0.30) solid currentColor;
  transform: translateX(12%);
}

.canli-oynat-btn:hover {
  transform: scale(1.04);
}

.canli-oynat-btn:active {
  transform: scale(0.96);
}

/* Küresel `:focus-visible` kuralı elemana `border-radius: var(--radius-sm)`
   YAZAR ve daireyi köşelendirirdi — burada geri alınıyor (özgüllük 0,2,0 > 0,1,0).
   offset 4px: halka, hemen içindeki 14:1'lik hairline'a yaslanır, o yüzden odak
   göstergesi kendi komşusundan da ayrışır. */
.canli-oynat-btn:focus-visible {
  border-radius: 50%;
  outline: 3px solid var(--color-focus);
  outline-offset: 4px;
}

/* ── bekliyor: basıldı, kare henüz akmıyor ──────────────────────────────────
   Sınıf SARMALDA durur (SEAM §2), düğmede değil. ▶ kapanır, yerini dönen halka
   alır. `border-color` düşerse (color-mix yok) yalnız üst yay kalır — okunur
   bir düşüş, görünmez bir düşüş değil. */
.canli-oynat--bekliyor .canli-oynat-btn::before {
  display: none;
}

.canli-oynat--bekliyor .canli-oynat-btn::after {
  content: "";
  width: calc(var(--canli-oynat-cap) * 0.38);
  height: calc(var(--canli-oynat-cap) * 0.38);
  border-radius: 50%;
  border: 3px solid transparent;
  border-color: color-mix(in srgb, var(--color-on-accent) 30%, transparent);
  border-top-color: var(--color-on-accent);
  animation: canli-oynat-doner 900ms linear infinite;
}

/* ── not: yalnız engellenme/ulaşılamama hâlinde ─────────────────────────────
   Diskin ÜSTÜNDE durur: karenin ALT bandı native kontrol çubuğunundur.
   Zemin --color-paper: iki temada da OPAK. --color-surface KULLANILAMAZ, gecede
   yarı-saydamdır ve metin kontrastı garanti edilemezdi (12.27:1 / 15.46:1).
   Gizleme `:empty` iledir, `hidden` ile DEĞİL: `role="status"` canlı bölgesi
   DOM'da kalmalı ki metin yazıldığında duyuru güvenilir olsun.
   Emsal: `.radyo-kaset-not` (kaset oynatıcının "tarayıcı sesi engelledi" satırı). */
.canli-oynat-not {
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--canli-oynat-cap) / 2 + var(--space-3));
  transform: translateX(-50%);
  margin: 0;
  width: max-content;
  max-width: min(30ch, 88%);
  padding: var(--space-2) 16px;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  background: var(--color-paper);
  color: var(--color-ink);
  font-size: var(--font-size-sm);
  line-height: 1.35;
  text-align: center;
  box-shadow: var(--shadow-sm);
  pointer-events: none;
}

.canli-oynat-not:empty {
  display: none;
}

/* ── hareket ──────────────────────────────────────────────────────────────── */
@keyframes canli-oynat-belir {
  from { opacity: 0; transform: scale(0.92); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes canli-oynat-doner {
  to { transform: rotate(360deg); }
}

/* Küresel blok zaten süreleri 0.001ms'ye çeker; transform'lar ondan ETKİLENMEZ,
   bu yüzden `.btn` emsalindeki gibi ayrıca söndürülüyor. Dönen halka DURUR ama
   KALIR: statik kesik halka "hazır değil" der, ve aria-busy yardımcı tekniği
   zaten taşır. Diskte boşta nabız/nefes YOK — ekranda nefes alan tek öğe canlı
   noktasıdır (`.canli-nokta`, gece-nefes). */
@media (prefers-reduced-motion: reduce) {
  .canli-oynat-btn {
    animation: none;
    transition: none;
  }
  .canli-oynat-btn:hover,
  .canli-oynat-btn:active {
    transform: none;
  }
  .canli-oynat--bekliyor .canli-oynat-btn::after {
    animation: none;
  }
}

/* Yüksek kontrast (Windows HCM): ▶ bir kenarlık üçgeni olduğu için sistem
   renk-zorlaması altında kaybolabilirdi; disk ve üçgen sistem renklerine
   sabitlenir. */
@media (forced-colors: active) {
  .canli-oynat-btn {
    forced-color-adjust: none;
    background: ButtonFace;
    color: ButtonText;
    box-shadow: 0 0 0 2px ButtonText;
  }
  .canli-oynat-btn::before {
    border-left-color: ButtonText;
  }
  .canli-oynat-not {
    background: Canvas;
    color: CanvasText;
    border-color: CanvasText;
  }
}


/* ===== FAZ-2 GOVERNOR EKLERİ — çapraz-grup sahipsiz kalanlar (2026-08-22) ===== */
/* a+c eleştirmenleri: kenar-panel başlıkları ("radyo", "yorumlar", "işaretli anlar")
   VERSAL kalmıştı; üslubun küçük-harf etiket dili buraya da uygulanır. */
.sidebar-section-title {
  text-transform: lowercase;
}

/* ===== FAZ-2 EK (2026-08-23) — durum metin satırları ===== */
/* .mikser-durum (KAYIT/ARŞİV oynatıcısının mikser durum satırı, KURULUŞU
   `kayitMikseriKur()` — app.js 1805/1830, kutuda `baslatBtn` da var,
   DOKUNULMADI; canlı ekranın kendi mikserinde bu sınıf YOK — eleştiri-1 E3,
   önceki sürüm burayı yanlışlıkla "canlı mikser" diye adlandırıyordu) ve
   .studyo-durum-metin (app.js 6152, 6155, 6405, 6430) FAZ-2 turunun
   (2026-08-22, yukarıdaki iki blok)
   dışında kaldı. Renkleri zaten doğruydu — ikisi de tabanlarından
   (.mikser-not satır 1183; bu dosyanın .studyo-durum-metin kuralı satır
   2201) --color-ink-muted + --font-size-sm taşıyor, YENİ token/ham renk
   gerekmedi. Eksik olan tek şey biçim diliydi: ikisi de hap/rozet DEĞİL,
   tek satırlık sakin durum beyanı — .radyo-kapali-not + .radyo-kaset-not +
   .radyo-sh-durum--kapali'nin katıldığı "fısıltı register"ın (yukarıda,
   "Sessiz durum notları" yorumu) aynı ailesi: "henüz bir şey söylenmiyor /
   şu an bir şey yok" hâli aynı sesle konuşmalı.
   Karışık mesaj precedent'i: .radyo-kaset-not TEK sınıfta hem "bağlanıyor…"
   (geçişli/aktif) hem "engellendi" (sessiz) taşıyor ve italik ORADAN da
   geri alınmadı — .mikser-durum ("çalıyor" / "kapalıydı" karışımı) ve
   .studyo-durum-metin ("bağlı" / "bağlı değil" karışımı) aynı örüntüde;
   app.js'e dokunmadan (yasak) durum-başına ayrı sınıf açılamayacağı için
   tek-sınıf üzerinden aynı precedent uygulanıyor.
   Kontrast DEĞİŞMEDİ (yalnız font-style, renk yok) — mevcut çift zaten eşiğin
   üstünde: gündüz ink-muted/surface 5.82:1 (üstteki tabloyla birebir),
   gece ink-muted/glass-card-bg(6%, .video-mikser zemini) 8.02:1, gece
   ink-muted/surface(7%, .sidebar-section zemini — .studyo-durum-metin'in
   kutusu) 7.82:1 — üçü de eşik 4.5'in üstünde (python3, WCAG relative-
   luminance). Gece bloğu gerekmiyor: font-style renk taşımıyor, ayrı
   tanıma ihtiyaç yok. */
.mikser-durum,
.studyo-durum-metin {
  font-style: italic;
}

/* ===== FAZ-2 EK (2026-08-24) — müzik / “çalarken” browse ===== */
/* Sahiplik `.muzik-*` yüzeyi, yeni kabuk sekmesi ve async rota mount çitidir.
   Renk, gölge, ölçü ve malzeme mevcut Pembe Zarf / Gece Penceresi
   token'larından gelir; bu blok yeni bir palet ya da tema forku açmaz. */

.route-mount {
  width: 100%;
  min-width: 0;
}

.topbar-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 0;
}

.topbar-actions .btn:active:not(:disabled),
.muzik-yukleme-hatasi .btn:active:not(:disabled) {
  border-color: var(--color-accent);
  background: var(--color-surface-sunken);
  transform: translateY(1px);
}

/* Şeritte "buradasın" GÖRSELİ yok (owner kararı 2026-08-25). Eskiden yalnız
   müzik sekmesi accent bir alt çizgi + `border-radius: 0` taşıyordu: beş
   sayfadan yalnız birinde yanan, üstelik kardeşleri hap biçimindeyken tek
   başına dikdörtgenleşen bir durum. Genelleştirmek yerine SÖKÜLDÜ — her ekran
   artık kendi adını `.ekran-basligi-ad`da söylüyor, şeridin ikinci bir kez
   söylemesine gerek yok. `aria-current="page"` app.js'te DÖRT sekmeye birden
   yazılır ve görselsizdir: ekran okuyucu konumu bilir, göz gürültü görmez. */

.muzik-view,
.muzik-detail {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  width: 100%;
  max-width: var(--olcu-okuma);
  min-width: 0;
  margin: 0 auto;
}

/* Müzik liste ekranının kabı flex+gap taşıyor; şeridin kendi `margin-bottom`u
   buna EKLENİYORDU (24+32 = 56px). Dikey boşluğun tek sahibi kap olsun. Detay
   DOM'u `.ekran-basligi` kurmadığı için seçici yalnız gerçek eşleşmeyi taşır. */
.muzik-view > .ekran-basligi {
  margin-bottom: 0;
}

.muzik-yukleme-hatasi {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  width: 100%;
  max-width: var(--olcu-okuma);
  margin: 0 auto;
}

.muzik-kapsam,
.muzik-sayac,
.muzik-an-saat,
.muzik-an-not,
.muzik-zaman,
.muzik-rank,
.muzik-rozet,
.muzik-daralt-not,
.muzik-gun-baslik,
.muzik-ince-not {
  font-variant-numeric: tabular-nums;
}

.muzik-kapsam {
  min-width: 0;
  overflow: hidden;
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.muzik-arama {
  width: 100%;
  min-height: var(--touch-target);
  padding: 0 20px;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-ink);
}

.muzik-arama::placeholder {
  color: var(--color-ink-muted);
}

.muzik-arama:focus {
  border-color: var(--color-accent);
}

html[data-tema="gece"] .muzik-arama {
  background: var(--glass-well-bg);
  border-color: var(--glass-border);
  box-shadow: inset 0 2px 6px var(--glass-well-shadow);
}

.muzik-bolum {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.muzik-bolum-baslik {
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: lowercase;
}

.muzik-son-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.muzik-son-kart,
.muzik-sira-satir,
.muzik-an,
.muzik-geri {
  color: inherit;
  text-decoration: none;
}

/* Malzeme `.session-card--large` ile AYNI (2026-08-25): aynı işi yapan iki
   liste satırı — küçük resim + iki satır metin + tıkla-git — iki farklı kart
   dili konuşuyordu (22px/shadow-md/güçlü kenar vs 12px/shadow-sm/ince kenar).
   Kaçan taraf müzikti; gün listesinin diline çekildi. */
.muzik-son-kart {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 74px;
  padding: var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-kart);
  background: var(--color-surface);
  box-shadow: var(--shadow-md), inset 0 -1px 0 var(--kagit-kenar);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast),
    background-color var(--transition-fast), border-color var(--transition-fast);
}

.muzik-son-kart:hover {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.muzik-son-kart:active {
  border-color: var(--color-accent);
  background: var(--color-surface-sunken);
  box-shadow: var(--shadow-sm);
  transform: translateY(1px) scale(.99);
}

html[data-tema="gece"] .muzik-son-kart {
  background: var(--glass-card-bg);
  border-color: var(--glass-card-border);
  border-radius: var(--radius-kart);
  box-shadow: inset 0 1px 0 var(--glass-card-hi);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
}

.muzik-thumb,
.muzik-thumb-fallback {
  flex: 0 0 56px;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-kart-ic);
  background: var(--color-surface-sunken);
}

.muzik-thumb {
  object-fit: cover;
}

.muzik-thumb-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-ink-muted);
  font-family: var(--font-display);
  font-size: var(--font-size-lg);
}

.muzik-son-meta,
.muzik-sira-meta,
.muzik-an-meta {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}

.muzik-sarki-adi {
  overflow: hidden;
  color: var(--color-ink);
  font-family: var(--font-display);
  font-size: var(--font-size-muzik-sarki);
  font-style: italic;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.muzik-sanatci,
.muzik-zaman,
.muzik-an-not,
.muzik-daralt-not,
.muzik-empty,
.muzik-alt,
.muzik-sayac,
.muzik-ince-not {
  color: var(--color-ink-muted);
}

.muzik-sanatci,
.muzik-zaman,
.muzik-an-not,
.muzik-daralt-not,
.muzik-gun-baslik {
  font-size: var(--font-size-sm);
}

.muzik-sanatci,
.muzik-zaman {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.muzik-ok {
  flex: 0 0 auto;
  color: var(--color-ink-muted);
  font-size: var(--font-size-md);
}

.muzik-siralama {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.muzik-sira-satir {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--touch-target);
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  transition: transform var(--transition-fast), background-color var(--transition-fast),
    border-color var(--transition-fast);
}

.muzik-sira-satir:hover {
  border-color: var(--color-border);
  background: var(--color-surface-sunken);
}

.muzik-sira-satir:active {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
  transform: scale(.99);
}

.muzik-rank {
  flex: 0 0 1.9rem;
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  text-align: right;
}

.muzik-rozet {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  min-height: 28px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-on-accent);
  box-shadow: inset 0 -1px 1px var(--muhur-golge), 0 0 0 1px var(--muhur-halka);
  font-size: var(--font-size-sm);
  font-weight: 700;
}

.muzik-daralt-not {
  padding: var(--space-2);
}

.muzik-empty {
  padding: var(--space-4) 0;
}

.muzik-geri {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  min-height: var(--touch-target);
  margin-left: calc(-1 * var(--space-1));
  padding: 0 var(--space-1);
  color: var(--color-ink-muted);
  font-size: var(--font-size-sm);
  font-weight: 700;
}

.muzik-geri:hover {
  color: var(--color-accent);
}

.muzik-geri:active {
  color: var(--color-accent-strong);
  transform: translateY(1px);
}

.muzik-hero {
  min-width: 0;
}

.muzik-detail-title {
  color: var(--color-ink);
  font-family: var(--font-display);
  font-size: var(--font-size-xl);
  font-style: italic;
  font-weight: 500;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.muzik-calarken {
  color: var(--color-ink-muted);
  font-family: var(--font-body);
  font-size: var(--font-size-md);
  font-style: normal;
  font-weight: 400;
}

.muzik-alt {
  min-width: 0;
  margin-top: var(--space-1);
  overflow-wrap: anywhere;
}

.muzik-sayac strong {
  color: var(--color-ink);
}

.muzik-anlar {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.muzik-gun {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.muzik-gun-baslik {
  margin-bottom: var(--space-1);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  color: var(--color-ink);
  font-weight: 700;
  text-transform: lowercase;
}

.muzik-gun:first-child .muzik-gun-baslik {
  padding-top: 0;
  border-top: 0;
}

.muzik-an {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 74px;
  padding: var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  transition: transform var(--transition-fast), background-color var(--transition-fast),
    border-color var(--transition-fast);
}

.muzik-an:hover {
  border-color: var(--color-border);
  background: var(--color-surface-sunken);
}

.muzik-an:active {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
  transform: scale(.99);
}

.muzik-an-meta {
  gap: 3px;
}

.muzik-an-saat {
  font-weight: 700;
}

.muzik-mini-cubuk {
  display: block;
  width: 100%;
  max-width: 220px;
  height: 8px;
  margin-top: 2px;
  overflow: visible;
}

.muzik-mini-cizgi {
  stroke: var(--color-border-strong);
  stroke-linecap: round;
  stroke-width: 3;
}

.muzik-mini-nokta-halka,
.muzik-mini-nokta {
  stroke-linecap: round;
}

.muzik-mini-nokta-halka {
  stroke: var(--color-surface);
  stroke-width: 12;
}

.muzik-mini-nokta {
  stroke: var(--color-accent);
  stroke-width: 8;
}

.muzik-ince-not {
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
  font-size: .75rem;
}

@media (max-width: 720px) {
  .topbar {
    gap: var(--space-1);
    padding-right: var(--space-3);
    padding-left: var(--space-3);
  }

  .topbar-brand {
    flex: 0 0 auto;
  }

  .topbar-actions {
    flex: 1;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .topbar-actions::-webkit-scrollbar {
    display: none;
  }

  .topbar-actions .btn {
    flex: 0 0 auto;
    padding-right: var(--space-2);
    padding-left: var(--space-2);
  }

  /* Başlığın sağ yuvası telefonda tek karaktere kadar sıkışmasın: ebeveyn
     zaten wrap'li, kapsamı kendi satırına alıp metni okunabilir biçimde sar. */
  .ekran-basligi > .muzik-kapsam {
    flex-basis: 100%;
    overflow: visible;
    overflow-wrap: anywhere;
    text-overflow: clip;
    white-space: normal;
  }
}

@media (prefers-reduced-motion: reduce) {
  .muzik-son-kart,
  .muzik-sira-satir,
  .muzik-an {
    transition: none;
  }

  .muzik-son-kart:hover,
  .muzik-son-kart:active,
  .muzik-sira-satir:active,
  .muzik-an:active,
  .muzik-geri:active,
  .topbar-actions .btn:active:not(:disabled),
  .muzik-yukleme-hatasi .btn:active:not(:disabled) {
    transform: none;
  }
}
