/* ============================================================================
   T-spektral-insa · hareket.css  —  sahne durumları + imza öğe stilleri
   YÖN: DOLU-DOYGUN + NET + ASİMETRİK, kutusuz (madde 14+15+18+19); hero'da
   realistik "kurulan ekran" (m22/25); tam-ekran işlenmiş geçiş (m23/25).
   ----------------------------------------------------------------------------
   PIN YERİNE CSS STICKY (mühendislik): "tam-ekran işlenmiş geçiş" = position:
   sticky (.sahne-sabit, 100vh) + ScrollTrigger SCRUB (pin YOK) → pin-spacer
   CLS'i YOK. Yapı:
     <section data-sahne> (overflow:visible)
       <div class="sahne-uzun"> (scrub mesafesi — SADECE js-anim'de uzar)
         <div class="sahne-sabit"> (sticky;top:0;100vh;overflow:clip)
   sahne-uzun yüksekliği js-anim'e KİLİTLİ → no-js/reduced'da temiz 100vh blok
   (taşma/boş sticky yok — madde 25a).
   ----------------------------------------------------------------------------
   İLERİCİ GELİŞTİRME: VARSAYILAN (js yok)=SON/KURULMUŞ durum (dolu-renk,
   ölçülebilir → duman & no-js güvenli). `.js-anim`→ham/gizli başlangıç (intro);
   `.wght-kuruldu`/`.cizildi` TEK-SEFER CSS geçişi (CLS-güvenli). reduced-motion
   → `.js-reduced`: son kare (kurulmuş, dolu-doygun) kalır. 16c: metin gizli kalmaz.
   BAĞIMLILIK: tokenlar.css + tokenlar-ek.css.
   ============================================================================ */

[data-sahne] { position:relative; overflow:clip; isolation:isolate; }
[data-sahne]:has(.sahne-uzun) { overflow:visible; display:block; min-height:0; }
/* ── VİEWPORT BİRİMİ: svh, vh DEĞİL ──────────────────────────────────────────
   `vh` mobil tarayıcıda adres çubuğu GİZLİYKENki (en büyük) alanı ölçer. Sayfa
   açılırken çubuk görünür olduğu için gerçek alan ~%13 daha kısadır → 100vh'lik
   yapışkan sahne ekrandan taşar ve `overflow:clip` taşan kısmı KIRPAR: dikey
   ortalanmış içerik olması gerekenden aşağıda durur, altı kesilir.
   `svh` = adres çubuğu GÖRÜNÜRKENki (en küçük) alan. Bedeli: çubuk gizlenince
   sahne ekrandan ~%13 kısa kalır — ama .sahne-sabit'in kendi arka planı YOK,
   boşlukta sitenin sürekli zemini görünür, fark edilmez. Kırpma ise görünür.
   `dvh` DEĞİL: her kaydırmada değer değişir, scrub sahnesinin ortasında yeniden
   yerleşim/zıplama üretir. Masaüstünde üçü de aynı sayıdır (etki yok).
   ⚠ 220vh/720vh/1229vh SCRUB YOLU uzunluklarıdır, yükseklik değil — birimleri
   değişirse tüm sahnelerin temposu değişir. ONLARA DOKUNMA. */
.sahne-uzun  { position:relative; height:100svh; }
:root.js-anim:not(.js-reduced) .sahne-uzun { height:220vh; }   /* scrub mesafesi (m25a) */
@media (prefers-reduced-motion: reduce) { .sahne-uzun { height:auto !important; } }
.sahne-sabit { position:sticky; top:0; min-height:100svh; overflow:clip; isolation:isolate;
  display:flex; align-items:center; }
@supports not (height: 100svh) {
  .sahne-uzun  { height:100vh; }
  .sahne-sabit { min-height:100vh; }
}

/* Sticky ofset düzeltmesi (opak header'ın altına hizalama) dosyanın SONUNDA,
   "STICKY OFSET" başlığı altında — sahnelerin kendi ezmelerinden sonra gelmesi
   gerekiyor (aynı özgüllükte kaynak sırası kazanır). */

:root { --tel-kalinlik: 13; --isin-kalinlik: 5; }

/* ── İMZA ÖĞELERİ — dolgun + ağır glow ────────────────────────────────────── */

