/* =============================================================================
   base.css — 20 varyantın tamamının paylaştığı temel
   -----------------------------------------------------------------------------
   Burada GÖRSEL STİL YOK. Sadece:
     · reset
     · Safari / iOS düzeltmeleri
     · Türkçe tipografi kuralları
     · erişilebilirlik tabanı
   Her varyantın kendi karakteri kendi <style> bloğunda tanımlanır.

   Her kuralın yanında NEDEN orada olduğu yazılı — çünkü bu dosyayı bir sonraki
   dönem başka bir gönüllü devralacak ve "bu ne işe yarıyor" diye soracak.
============================================================================= */

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

* { margin: 0; }

/* `hidden` özniteliği GERÇEKTEN gizlesin.
   Tarayıcının kendi kuralı `[hidden] { display: none }` ama o kural TARAYICI
   sayfasında; bizim yazdığımız her `display` onu yeniyor. Sonuç: JS bir öğeye
   `hidden` koyuyor, öğe ekranda kalmaya devam ediyor ve hiçbir yerde hata
   görünmüyor.

   Sahada beş ekranda on üç öğe böyleydi: a-03'te hiçbir satır seçili değilken
   "Seçimi temizle" çubuğu duruyordu, a-06'da bütün kayıt detayları açıktı,
   a-04'te "Yeni değer" alanı İKİ KEZ (biri metin, biri açılır liste) birden
   görünüyordu.

   `!important` burada bilinçli: `[hidden]` özgüllüğü 0,1,0 — `.alan` ile eşit,
   `.kutu .alan` ile kaybeder. Amaç zaten "her şeyi yen"; erişilebilirlik
   sözleşmesinin kendisi bu. */
[hidden] { display: none !important; }

/* <dialog> yerleşimini geri ver.
   Modal bir <dialog>'u ekranda ortalayan şey tarayıcının `margin: auto`
   kuralı. Yukarıdaki `* { margin: 0 }` onu da siliyordu ve dokuz pencere
   yedi ekranda sol ÜST KÖŞEYE yapışıyordu — üstelik `showModal()` doğru
   çağrılıyordu, backdrop da vardı; yalnız konum yanlıştı. */
dialog { margin: auto; }

html {
  /* iOS Safari yatay modda ve geniş tek sütun bloklarda gövde metnini kendi
     kendine büyütür ("text inflation") ve tipografi ölçeğini bozar.
     100% kullanılır; none KULLANILMAZ — kullanıcının kendi yakınlaştırmasını
     engellemek erişilebilirlik ihlalidir. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;

  /* Yapışkan menü, çapa (#bolum) bağlantılarında hedef başlığı örtmesin.
     --nav-h değerini her varyant kendi menü yüksekliğine göre ezer. */
  --nav-h: 64px;
  scroll-padding-top: calc(var(--nav-h) + env(safe-area-inset-top, 0px));
}

/* Yumuşak kaydırma, ama hareket hassasiyeti olan kullanıcıya zorlanmaz. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  /* IEEE Digital Style Guide minimumları: gövde ≥ 15px, satır yüksekliği ≥ 1.5 */
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;

  /* DİKKAT: body'ye ASLA overflow-x: hidden konmayacak.
     position: sticky, kendisiyle kaydırma kökü arasındaki herhangi bir
     atanın overflow'u hidden/auto/scroll ise sessizce çalışmayı bırakır —
     "yapışkan menüm demoda çalışıyordu" hatasının bir numaralı sebebi budur.
     Yatay taşmayı kırpmak gerekirse `overflow-x: clip` kullanılır; clip
     kaydırma bağlamı oluşturmadığı için sticky hayatta kalır. */
  overflow-x: clip;
}

/* Türkçe sondan eklemeli bir dil; kelimeler uzar ("gerçekleştirilebilecek").
   break-word kullanılır — break-all heceyi ortasından böler ve okunmaz.

   DİKKAT — anywhere ile break-word arasındaki fark burada kritik:
   `anywhere` kelimeyi bölmenin yanında öğenin MIN-CONTENT genişliğini de tek
   karaktere düşürür. Bu, flex/grid içindeki menü bağlantılarının sıkışıp
   "Hakkımızd/a" diye ortadan bölünmesine yol açar. `break-word` ise sadece
   taşma anında böler, min-content'i (= en uzun kelime) korur.
   Bu yüzden bağlantı ve butonlar bu listede YOK. */
body, h1, h2, h3, h4, p, li { overflow-wrap: break-word; }

/* Tablo hücreleri ve uzun kırılmaz dizeler (IBAN, e-posta, URL) için
   `anywhere` gerçekten gerekli: hücrenin daralabilmesi lazım. */
