/* =====================================================================
   TURKODRA — Kurumsal site  ·  site.css
   Layout + bileşenler. Tüm değerler tokens.css değişkenlerinden gelir.
   Motion: Emil Kowalski prensipleri — yalnız transform+opacity,
   150–250ms, ease-out giriş, prefers-reduced-motion saygısı.
   ===================================================================== */

/* ---- Layout primitives ------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--sp-6);
}
.section { padding-block: var(--sp-24); }   /* offset artık html'de scroll-padding-top */
.section--tight { padding-block: var(--sp-16); }
.section-head { max-width: 62ch; margin-bottom: var(--sp-12); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-eyebrow { margin-bottom: var(--sp-3); display: inline-flex; align-items: center; gap: var(--sp-2); }
.section-title { font-size: var(--fs-h1); margin-bottom: var(--sp-4); }
.section-lead { font-size: var(--fs-h4); color: var(--text-2); line-height: var(--lh-snug); font-weight: 400; }
.section--alt { background: var(--surface-2); }

/* ---- Buttons ----------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  font-family: var(--font-sans); font-weight: 600; font-size: var(--fs-sm);
  padding: 12px 22px; border-radius: var(--r-pill); border: 1px solid transparent;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  /* Basış geri bildirimi SNAP etmeli: --ease (cubic-bezier(.4,0,.2,1)) yavaş
     başlıyor ve kullanıcının tam baktığı anı geciktiriyordu. 160ms ease-out. */
  transition: transform 160ms var(--ease-out), background var(--dur) var(--ease),
              border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn:active { transform: scale(0.97); }
.btn--primary { background: var(--primary); color: var(--text-on-accent); box-shadow: var(--sh-sm); }
.btn--primary:hover { background: var(--primary-hover); box-shadow: var(--sh-md); }
.btn--ghost { background: transparent; color: var(--text); border-color: var(--border-strong); }
.btn--ghost:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
.btn--brand { background: var(--brand); color: var(--text-on-brand); }
.btn--brand:hover { background: var(--brand-hover); }
.btn--lg { padding: 15px 30px; font-size: var(--fs-body); }
.btn__icon { width: 18px; height: 18px; }

/* ---- Header ------------------------------------------------------ */
.site-header {
  /* `fixed`, `sticky` DEĞİL. Sayfa yakınlaştırması %100'den farklıyken
     (pinch/cihaz zoom'u) sticky başlık her kaydırma karesinde 1px oynuyor —
     gözde titreme olarak görünen şey bu. Ölçüm (screencast karelerinde barın
     kenarı, ölçek 1.02):
       sticky → y=11 (17 kare) ↔ y=12 (103 kare)   oynuyor
       fixed  → y=12 (112/112 kare)                sabit
     Ölçek 1.05'te de fixed 113/113 karede sabit. Akıştan çıktığı için
     yerini body'nin padding-top'u dolduruyor (aşağıda) — yerleşim
     sticky hâliyle birebir aynı kalır. */
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-header);
  min-height: var(--header-h);   /* height DEĞİL — bkz. tokens.css --header-h notu */
  /* NOT: burada bir ara `will-change: transform` (katman terfisi) denendi ve
     GERİ ALINDI. Ölçüm faydasını göstermedi — screencast karelerinde barın
     kenarı terfi varken de yokken de 101/101 karede aynı pikseldeydi — kare
     istatistiğini ise kötüleştirdi (>33ms kare: terfisiz 0, terfili 5).
     Ayrıca terfi, başlığı sabit konumlu torunlar için kapsayıcı bloğa
     çevirdiğinden .mobile-nav'ın anlamını sessizce değiştiriyordu; o kural
     yine de netleştirilmiş hâlde bırakıldı (absolute; top:100%). */
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  /* Geçiş TABAN kuralda: daha önce yalnız `body.has-wave-field .site-header`
     üzerindeydi, dolayısıyla WebGL düştüğünde (zayıf cihaz / forced-colors /
     reduced-motion) `is-scrolled` opaklaşması ve blur'un kaybolması 0ms'de
     zıplıyordu. Yan fayda: aşağıdaki reduced-motion kuralı (`transition: none`)
     bugüne kadar ÖLÜYDÜ — özgüllüğü alan yolundaki kuralın altında kalıyordu;
     artık gerçekten bir şeyi eziyor. */
  transition: background var(--dur) var(--ease-out),
              backdrop-filter var(--dur) var(--ease-out),
              -webkit-backdrop-filter var(--dur) var(--ease-out);
}
/* Başlık `fixed` olduğu için akıştan çıktı; yerini bu pay dolduruyor.
   Böylece içerik tam da sticky hâlindeki y'de başlar — yerleşim değişmez. */
body { padding-top: var(--header-h); }

.site-header__inner {
  /* -1px: .site-header'ın border-bottom'ı bu kutunun DIŞINDA; çıkarmazsak
     başlığın toplam yüksekliği --header-h + 1 olur ve --header-h'ye dayanan
     .mobile-nav inset'i ile scroll-padding-top 1px kayar. */
  min-height: calc(var(--header-h) - 1px);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6);
}
.brand { display: inline-flex; align-items: center; gap: var(--sp-3); text-decoration: none; }
/* .icon-btn'in yüksekliğiyle BİREBİR aynı → marka, aksiyon düğmeleriyle aynı
   optik satırda oturuyor; ölçü sistemden geliyor, göz kararı değil. Barda
   üstte ve altta kalan hava da aynı oranda büyür (tabanda 15'er px).
   Sabit 38px yerine --header-ctl: iki taraf da --header-scale'den türediği
   için ölçek değişince hiza KENDİLİĞİNDEN korunuyor. */
.brand__logo { height: var(--header-ctl); width: auto; display: block; }
.brand__logo--dark { display: none; }
[data-theme="dark"] .brand__logo--light { display: none; }
[data-theme="dark"] .brand__logo--dark  { display: block; }

.nav { display: flex; align-items: center; gap: var(--sp-2); }
.nav__link {
  /* Yazı ve dolgu BİRLİKTE ölçekleniyor: yalnız yazı büyüseydi hover hapı
     metne yapışırdı (dolgu oransal olarak küçülür). Taban 14px / 8-12px. */
  font-size: calc(var(--fs-sm) * var(--header-scale)); font-weight: 500; color: var(--text-2);
  padding: calc(8px * var(--header-scale)) calc(12px * var(--header-scale));
  border-radius: var(--r-sm); text-decoration: none;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.nav__link:hover { color: var(--text); background: var(--surface-2); }
.nav__link.is-active { color: var(--primary); }

.header-actions { display: flex; align-items: center; gap: var(--sp-3); }
/* Başlık kontrolleri TEK yükseklikte: ölçüldü, üç farklı yükseklik vardı —
   dil hapı 31, ikon düğmeleri 38, CTA 48,4px. 38px logo ve ikon düğmesiyle
   aynı; sayfanın geri kalanındaki .btn dolgusu etkilenmesin diye kural
   .header-actions'a kapsanmış. */
.header-actions .btn {
  padding-block: 0; min-height: var(--header-ctl);
  /* Yazı ve yatay dolgu da ölçekte: 38 -> 53px'lik bir hapın içinde 14px yazı
     ve 22px yan dolgu kalsaydı düğme boşalır, "şişmiş" görünürdü.
     Taban: --fs-sm (14px) / 22px — .btn'in kendi değerleri. */
  font-size: calc(var(--fs-sm) * var(--header-scale));
  padding-inline: calc(22px * var(--header-scale));
}

/* Lang toggle (segmented) */
.lang-toggle {
  /* min-height 38px = ikon düğmeleriyle aynı. align-items VERİLMEZ: flex'in
     varsayılan stretch'i .lang-btn'i 23 → 30px'e uzatır, yani hem hap 38px'e
     oturur hem dokunma hedefi büyür. `center` verilseydi düğme 23px'te kalırdı. */
  display: inline-flex; padding: calc(3px * var(--header-scale)); gap: 2px;
  min-height: var(--header-ctl);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-pill);
}
.lang-btn {
  font-family: var(--font-mono); font-size: calc(var(--fs-xs) * var(--header-scale));
  font-weight: 500; letter-spacing: .04em;
  display: inline-grid; place-items: center;
  min-height: calc(30px * var(--header-scale)); padding: 0 calc(12px * var(--header-scale));
  border: 0; background: transparent; color: var(--text-3);
  border-radius: var(--r-pill); cursor: pointer; position: relative;
  /* transform LİSTEYE EKLENDİ, liste EZİLMEDİ: color/background 200ms var(--ease)
     ile kalıyor (DURUM değişimi — hangi dil seçili), basış ayrı bir kanaldan
     160ms var(--ease-out) ile geliyor. Sıra .icon-btn'inkiyle aynı: transform sonda. */
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform 160ms var(--ease-out);
}
/* Görünür hapı büyütmeden dokunma alanını 44px'e çıkarır (ölçülen 35×23 →
   39×44). Yalnız DİKEY büyütür; TR ile EN arasındaki 2px'lik boşluk sürüyor. */
.lang-btn::after { content: ""; position: absolute; left: 0; right: 0; top: -7px; bottom: -7px; }
.lang-btn.is-active { background: var(--surface); color: var(--text); box-shadow: var(--sh-xs); }
/* Basış geri bildirimi — .icon-btn ile BİREBİR aynı reçete (yukarıdaki transition
   satırı + buradaki scale). Değer sistemden geliyor, yeni sayı YOK: 160ms bu deponun
   basış sabiti (gerekçesi .btn'in transition yorumunda: --ease yavaş başlıyor ve
   basışın tam bakıldığı anı geciktiriyordu), 0.94 ise BU BOYUTTAKİ denetimin cevabı
   (.icon-btn 38x38 -> 0.94; daha geniş .btn -> 0.97). .lang-btn ölçüldü: 39,38x30 —
   boyut olarak .icon-btn'in komşusu, .btn'in değil. Yani 0.94 seçim değil, okuma.

   ALGILANABİLİRLİK, DÜRÜST HÂLİYLE — bu satırın kaldıracı DÜŞÜK.
   Basılan düğme genelde PASİF olandır (TR'deyken EN'e basılır) ve pasif .lang-btn'in
   ne zemini ne kenarlığı var (background: transparent, border: 0). Ekranda büzülen bir
   kontur yok; büzülen tek şey iki harf. Ölçüldü: metin akışı 15,38x15 px, scale(0.94)
   altında dış kenarı 0,46 px yatay / 0,45 px dikey oynuyor — bir CSS pikselinin ALTINDA.
   Görünür düğme kutusunun kenarı 1,18 px oynuyor ama o kenar pasif düğmede boyanmıyor.
   Karşılaştırma (aynı ölçek, ölçülen kutular): .icon-btn'in 18x18 ikonu 0,54 px oynuyor,
   yani MÜREKKEP hareketi neredeyse aynı; .icon-btn'i okunur yapan şey 38x38'lik KAPALI
   konturunun (çevresi ~119 px) 1,14 px büzülmesi. Aktif .lang-btn'de kontur var ama
   kontrastı düşük: --surface dolgusu --surface-2 rayında açık temada 1,13:1, koyuda 1,15:1.
   Yani bu kural DELIGHT için değil BÜTÜNLÜK için: başlıktaki dört basılabilir denetimden
   üçü (.btn, tema .icon-btn, menü .icon-btn) basışa cevap veriyordu, biri vermiyordu.

   DOKUNMA HEDEFİ: yukarıdaki ::after hedefi 44 px'e çıkarıyor ve scale onu da ölçekliyor
   (39,38x44 -> 37,02x41,36). Ölçüldü: basış sırasında hedefin dış ~1,2-1,3 px'lik bandı
   gerçekten parmağın altından çekiliyor (elementFromPoint üstte header__inner, sağda
   .lang-toggle döndürüyor) ve dinleyici click üzerinde olduğu için o bantta bırakılan
   basış YUTULUR. Kabul edildi: .icon-btn (1,14 px) ve .btn aynı riski bugün zaten
   taşıyor, ata elemanlarda hiç tıklama dinleyicisi yok (yanlış eylem imkânsız, tıklama
   sessizce düşer) ve kullanıcının NİŞAN ALDIĞI dinlenme kutusu 39,38x44 olarak duruyor.
   ::after'ı karşı-ölçekleme DENENMEDİ ve önerilmiyor: yeni sayı + ikinci animasyonlu kutu. */
