/*
 * Hareket katmanı — mikro animasyonlar ve durum geçişleri.
 *
 * **Neden Framer Motion değil.** Framer Motion React'a özgü bir
 * kütüphane; bu ürünün yüzeyi sunucu tarafı HTML (ADR-0020). Onu
 * kullanmak React eklemek, o da tüm ön yüzü yeniden yazmak demek —
 * "mevcut mimariyi bozma" kuralının tam karşısı.
 *
 * Karşılığında istenen **etkiler** birebir veriliyor: scroll reveal,
 * fade, scale, hover, progress, skeleton, shimmer, sayaç. Hepsi CSS
 * geçişleri ve tek bir IntersectionObserver ile; toplam maliyet ~3 KB ve
 * ana iş parçacığını bloke eden hiçbir şey yok.
 *
 * **Hareket bir tercih, varsayılan değil.** `prefers-reduced-motion`
 * tanımlıysa tüm animasyonlar kapanıyor ve içerik son hâliyle
 * görünüyor. Vestibüler bozukluğu olan bir kullanıcı için kayan bir
 * arayüz baş dönmesi demek; WCAG 2.3.3 bunu tam olarak bu yüzden
 * istiyor. Kapatma "animasyonu hızlandır" değil **tamamen durdur**.
 */

:root {
  /* Süre ölçeği. Üç değer yeterli: bir arayüzde beşinci bir süre,
     tutarsızlık olarak hissedilir. */
  --t-fast: 120ms;
  --t-base: 260ms;
  --t-slow: 620ms;

  /* Yumuşama. `--ease` tasarım sisteminden geliyor; buradaki iki ek
     eğri farklı işler için: `--ease-out` girişler, `--ease-spring`
     vurgu gerektiren tek seferlik hareketler. */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);

  /* Scroll reveal'da elemanın kalkacağı mesafe. Küçük tutuldu:
     büyük mesafe "sayfa yükleniyor" hissi verir, oysa içerik hazır. */
  --reveal-shift: 14px;
}

/* --- Scroll reveal ------------------------------------------------------
 *
 * `data-reveal` taşıyan her eleman görünür alana girince açılıyor.
 * Başlangıç durumu CSS'te, tetikleme JS'te — JS yüklenmezse eleman
 * `.is-visible` almasa da `@media (scripting: none)` ile görünür
 * kalıyor. Yani JavaScript kapalıyken sayfa boş görünmüyor.
 */

[data-reveal] {
  opacity: 0;
  transform: translateY(var(--reveal-shift));
  transition:
    opacity var(--t-slow) var(--ease-out),
    transform var(--t-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}

[data-reveal].is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* JavaScript yoksa gizleme hiç başlamasın. */
@media (scripting: none) {
  [data-reveal] { opacity: 1; transform: none; }
}

/* Kademeli giriş: kardeşler sırayla açılıyor. Sıra numarasını JS veriyor
   (`--reveal-index`, CSSOM üzerinden — CSP satır içi stili yasakladığı
   için şablon bunu yazamaz, bkz. `scale.css`). */
[data-reveal-group] > * { --reveal-delay: calc(var(--reveal-index, 0) * 70ms); }

/* Elle sıralama: gruba girmeyen, sayfada tek tek yerleştirilen ögeler
   için. Dört basamak yetiyor; beşinciye ihtiyaç duyulduğu an o bölüm
   zaten bir gruptur. */
.delay-1 { --reveal-delay: 60ms; }
.delay-2 { --reveal-delay: 120ms; }
.delay-3 { --reveal-delay: 180ms; }
.delay-4 { --reveal-delay: 240ms; }

/* --- Hover ve basma -----------------------------------------------------
 *
 * `:hover` yalnızca gerçekten işaretçi olan cihazlarda. Dokunmatikte
 * hover "yapışıyor" ve kullanıcı kartın neden farklı göründüğünü
 * anlamıyor.
 */

@media (hover: hover) and (pointer: fine) {
  .lift {
    transition:
      transform var(--t-base) var(--ease-out),
      box-shadow var(--t-base) var(--ease-out),
      border-color var(--t-base) var(--ease-out);
  }

  .lift:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow);
    border-color: var(--border-strong);
  }
}

.press:active { transform: scale(.985); }

/* --- Skeleton ve shimmer ------------------------------------------------
 *
 * Yükleme durumunda dönen bir çark yerine içeriğin **iskeleti**
 * gösteriliyor: kullanıcı ne geleceğini görüyor ve sayfa yerleşimi
 * içerik gelince zıplamıyor (CLS = 0).
 */