/* ── HERO: realistik "KURULAN EKRAN" (m19/22/25) — foto, GÖRÜNÜR/luminöz (25b) ─
   .kurulan-foto: gerçek ekran/arayüz fotosu, spektral çerçeve glow + hafif
   parlaklık → karanlık kalmaz, "aktif ekran" gibi okunur. Kutusuz his: glow
   zemine karışır. Alternatif soyut bantlar (.kurulan-ekran/.ekran-bant) korunur
   (foto yoksa fallback). */

.kurulan-foto {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--isin-beyaz) 24%, transparent),
    0 30px 90px -34px color-mix(in srgb, var(--hue-6-ink) 50%, transparent),
    0 0 64px -8px  color-mix(in srgb, var(--hue-7-ink) 34%, transparent);
}
.kurulan-foto img { filter: brightness(1.1) contrast(1.05) saturate(1.06); }
/* hero fotosunda alt-karartmayı hafiflet (25b: görünür kalsın) */


/* Soyut fallback bantlar (opsiyonel) */
.kurulan-ekran {
  position:absolute; top:50%; right:4%; transform:translateY(-50%);
  width:min(44vw, 600px); aspect-ratio:16/11;
  display:grid; grid-template-rows: 0.5fr 2.1fr 1.2fr 0.5fr; gap:2.6%; z-index:0; pointer-events:none;
}

/* ── surec-akis — TAM-EKRAN ardışık akış (sticky + scrub; hareket.js) ──────────
   MOTION durumu: sahne-uzun uzar (≈adım×100vh), sahne-sabit sticky 100vh, adımlar
   TEK merkez hücrede TAM üst üste (grid-area:1/1, place-items:center) — yalnız
   transform/opacity oynar. Gizli adım autoAlpha ile visibility:hidden (JS) →
   OKUNMAZ + a11y/tab dışı + pointer-events yok. Başlangıçta yalnız 1. adım. */
/* Bölümün global `section { padding-block: var(--s-8) }` payı bu sahnede SIFIR.
   O 128px, sticky sahneyi akışta 128px AŞAĞI itiyordu: yapışmadan önce kutu
   [197px, …], yapıştıktan sonra [69px, …] oluyor ve yazı açılışta tam 128px
   aşağıda duruyordu (her ekran boyutunda birebir 128 — sabit px olduğu için).
   Sahne tam ekran; kenar payına zaten ihtiyacı yok.
   Sadece animasyonlu modda: JS'siz/reduced-motion'da adımlar okunur dikey yığın,
   orada bölüm payı korunmalı. */
:root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir { padding-block: 0; }
:root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir .sahne-uzun { height: 720vh; }
/* svh gerekçesi için yukarıdaki "VİEWPORT BİRİMİ" notuna bak. Bu kural genel
   .sahne-sabit'i EZDİĞİ için birimi burada da çevrilmeli, yoksa surec.html
   düzeltmenin dışında kalırdı (720vh scrub YOLU'na dokunulmuyor). */
/* ⚠ SAHNE KUTUSU HER İKİ DURUMDA DA AYNI OLMALI — yoksa açılışta yazı aşağıda durur.
   Eskiden `top:0; height:100svh` idi. Sticky öğe HENÜZ YAPIŞMAMIŞKEN kendi akış
   konumunda durur; bu sahne header'dan sonra geldiği için o konum y=69px. Yani:
     kaydırmadan önce → kutu [69px, 69px+100svh]  (altı ekran DIŞINDA)
     yapıştıktan sonra → kutu [0, 100svh]
   Ortalama kutuya göre yapıldığından sayfa ilk açıldığında yazı ~100px aşağıda
   duruyor, kullanıcı kaydırıp sahne yapışınca ortaya sıçrıyordu.
   ÇÖZÜM: kutuyu header'ın ALTINA sabitle ve yüksekliğinden header'ı düş →
   iki durumda da tam olarak [header altı, ekran altı] = görünür alan.
   Böylece .akis-adimlar'ın ayrıca padding-top'u da gerekmiyor. */
:root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir .sahne-sabit {
  position: sticky; top: var(--ust-h, 69px);
  height: calc(100svh - var(--ust-h, 69px)); min-height: calc(100svh - var(--ust-h, 69px));
  overflow: clip; }