.lang-btn:active { transform: scale(0.94); }

/* Theme + nav toggle icon buttons */
.icon-btn {
  display: inline-grid; place-items: center;
  width: var(--header-ctl); height: var(--header-ctl);
  border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface); color: var(--text-2); cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), transform 160ms var(--ease-out);
}
.icon-btn:hover { color: var(--primary); border-color: var(--primary); }
.icon-btn:active { transform: scale(0.94); }
/* İkonun kutuya oranı sabit kalsın diye o da ölçekte (taban 18px, 38px'lik
   kutuda 10+10px hava). Hamburger -> X dönüşümündeki translateY(6px) SVG
   kullanıcı biriminde (viewBox 24) olduğu için bu satırdan ETKİLENMEZ. */
.icon-btn svg { width: calc(18px * var(--header-scale)); height: calc(18px * var(--header-scale)); }
.theme-toggle .icon-moon { display: none; }
[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
[data-theme="dark"] .theme-toggle .icon-moon { display: block; }

.nav-toggle { display: none; }

/* ---- Hamburger → X: düğme AÇIKKEN kendi durumunu söylesin --------- */
/* Panel açıkken de ikon üç çizgi olarak duruyordu; düğme "aynı düğme
   kapatır mı?" sorusunu cevapsız bırakıyordu. Durum ZATEN DOM'da yazılı —
   main.js her tıklamada aria-expanded'ı "true"/"false" yapıyor — burada
   yalnız o durumun görsel karşılığı veriliyor. MARKUP VE JS DEĞİŞMİYOR.

   PATH SIRASI SEZGİSEL DEĞİL. index.html'deki sıra: birinci path
   d="M4 12h16" (ORTA çizgi), ikinci d="M4 6h16" (ÜST), üçüncü
   d="M4 18h16" (ALT). Yani nth-child(1)=ORTA, (2)=ÜST, (3)=ALT.
   "Üstten alta" varsayan bir eşleştirme sessizce çarpık bir X üretir.

   transform-box: view-box ŞART — fill-box DEĞİL. Yatay bir çizginin
   sınırlayıcı kutusu SIFIR YÜKSEKLİKTE (ölçüldü: getBBox height=0), yani
   fill-box'ta yüzdeli her y değeri 0'a çöküyor: `transform-origin:50% 50%`
   hesaplanan değerde "8px 0px" oluyor ve başlangıç noktası çizginin ÜSTÜNE
   düşüyor — X, düğme merkezinin 1,86px soluna kayıyor. fill-box + 12px 12px
   daha da kötü: alt kol x=342,09'a savrulup svg kutusunun (sol kenar 346)
   dışında kalıyor ve overflow:hidden ile KIRPILIYOR. view-box referans
   kutusu olarak viewBox'ı (0 0 24 24) alıyor, path'in dejenere kutusunu
   değil. Bugünkü Edge'de varsayılan zaten view-box (ölçüldü); bildirim
   ESKİ MOTORLAR için sigorta — orada varsayılan border-box ve SVG'de
   fill-box'a düşüyor. SİLME.

   transform-origin AÇIKÇA YAZILMALI. SVG elemanlarında varsayılanı
   50% 50% DEĞİL, `0px 0px` — yani viewBox'ın SOL ÜST KÖŞESİ (ölçüldü).
   Yazılmazsa kollar (341,757 / 32,985) ve (354,485 / 20,257)'ye savrulur,
   ikisi de svg kutusunun dışına taşıp kırpılır: ekranda ikon kaybolur.

   FONKSİYON SIRASI KRİTİK: transform listesinde EN SAĞDAKİ fonksiyon
   elemana ÖNCE uygulanır. İstenen "önce merkeze ötele, sonra merkez
   etrafında döndür" olduğu için translate SAĞDA, rotate SOLDA. Ters yazım
   (translateY(6px) rotate(45deg)) da geçerli CSS'tir ve X'e BENZER ama
   simetrik değildir: ölçüldü, iki kolun kutuları farklı yerde başlıyor
   (üst 30,575 · alt 27,939) ve kesişim düğme merkezinin 1,86px sağına
   kayıyor. Doğru yazımda iki kolun kutusu BİREBİR AYNI: 8,485x8,485,
   sol üst (350,757 / 29,257), kesişim (355 / 33,5) = düğmenin merkezi.

   SÜRELER ve EĞRİ. Yer değiştirme --dur (200ms) + --ease-out: bu, aşağıdaki
   .mobile-nav kuralının süresi ve eğrisiyle BİREBİR aynı — düğme ile
   açtığı panel TEK JEST okunmalı. Opaklık AYNI eğriyi alıyor: bu dosyada
   sayıldı, var(--ease) yalnız 5 satırda geçiyor ve beşinde de renk/kenarlık/
   gölge sürüyor; transform ve opacity'nin İSTİSNASIZ hepsi --ease-out
   (opacity için 6/6). Ayrışma eğride değil SÜREDE: orta çizgi 120ms'de
   (--dur-fast) çekilmeli, çünkü kollar tam onun üstünden geçerek kesişiyor
   ve 200ms'de dursaydı jestin ortasında üç çizgi üst üste binerdi. Tek
   listede özellik başına farklı süre bu dosyanın mevcut kalıbı (.btn:
   transform 160ms, gerisi --dur). --dur-fast'in bu depodaki İLK kullanımı;
   yeni sayı üretilmedi, var olan token'a iş verildi.

   keyframes DEĞİL transition: ard arda dokunuşta animation baştan
   başlardı, transition bulunduğu değerden yeniden hedefliyor (ölçüldü:
   kapanışın ortasında yeniden basınca üst kolun sağ ucu y=33,338'de, yani
   düz konum 29 ile X kolu 37,743 ARASINDA — başa dönmemiş).

   REDUCED-MOTION İÇİN EK KURAL YOK ve GEREKMİYOR: tokens.css'teki global
   `*` kuralı transition-duration'ı .001ms'ye çekiyor (ölçüldü: 1e-06s),
   yani tween düşüyor ama BİTİŞ DURUMU aynen oluşuyor — X yine görünüyor.
   Aşağıdaki "reduced-motion: BİLEŞEN hareketi de düşmeli" bloğuna bu
   path'ler için `transform: none` YAZMA — gerekçe kaskad DEĞİL, niyet:
   oradaki "yer değiştirme gider" kuralı DEKORATİF yer değiştirme içindir,
   burada yer değiştirmenin kendisi DURUM BİLGİSİDİR. Kaskad notu, yanlış
   hatırlanmasın diye ölçüldü: o satır aynen yazılırsa ETKİSİZDİR —
   `.nav-toggle[aria-expanded="true"] svg path` özgüllüğü (0,2,2),
   aşağıdaki :nth-child kurallarının (0,3,2) ALTINDA kalır ve medya
   sorgusu özgüllük eklemez; ölçüldü, X aynen oluşuyor. X'i ancak
   `!important` ya da :nth-child'a EŞLENMİŞ bir seçici öldürür — ölçüldü,
   o zaman kollar düz kalıyor ((349,29)-(361,29) ve (349,38)-(361,38)),
   orta çizgi de opacity:0 → ekranda X değil İKİ YATAY ÇİZGİ. Yazılmaması
   gereken tam olarak budur.

   @media (hover:hover) KAPISI YOK — bilinçli. Bu bir hover süsü değil,
   dokunmatikte de görünmesi gereken bir durum göstergesi. Kural masaüstünde
   de duruyor ama orada .nav-toggle display:none olduğu için etkisiz. */
.nav-toggle svg path {
  transform-box: view-box;
  transform-origin: 12px 12px;   /* viewBox'ın (0 0 24 24) merkezi */
  transition: transform var(--dur) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}
/* (1) ORTA çizgi — kesişme noktasında zaten iki kol var, çekilsin.
   scaleX(0) ile büzmek DENENMEDİ ve İSTENMİYOR: tam kolların kesiştiği
   noktada üçüncü bir hareket, bilgi katmadan gürültü ekler. */
.nav-toggle[aria-expanded="true"] svg path:nth-child(1) { opacity: 0; }
/* (2) ÜST çizgi: 6 birim aşağı (y 6 → 12 = merkez), sonra +45° */
.nav-toggle[aria-expanded="true"] svg path:nth-child(2) { transform: rotate(45deg) translateY(6px); }
/* (3) ALT çizgi: 6 birim yukarı (y 18 → 12 = merkez), sonra −45° */
.nav-toggle[aria-expanded="true"] svg path:nth-child(3) { transform: rotate(-45deg) translateY(-6px); }

/* Mobile nav sheet.
   `fixed` + `inset: var(--header-h) …` DEĞİL: başlığa katman terfisi verince
   (aşağıdaki will-change) başlık, sabit konumlu torunlar için kapsayıcı blok
   oluyor ve o kural sessizce anlam değiştiriyor. `absolute; top:100%` niyeti
   doğrudan yazıyor — "başlığın hemen altı" — ve başlığın yüksekliği değişse
   (bkz. --header-h max() notu) kendiliğinden takip ediyor. */
.mobile-nav {
  position: absolute; top: 100%; left: 0; right: 0; z-index: calc(var(--z-header) - 1);
  background: var(--surface); border-bottom: 1px solid var(--border);
  /* Bağlantının kendi 8px iç boşluğu buradan DÜŞÜLÜYOR: metin markayla aynı
     dikey çizgiye otursun. Kapsayıcı kenar payı kırılma noktalarında değiştiği
     için (24 / 16 / 12) bu değer de üç yerde takip ediyor. */
  padding: var(--sp-4) var(--sp-4) var(--sp-6);
  display: grid; gap: var(--sp-1);
  transform: translateY(-8px); opacity: 0; visibility: hidden;
  /* Giriş TEK JEST: kayma ve sönüm aynı eğride ilerlemeli. İki ayrı eğriyle
     ölçüldü — t=40ms'de kayma %75 bitmişken opaklık yalnız %13, yani 8px'lik
     jestin tamamı panel görünmezken tamamlanıyor ve hareket düz bir fade
     olarak okunuyordu. Dosya başlığının kendi kuralı da bu: "ease-out giriş". */
  transition: transform var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out), visibility var(--dur);
}
.mobile-nav.is-open { transform: translateY(0); opacity: 1; visibility: visible; }
/* Bağlantı kutusu ÖLÇÜLDÜ (Edge, 390×844, panel açık): 374 × 49,59px — 12+12px
   dolgu + 25,59px satır kutusu. Dokunma hedefi 44px'in zaten üstünde; bu kural
   GEOMETRİYE DOKUNMUYOR, yalnız basış geri bildirimi ekliyor. */
.mobile-nav a {
  padding: 12px 8px; border-radius: var(--r-sm); color: var(--text); font-weight: 500; text-decoration: none;
  /* Geçiş TABAN kuralda duruyor ki YALNIZ BIRAKIŞ sönümlensin, giriş tek kare
     kalsın. Mekanizma: bir geçişin süre/eğrisi "after-change style"den okunur —
     basışta o stil aşağıdaki :active kuralıdır ve `transition: none` taşır
     (geçiş hiç başlamaz, tek kare); bırakışta :active artık eşleşmediği için
     after-change stil BU kuraldır ve 200ms'lik sönüm oradan gelir.
     Ölçüldü (Edge; İKİ YOL AYRI ölçüldü, :active geçici olarak kırmızıyken):
       işaretçi yolu (fare, ≤720px — hover kuralı eşleşiyor): basış ilk
         örneklenen karede (14ms) tam değerinde; bırakışta renk saydama DEĞİL,
         --surface-2'ye çözülüyor — 48ms rgb(253,20,21) · 82ms rgb(247,110,113)
         · 148ms rgb(238,222,227) · 215ms rgb(237,241,247). Opak karışım.
       hover eşleşmeyen yol (dokunmatik emülasyonu): bırakışta yalnız ALFA
         düşüyor — +33ms %91 · +67ms %54 · +134ms %8 · +200ms bitmiş. Kanallar
         sabit: interpolasyon premultiplied, saydama giderken siyaha uğramıyor.
     Sönüm sürerken YENİDEN basılırsa çalışan geçiş iptal oluyor ve zemin tek
     karede tam değerine dönüyor (ölçüldü, işaretçi yolu) — hızlı art arda
     basışta yarım kalmış bir renk takılıp kalmıyor.
     200ms/--ease UYDURULMADI: .nav__link (yukarıda) zemini zaten
     `background var(--dur) var(--ease)` ile değiştiriyor. Bu satır mobil paneli
     başlığın geri kalanıyla aynı ritme sokuyor; bugün panelin hover'ı başlıktaki
     TEK anlık zemin değişimiydi. */
  transition: background var(--dur) var(--ease);
}
/* Hover KAPILANDI — bu bir DÜZELTME, süsleme değil. Panel yalnız nav-toggle ile
   açılıyor, o da ≤720px'te görünüyor (ölçüldü: 720px→grid, 721px→none), yani
   kural dokunmatik genişlikte yaşıyor ama tek geri bildirimi bir İŞARETÇİ
   durumuydu. Ölçüldü (dokunmatik emülasyonu, kapısız hâl): basılı tutulan
   dokunuşta zemin HİÇ gelmiyor (30/120/300/600ms), bırakıştan ~40ms sonra
   geliyor; panel kapanmazsa da GİTMİYOR — 917ms'de hâlâ orada, :hover hâlâ
   true. Yani parmak basılıyken değil, karar verildikten sonra ve yapışarak.
   Kapı deponun kendi kalıbı: .card:hover ve .product-card__link:hover ile
   birebir aynı medya sorgusu. */