.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--surface-2);
  border-radius: var(--r-sm);
  color: transparent;
  user-select: none;
}

.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in srgb, var(--surface) 70%, transparent),
    transparent
  );
  animation: shimmer 1.4s infinite;
}

@keyframes shimmer {
  100% { transform: translateX(100%); }
}

/* --- Progress / meter dolumu -------------------------------------------
 *
 * `.meter > i` genişliği tasarım sisteminde zaten geçişli. Burada
 * yalnızca **başlangıç** durumu veriliyor: reveal olmadan önce sıfır,
 * sonra hedefe akıyor.
 *
 * Hedef genişliğin kendisi `<i>` üzerindeki `.pct-N` sınıfından geliyor
 * (`scale.css`). Bu yüzden görünür duruma dair **hiçbir kural yok**:
 * `.is-visible` gelince aşağıdaki seçici eşleşmeyi bırakıyor ve sınıf
 * kendiliğinden devreye giriyor. Bir `!important` daha yazmak, o sınıfı
 * ezip her çubuğu aynı boyda gösterirdi.
 *
 * **Sıfırlama koşullu ve koşulun ikisi de zorunlu.** Animasyonu
 * başlatacak JavaScript yoksa veya kullanıcı hareket istemiyorsa çubuk
 * hiç sıfırlanmamalı — yoksa doğru sayının yanında boş bir çubuk kalır
 * ve bu, yanlış çubuktan daha kötüdür. `scripting`/`prefers-reduced-motion`
 * bilmeyen eski bir tarayıcı sorguyu tamamen ıskalar; o durumda da çubuk
 * hedefinde durur, yalnızca akmaz. Her yanlış cevap doğru tarafa düşüyor.
 */

@media (prefers-reduced-motion: no-preference) and (scripting: enabled) {
  [data-fill]:not(.is-visible) > i { width: 0 !important; }
}

/* --- Sayaç --------------------------------------------------------------
 *
 * Rakamlar `tabular-nums` ile sabit genişlikte: aksi hâlde sayarken
 * kutu titrer ve göz onu okuyamaz.
 */

[data-count] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* --- Demo oynatıcı ------------------------------------------------------ */

.demo-step {
  opacity: .35;
  transition: opacity var(--t-base) var(--ease-out);
}

.demo-step[data-state="active"] { opacity: 1; }
.demo-step[data-state="done"] { opacity: .8; }

.demo-stage > [data-panel] { display: none; }
.demo-stage > [data-panel].is-active { display: block; animation: panel-in var(--t-slow) var(--ease-out) both; }

/* JavaScript yoksa adımları sırayla oynatacak kimse yok — o hâlde
   hepsi birden görünmeli. `<noscript>` kutusu ziyaretçiye "sonucun
   tamamı aşağıda" diyor; bu kural o cümleyi doğru kılan şey. */
@media (scripting: none) {
  .demo-stage > [data-panel] { display: block; }
  .demo-stage > [data-panel] + [data-panel] { margin-top: var(--s5); }
}

/* Aynı gerekçe hareketi azaltan kullanıcı için de geçerli; sınıfı
   `motion.js` koyuyor. */
.demo-static .demo-stage > [data-panel] { display: block; }
.demo-static .demo-stage > [data-panel] + [data-panel] { margin-top: var(--s5); }

@keyframes panel-in {
  from { opacity: 0; transform: translateY(10px) scale(.995); }
  to   { opacity: 1; transform: none; }
}

/* Yükleme çubuğu — belirsiz değil **belirli**: gerçek adım sayısına
   göre ilerliyor. Belirsiz bir çubuk "ne kadar sürecek" sorusunu
   cevapsız bırakır. */
.demo-progress { height: 3px; background: var(--surface-3); border-radius: 2px; overflow: hidden; }
.demo-progress > i {
  display: block; height: 100%; width: 0;
  background: var(--accent); border-radius: 2px;
  transition: width var(--t-slow) var(--ease-out);
}

/* --- Erişilebilirlik: hareketi kapat ------------------------------------
 *
 * Tek bir blok, istisnasız. "Şu animasyon zararsız" istisnası, kuralın
 * anlamını yok eder.
 */

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

  [data-reveal] { opacity: 1; transform: none; }
  /* Çubuk sıfırlaması zaten `no-preference` altında; burada iptal
     edilecek bir şey yok. */
  .skeleton::after { display: none; }
  .lift:hover { transform: none; }
}