@supports not (height: 100svh) {
  :root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir .sahne-sabit {
    height: calc(100vh - var(--ust-h, 69px)); min-height: calc(100vh - var(--ust-h, 69px)); }
}
:root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir .akis-adimlar {
  position: absolute; inset: 0; z-index: 1; display: grid; place-items: center;
  /* TAM ORTALAMA — padding YOK. Sahne kutusu (yukarıda) zaten tam olarak görünür
     alana denk geliyor, place-items:center orada gerçekten ortalar. Buraya
     padding-top eklenirse header İKİ KEZ sayılır ve yazı aşağı kayar. */
  padding: 0; gap: 0; }
/* FAIL-SAFE: adım METNİNİ gizleyen kural `.akis-hazir`e bağlı — hareket.js bu
   sınıfı sahne (G.set + timeline) SORUNSUZ kurulduktan sonra ekler, hata hâlinde
   geri alır. Sahne kurulamazsa 7 adımın hepsi akışta ve okunur kalır.
   (Önceden yalnız .js-anim'e bağlıydı; lazy() hatayı yuttuğu için sahne patlasa
   bile js-anim düşmüyor → 1. adım dışındaki 6 adım kalıcı kayboluyordu.) */
:root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir .akis-adim {
  grid-area: 1 / 1; width: min(100%, 900px); margin-inline: auto;
  padding-inline: var(--gutter); opacity: 0; visibility: hidden; pointer-events: none;
  will-change: transform, opacity; }
:root.js-anim:not(.js-reduced) [data-sahne="surec-akis"].akis-hazir .akis-adim:first-child { opacity: 1; visibility: visible; }

/* ── slogan-akis — harf harf bindirmeli aydınlanma (sticky + scrub) ──────────
   Scrub yolu: 1229vh — iki cümle + aralarındaki geçiş + ZOOM DEVRİ için.
   935 → 1028 → 1114 → 1229: zoom fazı adım adım yavaşlatıldı
   (hareket.js ZSURE 21 → 34 → 46 → 62).
   İKİSİ BİRLİKTE
   değişir; yalnız biri değişirse birim başına düşen mesafe (7.19vh) kayar ve
   cümlelerin parlama temposu da farklılaşır.
   Sticky 100vh olduğu için sahne ~835vh boyunca ekranda sabit kalır; harf başına ~6vh (tek cümlelik
   340vh temposuyla AYNI, ikinci cümle eklenince yol orantılı büyütüldü).
   TEMPO KOLU BURASI: bu yükseklik aydınlanmanın hızını belirler (uzun = yavaş).
   Timeline sürelerini değiştirme — onlar ritmi (giriş/bindirme/tutuş) kurar,
   hızı değil; scrub oranı zaten yola göre normalize eder.

   SÖNÜK BAŞLANGIÇ `.slogan-hazir`e BAĞLI — hareket.js bu sınıfı yalnız bölme +
   ScrollTrigger kurulumu SORUNSUZ bittiğinde ekler, hata olursa geri alır.
   Yani JS yoksa/patlarsa cümle tam kontrastta okunur kalır; asla sönük takılmaz.
   (Aynı fail-safe sözleşmesi .akis-hazir ve .split-hazir'da da var.) */
/* İki cümle TEK hücrede üst üste → geçişte layout kaymaz, sadece opaklık oynar. */
:root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .slogan-in { gap: 0; }
:root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .slogan { grid-area: 1 / 1; align-self: center; }
:root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .sahne-uzun { height: 1229vh; }
:root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .slogan-harf { opacity: .18; }

/* Zoom devri katmanları YALNIZ sahne kurulduğunda var olur. .sahne-sabit
   overflow:clip olduğu için ikisi de viewport'a kırpılır. */
:root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .slogan-beyaz {
  display: block; position: absolute; inset: 0; background: var(--paper);
  z-index: 3; opacity: 0; pointer-events: none;
}
/* Beyaz oturduktan SONRA yerinde beliren metin. Beyaz panelin (z-index 3) üstünde
   durur; zemini kendinde olduğu için panelle arasında sınır görünmez.
   Görünürlüğü GSAP autoAlpha'ya bırakılmıştır (opacity + visibility): görünmezken
   visibility:hidden olur, yani içindeki bağlantılar KLAVYEYLE de odaklanılamaz.
   Buraya opacity YAZMA — başlangıç değerini JS kuruyor; ikisi birden yazılırsa
   kurulum patladığında blok görünmez kalır (fail-safe sözleşmesi). */