@media (hover: hover) and (pointer: fine) {
  .mobile-nav a:hover { background: var(--surface-2); }
}
/* BASIŞ — kaynak durum :active, yani basışın kendisi; geliş ANINDA (tek kare).
   `transition: none` bir hız değil bir YÖN kararı: giriş ani, çıkış sönümlü.
   .btn'in "basış SNAP etmeli" notuyla aynı fikir; orada yol alan şey transform
   olduğu için 160ms'lik bir eğri gerekiyor, burada yol alan bir şey yok (renk),
   o yüzden eğri değil sıfır.
   DÜRÜST SINIR: :active'in DOKUNMATİKTE parmak basılıyken mi geldiği bu makinede
   doğrulanamadı — emülasyonda yalnız TAMAMLANMIŞ dokunuşta geliyor (ölçüldü:
   touchstart'tan ~16ms sonra uygulanıyor, ~150ms tutuluyor), basılı tutulan
   dokunuşta hiç gelmiyor. Gerçek cihaz doğrulaması açık kalıyor.
   RENK var(--surface-2), YENİ BİR KADEME DEĞİL: .nav__link:hover ile aynı token,
   "bu nav öğesi tutuluyor" bu sitede zaten bu renk. Ölçülen basamak (panel
   zemini --surface'e karşı): açık 1,134:1 · koyu 1,153:1 — iki temada neredeyse
   aynı. --surface-3 denendi ve BIRAKILDI: basamağı büyütüyor ama temaya göre
   1,223 ↔ 1,357 salınıyor, dosyada başka hiç kullanılmıyor ve işaretçili cihazda
   hover'dan ayrı bir ÜÇÜNCÜ kademe açıyordu — hover'ı hiç görmeyen dokunmatik
   kullanıcıya bir şey anlatmayan bir ayrım.
   OKUNURLUK ölçüldü: --text bu zeminde açık 15,2:1 · koyu 13,0:1 (düz panel
   zemininde 17,23 ve 14,98'di). Basış kontrastı düşürüyor ama AA eşiğinin
   (4,5:1) üç katı üstünde kalıyor.
   -webkit-tap-highlight-color'a DOKUNULMUYOR: UA vurgusu rgba(51,181,229,.4),
   yani tasarım sisteminin dışında bir mavi — ama kaldırmak dokunmatikte tek
   anlık cevabı da alırdı. Bu kural onun ÜSTÜNE geliyor, yerine değil. */
.mobile-nav a:active { background: var(--surface-2); transition: none; }