td, th, .kirilabilir { overflow-wrap: anywhere; }

/* GRID/FLEX ÖĞELERİNİN min-width:auto TUZAĞI — mobil taşmaların bir numaralı sebebi.
   Bir grid/flex öğesinin varsayılan asgari genişliği "auto"dur: içeriğinin
   min-content genişliğinden daha dar OLAMAZ. İçeride sıkışmayan tek bir şey
   (bir tablo satırı, max-content sütunlu bir alt ızgara, uzun bir başlık) önce
   o öğeyi, sonra track'i, sonra konteyneri, en sonunda sayfayı şişirir —
   320px'te sayfa yana kaymaya başlar. Küçük ve derindeki bir hata tüm sayfayı
   bozar, sebebini bulmak çok zordur.

   :where() ile sarıldı → özgüllüğü SIFIR. Bir varyantın kendi kuralı
   (örn. .yan-sutun { min-width: 240px }) bunu her zaman ezer. */
:where(main, section, article, aside, header, footer, nav, div,
       ul, ol, li, dl, dd, form, figure, p, h1, h2, h3, h4) { min-width: 0; }

h1, h2, h3, h4 { line-height: 1.15; text-wrap: balance; }
p { text-wrap: pretty; }

/* Görsellerin oranı korunur ve düzen kaymasına yol açmaz.
   NOT: CSS tek başına yetmez — <img> üzerinde width/height ÖZNİTELİKLERİ de
   olmalı, çünkü tarayıcı CSS yüklenmeden yeri onlarla ayırır. */
img, picture, svg, video, canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

/* --- Form alanları -------------------------------------------------------- */
input, button, textarea, select { font: inherit; color: inherit; }

/* iOS Safari, hesaplanmış font-size 16px'in ALTINDA olan bir alana
   odaklanıldığında sayfayı zorla yakınlaştırır ve yakınlaşmış bırakır.
   Sadece dokunmatik cihazlarda 16px'e sabitlenir; masaüstü kendi ölçeğini
   korur. Bunu viewport meta'sına user-scalable=no yazarak "çözmek" WCAG
   1.4.4 ihlalidir ve yapılmaz. */
@media (pointer: coarse) {
  input, select, textarea { font-size: 16px; }
}

/* --- Erişilebilirlik ------------------------------------------------------ */
/* Odak halkası asla kaldırılmaz. :focus-visible sayesinde fare kullanıcısı
   görmez, klavye kullanıcısı her zaman görür. İki tonlu halka hem açık hem
   koyu yüzeyde ayırt edilir. */