:root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .gorunur-in {
  position: absolute; inset: 0; z-index: 4;
  padding-block: 0; display: grid; align-content: center;
}
/* ⚠ .slogan'a will-change KOYMUYORUZ — BİLEREK. Kalıcı will-change:transform
   öğeyi doğal boyutunda tek bir bitmap'e promote edip sonra o bitmap'i geriyor;
   cümle 14× büyüyünce görünür şekilde pikselleşiyordu. will-change'siz tarayıcı
   ölçek değiştikçe yeniden raster'lıyor. Cümle zaten bu fazda sönüyor, ekstra
   paint maliyeti kısa; net görüntü buna değer. */

/* ── hs-yatay — HAZIR SİTELER: dikey scroll → YATAY ray kayması (sticky+scrub) ──
   VARSAYILAN her koşulda native yatay kaydırmadır (temel.css .hs-ray). Bu blok
   yalnız hareket.js `.hs-scrub` ekleyince (geniş ekran + pointer:fine + js-anim)
   devreye girer: ray max-content genişliğe açılır, native kaydırma/snap kapanır,
   scroll pozisyonu translateX'e bağlanır. PIN YOK — sticky + scrub.
   .sahne-uzun yüksekliği = 100vh + yatay yol (--hs-yol, JS ölçer) → sahne tam
   yol boyunca ekranda kalır, sonra sayfa normal akışına devam eder. */
[data-sahne="hs-yatay"] .sahne-sabit {
  flex-direction: column; align-items: stretch; justify-content: center; gap: var(--s-4);
}
/* Genel 220vh scrub kuralını EZ: bu sahnenin yolu ölçülene kadar tek ekran.
   Buradaki 100svh EKRAN payıdır (yol değil) — var(--hs-yol) yatay mesafeyi ayrıca
   ekler, ona dokunulmuyor. Kap ile sticky çocuk aynı birimde olmalı: biri vh biri
   svh kalsaydı aralarında ~%13'lük bir fark doğar, sahne yolun sonunda erken
   bırakırdı. */
:root.js-anim:not(.js-reduced) [data-sahne="hs-yatay"] .sahne-uzun { height: 100svh; }
:root.js-anim:not(.js-reduced) [data-sahne="hs-yatay"].hs-scrub .sahne-uzun {
  height: calc(100svh + var(--hs-yol, 0px)); }
@supports not (height: 100svh) {
  :root.js-anim:not(.js-reduced) [data-sahne="hs-yatay"] .sahne-uzun { height: 100vh; }
  :root.js-anim:not(.js-reduced) [data-sahne="hs-yatay"].hs-scrub .sahne-uzun {
    height: calc(100vh + var(--hs-yol, 0px)); }
}
.hs-scrub .hs-ray {
  width: max-content; max-width: none; align-self: start;
  overflow: visible; scroll-snap-type: none; will-change: transform;
}
/* İnce yatay ilerleme çubuğu — yalnız scrub modunda anlamlı */
.hs-ilerleme { display: none; }
.hs-scrub .hs-ilerleme {
  display: block; height: 2px; margin-inline: var(--gutter); border-radius: 2px;
  background: color-mix(in srgb, var(--murekkep) 14%, transparent); overflow: hidden;
}
.hs-ilerleme i { display: block; height: 100%; background: var(--murekkep);
  transform: scaleX(var(--p, 0)); transform-origin: left center; }


/* ── bloom-kapanis — dolgun 9 parça (net tek-hue) ─────────────────────────── */
[data-sahne="bloom-kapanis"] .bloom-parca {
  --bk: var(--cz-renk, var(--hue-5-ink)); background:var(--bk);
  box-shadow:0 0 28px color-mix(in srgb, var(--bk) 72%, transparent),
             0 0 12px color-mix(in srgb, var(--bk) 88%, transparent);
}
:root.js-anim:not(.js-reduced) [data-sahne="bloom-kapanis"] .bloom-parca {
  background:var(--isin-beyaz); box-shadow:0 0 16px color-mix(in srgb, var(--isin-beyaz) 70%, transparent);
}