/* ---- Hero -------------------------------------------------------- */
.hero { position: relative; overflow: hidden; padding-block: var(--sp-32) var(--sp-24); }
.hero__bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: var(--grad-mesh); opacity: .10;
}
[data-theme="dark"] .hero__bg { opacity: .5; }
.hero__grid {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(color-mix(in srgb, var(--border) 60%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--border) 60%, transparent) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(circle at 70% 30%, #000 0%, transparent 62%);
  -webkit-mask-image: radial-gradient(circle at 70% 30%, #000 0%, transparent 62%);
}
/* =====================================================================
   SAYFA-BOYU DALGA ALANI — scripts/hero-waves.js (WebGL, dekoratif, aria-hidden)
   FAZ 2: alan artık hero'nun içinde değil, <body>'nin ilk çocuğu ve SABİT.
   Sayfa kayarken alan yerinde durur, bölümler onun üzerinden geçer.
   Modül yoksa/çalışmazsa `has-wave-field` hiç eklenmez → sayfa bugünkü statik
   görünümünde kalır (.hero__bg + .hero__grid yerinde): sıfır regresyon.
   ===================================================================== */
.bg-field {
  position: fixed; inset: 0; z-index: 0;
  width: 100%;
  /* lvh — dvh DEĞİL: dvh, mobilde adres çubuğu her açılıp kapandığında yüksekliği
     değiştirir; canvas o an drawing buffer'ını yeniden ayırır — kaydırma sırasındaki
     asıl kasma kaynağı budur. lvh sabittir: alan bir kez ölçülür, kaydırmada oynamaz. */
  height: 100vh; height: 100lvh;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.bg-field.is-live { opacity: 1; }

/* İçerik alanın ÜSTÜNDE kalmalı: body'nin arka planı canvas'ın altında boyanır,
   pozisyonlanmış içerik ise üstünde. Alan yokken de zararsız. */
main, .site-footer { position: relative; z-index: 1; }

/* Alan canlıyken hero'nun statik dokuları devri teslim eder. .hero__bg de sönmeli:
   grad-mesh'in tabanı opak navy (koyu temada %50) ve canvas'ın ÜSTÜNE biner —
   kalırsa hero, sayfanın geri kalanından koyu görünür.
   `.hero >` KAPSAMI ŞART: .hero__grid sınıfı Vizyon panelinde de kullanılıyor
   (index.html, .vision__panel içinde). Kapsamsız seçici oranın dekoratif
   ızgarasını da siliyordu — panel düz bir gradyana dönüyordu. */
body.has-wave-field .hero > .hero__bg,
body.has-wave-field .hero > .hero__grid {
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}

/* OKUNABİLİRLİK PEÇESİ. Bölümler alanın üstünden yarı saydam geçer; alan doku
   olarak görünür ama metnin kontrast tabanı ölçülebilir kalır. Hero'da peçe YOK —
   alan orada tam gücünde (shader zaten hero dışında kendini kısıyor).

   İKİ PEÇENİN SAYDAMLIĞI AYNI OLMALI (%58). Farklı olursa alan iki bölümde farklı
   oranda geçer ve bölüm sınırında akan görüntüyü kesen sert bir yatay DİKİŞ oluşur;
   eşitken sınırda yalnız zeminin kendi ton farkı kalır — yani eskisiyle aynı ritim. */
body.has-wave-field main > .section      { background: color-mix(in srgb, var(--bg) 48%, transparent); }
body.has-wave-field main > .section--alt { background: color-mix(in srgb, var(--surface-2) 48%, transparent); }

/* color-mix YOKSA peçe komple düşer ve metin doğrudan canlı shader'ın üstünde
   kalır — peçenin var olma sebebinin tam tersi. (.section'ın başka arka plan
   bildirimi yok.) Etkilenen: WebGL1'i olan ama color-mix'i olmayan tarayıcılar —
   Chrome/Edge ≤110, Firefox ≤112, Safari ≤16.1.
   @supports ile yazılıyor, öncül satırla DEĞİL: koyu tema farklı bir renk ister,
   o da [data-theme] seçicisi demek — özgüllüğü color-mix kuralından yüksek olur
   ve destekleyen tarayıcılarda onu ezerdi. Değerler token'ların karşılıkları. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  body.has-wave-field main > .section      { background: rgba(244, 247, 250, .48); }
  body.has-wave-field main > .section--alt { background: rgba(237, 241, 247, .48); }
  [data-theme="dark"] body.has-wave-field main > .section      { background: rgba(1, 10, 30, .48); }
  [data-theme="dark"] body.has-wave-field main > .section--alt { background: rgba(11, 37, 81, .48); }
}

/* EYEBROW'LAR ALANIN ÜSTÜNDE --text-2'ye çıkar. --text-3 düz zeminde bile
   3.91:1 idi (küçük metin için AA eşiği 4.5:1); alan güçlendirilince en kötü
   durum 2.53:1'e düşüyor. Peçeyi koyulaştırmak kaldıraç değil — ölçüldü, 0.58→0.64
   oranı yalnız 3.32→3.40 yapıyor. Yeni renk UYDURULMADI: mevcut --text-2 her iki
   temada da eşiği geçiyor (açık 4.96:1, koyu 5.67:1).
   :not(.vision__eyebrow) ŞART — vizyon paneli opak koyu bir yüzey, eyebrow'u
   oradaki teal-200 kalmalı; bu kuralın özgüllüğü onu ezerdi.

   GÜNCELLEME — --text-2 de YETMİYOR. Metni saydamlaştırıp gerçek zemini 7 ayrı
   anda ölçen yöntemle (raporlanan "4.96:1" tek karelik ve iyimserdi):
     masaüstü açık  4.17–5.32   ·  mobil açık  3.20–4.65   ·  koyu  4.59–5.85
   Alan tekrarsız olduğu için en kötü an tura göre değişiyor — yani --text-2 ile
   AA bir GARANTİ değil, bir şans. Scrim kutusunu büyütmek masaüstünü 4.51'e
   çıkardı ama mobili çıkarmadı; shader sönümünü artırmak ölçüm gürültüsünün
   içinde kaldı ve alanı bedavaya kısıyordu (geri alındı).
   --text alandan BAĞIMSIZ çözüm: ölçülen en kötü zeminde bile 7.6–9.6:1.
   Bedeli 12px'lik mono etiketin bir tık ağırlaşması — yalnız alan canlıyken. */
body.has-wave-field .eyebrow:not(.vision__eyebrow) { color: var(--text); }

/* BAŞLIK ALANIN ÜSTÜNDE DAHA SAYDAM. Varsayılan %82, alan yokken doğru değer —
   orada arkasından yalnız kayan içerik geçiyor ve okunaklılık için kapatıcı
   olmalı. Alan varken aynı değer animasyonu tamamen yutuyordu.
   %50 ölçümle seçildi: nav bağlantısı en kötü 5.38:1 (AA eşiği 4.5) — pay bol.

   BULANIKLIK KALDIRILDI, asıl sınırlayıcı oydu. Saydamlığı %82'den %50'ye
   indirmek tek başına yetmedi: ekranda ölçülen zemin yayılımı yalnız 4.6'ydı
   (başlığın hemen ALTINDA 37.9). Blur alanın yapısını ortalayıp siliyordu.
   blur 9 → 5 → 2 → 0 süpürüldü: yayılım 4.6 → 5.4 → 6.5 → 13.0; nav kontrastı
   ise 5.53 → 5.38'e inerek neredeyse hiç değişmedi. Yani bulanıklık kontrast
   için gerekli değildi, yalnız animasyonu gizliyordu.
   Yan fayda: backdrop-filter, arkasındaki alan her karede değiştiği için her
   karede yeniden hesaplanıyordu — tamamen kaldırılınca o maliyet de gitti.
   Alan YOKKEN varsayılan buzlu cam görünümü korunur (kural has-wave-field'a
   kapsanmış): orada arkadan yalnız kayan içerik geçiyor ve blur gerekli. */
body.has-wave-field .site-header {
  background: color-mix(in srgb, var(--bg) 50%, transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: background var(--dur) var(--ease-out);
}
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  body.has-wave-field .site-header { background: rgba(244, 247, 250, .5); }
  [data-theme="dark"] body.has-wave-field .site-header { background: rgba(1, 10, 30, .5); }
}
/* SAYFA KAYDIYSA OPAKLAŞ. %50 saydamlık yalnız en üstte doğru: orada başlığın
   arkasında sadece dalga alanı var, içerik yok — animasyon tam görünür.
   Bir piksel kaydırınca arkadan İÇERİK geçmeye başlıyor; hero başlığı TR/EN ve
   İletişim düğmelerinin içinden okunur hâlde akıyor, bar görünmez oluyor ve
   düğmeler boşlukta savrulmuş gibi duruyordu. Blur'a dönmüyoruz (ölçülmüş GPU
   maliyeti + alanın yapısını siliyordu); düz opak zemin bedava.

   KOŞULSUZ: has-wave-field'e bağlamak hataydı — WebGL kapalı/başarısızsa (ya da
   backdrop-filter GPU hızlandırma olmadan düşerse) kural hiç çalışmıyor ve
   varsayılan %82 saydam başlık aynı sızıntıyı veriyordu. Kaydırılmış bir başlık
   her kod yolunda opak olmalı. Opakken backdrop-filter'ın görsel etkisi de
   kalmıyor, kapatınca bedava GPU tasarrufu.

   ÖZGÜLLÜK TUZAĞI: yukarıdaki @supports yedeğinde
   `[data-theme="dark"] body.has-wave-field .site-header` (0,3,1) var; sade
   `body.is-scrolled .site-header` (0,2,1) ONU YENEMEZ. color-mix desteklemeyen
   tarayıcılarda (eski Android WebView, uygulama-içi tarayıcılar) koyu temada
   başlık kaydırılmış hâlde bile %50 saydam kalırdı. `[data-theme]` öneki
   özgüllüğü eşitliyor, kaynak sırası da bizden yana. */
[data-theme] body.is-scrolled .site-header,
body.is-scrolled .site-header {
  background: var(--bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
@media (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }
}

/* Hero scrim'i: metin bloğunun altında yumuşak bir --bg yıkaması. */
body.has-wave-field .hero__inner::before {
  content: ""; position: absolute; inset: -120px -48px -64px; z-index: -1;
  pointer-events: none;
  /* closest-side ŞART: yüzde yarıçaplı bir gradyan kutu kenarına ulaşmadan
     şeffaflaşmazsa scrim keskin kenarlı bir dikdörtgen olarak görünür. */
  /* Orta durak 34 → 46: kamera eğimi düzeltilince hero'nun üst yarısı da yüzeyle
     doldu ve alan zenginleşti; açık temada .hero__lead 4.42:1'e (eşik 4.5) düştü.
     En kötü pikseller merkezde değil KENARLARDA olduğu için merkez durağı değil
     orta durağı yükseltmek gerekiyordu. Ölçüldü, aşağıdaki değerlerle AA'ya döndü. */
  background: radial-gradient(closest-side at 50% 50%,
    color-mix(in srgb, var(--bg) 68%, transparent) 0%,
    color-mix(in srgb, var(--bg) 46%, transparent) 55%,
    transparent 100%);
}
/* Scrim de color-mix'e bağlı — desteklenmezse hero metni çıplak alanın üstünde
   kalır. Peçedekiyle aynı gerekçe, aynı çözüm. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  body.has-wave-field .hero__inner::before {
    background: radial-gradient(closest-side at 50% 50%,
      rgba(244, 247, 250, .68) 0%, rgba(244, 247, 250, .46) 55%, transparent 100%);
  }
  [data-theme="dark"] body.has-wave-field .hero__inner::before {
    background: radial-gradient(closest-side at 50% 50%,
      rgba(1, 10, 30, .68) 0%, rgba(1, 10, 30, .46) 55%, transparent 100%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .bg-field { opacity: 0 !important; transition: none !important; }
}
/* Yüksek kontrast modunda tarayıcı metni sistem renklerine zorlar ama canvas
   piksellerine dokunmaz → kontrast garantisi çöker. Alanı tamamen kaldır.
   (JS de aynı sorguyu kontrol ediyor ve hiç başlamıyor — yoksa görünmeyen bir
   kare sonsuza dek çizilir ve peçeler yine de devreye girerdi.) */
@media (forced-colors: active) { .bg-field { display: none; } }

/* YAZDIRMA: sabit canvas ve yarı saydam peçeler kâğıda basılmamalı. Alan zaten
   dekoratif; peçe ise kâğıtta gri bir zemin olarak çıkıp mürekkep yakar ve
   metnin kontrastını düşürür. */
@media print {
  .bg-field { display: none !important; }
  body.has-wave-field main > .section,
  body.has-wave-field main > .section--alt { background: none !important; }
  body.has-wave-field .hero > .hero__bg,
  body.has-wave-field .hero > .hero__grid { display: none !important; }
}

/* 62ch = 626px KENAR kutusu (bu blok aynı zamanda .container, yani 24px yatay
   dolgu taşıyor ve box-sizing:border-box). Metnin gerçek ölçüsü 578px'ti ve
   "Kendi"(187) + "teknolojimizi"(420) = 607px oraya sığmıyordu — H1 dört satıra
   kırılıp ilk satırda tek kelime bırakıyordu. 46rem → içerik 688px, üç satır.
   DİKKAT: bu genişlik bir SHADER GİRDİSİ — hero-waves.js'teki okunabilirlik
   elipsi kolon kenarına göre ayarlı; ikisi birlikte değişmeli. */
.hero__inner { position: relative; z-index: 1; max-width: 46rem; }
.hero__eyebrow { margin-bottom: var(--sp-5); }
.hero__title { font-size: var(--fs-display); margin-bottom: var(--sp-6); }
/* Dekoratif roller --accent kullanır (büyük metin/süs, eşik 3:1), mürekkep
   rolleri --primary (eşik 4,5:1). Bkz. tokens.css'teki ayrım notu. */
.hero__title .accent { color: var(--accent); }
.hero__lead { font-size: var(--fs-h4); color: var(--text-2); line-height: var(--lh-body); font-weight: 400; margin-bottom: var(--sp-8); max-width: 54ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-12); }
/* text-wrap:balance — TR tek satira sigiyor, EN sigmiyor ve son satirda
   iki kelime kaliyordu ("...the wrong / one is."). Balance iki satiri
   esitliyor. Ilerici gelistirme: desteklemeyen tarayicida eski davranis. */
.hero__quote {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  text-wrap: balance;
  padding: var(--sp-4) var(--sp-5); border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--primary-soft) 60%, transparent); border-radius: var(--r-sm);
  font-family: var(--font-display); font-weight: 500; font-size: var(--fs-h4); color: var(--text);
}

/* ---- Capability cards (Ne yapıyoruz) ----------------------------- */
.grid { display: grid; gap: var(--sp-6); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
/* Tek kart: 3 sütunun birinde yalnız kalmasın diye tek, sınırlı sütun. */
.grid--3.grid--single { grid-template-columns: minmax(0, 1fr); max-width: 40rem; }

.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: var(--sp-8); box-shadow: var(--sh-xs);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
/* Hover KAPILI: dokunmatikte :hover dokunuştan sonra yapışır ve kart havada
   asılı kalırdı. İşaretçisi olan cihazlarda aynı. */
@media (hover: hover) and (pointer: fine) {
  .card:hover { transform: translateY(-4px); box-shadow: var(--sh-lg); border-color: var(--border-strong); }
}

.cap-card__icon {
  display: inline-grid; place-items: center; width: 48px; height: 48px; margin-bottom: var(--sp-5);
  border-radius: var(--r-md); background: var(--primary-soft); color: var(--primary);
}
.cap-card__icon svg { width: 24px; height: 24px; }
/* Başlık 1 mi 2 satır mı DİLE göre değişiyor (TR "Yazılım" tek satır, EN
   "Communications technology" iki satır). align-items:center rozeti iki satırın
   ARASINA asıyordu; flex-start onu her zaman ilk satırın hizasına oturtur.
   min-height ise çok sütunlu düzende üç kartın paragrafını aynı y'de başlatır —
   tek sütuna düşen mobilde hizalanacak komşu olmadığı için uygulanmaz.
   px değil calc: bu dosyanın kendi --header-h dersi (px kutu + rem içerik
   kırılgan) burada da geçerli. */
.cap-card__head { display: flex; align-items: flex-start; gap: var(--sp-3); margin-bottom: var(--sp-3); }
@media (min-width: 721px) {
  .cap-card__head { min-height: calc(var(--fs-h3) * var(--lh-tight) * 2); }
}
.cap-card__title { font-size: var(--fs-h3); }
.cap-card__text { color: var(--text-2); font-size: var(--fs-sm); line-height: var(--lh-body); }

/* Durum rozetleri — dürüstlük yapısal: hangi işin kanıtlı, hangisinin niyet
   olduğu sayfadan okunsun. İki eksen var, renk hangisi olduğunu söyler:
     hedef (amber) → pilot (mavi) → canlı (yeşil)   KANITLANMIŞLIK ekseni
     sürekli (nötr gri)             → EKSEN DIŞI; alan değil çalışma biçimi
   Renk sırası kasıtlı: amber "niyet", mavi "ilk müşteride deneniyor", yeşil
   "sahada çalışıyor". ÜRÜN kartlarında bu eksende bir rozet HER ZAMAN olmalı —
   boş bırakmak "unutulmuş" gibi okunuyor (Navena'da yaşandı).
   "Ar-Ge ve üretim" üçüncü bir alan değil, diğer ikisinin üstünden geçen bir
   yöntem — bu yüzden ona canlı/hedef takmak kategori hatası olurdu (Ar-Ge
   zaten canlı, üretim değil: tek rozet hangisi olsa bir yarısı için yalan). */
.tag {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  padding: 3px 9px; border-radius: var(--r-pill); white-space: nowrap;
}
.tag--goal    { background: var(--warning-soft); color: var(--warning); }
.tag--pilot   { background: var(--pilot-soft);   color: var(--pilot); }
.tag--live    { background: var(--success-soft); color: var(--success); }
.tag--live::before { content: "●"; margin-right: 5px; font-size: 9px; vertical-align: 1px; }
.tag--ongoing { background: var(--surface-2); color: var(--text-2); box-shadow: inset 0 0 0 1px var(--border); }

/* ---- Product cards (Öne çıkan ürünler) --------------------------- */
.product-card { display: flex; flex-direction: column; gap: var(--sp-4); }
.product-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); }
.product-card__name { font-size: var(--fs-h3); font-family: var(--font-display); }
.product-card__sector { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-3); letter-spacing: .04em; }
.product-card__desc { color: var(--text-2); font-size: var(--fs-sm); line-height: var(--lh-body); flex: 1; }
.product-card__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-top: var(--sp-2); }
.product-card__link {
  display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: var(--fs-sm); color: var(--primary);
  /* Dokunma hedefi 22px'ten 44px'e: dolgu büyütür, negatif pay onu akıştan
     geri çeker — .product-card__foot satır yüksekliği ve görsel yerleşim
     birebir aynı kalır. */
  padding-block: 11px; margin-block: -11px;
}
/* Oku kaydıran şey ARTIK gap DEĞİL. gap bir yerleşim özelliği; her karede
   layout tetikliyordu. transform aynı görüntüyü compositor'da veriyor. */
.product-card__link svg { transition: transform var(--dur) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .product-card__link:hover svg { transform: translateX(4px); }
}
/* Uzun URL kırılabilmeli: alt alan adlı bir adres kırılamayan tek parça
   olduğu için kartın min-content'ini dayatıyor, 1fr sütun onun altına inemiyor
   ve dar ekranda SAYFAYA yatay kaydırma açılıyordu (280px'te +34.7px). */
.product-card__link { overflow-wrap: anywhere; }
.product-card__link svg { width: 16px; height: 16px; }