:focus-visible {
  outline: 3px solid var(--focus, #00629B);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px rgb(255 255 255 / 0.6);
  border-radius: 4px;
}
:focus:not(:focus-visible) { outline: none; }

/* DOKUNMA HEDEFİ — yalın metin bağlantıları (WCAG 2.5.8, en az 24×24)

   Bir cümlenin İÇİNDEKİ bağlantı ölçütten muaftır: boyu satır yüksekliğine
   bağlıdır, büyütmek metni bozar. Ama tek başına duran bir bağlantı —
   "Şifremi unuttum", "Üye ol", "← Girişe dön", bir `dd` içindeki e-posta —
   muaf değil ve ölçüldüğünde 17–21px çıkıyordu. Yedi tanesi 24'ün altındaydı.

   Kutu büyütülmüyor, HALE ekleniyor: `::after` düzeni hiç değiştirmiyor.
   Yükseklik 26px, 44 değil — ve bu bilinçli. Hale bağlantının kendi
   genişliğinde ama dikeyde taşıyor; 44px yapmak komşu alanın (etiket, girdi)
   üstüne binip ONUN tıklamasını çalardı. 26px, eşiğin 2px üstünde kalıp
   komşuya değmiyor.

   Kural: tools/dokunma.mjs — eşik `content.js` k-14 beyanından geliyor. */
.auth-alt a, .alan-satir a, .kayit-dip a, dd > a { position: relative; }
.auth-alt a::after, .alan-satir a::after,
.kayit-dip a::after, dd > a::after {
  content: ''; position: absolute; left: 0; right: 0;
  top: 50%; height: 26px; transform: translateY(-50%);
}

/* =============================================================================
   İLK ÇİZİM — İÇERİK DOLMADAN GÖSTERME
   -----------------------------------------------------------------------------
   NİÇİN VAR
   Bu maket bütün metnini `content.js`ten alıyor ve DOM'u JS dolduruyor. Ekran
   boş iskeletle açılıyor, JS dolduruyor ve her şey aşağı zıplıyor. Ölçüldü
   (Tur 29, 390px, `file://`): 61 ekranın 11'inde kullanıcının GÖRDÜĞÜ düzen
   kayması 0.1 eşiğinin üstünde, en kötüsü 0.939. CPU dört kat yavaşlatılınca
   (orta sınıf telefon) 31 ekran.

   NİÇİN "YER AYIRMA" DEĞİL
   Ölçüldü: her büyüyen öğeye `min-height` vermek 843 seçici demek ve 801'i
   ekranların kendi `<style>`ında. Hiçbirinin veride karşılığı olmaz, hiçbir
   kural doğrulayamaz, ilk metin değişiminde sessizce eskir — 3. ve 8.
   değişmezin yasakladığı şey. Üstelik tavanı 0.351: sıfırlamıyor bile.
   Aynı ekranın iki hâli arasında 1009px fark ölçüldü; tek bir sayı ikisine
   birden doğru gelmiyor.

   `visibility` — `display` DEĞİL
   `display: none` düzeni yok ediyor ve `panel.js` `kaydirmaIpucu()`
   (`scrollWidth`), `syncNavHeight()` (`offsetHeight`), `kabuk.js altMenu()`
   (`getBoundingClientRect`) sıfır okuyor. `visibility: hidden` düzeni
   koruyor, yalnız çizmiyor.

   KURTARMA — JS HİÇ ÇALIŞMAZSA
   Açma satırı `DOMContentLoaded`ta çalışıyor; ekranın kendi betiği hata
   verse bile o olay yine ateşleniyor, yani sayfa bugünkü hâline düşüyor.
   Ama `panel.js`/`kabuk.js` hiç yüklenmezse kimse açmaz. `GUNLUK.md` Tur
   16'da bir kesme işareti `index.html`i bir tur boyunca öldürmüştü ve
   hiçbir araç yakalamamıştı — o hata bu kural altında "bembeyaz hiçlik"e
   dönerdi. Aşağıdaki animasyon üç saniye sonra sayfayı KENDİLİĞİNDEN
   açıyor.

   `prefers-reduced-motion` bunu BOZMUYOR: aşağıdaki blok `animation-duration`
   eziyor, `animation-delay`e dokunmuyor (ölçüldü).

   ⚠ BU BİR MAKET KATMANI DÜZELTMESİDİR. Kayma `content.js`in ilk çizimden
   sonra gelmesinden doğuyor; gerçek uygulama sunucuda render edildiğinde
   sorun da bu blok da gereksizleşir. `SUNUCU.md` §1'de yazılı.
============================================================================= */
html:not(.hazir) body {
  visibility: hidden;
  animation: ieee-kurtarma 1ms linear 3000ms forwards;
}
@keyframes ieee-kurtarma { to { visibility: visible; } }

/* Hareket hassasiyeti: animasyon tamamen kapatılmaz (bu açılır menü gibi
   işlevsel geçişleri bozar), süresi sıfıra yaklaştırılır. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Ekran okuyucuya görünür, gözle görünmez. */
.gorsel-gizli {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* İçeriğe atlama bağlantısı — her sayfadaki ilk odaklanabilir öğe.
   Hedefte tabindex="-1" olmalı, yoksa Safari kaydırır ama odağı taşımaz. */
.atla {
  position: absolute; left: 8px; top: -100px; z-index: 999;
  padding: 12px 20px; border-radius: 8px;
  background: #00629B; color: #fff; text-decoration: none;
  transition: top .15s;
}
.atla:focus { top: calc(8px + env(safe-area-inset-top, 0px)); }

/* --- Dokunma hedefi ------------------------------------------------------- */
/* Tıklanabilir her şey en az 44x44 px. İkon büyütülerek değil, dolgu
   eklenerek sağlanır. */
a, button, [role="button"], input[type="submit"] { touch-action: manipulation; }

@media (pointer: coarse) {
  .dokunma-hedefi { min-width: 44px; min-height: 44px; }
}

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

/* Tam ekran bölüm.
   100svh kullanılır, 100dvh DEĞİL: iOS'ta dvh adres çubuğu her kaydırmada
   yeniden hesaplandığı için gözle görülür titreme yapar. svh ise "araç
   çubukları görünürken" ölçüsüdür, yani içerik hiçbir zaman kesilmez.
   100vh iOS'ta BÜYÜK viewport'tur, yani adres çubuğunun kapladığı alanı da
   sayar ve hero'yu ~110-130px fazla uzatır — sadece yedek olarak durur. */
.tam-ekran { min-height: 100vh; min-height: 100svh; }

/* Çentik ve ana çubuk güvenli alanı. env() SADECE viewport meta'sında
   viewport-fit=cover varsa çalışır; yoksa sessizce 0px döner. */
.guvenli-alan {
  padding-left:   max(16px, env(safe-area-inset-left,  0px));
  padding-right:  max(16px, env(safe-area-inset-right, 0px));
}
.guvenli-alt { padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
.guvenli-ust { padding-top:    env(safe-area-inset-top, 0px); }

/* Buzlu cam. -webkit- öneki ÖNCE gelmeli: Safari 18'e kadar öneksiz sürüm
   hiç render edilmiyordu ve iOS 16/17'de kalmış cihazlar hâlâ dolaşımda.
   @supports ile opak yedek şart — bulanıklık olmadan yarı saydam bir menü
   okunmaz hale gelir. */
/* CAM KALDIRILDI — Tur 34, kullanıcı kararı, ölçümle. Kaydırırken her
     karede arkasındaki yüzeyi yeniden bulanıklaştırmak, aurora katmanıyla
     birlikte kare hızını 19.5 FPS'e düşürüyordu. Opak zemin ZATEN yazılıydı
     (`@supports not` yedeği) — yani tasarımda karşılığı düşünülmüştü; o
     değer buraya taşındı ve ölü kalan `@supports` bloğu silindi.
     Cam yalnız üst menüde (`.ust`) kaldı. */
.cam {
  background-color: var(--cam-yedek, rgb(255 255 255 / 0.94));
}

/* Üst menüdeki bağlantı ve butonlar satır ortasından bölünmez.
   "Giriş Yap" iki satıra düştüğünde menü yüksekliği artıyor ve menü öğeleri
   butonların altında kalıyordu. Menü etiketleri zaten kısa; sarmalamaya
   ihtiyaçları yok. */
header a, header button { white-space: nowrap; }

/* Masaüstü menüsü SIKIŞTIRILAMAZ.
   Flex, yer daraldığında .menu kutusunu küçültüyor ama içindeki bağlantılar
   küçülmediği için içerik kutudan taşıp sağdaki "Giriş Yap / Üye Ol"
   butonlarının ALTINA giriyordu — son menü öğesi ("İletişim") gözden
   kayboluyordu. flex-shrink:0 ile menü daima kendi genişliğini korur;
   yer yoksa hamburger menü devreye girer (bkz. 72rem eşiği). */
header nav.menu, header .menu { flex-shrink: 0; }

/* Geri sayım rakamları (render.js bu sınıfları basar).
   nowrap şart: gün sayısı üç haneye çıktığında ("129") dar bir kutuda
   "12 / 9" diye ikiye bölünüyor. tabular-nums ise rakam değişirken
   kutunun genişliğinin oynamasını engeller. */
.gs-sayi { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Kart görselleri: sabit oran + kırpma, karışık boyutlu mockup görselleri
   düzeni zıplatmasın diye. */
.oran-16-9 { aspect-ratio: 16 / 9; object-fit: cover; }
.oran-4-3  { aspect-ratio: 4 / 3;  object-fit: cover; }
.oran-1-1  { aspect-ratio: 1 / 1;  object-fit: cover; }

/* Medya sorgusuz duyarlı ızgara. İçteki min(100%, …) 320px'lik telefonda
   yatay taşmayı önleyen kısımdır; çıplak minmax(280px, 1fr) taşar.

   ⛔ `auto-fill`, `auto-fit` DEĞİL · Tur 66 · ÖLÇÜLDÜ. `auto-fit` boş
   izleri 0px'e çökertip kalan alanı tek dolu kartın üstüne yığıyor;
   canlıda tek kayıtla `1140px 0px 0px …` ölçüldü ve kart 1140×1192 oldu.
   Topluluk yeni olduğu sürece listelerin çoğu 1–2 kayıt taşıyor, yani o
   hâl istisna değil VARSAYILAN. Ayrıntı `bilesenler.css` → `.kadro`. */
.izgara-oto {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: var(--bosluk, 20px);
}

/* Yatay kart rayı. mandatory yerine proximity: iOS'un atalet fiziğiyle
   mandatory birleşince hızlı kaydırma birkaç kartı birden atlar. */
.ray {
  display: flex;
  gap: var(--bosluk, 20px);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-padding-inline: 16px;
  padding-bottom: 4px;
}
.ray > * { scroll-snap-align: start; flex: 0 0 auto; }

/* Geniş tablo sarmalayıcı. tabindex="0" + role="region" + erişilebilir ad
   ZORUNLU — bunlar olmadan klavye kullanıcısı bölgeyi kaydıramaz (WCAG 2.1.1
   ihlali). */
.tablo-sarmal { overflow-x: auto; }

/* --- Yazdırma ------------------------------------------------------------- */
@media print {
  .yazdirma-gizle { display: none !important; }
  body { background: #fff; color: #000; }
}