/* ── TİPOGRAFİ AĞIRLIĞI — ham(300)→kurulmuş(700), TEK-SEFER geçiş ───────────── */
[data-wght-gecis] {
  font-variation-settings:"wght" var(--w-kurulmus); font-weight:var(--w-kurulmus);
  transition:font-variation-settings var(--wght-tween) var(--ease-cikis),
             font-weight var(--wght-tween) var(--ease-cikis);
}
:root.js-anim:not(.js-reduced) [data-wght-gecis] {
  font-variation-settings:"wght" var(--w-ham); font-weight:var(--w-ham);   /* GÖRÜNÜR, ince (16c) */
}
:root.js-anim:not(.js-reduced) .wght-kuruldu [data-wght-gecis],
:root.js-anim:not(.js-reduced) [data-wght-gecis].wght-kuruldu {
  font-variation-settings:"wght" var(--w-kurulmus); font-weight:var(--w-kurulmus);
}

/* ── SAKİN AKIŞ REVEAL · [data-reveal-akis] ───────────────────────────────────
   B1 (animasyon hiyerarşisi): uzun paragrafların SATIR SATIR açılması okumayı
   yoruyordu. Yerine TEK TİP, sakin, ÖĞE bazında fade-up: split yok, GSAP yok,
   yalnız opacity+transform (temel.js IntersectionObserver → .goruldu).
   JS-off / reduced-motion: hiç gizlenmez, tam ve statik okunur.
   ---------------------------------------------------------------------------
   FAIL-SAFE SÖZLEŞMESİ (bug sonrası): gizleme `.reveal-hazir`e BAĞLI. O sınıfı
   temel.js, IntersectionObserver'ı BAŞARIYLA kurduktan SONRA ekler. Yani "gizle"
   kararının sahibi JS'tir: JS yoksa, patlarsa, eski sürümü cache'ten gelirse ya da
   observer kurulamazsa sınıf hiç eklenmez → metin HİÇBİR ZAMAN gizlenmez.
   (Eskiden tersiydi: CSS gizler, JS açardı → JS aksarsa metin kalıcı kayboluyordu.) */
:root.js-anim:not(.js-reduced) [data-reveal-akis].reveal-hazir > * {
  opacity: 0; transform: translateY(16px);
  transition: opacity var(--sure-reveal) var(--ease-cikis),
              transform var(--sure-reveal) var(--ease-cikis);
}
:root.js-anim:not(.js-reduced) [data-reveal-akis].reveal-hazir > .goruldu { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  :root.js-anim [data-reveal-akis] > * { opacity: 1; transform: none; transition: none; }
}

/* ── LENIS — yumuşak scroll taban kuralları (lenis.css 1.3.25 birebir) ────────
   Sınıfları Lenis kendisi <html>'e ekler; script yüklü değilse hiçbiri eşleşmez. */
html.lenis, html.lenis body { height:auto; }
/* NOT: Lenis'in önerdiği `.lenis-stopped { overflow:clip }` BİLEREK kaldırıldı.
   Safari'de <html>'de overflow:clip, position:sticky header'ın tıklama alanını
   bozuyordu → deck kilitliyken sekmelere "girilemiyor"du. Deck zaten Observer
   (wheel/touch preventDefault) + klavye engeliyle kaydırmayı durduruyor; clip'e
   gerek yok. Başka yerde lenis.stop() kullanılmıyor. */
.lenis [data-lenis-prevent],
.lenis [data-lenis-prevent-wheel],
.lenis [data-lenis-prevent-touch],
.lenis [data-lenis-prevent-vertical],
.lenis [data-lenis-prevent-horizontal] { overscroll-behavior:contain; }
.lenis.lenis-smooth iframe { pointer-events:none; }
.lenis.lenis-autoToggle { transition-property:overflow; transition-duration:1ms; transition-behavior:allow-discrete; }

/* ── SPLIT-TEXT — SplitText maskeli satır/harf reveal ([data-split]) ─────────── */
/* Bölme fonts.ready sonrası; o ana kadar gizli → yanlış satır kırılmasıyla
   yanıp sönme olmaz. JS yoksa/SplitText yüklenmezse .split-hazir hemen eklenir,
   hata olursa .js-anim düşer → her iki durumda da metin görünür kalır. */
/* FAIL-SAFE: gizleme kökteki `.split-motoru`ya bağlı — hareket.js bu sınıfı,
   SplitText'in varlığını doğrulayıp bölmeye başlamadan HEMEN ÖNCE ekler. Motor
   hiç kurulmazsa (GSAP/SplitText yüklenmedi, hata, eski cache) sınıf gelmez →
   metin hiçbir zaman gizlenmez. Ayrıca temel.js watchdog'u 1.5s sonra hâlâ
   `.split-hazir` almamış öğeleri zorla açar. */