/* ---- Vizyon ------------------------------------------------------ */
.vision__panel {
  position: relative; overflow: hidden;
  background: var(--grad-brand); color: #fff; border-radius: var(--r-2xl);
  padding: var(--sp-20) var(--sp-16);
}
.vision__panel .hero__grid { opacity: .16; mask-image: radial-gradient(circle at 85% 20%, #000, transparent 60%); -webkit-mask-image: radial-gradient(circle at 85% 20%, #000, transparent 60%); }
.vision__inner { position: relative; z-index: 1; max-width: 60ch; }
.vision__eyebrow { color: var(--teal-200); margin-bottom: var(--sp-4); }
.vision__quote { font-family: var(--font-display); font-size: clamp(1.6rem, 3vw, 2.4rem); font-weight: 600; line-height: var(--lh-snug); letter-spacing: var(--ls-tight); margin-bottom: var(--sp-6); }
.vision__text { color: var(--navy-100); font-size: var(--fs-h4); font-weight: 400; line-height: var(--lh-body); }
.vision__text strong { color: #fff; font-weight: 600; }

/* ---- Kültür (Kur · Yenile · Güçlendir) --------------------------- */
.value-card__k { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-4); }
/* font-weight açıkça 600: bildirilmediğinde sayfadaki TEK 400 ağırlıklı
   Space Grotesk metni oluyordu (diğer tüm display metinleri 600). */
.value-card__tr { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 600; color: var(--text); }
.value-card__en { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--primary); letter-spacing: .08em; text-transform: uppercase; }
.value-card__text { color: var(--text-2); font-size: var(--fs-sm); line-height: var(--lh-body); }
.value-card__spark { margin-bottom: var(--sp-5); }
.value-card__spark .spark { width: 20px; height: 20px; }

/* ---- Şirket / künye ---------------------------------------------- */
.company__grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: var(--sp-16); align-items: start; }
.facts { display: grid; gap: 0; border-top: 1px solid var(--border); }
.fact { display: grid; grid-template-columns: 148px 1fr; gap: var(--sp-4); padding: var(--sp-4) 0; border-bottom: 1px solid var(--border); }
.fact__k { font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); padding-top: 2px; }
.fact__v { color: var(--text); font-size: var(--fs-sm); line-height: var(--lh-snug); }
.fact__v strong { font-weight: 600; }

/* ---- İletişim ---------------------------------------------------- */
/* Künye: İletişim panelinin altında, aynı bölümde (5651 Yön. m.5 "iletişim
   başlığı altında" diyor). Eski Şirket bölümünün .facts/.fact satırlarını
   kullanıyor; dl/dd tarayıcı boşlukları sıfırlanıyor. */
.kunye {
  margin-top: var(--sp-6);
  /* html'deki scroll-padding-top'a EK pay: /#kunye ile gelince kart açılıp
     uzarken hizalama ~16px kayıyor ve başlık satırı sabit barın altına giriyordu. */
  scroll-margin-top: var(--sp-8);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl);
}
.kunye__summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-8); cursor: pointer; list-style: none;
  border-radius: inherit; color: var(--text-2);
}
.kunye__summary::-webkit-details-marker { display: none; }
.kunye__title { font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .08em; text-transform: uppercase; }
.kunye__chev { width: 18px; height: 18px; flex: none; transition: transform 200ms var(--ease); }
.kunye[open] .kunye__chev { transform: rotate(180deg); }
@media (hover: hover) { .kunye__summary:hover { color: var(--text); } }
@media (prefers-reduced-motion: reduce) { .kunye__chev { transition: none; } }
.kunye__facts { margin: 0 var(--sp-8) var(--sp-6); }
@media (max-width: 720px) {
  .kunye__summary { padding: var(--sp-4) var(--sp-5); }
  .kunye__facts { margin: 0 var(--sp-5) var(--sp-4); }
}
.kunye__facts dd { margin: 0; }
.kunye__facts a { color: var(--primary); }
.footer__kunye a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.footer__kunye .legal__todo { color: inherit; } /* footer lacivert: --text orada okunmaz */
.contact__panel {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-2xl);
  padding: var(--sp-16); box-shadow: var(--sh-md);
  display: grid; grid-template-columns: 1.2fr 1fr; gap: var(--sp-16); align-items: center;
}
.contact__methods { display: grid; gap: var(--sp-5); }
.contact__row { display: flex; align-items: center; gap: var(--sp-4); }
.contact__ic { display: inline-grid; place-items: center; width: 42px; height: 42px; border-radius: var(--r-md); background: var(--primary-soft); color: var(--primary); flex: none; }
.contact__ic svg { width: 20px; height: 20px; }
.contact__k { font-size: var(--fs-xs); color: var(--text-3); font-family: var(--font-mono); letter-spacing: .04em; }
.contact__v { font-size: var(--fs-body); color: var(--text); font-weight: 500; }
.contact__v a { color: var(--text); }
.contact__v a:hover { color: var(--primary); }

/* ---- Footer ------------------------------------------------------ */
.site-footer { background: var(--navy-950); color: var(--navy-200); padding-block: var(--sp-16) var(--sp-8); }
[data-theme="dark"] .site-footer { background: #030d1f; border-top: 1px solid var(--border); }
.footer__top { display: flex; justify-content: space-between; gap: var(--sp-12); flex-wrap: wrap; padding-bottom: var(--sp-10); border-bottom: 1px solid rgba(255,255,255,.08); }
.footer__brand-logo { height: 30px; margin-bottom: var(--sp-4); }
.footer__tagline { max-width: 34ch; font-size: var(--fs-sm); color: var(--navy-200); line-height: var(--lh-body); }
.footer__nav { display: flex; gap: var(--sp-16); flex-wrap: wrap; }
.footer__col h4 { font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--navy-300); margin-bottom: var(--sp-4); }
.footer__col a { display: block; color: var(--navy-100); font-size: var(--fs-sm); padding: 5px 0; text-decoration: none; }
.footer__col a:hover { color: var(--teal-300); }
.footer__bottom { display: flex; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; padding-top: var(--sp-6); font-size: var(--fs-xs); color: var(--navy-300); }
.footer__bottom .mono { font-family: var(--font-mono); }

/* ---- Scroll reveal (opt-in, reduced-motion safe) ----------------- */
/* JS yoksa içerik görünür kalır (progressive enhancement); reveal yalnız html.js altında gizler */
html.js [data-reveal] { opacity: 0; transform: translateY(16px); transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out); }
html.js [data-reveal].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { html.js [data-reveal] { opacity: 1; transform: none; transition: none; } }

/* Reveal bitince kart hover geçişini GERİ DEVRALIR.
   Sorun: yukarıdaki iki kural (0,2,1) ve (0,3,1) özgüllükte .card'ı (0,1,0) ve
   .card:hover'ı (0,2,0) eziyordu. Ölçüldü: hover'da üç kartın da top değeri
   500.34px'te sabit kalıyordu — kalkış HİÇ olmuyordu; üstelik reveal'ın
   transition listesi box-shadow'u kapsamadığı için gölge 0ms'de sıçrıyordu.
   opacity listede KALMALI: düşerse kartlar solmadan tek karede beliriyor
   (geçişler "after-change" listesine bakar, .is-in eklendiği an liste de değişir). */
html.js .card[data-reveal].is-in {
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  html.js .card[data-reveal].is-in:hover { transform: translateY(-4px); }
}

/* ---- Kart ızgarasında kademeli giriş (stagger) ------------------- */
/* Üç kart YAN YANA olduğu için IntersectionObserver eşiği (threshold .12)
   üçünde de AYNI KAREDE aşılıyor — giriş değil flaş. 0/60/120ms kademe
   hero girişinin ritmiyle aynı (aşağıdaki hero giriş bloğundaki 60ms adımlı
   transition-delay merdiveni).

   NEDEN transform DEĞİL de `translate`: reveal ile hover'ın TEK ortak
   özelliği transform. Gecikme kalıcı `.is-in` durumuna yazılsaydı hover
   ÇIKIŞINDA da uygulanırdı — geçişler süre/gecikmeyi "after-change"
   stilden okur, fare ayrılınca o stil hover'sız `.is-in` olur; üçüncü kart
   fare çekildikten 120ms sonra inerdi. `:hover` kuralına transition-delay:0s
   eklemek yalnız GİRİŞİ kurtarır, çıkışı kurtarmaz. Yükselişi bağımsız
   `translate` özelliğine taşıyınca iki hareket ayrışıyor: gecikme
   opacity+translate'e, hover'ın kullandıkları (transform/box-shadow/
   border-color) HİÇBİR yönde gecikmiyor. translate compositor'da transform
   ile aynı matrise giriyor, layout tetiklemiyor (bkz. yukarıdaki
   .product-card__link svg notu).

   YAN ETKİSİ VAR, "birebir aynı" değil (ölçüldü): transform ailesindeki
   (transform / translate / rotate / scale) HER özelliğin `none` DIŞINDAKİ her
   değeri — `translate: 0 0` dahil — yığılma bağlamı ve sabit/mutlak torunlar
   için kapsayıcı blok yaratıyor. DÜZELTME (2026-08-13): burada önce "translate
   yaratıyor, transform yaratmıyor" yazıyordu — YANLIŞTI. Aynı sondayla ölçüldü:
   `transform: translateY(0)` de birebir aynı kapsayıcı bloğu yaratıyor. Ayrım
   özellik adında değil, değerin `none` olup olmamasında. Buradaki gerçek fark
   şu: reveal bittiğinde `transform` `none`'a dönerken `translate` `0 0`'da
   kalıyor, yani bağlam KALICI oluyor.
   Yani kartlar artık DOM sırasına göre boyanıyor ve 1./2. kartın hover gölgesi
   komşusunun opak zemininin ALTINDA kalabilir. Ölçü: sütun aralığı 24px,
   --sh-lg'nin yatay ofseti 0 ve yanal erişimi ~14px → gölge komşunun kutusuna
   ulaşmıyor, görsel etki yok. Çıkarsa çözüm z-index DEĞİL, durumu bildirmek.

   YALNIZ >=901px: aşağıdaki Responsive bloğuna göre (max-width:900px -> 2
   sütun, max-width:720px -> 1 sütun) dar ekranda ızgara bölünüyor. Tek sütunda
   kartlar zaten tek tek eşiği geçiyor, gecikme onları "kademeli" değil GEÇ
   gösterir; 2 sütunda ise nth-child(3) alt satıra düşüyor, kaynak sırası görsel
   sırayı temsil etmiyor.

   `>` ÇOCUK BİRLEŞTİRİCİSİ ŞART: .section-head, .vision__panel ve
   .contact__panel da [data-reveal] taşıyor ama .grid--3 çocuğu değil —
   gecikme onlara sızmamalı.

   ÖZGÜLLÜK: `html.js .grid--3 > .card[data-reveal].is-in` (0,5,1) >
   `html.js .card[data-reveal].is-in` (0,4,1) — yani yukarıdaki reveal
   kuralında transition KISAYOLUNUN delay'i 0s'e sıfırlaması bizi vurmuyor.
   Hover kuralı da (0,5,1) ama yalnız `transform` yazıyor, biz yazmıyoruz
   → çakışma yok, kalkış korunuyor.

   translate desteği (Chrome 104 / Safari 14.1 / Firefox 72) bu deponun
   ana yolda kullandığı color-mix'ten (Chrome 111 / Safari 16.2) daha geniş,
   ayrı @supports gerekmiyor. Desteklenmezse `translate` düşer, aynı bloktaki
   `transform: none` kalır → kart yükselmeden yalnız soluklanır, kademe sürer. */
@media (min-width: 901px) {
  html.js .grid--3 > .card[data-reveal] {
    --reveal-delay: 0ms;
    /* yukarıdaki reveal kuralının translateY(16px)'i iptal; yükseliş translate'e taşındı */
    transform: none;
    translate: 0 16px;
  }
  html.js .grid--3 > .card[data-reveal]:nth-child(2) { --reveal-delay: 60ms; }
  html.js .grid--3 > .card[data-reveal]:nth-child(3) { --reveal-delay: 120ms; }

  html.js .grid--3 > .card[data-reveal].is-in {
    /* `0 0` yazılı; `none` da OLURDU. DÜZELTME (2026-08-13): burada
       "interpolasyon garantili, `none` olmaz" yazıyordu — ölçümle çürütüldü.
       Edge'de 2000ms linear ile aynı anda örneklendi: `0px 40px → none` ve
       `0px 40px → 0px 0px` ikisi de `0px 28.331px` okudu, yani `none` bu
       bağlamda 0'a çözülüyor ve birebir aynı interpole ediyor. `0 0` yalnız
       AÇIKLIK için duruyor — bitiş değerini okunur kılıyor. */
    translate: 0 0;
    /* Süreler yukarıdaki .is-in kuralıyla BİREBİR AYNI — bu blok hız
       değiştirmiyor, yalnız transform'un yerine translate'i listeye sokuyor. */
    transition: opacity var(--dur-slow) var(--ease-out),
                translate var(--dur) var(--ease-out),
                transform var(--dur) var(--ease-out),
                box-shadow var(--dur) var(--ease-out),
                border-color var(--dur) var(--ease-out);
    /* SIRA KRİTİK: transition KISAYOLUNDAN SONRA gelmeli, yoksa kısayol bunu
       0s'e sıfırlar. Değerler yukarıdaki listeyle birebir hizalı:
       opacity, translate -> kademe · transform, box-shadow, border-color
       (hover'ın kullandıkları) -> HER ZAMAN 0s. */
    transition-delay: var(--reveal-delay, 0ms), var(--reveal-delay, 0ms), 0s, 0s, 0s;
  }
}

/* reduced-motion'da kart YER DEĞİŞTİRMEMELİ. Yukarıdaki reduced-motion kuralı
   bunu `transform: none` ile sağlıyor ama özgüllüğü (0,2,1) — yukarıdaki
   `translate` bildirimimizi (0,4,1) göremez, kartlar 16px aşağıda durup .is-in
   gelince zıplardı. Bu kural yukarıdakiyle ÖZGÜLLÜK EŞİT (0,4,1) → kaynak
   sırası karar veriyor, bu yüzden SONRA gelmek ZORUNDA. Süre/gecikme için ek
   kural yok: tokens.css `*` üzerinde transition-duration .001ms ve
   transition-delay 0s !important veriyor. */
@media (prefers-reduced-motion: reduce) {
  html.js .grid--3 > .card[data-reveal] { translate: none; }
}

/* ---- Responsive -------------------------------------------------- */
@media (max-width: 900px) {
  .grid--3 { grid-template-columns: 1fr 1fr; }
  .company__grid, .contact__panel { grid-template-columns: 1fr; gap: var(--sp-10); }
  .vision__panel { padding: var(--sp-16) var(--sp-8); }
}
/* Yatay menü -> hamburger eşiği. 720px DEĞİL 1024px, ve bu KENDİ sorgusunda:
   --header-scale 1.4'e çıkınca bar içeriği 692 -> 968px'e genişledi (marka 64->90,
   menü 352->483, aksiyonlar 245->331; aradaki 2x24 boşluk ve 2x24 kenar payı
   ölçekten bağımsız). Ölçüm: 1024px'te 24px pay kalıyor, 900'de 44px, 768'de
   176px SAĞA TAŞIYOR — ve başlık `fixed` olduğu için bu taşma sayfaya yatay
   kaydırma AÇMIYOR, yani sessiz: CTA ile menü düğmesi ekranın dışında kalıyor,
   scrollWidth ölçümü de 0 diyor. Bu yüzden eşik ölçüye bağlandı: içerik 968px
   gerektiriyor, altında yatay menü sığmaz.
   720'lik bloktan ÇIKARILDI çünkü o blok yalnız menüyü değil ızgara/boşluk
   kurallarını da taşıyor; onların eşiği değişmedi. */
@media (max-width: 1023px) {
  .nav { display: none; }
  .nav-toggle { display: inline-grid; }
}
@media (max-width: 720px) {
  /* NOT: burada bir ara `.site-header { position: relative }` denendi (mobilde
     bar sabit olmasın) ve GERİ ALINDI — bar tepede kalmıyordu, istenmiyor.
     Titremenin kaynağı sticky değil, sayfa yakınlaştırmasının %100 olmaması:
     ölçek 1.00'da barın kenarı 100/100 karede aynı pikselde, 1.02'de 7px,
     1.05'te 13px salınıyor. Yakınlaştırma 1.00'a alınınca sticky sorunsuz.
     Yine de gerekirse çözüm tek satır: `.site-header { position: relative }`
     (static DEĞİL — .mobile-nav `absolute; top:100%` ile konumlanıyor ve
     konumlanmış bir ataya ihtiyacı var) + `html { scroll-padding-top: 0 }`. */
  .grid--3, .grid--2 { grid-template-columns: 1fr; }
  .section { padding-block: var(--sp-16); }
  .hero { padding-block: var(--sp-20) var(--sp-16); }
  .contact__panel { padding: var(--sp-8); }
  .footer__top { flex-direction: column; gap: var(--sp-8); }
  /* Sütunlar sardığında satır aralığı 64px'lik boşluk bırakıp "İletişim"i
     yetim gösteriyordu. Yalnız satır aralığı kısılıyor; sütun aralığı 64px
     kalıyor çünkü sığdığı genişliklerde doğru olan o. */
  .footer__nav { row-gap: var(--sp-8); }
}
@media (max-width: 480px) {
  .container { padding-inline: var(--sp-4); }
  .hero__cta .btn { width: 100%; }
  .fact { grid-template-columns: 1fr; gap: 2px; }
  /* Başlık çubuğunun payını artır — aşağıdaki taşma notuna bak. */
  .site-header__inner { gap: var(--sp-3); }
  .header-actions { gap: var(--sp-2); }
  .mobile-nav { padding-inline: var(--sp-2); }   /* 8+8=16, markayla aynı çizgi */
}
/* Dar telefonlarda başlık çubuğu YATAY TAŞIYORDU. Ölçüm (isMobile, TR):
     marka 50.7 + iç boşluk 24 + [dil 80.8 + tema 38 + CTA 94.4 + menü 38
     + 3×12 boşluk] + 2×16 kenar payı ≈ 394px gerekiyor.
   390px'te 12px pay kalıyor, 375px'te +3, 360px'te +18, 320px'te +58 taşma.
   Taşma sayfanın TAMAMINA yatay kaydırma açıyor; sticky başlık yalnız viewport
   genişliğinde olduğu için sağa kaydırıldığında zemini ve kenarlığı geride
   kalıyor, butonlar zeminsiz biçimde sayfa dışına taşmış görünüyordu.
   Çözüm CTA'yı burada gizlemek: işlev KAYBI YOK — mobil menü sayfasında
   "İletişim" bağlantısı, hero'da da tam genişlikte İletişim düğmesi zaten var. */
/* Eşik 400 DEĞİL 560: yukarıdaki ölçümün mobil karşılığı. CTA görünürken bar
   içeriği 1.4 ölçekte 522px istiyor (marka 90 + dil 123 + tema 53 + CTA 131 +
   menü 53 + 3x12 boşluk + 2x24 kenar payı); ölçüldü: 481px'te 53px, 430px'te
   72px sağa taşıyordu. 560 = 522'nin üstünde ilk güvenli yuvarlak değer.
   İşlev KAYBI YOK: "İletişim" hem mobil menüde hem hero'da tam genişlikte var. */
@media (max-width: 560px) {
  .header-actions > .btn { display: none; }
}
/* 320px'in altı da gerçek bir durum: Galaxy Fold kapak ekranı 280px, ama asıl
   yaygın sebep TARAYICI YAKINLAŞTIRMASI — 360px'lik bir telefonda %125 zoom
   efektif viewport'u ~288px'e düşürür. Burada dokunma hedefi küçültülmez;
   yalnız kenar payı, marka yüksekliği ve boşluklar kısılır. */
@media (max-width: 370px) {
  .site-header .container { padding-inline: var(--sp-3); }
  .site-header .brand__logo { height: calc(32px * var(--header-scale)); }
  .header-actions { gap: 4px; }
  .mobile-nav { padding-inline: var(--sp-1); }   /* 4+8=12, markayla aynı çizgi */
  /* Rozet + wordmark aynı satıra sığmazsa alt satıra insin — 280-340px'te
     .tag nowrap ve SVG küçülmüyor, taşma açılabilirdi. */
  .product-card__top { flex-wrap: wrap; row-gap: var(--sp-2); }
  /* NOT: burada bir ara `.product-card__lockup { height: 18px }` vardı. Taban
     22px'ken 186px genişlik dar sütuna sığmıyordu. Taban 16px'e (135px)
     inince kural TERS çalışmaya başladı — dar ekranda wordmark'ı 16'dan 18'e
     BÜYÜTÜYORDU. Kaldırıldı: 135px, 340px'te 244px'lik karta da 280px'te
     184px'lik karta da rahat sığıyor. */
}
/* En dar kademede %40 ARTIK SIĞMIYOR ve kısılacak başka şey kalmadı: yukarıdaki
   blok kenar payını, marka yüksekliğini ve boşlukları zaten dibe çekti, içerik
   yine 318px istiyor (280px'lik Galaxy Fold kapak ekranına 38px taşar).
   Burada dokunma hedefi küçültmek yerine ÖLÇEĞİN KENDİSİ geri alınıyor — bar
   bir sistem olduğu için tek katsayı hepsini birlikte küçültür ve hiza bozulmaz.
   Ölçüldü: 1.15'te 280px'e 2,9px taşıyor, 1.1'de 8px pay kalıyor. */
@media (max-width: 340px) {
  :root { --header-scale: 1.1; }
}

/* =====================================================================
   Cilalama (polish)
   ===================================================================== */

/* Hero giriş — Emil-motion: yalnız transform+opacity, ease-out, kademeli,
   prefers-reduced-motion güvenli, .js gate'li (JS yoksa anında görünür) */
html.js .hero__inner > * { opacity: 0; transform: translateY(14px); }
html.js .hero.is-in .hero__inner > * {
  opacity: 1; transform: none;
  /* 520ms + 450ms gecikme = son öğe ~970ms'de yerine oturuyordu; stagger
     adımları da 90-110ms ile standardın 30-80ms bandının iki katıydı.
     380ms + 60ms adım → dizi ~620ms'de biter, kademe hâlâ okunur. */
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
}
html.js .hero.is-in .hero__title   { transition-delay: 60ms; }
html.js .hero.is-in .hero__lead    { transition-delay: 120ms; }
html.js .hero.is-in .hero__cta     { transition-delay: 180ms; }
html.js .hero.is-in .hero__quote   { transition-delay: 240ms; }
@media (prefers-reduced-motion: reduce) {
  html.js .hero__inner > * { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---- reduced-motion: BİLEŞEN hareketi de düşmeli ------------------ */
/* Sayfa düzeyindeki üç hareket (dalga alanı, reveal, hero girişi) zaten
   kapsanmıştı; bileşen düzeyindekiler değildi. Emil kuralı: daha yumuşak,
   sıfır değil — renk ve gölge kalır, YER DEĞİŞTİRME gider. */
@media (prefers-reduced-motion: reduce) {
  .card:hover,
  html.js .card[data-reveal].is-in:hover { transform: none; }
  .btn:active, .icon-btn:active, .lang-btn:active { transform: none; }
  .mobile-nav { transform: none; }
  .product-card__link:hover svg { transform: none; }
}

/* Ürün kartı marka başlığı */
.product-card__brand { display: flex; align-items: center; gap: var(--sp-3); min-height: 32px; }
.product-card__symbol { height: 30px; width: auto; display: block; }
/* Navena wordmark'ı — satır içi SVG, harfler currentColor.
   Yükseklik KUTUYA değil MÜREKKEBE göre. Bu SVG sıkı kırpık ve tamamı büyük
   harf (viewBox 1044.8:123.77), yani kutu yüksekliği = harf yüksekliği.
   Komşu kartların markaları (o dönem iki tane vardı) farklı kutu/mürekkep
   oranları taşıyordu.
   Kutuları 22px'te eşitlemek mürekkebi eşitlemiyordu: ölçüldü, NAVENA
   komşularından %47 büyük duruyordu (186 / 109 / 83px) ve mobilde kart
   içeriğinin %63'ünü kaplıyordu. 16px = üç markanın ortak optik bandı.
   Genişlik 16 × 8.441 = 135px. */
.product-card__lockup { display: block; height: 16px; width: auto; color: var(--text); }
/* "CE", NAVENA wordmark'inin KENDI gramerinde cizildi (2026-08-25).
   Eskiden Space Grotesk metindi ve yan yana durunca iki ayri sey gibi
   okunuyordu: NAVENA monoline geometrik, hic egri yok, butun cizgiler ayni
   kalinlikta; Space Grotesk'in C'si kaseli ve kalinligi degisken, ustelik
   %44 daha uzundu. Punto/agirlik ayari denendi, yetmedi — sorun olcu degil
   YAPIYDI.
   Olculer wordmark'tan alindi: viewBox yuksekligi 123.77 (ayni), cizgi
   kalinligi 23 birim = teal E cubuklarinin kalinligi (kap yuksekliginin
   %18.6). C kose kirpmali (oktagonal): NAVENA'nin A ve V'si de capraz
   kullaniyor, yani gramer capraza izin veriyor; tam kare bir C ise "["
   gibi okunurdu.
   ERISILEBILIRLIK: bu SVG aria-hidden, adin TAMAMI wordmark'in
   aria-label="Navena CE" degerinde. Ikisi birden ad tasirsa ekran okuyucu
   "Navena CE CE" der — bu tuzaga bir kez dusuldu, tekrar dusulmesin. */
.product-card__ce-svg {
  height: 16px; width: auto; display: block; flex: none; color: var(--text);
}

/* Künye/Şirket sol sütun denge bloğu */
.company__aside {
  margin-top: var(--sp-8); padding: var(--sp-6);
  border-radius: var(--r-lg); background: var(--surface-2); border: 1px solid var(--border);
}
.company__aside-q {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 500;
  color: var(--text); line-height: var(--lh-snug);
}
.company__aside-q .spark { margin-top: 7px; flex: none; }

/* Kültür ilke şeridi (duruş — "neye inanıyoruz") */
.culture__principles { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2) var(--sp-3); margin-top: var(--sp-6); }
.culture__principles > span {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-2);
  padding: 6px 14px; border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--border);
}
.culture__principles > span::before {
  content: ""; width: 9px; height: 9px; flex: none; background: var(--accent);
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%);
}