:root.js-anim.split-motoru:not(.js-reduced) [data-split]:not(.split-hazir) { visibility:hidden; }
/* Parçalar inline-block; varsayılan baseline hizası satır kutusuna fazladan iniş
   boşluğu ekler (112px h1'de satır başına ~16px, 4 satırda 64px uzama). top hizası
   → satır yüksekliği ve sarma bölünmemiş metinle BİREBİR aynı kalır. */
[data-split] .spsatir, [data-split] .spkelime, [data-split] .spharf,
[data-split] [class$="-mask"] { vertical-align:top; }
/* KRİTİK: harfler ayrı inline-block kutular olduğu için tarayıcı kelime ORTASINDAN
   satır kırabiliyor (dar kapsayıcıda "Hızl / ıyız" gibi). Kelime kutusu kırılmaz. */
[data-split] .spkelime { white-space:nowrap; }
/* Dar line-height'lı başlıkta (h1 .98) SplitText maskesinin overflow:clip'i
   harfin taşan kısmını kesmesin. Eskiden yalnız ALT dolgu vardı (ğ/ş/y kuyruğu
   için); üst taraf açıkta kalıyordu → İ'nin noktası, Ğ'nin şapkası, Ü/Ö'nün
   noktaları kesiliyordu. Artık iki yön de dolgulu.
   NOT: bu maskenin kırpması AYRI bir mekanizma — gradyan kutusu onarımı
   tayf-tipografi.css'te. İkisi birlikte gerekiyor.
   YALNIZ harf maskesinde: satır maskesi blok seviyesinde, dolgu paragrafı uzatır. */
[data-split] .spharf-mask { padding-block:.18em; margin-block:-.18em; }
/* SATIR maskesinde aynı çare — GENELE DEĞİL, tek öğeye. Yukarıdaki not "satır
   maskesi blok seviyesinde, dolgu paragrafı uzatır" diyor; negatif margin dolguyu
   birebir geri aldığı için uzatmıyor, o yüzden dar line-height'lı TEK bir satırda
   güvenle kullanılabiliyor. Gerekçe: seo.html'deki "İlk yıl ücrete dahil."
   (.seo-vurgu) line-height:1 taşıyor — sayfadaki en sıkı satır kutusu, diğer split
   başlıklar 1.02-1.08'de. Bu kadar sıkı kutuda font'un üst taşması maskeyle
   kesiliyor ve İ'nin noktası yarım görünüyordu. Maskeyi kapatmak (data-split-maske)
   da çözerdi ama reveal'in kırpma karakterini kaybettirirdi; dolgu ikisini birden
   korur. Başka bir öğede aynı belirti görülürse buraya seçici EKLE, kuralı
   [data-split] geneline açma — geniş açmak her paragrafın satır kutusunu büyütür. */
.seo-vurgu .spsatir-mask { padding-block:.18em; margin-block:-.18em; }

/* ── MİKRO — hover pulse (dolgun spektral halka) · odak ─────────────────────── */
.tayf-hover { position:relative; }
.tayf-hover::after {
  content:""; position:absolute; inset:-4px; border-radius:inherit;
  border:2.5px solid transparent; pointer-events:none;
  transition:border-color var(--hover-puls) var(--ease-mikro),
             box-shadow var(--hover-puls) var(--ease-mikro),
             transform var(--hover-puls) var(--ease-mikro);
}
@media (prefers-reduced-motion: no-preference) {
  .tayf-hover:hover::after, .tayf-hover:focus-visible::after {
    border-color:color-mix(in srgb, var(--cz-renk, var(--hue-6-ink)) 90%, transparent);
    box-shadow:0 0 24px color-mix(in srgb, var(--cz-renk, var(--hue-6-ink)) 55%, transparent);
    transform:scale(1.02);
  }
}
@media (prefers-reduced-motion: reduce) {
  .tayf-hover:hover::after, .tayf-hover:focus-visible::after {
    border-color:color-mix(in srgb, var(--cz-renk, var(--hue-6-ink)) 90%, transparent);
  }
}
:where(a,button,[tabindex],input,textarea,select):focus-visible {
  outline:2px solid color-mix(in srgb, var(--hue-6-ink) 90%, transparent); outline-offset:2px;
}