/* Footer künye güven şeridi */
.footer__kunye {
  padding-top: var(--sp-6); font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: .02em; color: var(--navy-300);
}

/* =====================================================================
   BÖLÜM-BÖLÜM KAYDIRMA (yalnız masaüstü) — FAZ 1
   Native CSS scroll-snap: tarayıcının kendi kaydırması korunur, dolayısıyla
   klavye, kaydırma çubuğu, Ctrl+F, ekran okuyucu ve geri/ileri normal çalışır.
   (JS ile kaydırmayı ele geçiren "fullpage" yaklaşımı bunların hepsini bozuyor.)

   proximity — mandatory DEĞİL. Zorunlu snap'te iki nokta arası geçmek tek
   yerleşmiş kaydırmada >400px ister; bir fare tekerleği çentiği ~100px. Küçük
   adımlarla kaydıran kullanıcı footer'daki künye şeridine hiç ulaşamaz.

   KAPILAR — mobilde kasten KAPALI. Ölçüldü (390x844): bölümlerin çoğu bir
   ekrana sığmıyor; `.grid--3` tek sütuna düştüğü için üç kart alt alta tek
   başına bir ekrandan uzun. Sığdırmanın tek yolu metin kısaltmak olurdu.
   min-height `em` cinsinden: tipografi rem tabanlı olduğu için kullanıcı
   tarayıcı yazı boyutunu büyütünce içerik de büyür — kapı onunla kapanmalı.
   ===================================================================== */
@media (min-width: 901px) and (min-height: 55em) and (hover: hover) and (pointer: fine) {
  html { scroll-snap-type: y proximity; }

  .hero,
  main > .section { scroll-snap-align: start; }
  .site-footer { scroll-snap-align: end; }

  /* min-height — `height` DEĞİL: sabit yükseklik, .hero'daki overflow:hidden ile
     birlikte uzun metni (ör. EN sözlüğü, büyük yazı tipi ayarı) sessizce kırpar. */
  .hero,
  main > .section {
    min-height: calc(100vh - var(--header-h));
    min-height: calc(100svh - var(--header-h));
    display: flex; flex-direction: column; justify-content: center;
    padding-block: var(--sp-12);
  }
}

/* =====================================================================
   SAYFA GEÇİŞLERİ — View Transitions
   Dil değişimi 69 `data-i18n` + 4 `data-i18n-html` düğümün metnini TEK karede
   değiştiriyordu; H1 ve lead'in satır sayısı dile göre değiştiği için blok da
   sıçrıyordu. scripts/main.js'teki withViewTransition() araya çapraz sönüm
   koyuyor. Desteği olmayan tarayıcıda hiçbir sözde-eleman üretilmez, bu blok da
   ölü kalır — sayfa bugünkü davranışında sürer (yukarıdaki dalga alanı notuyla
   aynı felsefe).

   NEDEN SÜRE: UA varsayılanı 250ms
   (`::view-transition-group(*) { animation-duration: 0.25s }`; old/new onu
   `animation-duration: inherit` ile devralıyor). Değerler sistemin motion
   sözlüğünden gelmeli — tokens.css'teki --dur/--ease. Author bildirimi
   UA'nınkini KÖKEN sırasıyla yener, o yüzden özgüllük artırmaya
   (`:root::view-transition-...`) gerek yok.

   NEDEN EĞRİ VERİYORUZ: UA old/new'e eğri VERMİYOR — oradaki değer CSS'in
   başlangıç değeri olan `ease`, yani ezilmezse sistem sözlüğünün dışında bir
   eğri kullanılmış olurdu.

   NEDEN --ease, --ease-out DEĞİL: --ease-out = cubic-bezier(.16,1,.3,1) bir
   GİRİŞ eğrisi ve aşırı ön-yüklü. Elle hesaplandı — y1=y2=1 olduğu için
   y = 3s − 3s² + s³ — ilerleme 20ms'de %49, 78ms'de %94: yani 200ms'lik
   köprü optik olarak ~80ms'ye iniyor ve sönüm yine neredeyse ani görünüyor.
   Oysa çapraz sönüm bir giriş değil bir DURUM DEĞİŞİMİ; deponun bu iş için
   taşıdığı token --ease = cubic-bezier(.4,0,.2,1) ve .btn / .nav__link /
   .lang-btn / .icon-btn hep durum değişiminde onu kullanıyor. Onun y eğrisi
   (y1=0, y2=1) y = 3s² − 2s³: ilerleme 20ms'de %3, 70ms'de %50, 78ms'de %60,
   150ms'de %96 — ağırlık gerçekten 200ms'ye yayılıyor.
   Yan etki YOK: iki sönüm aynı eğriyi paylaştığı için opaklık toplamı her an
   ~1 kalıyor, ara karede beyazlama/çukur oluşmuyor.

   MİRAS: ::view-transition ağacının kökü :root'tan doğar ve kalıtsal özellikler
   — custom property'ler dahil — ağaca iner; yani var(--dur) burada çözülür.
   Literal yedek yine de bırakılıyor: --dur zaten 200ms, --ease zaten
   cubic-bezier(.4,0,.2,1) — iki yol da AYNI görüntüyü verir, yedek bedava
   sigorta (tarayıcı hatası ya da ağaç köke bağlanmazsa görüntü değişmez).

   GRUP KATMANINA DOKUNULMUYOR: eski görüntü ve yeni eleman ikisi de var olduğu
   için grup katmanına HER HÂLÜKÂRDA bir animasyon üretiliyor
   (-ua-view-transition-group-anim-root, UA'nın 250ms'sinde). Kök anlık
   görüntüsünün kutusu viewport'un kendisi ve dil/tema değişince geometri
   değişmediğinden bu animasyonun başlangıç ve bitiş değerleri ÖZDEŞ — görsel
   karşılığı yok, no-op. 250ms'de kalması da zararsız: old/new UA'dan
   `animation-fill-mode: both` devraldığı için 200ms'de son hâllerini tutuyor,
   aradaki 50ms ekranda hiçbir şeyi değiştirmiyor. (Geçişin BİTTİĞİ an yine de
   250ms'dir.)
   ===================================================================== */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--dur, 200ms);
  animation-timing-function: var(--ease, cubic-bezier(.4,0,.2,1));
}

/* =====================================================================
   ALT SAYFALAR — hata sayfaları (404/403/500) + hukuki sayfalar
   ---------------------------------------------------------------------
   Yeni hareket EKLENMEZ. Bu sayfalar zaten iki mevcut sistemi devralıyor:
   sayfa-boyu dalga alanı (.bg-field, hero-waves.js) ve hero'nun kademeli
   girişi (html.js .hero.is-in .hero__inner > *). İkisi de sınıf tabanlı,
   yani main.js/hero-waves.js'e tek satır eklemeden burada da çalışıyor.
   ===================================================================== */

/* Hata sayfası tek ekranlık: hero ekranı doldursun ki alan tam güçte
   görünsün. body'nin padding-top'u --header-h olduğu için ondan düşülür.
   lvh — dvh DEĞİL: .bg-field ile aynı gerekçe (adres çubuğu oynayınca
   yükseklik değişmesin, bkz. yukarıdaki .bg-field notu). */
.hero--page {
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: calc(100lvh - var(--header-h));
  padding-block: var(--sp-16) var(--sp-20);
}
.hero--page > .hero__inner { width: 100%; }

/* Hata kodu. Kasten STATİK ve kasten büyük: sayfadaki hareket bütçesi
   zaten alana ve kademeli girişe harcanmış durumda; üçüncü bir hareket
   Emil'in "her şey kıpırdarsa hiçbir şey kıpırdamaz" eşiğini geçerdi.
   Kademeli girişe yine de katılıyor, çünkü .hero__inner'ın doğrudan
   çocuğu — ayrı bir kural gerekmiyor. */
.error-code {
  font-family: var(--font-mono);
  font-size: clamp(4rem, 14vw, 8.5rem);
  line-height: 1;
  font-weight: 500;
  letter-spacing: -.04em;
  color: var(--accent);
  margin-bottom: var(--sp-5);
  /* Alanın üstünde okunurluk: rakam ince değil kalın bir kütle olduğu için
     peçeye ihtiyacı yok, ama teal'in açık temadaki kontrastı sınırda —
     hafif bir gölge zemini ne olursa olsun ayırıyor. */
  text-shadow: 0 1px 0 color-mix(in srgb, var(--bg) 70%, transparent);
}

/* Hata sayfasının kendi girişi hero başlığından bir kademe ÖNCE gelsin:
   kullanıcı önce "ne oldu"yu (kod), sonra "ne yapmalı"yı (başlık, metin,
   düğmeler) okusun. .hero__inner > * tabanı 0ms olduğu için ek kural yok;
   bu satır yalnız sıranın bilinçli olduğunu kayda geçirir. */

/* ---- Hukuki / uzun metin sayfaları ------------------------------- */
/* Metin sütunu sayfanın ortasında, satırlar sola dayalı. Hero da aynı
   sütuna oturuyor ki başlık ile metin aynı hizadan başlasın. */
.legal { max-width: 68ch; margin-inline: auto; }
.hero__inner.legal-hero { max-width: calc(68ch + 2 * var(--gutter, 24px)); }
.legal h2 {
  font-size: var(--fs-h3);
  margin-top: var(--sp-12);
  margin-bottom: var(--sp-4);
  scroll-margin-top: calc(var(--header-h) + var(--sp-6));
}
.legal h2:first-of-type { margin-top: 0; }
.legal h3 { font-size: var(--fs-h4); margin-top: var(--sp-8); margin-bottom: var(--sp-3); }
.legal p, .legal li { color: var(--text-2); line-height: var(--lh-body); }
.legal p { margin-bottom: var(--sp-4); }
.legal ul { margin: 0 0 var(--sp-4); padding-left: 1.25em; }
.legal li { margin-bottom: var(--sp-2); }
.legal a { color: var(--primary); }
.legal strong { color: var(--text); font-weight: 600; }
.legal__meta {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-3);
  margin-bottom: var(--sp-10);
}

/* Doldurulacak yer. Metnin içinde göze batmalı ki gözden kaçıp yayına
   çıkmasın — sessizce "[…]" bırakmak tam olarak fark edilmeyen şeydir. */
.legal__todo {
  font-family: var(--font-mono);
  font-size: .9em;
  background: color-mix(in srgb, var(--warning, #B45309) 16%, transparent);
  border-bottom: 1px dashed var(--warning, #B45309);
  padding: 1px 5px;
  border-radius: var(--r-xs);
  color: var(--text);
}

/* =====================================================================
   NAVENA CE ürün sayfası (navena.html)
   Yalnız bu sayfada kullanılan bileşenler. Site.css'te duruyorlar çünkü
   sayfa ayrı bir stil dosyası yüklemiyor: ikinci bir istek, ~2 KB uğruna
   render'ı bloklardı. Hepsi `nv-` ön ekli — ana sayfanın bileşen adlarıyla
   karışmasın diye.
   Kaynak metin/kompozisyon: Bridgeflow/doc/collateral/linkedin/
   (2026-08-19 post serisi). Kırmızı-çizgi denetimi sayfanın kendi HTML
   yorumunda.
   ===================================================================== */

/* ---- Hero: ürün adı ---------------------------------------------- */
/* Ad wordmark SVG'si DEĞİL düz metin: p0-intro görselindeki emsalin aynısı,
   ve metin seçilebilir/indekslenebilir olduğu için ürün sayfasının h1'i
   olabiliyor. Wordmark ana sayfadaki kartta kalıyor. */
.nv-ad { font-family: var(--font-display); font-weight: 600; letter-spacing: var(--ls-tight); }
.nv-alt {
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-3);
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  /* -12px: h1'in 24px'lik alt bosluguna giriyor, ad ile alt-ad tek blok
     okunsun diye. Alt bosluk ise OLCULDU: onsuz nv-alt ile lead arasi 0px
     kaliyordu ve alt-ad lead'in etiketi gibi gorunuyordu. */
  margin-top: calc(var(--sp-3) * -1); margin-bottom: var(--sp-5);
}
.nv-meta {
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-2);
  /* alt bosluk OLCULDU: onsuz CTA dugmeleri satira yapisiyordu (0px). */
  margin-top: var(--sp-5); margin-bottom: var(--sp-6);
}

/* ---- İki form / çelişki ------------------------------------------ */
/* 1fr auto 1fr: çarpışma işareti ortada KENDİ sütununda durur, kartların
   üstüne binmez. Mobilde tek sütuna düşüyor ve işaret iki kartın arasına
   dikey olarak giriyor — anlam aynı kalıyor. */
.nv-formlar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: var(--sp-4); margin-top: var(--sp-8);
}
.nv-form {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--sp-6); box-shadow: var(--sh-sm);
}
/* Tek bir kart bicimi. Eskiden --ok yesil / --carp kirmizi cerceveliydi;
   o ayrim "B yanlis" diyordu, oysa motor hangisinin dogru oldugunu bilmez.
   Ikisi de kendi icinde tutarli oldugunu iddia ediyor -> ikisi de ayni. */
.nv-form { border-color: color-mix(in srgb, var(--success) 40%, var(--border)); }
.nv-form__k {
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-3);
}
.nv-form__kisi {
  font-family: var(--font-mono); font-size: var(--fs-h3); letter-spacing: .12em;
  color: var(--text); margin-top: var(--sp-3);
}
.nv-form__durum {
  display: flex; align-items: baseline; gap: var(--sp-2);
  margin-top: var(--sp-3); font-size: var(--fs-body); line-height: var(--lh-snug);
}
.nv-form__durum { color: var(--success); }
.nv-form__zaman { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-2); margin-top: var(--sp-2); }
/* Çarpışma işareti. Dekoratif DEĞİL — anlamı taşıyan tek şey iki kartın
   metni, işaret onu tekrar ediyor, o yüzden aria-hidden. */
/* Carpisma isareti. 44px -> 64px: iki kartin arasindaki tek kirmizi oge bu ve
   bolumun butun anlamini o tasiyor, kartlara gore ezik duruyordu. Hale 8 -> 12px
   ve iki katmanli: yakin halka kesif, uzak halka yayilim veriyor.
   Icerik SVG (bkz. navena.html'deki gerekce), o yuzden yazi tipi metrigi yok. */
.nv-carp {
  width: 64px; height: 64px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--danger); color: var(--white);
  box-shadow: 0 0 0 12px color-mix(in srgb, var(--danger) 12%, transparent),
              0 0 0 22px color-mix(in srgb, var(--danger) 5%, transparent);
}
.nv-carp svg { width: 30px; height: 30px; display: block; }

/* Kartlar yerine oturduktan SONRA isaret gelsin: once iki kayit, sonra
   aralarindaki celiski. Amac dekorasyon degil ACIKLAMA — bolumun anlattigi
   sirayi hareket tekrar ediyor. Nadir gorulen bir an (sayfa basina bir kez),
   240ms, yalniz transform+opacity, ease-out. */
html.js [data-reveal] .nv-carp { opacity: 0; transform: scale(.82); }
html.js [data-reveal].is-in .nv-carp {
  opacity: 1; transform: none;
  transition: opacity 240ms var(--ease-out) 220ms, transform 240ms var(--ease-out) 220ms;
}
@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal] .nv-carp,
  html.js [data-reveal].is-in .nv-carp { opacity: 1 !important; transform: none !important; transition: none !important; }
}
/* Örneğin sonucu — hero__quote ile aynı alıntı kalıbı (şerit + kıvılcım).
   Düz metinken dipnot gibi okunuyordu; kutu onu bölümün sonucu yapıyor.
   ŞERİT TEAL, KIRMIZI DEĞİL. Kırmızı denendi ve bırakıldı: bu cümle
   "biz örneği böyle okuyoruz" diyen MARKA SESİ (hero alıntısı ve
   .company__aside-q ile aynı kayıt), bulgunun kendisi değil. Kırmızı kutu
   ≠ işaretinden büyük ikinci bir kırmızı nesne üretip açıklaması gereken
   işareti bastırıyordu; ayrıca pembe dolgu tarayıcı hata bandı gibi
   okunuyordu. Bölümün tek kırmızı odağı ≠ olarak kalıyor.
   Zemin --primary-soft DEĞİL --accent 8% + --surface: hero'nunki hero'nun
   kendi zemininde çalışıyor, burada açık temada görünmez kalıyordu (ölçüldü). */
.nv-vurgu {
  display: inline-flex; align-items: flex-start; gap: var(--sp-3);
  text-wrap: balance;
  margin-top: var(--sp-6); max-width: 46rem;
  padding: var(--sp-5) var(--sp-6);
  border-left: 3px solid var(--accent); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  font-family: var(--font-display); font-size: var(--fs-h4);
  font-weight: 500; color: var(--text); line-height: var(--lh-snug);
}
/* Kıvılcım ilk satırın x-yüksekliğine oturuyor; align-items:center iki
   satıra düşen çeviride kıvılcımı boşluğa kaydırırdı. */
.nv-vurgu .spark { margin-top: 9px; }
.nv-vurgu + .nv-not { margin-top: var(--sp-6); }

/* Kutu, kartlar ve ≠ yerine oturduktan SONRA gelsin: iki kayıt → çelişki →
   sonuç. ≠ 220ms'de başlayıp 460ms'de bitiyor, bu 480ms'de devralıyor.
   Amaç dekorasyon değil AÇIKLAMA; sayfa başına bir kez görülüyor. */
html.js [data-reveal] .nv-vurgu { opacity: 0; transform: translateY(6px); }
html.js [data-reveal].is-in .nv-vurgu {
  opacity: 1; transform: none;
  transition: opacity 260ms var(--ease-out) 480ms, transform 260ms var(--ease-out) 480ms;
}
@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal] .nv-vurgu,
  html.js [data-reveal].is-in .nv-vurgu { opacity: 1 !important; transform: none !important; transition: none !important; }
}
/* Kırmızı-çizgi #8: "temsilî örnek" ibaresi hem metinde hem görselde
   bulunmak zorunda. Burada görsel HTML olduğu için tek satır ikisini de
   karşılıyor — bu yüzden örneğin İÇİNDE, alt bilgi olarak duruyor. */
.nv-not {
  margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px dashed var(--border);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-3);
}

.nv-formlar__k {
  margin-top: var(--sp-8);
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-3);
}
.nv-formlar__k + .nv-formlar { margin-top: var(--sp-4); }

/* ---- Katman diyagramı -------------------------------------------- */
.nv-katman { margin-top: var(--sp-8); max-width: 52rem; }
.nv-kat { border-radius: var(--r-lg); padding: var(--sp-6) var(--sp-8); }
.nv-kat--ust {
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
}
.nv-kat--alt { border: 1px solid var(--border); background: var(--surface-2); }
.nv-kat__k {
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em;
  text-transform: uppercase;
}
.nv-kat--ust .nv-kat__k { color: var(--primary); }
.nv-kat--alt .nv-kat__k { color: var(--text-3); }
.nv-kat__v { margin-top: var(--sp-2); font-size: var(--fs-h4); color: var(--text); }
.nv-kat--alt .nv-kat__v { font-family: var(--font-mono); letter-spacing: .04em; }
.nv-kat__c {
  margin-top: var(--sp-4); padding-top: var(--sp-4);
  border-top: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  font-family: var(--font-mono); font-size: var(--fs-sm);
  letter-spacing: .04em; color: var(--text-2);
}
.nv-ok { display: grid; place-items: center; gap: var(--sp-2); padding: var(--sp-4) 0; }
.nv-ok__ucgen {
  width: 0; height: 0; border-left: 11px solid transparent; border-right: 11px solid transparent;
  border-bottom: 13px solid var(--accent);
}
.nv-ok__yazi { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-3); letter-spacing: .04em; }

/* ---- "Hiç istemediklerimiz" -------------------------------------- */
.nv-asla {
  /* max-width OLCULDU: sinirsizken 1280px'te kutu banner gibi uzuyor,
     uc kisa mono satir solda kaliyor ve sagda ~700px bos beyaz duruyordu.
     30rem = en uzun satirin ("veritabani baglantisi", ~310px) rahat sigdigi
     genislik; kutu banner degil kart olarak okunuyor. */
  max-width: 30rem;
  margin-top: var(--sp-8); border-radius: var(--r-lg); padding: var(--sp-8);
  border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--border));
  /* Hafif kirmizi tenti — .nv-kat--ust'un teal tentiyle ayni mantik.
     Duz --surface'te kutu acik temada bos beyaz bir dikdortgen gibi duruyordu. */
  background: color-mix(in srgb, var(--danger) 4%, var(--surface));
}
.nv-asla__k {
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em;
  text-transform: uppercase; color: var(--danger);
}
.nv-asla ul { list-style: none; margin: var(--sp-5) 0 0; padding: 0; display: grid; gap: var(--sp-4); }
.nv-asla li {
  font-family: var(--font-mono); font-size: var(--fs-body); color: var(--text-3);
  text-decoration: line-through; text-decoration-color: var(--danger); text-decoration-thickness: 2px;
}

/* ---- Rozet şeridi ------------------------------------------------- */
.nv-rozetler { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-6); }
.nv-rozet {
  display: inline-flex; align-items: center; padding: 8px 18px; border-radius: var(--r-pill);
  border: 1px solid var(--accent); color: var(--primary);
  font-family: var(--font-display); font-size: var(--fs-sm); font-weight: 500;
}

/* ---- Büyük sayı --------------------------------------------------- */
.nv-sayilar { display: flex; flex-wrap: wrap; gap: var(--sp-12); margin-top: var(--sp-8); align-items: flex-start; }
.nv-sayi__n {
  font-family: var(--font-mono); font-size: clamp(2.75rem, 7vw, 4.5rem); font-weight: 600;
  line-height: 1; color: var(--text); letter-spacing: -.03em;
}
.nv-sayi--vurgu .nv-sayi__n { color: var(--primary); }
.nv-sayi__k {
  margin-top: var(--sp-3); font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: .06em; text-transform: uppercase; color: var(--text-3);
}
.nv-kaynak { margin-top: var(--sp-8); font-size: var(--fs-sm); color: var(--text-3); line-height: var(--lh-body); }
.nv-kaynak a { color: var(--primary); }

/* Baslikta vurgu — LinkedIn kolateralinin dili: cumlenin ikinci yarisi
   teal. index.html'in .section-title'larinda .accent hic gecmiyor. */
.section-title .accent { color: var(--accent); }

/* ---- Dar okuma kolonu -------------------------------------------- */
.nv-dar { max-width: 62ch; }

/* ---- Mobil ------------------------------------------------------- */
@media (max-width: 780px) {
  .nv-formlar { grid-template-columns: 1fr; }
  .nv-carp { justify-self: center; width: 54px; height: 54px; }
  .nv-carp svg { width: 26px; height: 26px; }
  .nv-sayilar { gap: var(--sp-8); }
  .nv-asla { padding: var(--sp-6); }
  .nv-kat { padding: var(--sp-5) var(--sp-6); }
  .nv-vurgu { padding: var(--sp-4) var(--sp-5); gap: var(--sp-2); }
  .nv-vurgu .spark { margin-top: 7px; }
}

/* Bölüm içi boşluk yardımcıları — navena.html'de satır içi style yerine.
   Satır içi style bir gün CSP eklenirse (runbook: "CSP ekleme, gerekirse ayrı
   iş olarak") style-src'ye takılmasın diye sınıfa çevrildi. */
.nv-bosluk   { margin-top: var(--sp-10); }
.nv-bosluk-s { margin-top: var(--sp-6); }