/* ── Bölüm ayracı — DrawSVG refraksiyon (tek net hue) ─────────────────────── */
.tayf-ayrac { display:block; width:100%; height:8px; overflow:visible; }

/* ── nav aktif alt-çizgi = NET bantlı spektrum ─────────────────────────────── */

/* ═══════════════════════════════════════════════════════════════════════════
   INDEX-SCOPED REVİZYON (m30/31/32/33 + EK) — yalnız <body.sayfa-index> altında.
   Paylaşılan hareket.css'i diğer 5 sayfada BOZMADAN index'e özgü override.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── m30/EK · HERO "Işıktan Kurulan Ekran" — kompozisyon, kutusuz, entegre ──── */


/* çubuklar yazının/ekranın ARKASINDA */
.sayfa-index .hero-copy { position: relative; z-index: 3; isolation: isolate; }

/* SCRIM KUTUSU YOK (m30): yazı, koyu tabana + feather-glow (KUTU DEĞİL, kenarsız radial)
   + text-shadow ile okunur — "tasarım hilesi", dikdörtgen scrim değil. */
.sayfa-index .hero-copy::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  inset: -14% -26% -14% -34%;
  background: radial-gradient(58% 68% at 24% 46%,
    color-mix(in srgb, var(--ink) 78%, transparent) 0%,
    color-mix(in srgb, var(--ink) 40%, transparent) 52%,
    transparent 78%);
}
.sayfa-index .hero-copy .hero-display,
.sayfa-index .hero-copy .lead { text-shadow: 0 2px 26px rgba(0,0,0,.72), 0 1px 4px rgba(0,0,0,.6); }
.sayfa-index .hero-copy .eyebrow { text-shadow: 0 1px 12px rgba(0,0,0,.7); }

/* ── m34 · KELİME VURGUSU — beyaz→muted-ton metin gradyanı (SEÇİCİ/KONTROLLÜ) ──
   "beyaz ışık → renk" tezinin TİPOGRAFİYE taşınması: yalnız hero + "tek ışık"
   kilit "kurulmuş" kelimesinde (<b>). Ton: 9-hue ink'ten SEÇİLİ 1 muted, rafine.
   16c: bg-clip yoksa fallback SOLİD beyaz (tam okunur); AA korunur. */
.sayfa-index .hero-display b,
.sayfa-index .tek-isik .nefes-baslik b { color: var(--murekkep); }   /* FALLBACK — hep okunur */
/* ═══════════════════════════════════════════════════════════════════════════
   m31 + m35b · "DOKUZ PARÇA, TEK IŞIK" — CSS-güdümlü SONLU LED fanı.
   m35a: sıralı LED artık PUR CSS (rod çizim + LED pop + beyaz→spektrum renk
   geçişi = animation/transition, per-öğe --i gecikmesi). JS yalnız yaklaşınca
   `.tek-isik-basla` ekler. DrawSVG/GSAP timeline YOK → TBT'ye yük bindirmez.
   m35b YERLEŞİM: fan SAĞA, metin SOLA (koyu, sakin bölge) → rod yakınsama
   MERKEZİNDEN kaçar; başlık + alt satır ışıyan rod'ların üstünde KALMAZ.
   ═══════════════════════════════════════════════════════════════════════════ */

/* zamanlama değişkenleri (per-sahne) */
/* ── "TEK MUHATAP" · saf tipografi ────────────────────────────────────────
   Işık/huzme katmanı kaldırıldıktan sonra geriye yalnız söz kaldı: siyah
   zeminde ortalanmış beyaz başlık. Arkada karartma (scrim) da GEREKMİYOR —
   scrim ışığın parlaklığına karşı konmuştu; artık arkada yalnız yıldız zemini
   var ve metnin kendi text-shadow'u yetiyor.
   `--bas/--adim/--rod-sure/--renk-gecikme` zamanlama değişkenleri de silindi;
   yalnız kaldırılan animasyon kullanıyordu. */
.sayfa-index .tek-isik { text-align: center; }
.sayfa-index .tek-isik .nefes-in { z-index: 2; }
@media (min-width: 900px) {
  /* Buraya ch cinsinden bir max-width YAZMA: ch, KABIN font boyutuna göre
     hesaplanır (16px) — başlık --t-mega olduğu için kap başlıktan dar kalır ve
     taşan başlık ortalanmak yerine sağa kayar. .wrap'ın 1200'ü yeterli. */
  .sayfa-index .tek-isik .nefes-in {
    width: auto; margin-inline: auto; padding-inline: var(--gutter);
    justify-items: center; text-align: center; justify-self: center;
  }
}
.sayfa-index .tek-isik .nefes-baslik { text-shadow: 0 2px 16px rgba(0,0,0,.55); }
.sayfa-index .tek-isik .nefes-alt {
  text-shadow: 0 1px 12px rgba(0,0,0,.7);
  color: color-mix(in srgb, var(--murekkep) 88%, var(--zemin));
  max-width: 42ch; margin-inline: auto;
}

/* ── IŞIK/HUZME ANİMASYONU KALDIRILDI (2026-08-27) ────────────────────────
   9 maskeli SVG huzme + grup blur + mix-blend-mode + sürekli salınım/nefes
   animasyonları sayfada belirgin takılma yaratıyordu. Kök sebep: maske ve
   blend, animasyon compositor'da çalışsa bile katmanı her karede yeniden
   BİRLEŞTİRMEYE zorluyor — "transform/opacity ucuzdur" kuralı blur+mask+blend
   yığınının altında geçerliliğini yitiriyor.
   Bölüm artık saf tipografi. Tekrar denenecekse: maskesiz, blend'siz, statik
   tek katmanla başla; hareket eklemeden önce ölç. */


/* ── m32 · index'te glowing çizgi ayracı yok (HTML'den kaldırıldı); güvenlik gizle ── */
.sayfa-index .tayf-ayrac { display: none; }


/* ═══════════════════════════════════════════════════════════════════════════
   STICKY OFSET — yapışkan sahneleri opak header'ın ALTINA hizala (YALNIZ MOBİL)
   ───────────────────────────────────────────────────────────────────────────
   .sahne-sabit top:0'da yapışır, ama .site-header de top:0 · z-index:100 · TAM
   OPAK (backdrop-filter bilerek yok) → sahnenin üst ~69px'i header'ın ARKASINDA
   kalır. İçerik sahnenin KUTUSUNA göre ortalandığı için görünür alanın merkezine
   göre ~34px yukarıda durur; telefonda dikey bütçe darken üstteki içerik
   header'ın altına girip kesilir.

   top:0 KALIYOR — kabı kısaltmıyoruz. Sebep: position:fixed zemin katmanları
   (.spektrum-zemin · yildiz-zemin.css yıldızları) header'ın arkasına kesintisiz
   akmalı. Yalnız İÇERİK itiliyor. box-sizing:border-box global (temel.css:21)
   olduğu için padding yüksekliğe EKLENMEZ, içeriden yer açar → sahne taşmaz.

   ⚠ MUTLAK KONUMLU KATMANLAR AYRICA ELE ALINMALI: position:absolute + inset:0
   olan çocuk, atasının PADDING KUTUSUNA göre yerleşir — yani .sahne-sabit'e
   verilen padding-top onları İTMEZ. Bu yüzden .akis-adimlar ve .gorunur-in
   kendi padding-top'larını alıyor. .slogan-beyaz BİLEREK dışarıda: o, zoom
   devrini teslim alan TAM EKRAN beyaz katman; itilirse üstte bir şerit açılır
   ve "görünmez devir" sözleşmesi bozulur.

   --ust-h = header'ın ölçülen yüksekliği (temel.js yazar, 18/18 sayfada yüklü).
   Fallback 69px = .nav-in min-height 68px + 1px border.

   ≤1000px KAPSAMI BİLİNÇLİ: masaüstü kompozisyonu bu turda DEĞİŞMEYECEK
   (MOBILE_AUDIT.md Bölüm 7 · Soru 2 kararı). Masaüstündeki aynı ~34px
   hizasızlık bilerek yerinde bırakıldı.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1000px) {
  /* akış çocukları: .slogan-in (index) · .hs-ray + .hs-ilerleme (sablonlar) */
  .sahne-sabit { padding-top: var(--ust-h, 69px); }

  /* surec.html buradan ÇIKARILDI: padding-top artık taban kuralda (her genişlikte
     header altına göre ortalanıyor), burada tekrarlamaya gerek yok. */

  /* index.html — zoom'un teslim ettiği blok, aynı sebeple absolute/inset:0 */
  :root.js-anim:not(.js-reduced) [data-sahne="slogan-akis"].slogan-hazir .gorunur-in {
    padding-top: var(--ust-h, 69px); }
}
