/* ============================================================================
   components.css — komponent sözlüğü
   Onaylanan B×C yönünün somut karşılıkları. tokens.css + base.css'ten sonra.

   Her komponent yalnızca token okur. Hex literal yok.
   ============================================================================ */

/* ── Eyebrow / mono etiket ───────────────────────────────────────────────
   Sitenin en karakteristik tipografik öğesi: VERSAL mono, geniş harf
   aralığı. Bölüm etiketi, meta satırı, tablo başlığı — hepsi bu. */

.eyebrow {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-3);
}

.eyebrow--accent {
    color: var(--accent);
}

.meta {
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--ls-meta);
    color: var(--text-3);
}

/* ── Bölüm başlığı ──────────────────────────────────────────────────────
   [02] Yazılar ──────────────────────────── tümü →
   İndeks numarası ELLE yazılmaz; sayfa sırasına göre üretilir, böylece
   bir bölüm gizlendiğinde numaralandırma yalan söylemez (eski sitedeki
   01,02,03,04,05,07,08,09 hatası). */

.section-head {
    display: flex;
    align-items: center;
    gap: var(--sp-5);
    padding-top: var(--sp-22);
}

.section-head__index {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    color: var(--accent);
}

.section-head__title {
    font-size: var(--fs-h2);
    line-height: var(--lh-heading);
    letter-spacing: var(--ls-h2);
    font-weight: 500;
    color: var(--text-1);
}

.section-head__rule {
    flex-grow: 1;
    height: 1px;
    background: var(--line);
}

.section-head__link {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--accent);
}

/* ── Sol oluk işaretleri ────────────────────────────────────────────────
   "Ölçüm çıktısı" dilinin imzası: içeriğin solunda, bölümü işaretleyen
   cetvel çizgileri. Dekoratif → aria-hidden. */

.gutter-marks {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding-top: var(--sp-3);
}

.gutter-marks__num {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-label);
    color: var(--text-3);
}

.gutter-marks__tick {
    height: 1px;
    background: var(--line);
}

.gutter-marks__tick--major {
    background: var(--border-strong);
}

/* ── Kart ───────────────────────────────────────────────────────────────
   Melez yönün kalbi: B'nin kenarlı kutusu + C'nin üst kenar ışığı ve
   sıcak gölgesi. backdrop-filter YOK — derinlik ışıktan geliyor. */

.card {
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-top-color: var(--rim);
    border-radius: var(--r);
    box-shadow: var(--shadow-2);
    overflow: hidden;
    transition: border-color var(--dur) var(--ease),
                box-shadow var(--dur) var(--ease);
}

.card--flat {
    background: var(--surface-1);
    box-shadow: var(--shadow-1);
}

/* Kart geri bildirimi TEK seçiciden: imleç ya da klavye, ışık aynı şekilde
   değişir. Kartların çoğu <article> ve odağı İÇİNDEKİ bağlantı alıyor;
   /yonetim'de ise kartın kendisi <a class="card card--interactive">, orada
   :focus-visible doğrudan tutuyor — bu yüzden üç dal birden gerekiyor.
   :is() BAĞIŞLAYICI bir liste: :has()'ı tanımayan tarayıcı (Chrome 105
   öncesi) yalnızca o dalı atar, :hover ve :focus-visible çalışmaya devam
   eder. Düz bir seçici listesine yazılsaydı kuralın TAMAMI düşerdi.
   Özgüllük değişmedi: :is() en özgül argümanının değerini alır → (0,2,0). */
a.card:hover,
.card--interactive:is(:hover, :focus-visible, :has(:focus-visible)) {
    border-color: var(--border-strong);
    border-top-color: var(--rim-strong);
    box-shadow: var(--shadow-3);
}

/* Kartın gövdesi de başlıktaki bağlantıya gidiyorsa imleç bunu söylesin.
   Sınıfı hareket.js ekliyor (tiklanabilirKart): JS yüklenmezse gövde
   tıklaması da yok, o zaman yalancı bir imleç de olmamalı. Başlık
   bağlantısı her koşulda çalışır — bu sınıf yalnızca KISAYOLUN varlığını
   bildirir. */
.card--bagli {
    cursor: pointer;
}

/* Kart üst şeridi: [01] ————— 2026-03-12 · 8 dk */
.card__strip {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--line);
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-3);
}

.card__index {
    color: var(--accent);
}

.card__body {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-5);
    flex-grow: 1;
}

.card__title {
    font-size: var(--fs-h4);
    line-height: var(--lh-snug);
    letter-spacing: var(--ls-h4);
    font-weight: 500;
    color: var(--text-1);
}

.card__text {
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    color: var(--text-2);
    flex-grow: 1;
}

/* Kart görsel alanı — boşken bile ışık alır, düz gri kutu değil. */
.card__media {
    aspect-ratio: 16 / 9;
    background: var(--surface-1);
    background-image: radial-gradient(40vmax 30vmax at 30% 0%,
        rgba(232, 162, 74, 0.07) 0%, transparent 70%);
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ── Buton ──────────────────────────────────────────────────────────────
   min-height 44px — dokunma hedefi tabanı, mobilde de masaüstünde de. */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    min-height: var(--hit-min);
    padding: var(--sp-3) var(--sp-5);
    border-radius: var(--r);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    border: 1px solid transparent;
    transition: background-color var(--dur) var(--ease),
                border-color var(--dur) var(--ease),
                box-shadow var(--dur) var(--ease);
}

.btn--primary {
    background: var(--accent);
    color: var(--accent-ink);
    box-shadow: var(--glow-accent);
}

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

.btn--secondary {
    border-color: var(--border-strong);
    color: var(--text-1);
}

.btn--secondary:hover {
    border-color: var(--accent);
    color: var(--text-1);
}

.btn--ghost {
    border-color: var(--border);
    color: var(--text-2);
}

.btn--ghost:hover {
    border-color: var(--border-strong);
    color: var(--text-1);
}

.btn--danger {
    border-color: var(--danger-line);
    color: var(--danger);
}

.btn:disabled,
.btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    box-shadow: none;
}

/* ── Etiket / rozet ─────────────────────────────────────────────────── */

.tag {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: 0.04em;
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: var(--r-sm);
    padding: var(--sp-1) var(--sp-2);
}

.tag--outline {
    background: none;
    border: 1px solid var(--border);
    color: var(--text-2);
}

.badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    font-weight: 700;
    background: var(--accent);
    color: var(--accent-ink);
    border-radius: var(--r-sm);
    padding: 2px var(--sp-2);
}

/* ── Durum noktası ──────────────────────────────────────────────────── */

.status {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-meta);
    text-transform: uppercase;
}

.status::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: var(--r-pill);
    background: currentColor;
}

.status--ok { color: var(--ok); }
.status--warn { color: var(--warn); }
.status--danger { color: var(--danger); }

/* ── Veri paneli (kunye.json) ───────────────────────────────────────────
   "Her yüzey veri taşır" ilkesinin somut hâli. Etiket mono ve VERSAL,
   değer normal — okuma yönü soldan sağa net. */

.panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--line);
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-3);
}

.data-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--line);
}

.data-row:last-child {
    border-bottom: none;
}

.data-row__key {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-meta);
    text-transform: uppercase;
    color: var(--text-3);
    flex-shrink: 0;
}

.data-row__value {
    font-size: var(--fs-meta);
    color: var(--text-1);
    text-align: right;
}

/* ── Makale gövdesi ─────────────────────────────────────────────────────
   Blog "birinci sınıf vatandaş": gerçek editoryel serif, ölçülü satır
   uzunluğu. Makine çerçevesi (mono/grotesk) + insan metni (serif)
   karşıtlığı bu yönün fikri. */

.prose {
    font-family: var(--font-read);
    font-size: var(--fs-read);
    line-height: var(--lh-read);
    color: var(--text-1);
    max-width: var(--measure);
}

.prose > * + * {
    margin-top: var(--sp-5);
}

.prose h2 {
    font-family: var(--font-ui);
    font-size: var(--fs-h3);
    margin-top: var(--sp-10);
    color: var(--text-1);
}

.prose h3 {
    font-family: var(--font-ui);
    font-size: var(--fs-h4);
    margin-top: var(--sp-8);
}

.prose ul,
.prose ol {
    padding-left: var(--sp-6);
}

.prose li {
    list-style: disc;
    margin-top: var(--sp-2);
}

.prose ol li {
    list-style: decimal;
}

.prose blockquote {
    border-left: 2px solid var(--accent);
    padding-left: var(--sp-5);
    color: var(--text-2);
    font-style: italic;
}

.prose img {
    border-radius: var(--r);
    border: 1px solid var(--border);
}

.prose figcaption {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-meta);
    color: var(--text-3);
    margin-top: var(--sp-2);
}

/* Satır içi kod — blok kodla karışmasın diye farklı zemin. */
.prose :not(pre) > code {
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 0.1em 0.35em;
    font-size: 0.9em;
}

/* ── Kod bloğu ──────────────────────────────────────────────────────────
   Başlıklı: dosya adı + dil. Gömülü yüzey (--surface-sunken), çünkü
   kod "yükselen" değil "içine bakılan" bir alan. */

.code-block {
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-sunken);
    overflow: hidden;
}

.code-block__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--sp-2) var(--sp-4);
    border-bottom: 1px solid var(--line);
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-3);
}

.code-block pre {
    margin: 0;
    padding: var(--sp-4);
    overflow-x: auto;
    font-size: var(--fs-meta);
    line-height: 1.75;
    color: var(--text-1);
}

/* Sözdizimi renkleri — token'lardan, ayrı bir tema dosyası yok. */
.tok-comment { color: var(--text-3); font-style: italic; }
.tok-keyword { color: var(--accent); }
.tok-string { color: var(--ok); }
.tok-number { color: var(--warn); }

/* ── İçindekiler ────────────────────────────────────────────────────── */

.toc__link {
    display: block;
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--line);
    border-left: 2px solid transparent;
    font-size: var(--fs-meta);
    color: var(--text-2);
    transition: color var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
}

.toc__link:last-child {
    border-bottom: none;
}

.toc__link[aria-current="true"] {
    color: var(--accent);
    border-left-color: var(--accent);
    background: var(--accent-soft);
}

/* ── Form ───────────────────────────────────────────────────────────────
   Hata gösterimi alan bazlı. aria-invalid ile sürülür, ayrı bir sınıf
   gerekmez — ekran okuyucu ve göz aynı kaynağı okur. */

.field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.field__label {
    font-size: var(--fs-meta);
    color: var(--text-2);
}

.field__control {
    width: 100%;
    min-height: var(--hit-min);
    padding: var(--sp-3);
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r);
    color: var(--text-1);
    font-size: var(--fs-ui);
    transition: border-color var(--dur) var(--ease),
                box-shadow var(--dur) var(--ease);
}

.field__control::placeholder {
    color: var(--text-3);
}

.field__control:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--ring-focus);
}

.field__control[aria-invalid="true"] {
    border-color: var(--danger);
}

.field__control[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 3px rgba(240, 138, 122, 0.25);
}

.field__error {
    font-size: var(--fs-meta);
    color: var(--danger);
}

.field__hint {
    font-size: var(--fs-meta);
    color: var(--text-3);
}

textarea.field__control {
    min-height: 8rem;
    resize: vertical;
    line-height: var(--lh-base);
}

/* ── Tablo (yönetim paneli) ─────────────────────────────────────────── */

.table__head {
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--border);
    background: color-mix(in srgb, var(--bg) 50%, transparent);
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-3);
    text-align: left;
}

.table__row {
    border-bottom: 1px solid var(--line);
    transition: background-color var(--dur-fast) var(--ease);
}

.table__row:hover {
    background: color-mix(in srgb, var(--accent) 4%, transparent);
}

.table__row[aria-selected="true"] {
    background: color-mix(in srgb, var(--accent) 6%, transparent);
}

.table__cell {
    padding: var(--sp-4) var(--sp-5);
    font-size: var(--fs-ui);
    color: var(--text-1);
    vertical-align: middle;
}

.table__cell--num {
    text-align: right;
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    font-variant-numeric: tabular-nums;
    color: var(--text-2);
}

/* Kaydırma kabı — dar ekranda sayfa gövdesi YATAY KAYMAZ, tablo kayar. */
.table-scroll {
    overflow-x: auto;
}

/* ── Boş durum ──────────────────────────────────────────────────────── */

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-16) var(--sp-5);
    text-align: center;
    color: var(--text-2);
}

/* ── Yardımcılar ────────────────────────────────────────────────────── */

.stack {
    display: flex;
    flex-direction: column;
}

.row {
    display: flex;
    align-items: center;
}

.grid-12 {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--sp-6);
}

.grid-3 {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-5);
}

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

@media (max-width: 900px) {
    .grid-3,
    .grid-2 {
        grid-template-columns: minmax(0, 1fr);
    }

    .grid-12 > * {
        grid-column: 1 / -1 !important;
    }
}

/* ── Site navigasyonu ve alt bilgi ──────────────────────────────────────
   Eski sitede her sayfa kendi nav ve footer markup'ini yeniden kuruyordu
   (5 ayri kopya). Burada tek tanim, _Layout icinde. */

.site-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-6);
    padding-block: clamp(1.25rem, 0.9rem + 1vw, 2rem);
    border-bottom: 1px solid var(--line);
}

.site-nav__brand {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    color: var(--text-1);
    flex-shrink: 0;
}

.site-nav__brand:hover {
    color: var(--text-1);
}

.site-nav__mark {
    width: 22px;
    height: 22px;
    border: 1.5px solid var(--accent);
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    font-weight: 700;
    color: var(--accent);
}

.site-nav__domain {
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
}

.site-nav__links {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(1.25rem, 0.8rem + 1.4vw, 2.5rem);
}

/* Üst menü: kullanıcı özellikle bunu küçük buldu (11px ölçüldü).
   .eyebrow'un mono kimliği kalıyor ama boyut ve aralık okunur hale geliyor:
   VERSAL + geniş aralık küçük punto ile birleşince okunmazlaşıyordu. */
.site-nav__links a {
    font-size: var(--fs-nav);
    letter-spacing: 0.06em;
    padding-block: var(--sp-2);
}

.site-nav__domain {
    font-size: var(--fs-nav);
}

.site-nav__mark {
    width: 28px;
    height: 28px;
    font-size: var(--fs-meta);
}

.site-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-top: var(--sp-16);
    padding-block: var(--sp-5);
    border-top: 1px solid var(--line);
}

/* Cikis kapilari. Altbilgi eskiden iki olu metindi; sayfa sonuna inen
   ziyaretcinin gidecek yeri yoktu. Baglantilar tek sirada, aralarinda
   mono nokta yok — ayrimi bosluk ve alti cizgi tasiyor. */
.site-footer__links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-5);
    align-items: center;
}

.site-footer__links a {
    color: var(--text-2);
    text-decoration: underline;
    text-underline-offset: 0.35em;
    text-decoration-color: transparent;
    text-decoration-thickness: 1px;
    transition: color var(--dur) var(--ease),
                text-decoration-color var(--dur) var(--ease);
}

.site-footer__links a:hover {
    color: var(--accent);
    text-decoration-color: var(--accent-line);
}

.site-footer__meta {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    text-align: right;
}

@media (max-width: 640px) {
    .site-footer__meta {
        text-align: left;
    }
}

/* Marka ile baglantilar YAN YANA yalnizca ikisi tek satira sigdigi surece.
   Olculdu: alti baglanti + marka 1200px'in altinda sigmiyor ve son baglanti
   ("[05] CV") tek basina alt satira dusup oksuz duruyordu. Esik bu yuzden
   768 degil 1200: altinda nav dikey diziliyor, baglantilar tam genislikte
   kendi satirini aliyor — sarma o zaman kaza degil tasarim gorunuyor. */
@media (max-width: 1199px) {
    .site-nav {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--sp-4);
    }

    .site-nav__links {
        gap: var(--sp-4);
    }
}

/* ── Sayfa basligi (liste ve detay sayfalari) ──────────────────────────── */

.page-head {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    padding-block: var(--sp-12) var(--sp-8);
}

.page-head__title {
    font-size: var(--fs-h1);
    line-height: var(--lh-heading);
    letter-spacing: var(--ls-h1);
}

/* ── Makale basligi ──────────────────────────────────────────────────── */

.article-head {
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
    padding-block: var(--sp-12) var(--sp-6);
    border-bottom: 1px solid var(--line);
}

.article-head__title {
    font-size: var(--fs-h1);
    line-height: var(--lh-heading);
    letter-spacing: var(--ls-h1);
}

.article-head__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-4);
}

/* ── Sayfalama ──────────────────────────────────────────────────────────
   Eski sitede Array.from({length: totalPages}) ile TUM sayfalar basiliyordu;
   30 sayfada satir tasiyordu. Burada pencere + ellipsis mantigi var. */

.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding-block: var(--sp-10);
}

.pagination__item {
    min-width: var(--hit-min);
    min-height: var(--hit-min);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-inline: var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--r);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    color: var(--text-2);
}

.pagination__item:hover {
    border-color: var(--border-strong);
    color: var(--text-1);
}

.pagination__item[aria-current="page"] {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
}

.pagination__gap {
    padding-inline: var(--sp-2);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* ── Bolum govdesi ──────────────────────────────────────────────────── */

.section-body {
    padding-top: var(--sp-8);
}

.hero {
    padding-block: var(--sp-16);
}

.hero__title {
    font-size: var(--fs-display);
    line-height: var(--lh-tight);
    letter-spacing: var(--ls-display);
}

/* ── Bal küpü (honeypot) ────────────────────────────────────────────────
   Gözle görünmez ve ekran okuyucudan gizli, ama DOM'da gerçek bir alan.
   display:none KULLANILMIYOR — bazı botlar display:none alanları atlar,
   bu da tuzağı işlevsiz kılar. */

.honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ── CV sayfası ─────────────────────────────────────────────────────────
   Ekranda site diliyle aynı; yazdırmada tokens.css'in @media print bloğu
   zemini beyaza çevirir. Ayrı bir "yazdırma teması" yok. */

.cv {
    padding-block: var(--sp-10) var(--sp-16);
}

.cv__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding-bottom: var(--sp-8);
}

.cv__head {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding-bottom: var(--sp-6);
    border-bottom: 2px solid var(--accent);
}

.cv__name {
    font-size: var(--fs-h1);
    line-height: var(--lh-heading);
    letter-spacing: var(--ls-h1);
}

.cv__title {
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--accent);
}

.cv__contact {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    color: var(--text-2);
}

.cv__grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: var(--sp-10);
    padding-top: var(--sp-8);
    align-items: start;
}

.cv__main,
.cv__aside {
    display: flex;
    flex-direction: column;
    gap: var(--sp-8);
}

.cv__section-title {
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    font-weight: 500;
    letter-spacing: var(--ls-label);
    text-transform: uppercase;
    color: var(--text-3);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--line);
    margin-bottom: var(--sp-5);
}

.cv__entry + .cv__entry {
    margin-top: var(--sp-6);
    padding-top: var(--sp-6);
    border-top: 1px solid var(--line);
}

.cv__entry-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}

.cv__entry-title {
    font-size: var(--fs-h4);
    letter-spacing: var(--ls-h4);
}

.cv__list {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding-top: var(--sp-3);
}

.cv__list li {
    position: relative;
    padding-left: var(--sp-5);
    color: var(--text-2);
    font-size: var(--fs-ui);
    line-height: var(--lh-base);
}

.cv__list li::before {
    content: "—";
    position: absolute;
    left: 0;
    color: var(--accent);
    font-family: var(--font-mono);
}

.cv__info {
    border: 1px solid var(--border);
    border-radius: var(--r);
}

.cv__skills {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

@media (max-width: 900px) {
    .cv__grid {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--sp-8);
    }
}

/* Yazdırmada gizlenecekler: navigasyon, alt bilgi, buton, zemin katmanı. */
@media print {
    .no-print,
    .site-nav,
    .site-footer,
    .skip-link {
        display: none !important;
    }

    .cv {
        padding: 0;
    }

    .cv__entry {
        break-inside: avoid;
    }
}

/* ── Dokunma hedefleri ──────────────────────────────────────────────────
   Ölçüm: 390px genişlikte nav linkleri 14px yüksekliğindeydi — parmakla
   isabet ettirilemez. Ama masaüstünde bu sıkı tipografik satır DOĞRU
   görünüyor; her yerde 44px'e çıkarmak tasarımı bozar.

   Çözüm: yalnızca kaba işaretçili cihazlarda (parmak) büyüt.
   `pointer: coarse` fare kullanan masaüstünü etkilemez. */

@media (pointer: coarse) {
    .site-nav__links a,
    .site-nav__brand,
    .section-head__link,
    .card__body > a,
    .article-head > a {
        min-height: var(--hit-min);
        display: inline-flex;
        align-items: center;
    }

    /* Satırlar birbirine yapışmasın; hedefler ayrışsın. */
    .site-nav__links {
        gap: var(--sp-2) var(--sp-5);
    }
}

/* ── Yönetim paneli ─────────────────────────────────────────────────────
   Aynı tasarım dili, yoğun ve işleve odaklı varyantı. */

.admin {
    display: grid;
    grid-template-columns: 236px minmax(0, 1fr);
    min-height: 100vh;
    background: var(--bg);
}

.admin__side {
    background: var(--surface-1);
    border-right: 1px solid var(--line);
    display: flex;
    flex-direction: column;
}

.admin__brand {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-5);
    border-bottom: 1px solid var(--line);
    color: var(--text-1);
}

.admin__brand:hover { color: var(--text-1); }

.admin__nav {
    display: flex;
    flex-direction: column;
    padding-block: var(--sp-4);
}

.admin__nav-group {
    padding: var(--sp-5) var(--sp-5) var(--sp-3);
}

.admin__nav-group:first-child { padding-top: 0; }

.admin__link {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-height: var(--hit-min);
    padding: var(--sp-2) var(--sp-5);
    border-left: 2px solid transparent;
    font-size: var(--fs-ui);
    color: var(--text-2);
    transition: color var(--dur) var(--ease),
                background-color var(--dur) var(--ease),
                border-color var(--dur) var(--ease);
}

.admin__link:hover {
    color: var(--text-1);
    background: color-mix(in srgb, var(--accent) 5%, transparent);
}

.admin__link.is-active {
    color: var(--text-1);
    border-left-color: var(--accent);
    background: var(--accent-soft);
}

.admin__link .badge { margin-left: auto; }

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

.admin__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-6);
    border-bottom: 1px solid var(--line);
}

.admin__user {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
}

.admin__main {
    padding: var(--sp-6);
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
}

.admin__head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
}

.admin__title {
    font-size: var(--fs-h2);
    letter-spacing: var(--ls-h2);
}

/* Dar ekranda kenar çubuğu üste geçer, yatay kaydırılır. */
@media (max-width: 900px) {
    .admin {
        grid-template-columns: minmax(0, 1fr);
    }

    .admin__side {
        border-right: none;
        border-bottom: 1px solid var(--line);
    }

    .admin__nav {
        flex-direction: row;
        overflow-x: auto;
        padding: var(--sp-2);
        gap: var(--sp-1);
    }

    .admin__nav-group { display: none; }

    .admin__link {
        border-left: none;
        border-bottom: 2px solid transparent;
        white-space: nowrap;
        border-radius: var(--r);
    }

    .admin__link.is-active {
        border-left: none;
        border-bottom-color: var(--accent);
    }
}

/* ── Onay kutusu ve radyo ───────────────────────────────────────────────
   Eksikti: tarayıcı varsayılanı koyu temada mavi çıkıyordu ve paletin
   dışına düşüyordu. accent-color tek satırda çözer, özel işaretleme
   (span + SVG) gerektirmez — erişilebilirlik de bozulmaz. */

input[type="checkbox"],
input[type="radio"] {
    accent-color: var(--accent);
    width: 1rem;
    height: 1rem;
    margin: 0;
    cursor: pointer;
}

/* Dokunmatikte kutunun kendisi 16px kalır ama tıklama alanı büyür. */
@media (pointer: coarse) {
    .table__cell input[type="checkbox"] {
        width: 1.25rem;
        height: 1.25rem;
    }
}

/* Okunmamış / dikkat isteyen tablo satırı. Renk TEK işaret değil —
   satırda ayrıca bir durum rozeti bulunmalı (renk körlüğü). */
.table__row--dikkat {
    background: var(--accent-soft);
}

/* ── Zengin metin editörü (TipTap adacığı) ──────────────────────────────
   Sitedeki tek React adacığı. Yalnızca yönetim panelinde yüklenir. */

.editor {
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-sunken);
    overflow: hidden;
}

.editor__arac-cubugu {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-1);
    padding: var(--sp-2);
    border-bottom: 1px solid var(--line);
    background: var(--surface-1);
    position: sticky;
    top: 0;
    z-index: 1;
}

.editor__dugme {
    min-width: 34px;
    min-height: 34px;
    padding: 0 var(--sp-3);
    border-radius: var(--r-sm);
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
    color: var(--text-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color var(--dur-fast) var(--ease),
                color var(--dur-fast) var(--ease);
}

.editor__dugme:hover {
    background: var(--surface-3);
    color: var(--text-1);
}

/* Etkin biçim, rengin YANINDA zeminle de işaretlenir — renk tek
   ayırt edici sinyal olmamalı. */
.editor__dugme[data-etkin="evet"] {
    background: var(--accent-soft);
    color: var(--accent);
}

.editor__ayrac {
    width: 1px;
    height: 20px;
    background: var(--border);
    margin-inline: var(--sp-1);
}

.editor__sayac {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: var(--fs-micro);
    color: var(--text-3);
    padding-right: var(--sp-2);
}

/* Editör gövdesi .prose sınıfını da taşır: yazarken görülen tipografi,
   yayınlandığında görünenle AYNI olur. */
.editor__govde {
    min-height: 22rem;
    max-height: 40rem;
    overflow-y: auto;
    padding: var(--sp-5);
    outline: none;
    max-width: none; /* .prose'un ölçü sınırı editörde istenmiyor */
}

.editor__govde:focus-visible {
    outline: none;
}

.editor:focus-within {
    border-color: var(--accent);
    box-shadow: var(--ring-focus);
}

/* Boş belgede ipucu metni. */
.editor__govde p.is-editor-empty:first-child::before {
    content: attr(data-placeholder);
    float: left;
    height: 0;
    pointer-events: none;
    color: var(--text-3);
}

.editor__govde pre {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r);
    padding: var(--sp-4);
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: var(--fs-meta);
}

/* JavaScript yüklenmediyse: editör hiç oluşmaz, textarea görünür kalır
   ve yazı yine yazılabilir. Bu bir yedek değil, tasarımın parçası. */
.editor-yedek-ipucu {
    font-size: var(--fs-meta);
    color: var(--text-3);
}

/* ══════════════════════════════════════════════════════════════════════════
   HAREKET — "sörf" hissi
   Sayfa sert zıplamaz, dalga üstünde süzülür. Katmanlar hareket.js'te
   anlatılıyor; burada yalnızca görsel karşılıkları var.

   Hâlâ geçerli olan ret listesi: partikül canvas, 3D tilt kart, daktilo
   efekti, mount'ta başlayan sayan rakamlar. Onlar CPU yakıp bilgi
   taşımıyordu; buradakilerin hepsi transform/opacity — GPU'da, düzen
   hesabı tetiklemeden çalışır.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Hareket eğrileri ───────────────────────────────────────────────────
   "Dalga" eğrisi: hızlı başlar, uzun süre yavaşlayarak oturur — suyun
   üstünde bırakılan bir şeyin durması gibi. */
:root {
    --dalga: cubic-bezier(0.22, 1, 0.36, 1);
    --dalga-sure: 900ms;
    --dalga-adim: 90ms;   /* art arda gelen kartlar arası gecikme */
}

/* ── Ataletli kaydırma (Lenis) ──────────────────────────────────────────
   Lenis aktifken tarayıcının kendi yumuşak kaydırması KAPANMALI; ikisi
   birlikte çalışınca kaydırma iki kez yumuşatılır ve gecikmeli hissettirir. */
html.atalet {
    scroll-behavior: auto;
}

html.lenis,
html.lenis body {
    height: auto;
}

.lenis.lenis-stopped {
    overflow: clip;
}

.lenis [data-lenis-prevent] {
    overscroll-behavior: contain;
}

.lenis.lenis-smooth iframe {
    pointer-events: none;
}

/* ── Işık kayması ───────────────────────────────────────────────────────
   Sayfa zeminindeki tungsten ışığı kaydırmayla akar: tepede sol üstte,
   sayfa ilerledikçe sağa ve aşağı süzülür — suyun üstünde kayan güneş.

   JS YOK. Kaydırmaya bağlı CSS animasyonu; tarayıcı bunu ana iş
   parçacığına uğramadan, GPU'da yürütür. Önceki sürüm her karede CSS
   değişkeni yazıyor ve tam ekran gradyanı baştan boyatıyordu.
   Desteklemeyen tarayıcı (bugün Firefox) sabit ışığı görür. */
@supports (animation-timeline: scroll()) {
    .page-ground__isik {
        will-change: transform;
        animation: isik-akisi auto linear both;
        /* Kısaltma animation-timeline'ı sıfırlar: bu satır ONDAN SONRA. */
        animation-timeline: scroll(root block);
    }
}

@keyframes isik-akisi {
    to { transform: translate3d(44vw, 46vh, 0); }
}

/* ── Sayfa geçişi (View Transitions API) ────────────────────────────────
   Tarayıcının yerlisi: JS ve kütüphane YOK. Desteklemeyen tarayıcı bu
   bloğu yok sayar, sayfa normal geçer. */
@view-transition {
    navigation: auto;
}

::view-transition-old(root) {
    animation: cikis 260ms var(--ease) both;
}

::view-transition-new(root) {
    animation: giris 520ms var(--dalga) both;
}

@keyframes cikis {
    to { opacity: 0; transform: translateY(-10px); }
}

@keyframes giris {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: none; }
}

/* ── Paylaşılan başlık ──────────────────────────────────────────────────
   Kart başlığı ile makale başlığı aynı adı taşır; tarayıcı o elemanı iki
   sayfa arasında uçurur. Sayfa geçişinin devamı: kök kayarken bir nesne
   yerinde kalır, göz onu takip eder ve iki sayfa tek nesnenin iki hâli olur.

   Adı Razor DEĞİL hareket.js veriyor. Sebebi: aynı view-transition-name
   sayfada iki elemanda birden bulunursa tarayıcı geçişi SESSİZCE iptal
   eder; üstelik listedeki dokuz kart adlandırılsaydı makale sayfasında eşi
   olmayan sekizi kendi katmanına çıkıp kökten ayrı hareket ederdi.
   Buradaki sınıf ise addan bağımsız: ad slug'dan geldiği için ona seçici
   yazılamaz, view-transition-class tam bu boşluk için var.

   Destek eşiği sorun değil: çapraz belge geçişini yapabilen her tarayıcı
   (Chrome 126+, Safari 18.2+) sınıfı da biliyor (Chrome 125, Safari 18.2).
   Yani "geçiş çalışıyor ama sınıf tutmuyor" aralığı YOK. Firefox ikisini de
   yapmaz; orada sayfa bugünkü gibi, geçişsiz açılır. */
.card__title[data-gecis],
.article-head__title[data-gecis] {
    view-transition-class: baslik;
}

::view-transition-group(*.baslik) {
    animation-duration: 520ms;              /* kökün girişiyle aynı ölçü */
    animation-timing-function: var(--dalga);
    overflow: clip;                         /* doğal boyuttaki görüntü taşmasın */
}

/* KRİTİK — glif ÖLÇEKLENMEZ. Anlık görüntüler birer bitmap; tarayıcının
   varsayılanı (inline-size: 100%) kart başlığının 24px rasterini makale
   başlığının 64px kutusuna GERER ve yazı bulanıklaşır. object-fit: none
   ikisini de kendi doğal boyutunda bırakır: değişen tek şey kutunun yeri
   ve opaklık — yani ışık. Küçük başlık uçarken büyüğü kutu açıldıkça
   ortaya çıkar; iki raster de hiç esnemez. */
::view-transition-old(*.baslik),
::view-transition-new(*.baslik) {
    width: 100%;
    height: 100%;
    object-fit: none;
    object-position: left top;
}

/* Eşi olmayan başlık — makaleden listeye dönerken eski, bir yazıya metin
   içindeki bağlantıdan girerken yeni. Kendi katmanına çıktığı için kökün
   animasyonuna dahil değil; aynı eğriyi burada elle alıyor, yoksa sayfa
   kayarken başlık yerinde asılı kalırdı. */
::view-transition-old(*.baslik):only-child {
    animation: cikis 260ms var(--ease) both;
}

::view-transition-new(*.baslik):only-child {
    animation: giris 520ms var(--dalga) both;
}

/* ── Hero açılışı ───────────────────────────────────────────────────────
   Sayfa açılınca hero'nun parçaları art arda yükselir.

   CSS animasyonu, JS'i BEKLEMEZ. Önceki sürümde gizlemeyi JS ekliyordu:
   sayfa önce tam çiziliyor, script çalışınca kayboluyor, sonra
   yükseliyordu — göz kırpması. Üstelik en büyük içerik (isim) opacity:0'da
   bekletildiği için LCP ölçüsü gecikiyordu. Şimdi hareket ilk boyamadan
   başlıyor; animasyon bitince içerik görünür kalıyor (fill: both).

   İsim YALNIZCA kayar, hiç saydamlaşmaz ve beklemez: ilk karede zaten
   ekranda, LCP ilk boyamaya denk gelir. */
.hero__parca {
    animation: hero-yuksel var(--dalga-sure) var(--dalga) both;
    animation-delay: calc(var(--sira, 0) * 110ms + 80ms);
}

.hero__title.hero__parca {
    animation-name: hero-kay;
    animation-duration: 1100ms;
    animation-delay: 0ms;
}

@keyframes hero-yuksel {
    from { opacity: 0; transform: translateY(28px); }
}

@keyframes hero-kay {
    from { transform: translateY(0.22em); }
}

/* ── Bölüm belirme ──────────────────────────────────────────────────────
   KRİTİK: gizleme yalnızca `.belirme-acik` varken. Onu JS ekliyor — ve
   gözlemci hiç çalışmazsa GERİ ALIYOR (hareket.js, "Emniyet ağı"): içeriğin
   kalıcı gizli kalmaması bu sınıfın kaldırılmasına bağlı. Bu yüzden bu
   sınıfın altına GİZLEMEDEN BAŞKA bir şey (kalıcı düzen, renk, boşluk)
   yazılmaz; yazılırsa ağ devreye girdiğinde o da kaybolur. */
.belirme-acik [data-belir] {
    opacity: 0;
    transform: translateY(40px);
}

.belirme-acik [data-belir].belirdi {
    opacity: 1;
    transform: none;
    transition: opacity var(--dalga-sure) var(--dalga),
                transform var(--dalga-sure) var(--dalga);
}

/* Bölüm başlığının çizgisi soldan sağa "çizilir" — dalganın tepesi gibi. */
.belirme-acik [data-belir] .section-head__rule {
    transform: scaleX(0);
    transform-origin: 0 50%;
}

.belirme-acik [data-belir].belirdi .section-head__rule {
    transform: scaleX(1);
    transition: transform 1400ms var(--dalga) 200ms;
}

/* ── Dalga: kartlar art arda gelir ──────────────────────────────────────
   Kap görünür olunca çocukları SIRAYLA yükselir. --sira JS'ten gelir.
   Hafif ölçek ve yükseklik: kıyıya vuran dalga gibi.

   DİKKAT — `transform` DEĞİL, ayrı `translate` ve `scale` özellikleri:
   kartın hover'daki kalkması `transform` kullanıyor. Dalga da transform
   kullansaydı, bu kural daha özgül olduğu için hover'ı EZERDİ ve kartlar
   fare üstüne gelince kalkmazdı. Ayrı özellikler birbirini ezmez, birleşir. */
.belirme-acik [data-dalga] > * {
    opacity: 0;
    translate: 0 56px;
    scale: 0.97;
}

.belirme-acik [data-dalga].belirdi > * {
    opacity: 1;
    translate: none;
    scale: none;
    transition: opacity var(--dalga-sure) var(--dalga),
                translate var(--dalga-sure) var(--dalga),
                scale var(--dalga-sure) var(--dalga),
                transform 500ms var(--dalga),
                box-shadow 500ms var(--dalga),
                border-color var(--dur) var(--ease);
    transition-delay: calc(var(--sira, 0) * var(--dalga-adim)),
                      calc(var(--sira, 0) * var(--dalga-adim)),
                      calc(var(--sira, 0) * var(--dalga-adim)),
                      0ms, 0ms, 0ms;
}

/* Çapa ile atlanınca bekleme YOK — hedef anında görünür. */
.belirme-acik .anlik,
.belirme-acik .anlik > *,
.belirme-acik .anlik .section-head__rule {
    transition: none !important;
}

/* ── İmleç ışığı ────────────────────────────────────────────────────────
   Kartın üstünde imleci izleyen sıcak parıltı: tungsten ışığının yüzeye
   düşmesi. Konum hareket.js'ten (--mx, --my). Yalnızca üzerindeyken. */
.card--interactive {
    position: relative;
    isolation: isolate;
    transition: transform 500ms var(--dalga),
                border-color var(--dur) var(--ease),
                box-shadow 500ms var(--dalga);
}

.card--interactive::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background: radial-gradient(
        420px circle at var(--mx, 50%) var(--my, 0%),
        rgba(255, 196, 120, 0.08),
        transparent 60%);
    opacity: 0;
    transition: opacity 400ms var(--ease);
}

/* İmleç ışığı klavyeye de geliyor. --mx/--my hiç yazılmamışken
   yukarıdaki varsayılan (`50% 0%`) devreye girer: ışık üst ortada doğar,
   yani sabit ışık kaynağının bulunduğu yerde. Sekmeyle gelen kullanıcı
   fareyle gelenle aynı sahneyi görüyor. Seçici kart kenarınınkiyle birebir
   aynı (gerekçesi orada yazılı). */
.card--interactive:is(:hover, :focus-visible, :has(:focus-visible))::after {
    opacity: 1;
}

/* Işık şeride düşünce şeridin metni de aydınlanır. Süs değil, zorunluluk:
   --text-3 kartın üst yüzeyinde (#1C1916) 4,6:1 ile sınırda; parıltı
   zemini açınca 3,7:1'e düşüyordu (AA 4,5:1'in altı). --text-2 parıltının
   tam merkezinde bile ~6:1. */
.card--interactive .card__strip {
    transition: color 400ms var(--ease);
}

/* Üstteki kontrast gerekçesi odak için de aynen geçerli: ışık hangi
   yolla yanarsa yansın (fare ya da klavye) şeridin zemini açılıyor,
   dolayısıyla --text-3 AA sınırının altına düşüyor. Seçici imleç
   ışığınınkiyle birebir aynı tutuldu ki ikisi asla ayrışmasın. */
.card--interactive:is(:hover, :focus-visible, :has(:focus-visible)) .card__strip {
    color: var(--text-2);
}

/* IŞIK hem imleçte hem odakta: halka ve gölge aynı seçiciden. */
.card--interactive:is(:hover, :focus-visible, :has(:focus-visible)) {
    box-shadow: var(--shadow-3), 0 0 0 1px var(--accent-soft);
}

/* GEOMETRİ yalnızca imleçte. Kalkma bir fare tepkisi; klavyede ortak dil
   ışık (kenar + halka + imleç ışığı + kenar parıltısı). Odaklanmış öğeyi
   oynatmak Tab'la hızlı gezinirken kartları zıplatır, üstelik bu sistemde
   hareket = ışığın değişmesi. Azaltılmış hareket bloğundaki mevcut
   `.card--interactive:hover, .btn:hover { transform: none }` bunu zaten
   kapatıyor; ayrı bir kural gerekmiyor. */
.card--interactive:hover {
    transform: translateY(-6px);
}

/* ── Kart üst kenarının parlaması ───────────────────────────────────────
   İmleç ya da odak karta girince ÜST kenarın ışığı bir kez açılıp düşük
   bir seviyede oturur. Dönen kenar ışığı (border beam) DEĞİL: bütün
   sistem "tek ve sabit ışık kaynağı yukarıda" varsayımına dayanıyor;
   ışığın kenar boyunca dolaşması o varsayımı bozar ve kartı bir rozete
   çevirir. Burada parlama yer değiştirmiyor — üst kenar boyunca genişleyip
   sönüyor. Işığın DEĞİŞMESİ var, geometrinin oynaması yok.

   NEDEN @property: parlamanın eni bir gradyan durağının yüzdesi olarak
   yazılıyor. Kaydedilmemiş özel değişken tarayıcı için tiplenmemiş bir
   jetondur; ara değer üretilemez, keyframe SESSİZCE hiçbir şey yapmaz ve
   konsola hata da düşmez. Kayıt, değişkene <percentage> tipini verip
   interpolasyonu açan tek yol.

   DESTEK: Chrome/Edge 85, Safari + iOS 16.4, Firefox 128 (≈%95).
   Desteklemeyen tarayıcı @property'yi bilinmeyen at-kuralı sayıp atar;
   --parilti-eni değersiz kalır, onu okuyan `background` bildirimi
   hesaplama anında geçersiz olur ve `unset`e düşer — non-inherited
   olduğu için transparent. Geriye 1px'lik saydam bir şerit kalır: kart
   bugünküyle birebir aynı görünür. Yedek değer (var(--parilti-eni, 50%))
   BİLEREK yazılmadı; yazılsaydı desteklemeyen tarayıcıda hareketsiz ama
   görünür bir kehribar çubuk asılı kalırdı. */
@property --parilti-eni {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 0%;
}

/* ::after zaten imleç ışığında; bu katman ::before'a kuruluyor. Kartın
   KENDİSİNE dokunulmuyor: animasyon yalnızca bir özel değişkeni ve bu
   pseudo-elemanın opacity'sini sürüyor, dolayısıyla hover'ın transform
   kalkmasıyla da dalganın translate/scale'iyle de çakışmıyor.
   Şerit padding kutusunun tepesinde duruyor; kartın overflow:hidden'ı onu
   yuvarlatılmış köşelerde kırpıyor ve üst kenar çizgisiyle birleşerek
   o çizginin parlaması gibi okunuyor. */
.card--interactive::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(
        90deg,
        transparent calc(50% - var(--parilti-eni)),
        var(--accent-line) calc(50% - var(--parilti-eni) * 0.45),
        var(--accent) 50%,
        var(--accent-line) calc(50% + var(--parilti-eni) * 0.45),
        transparent calc(50% + var(--parilti-eni)));
    /* İmleç karttan çıkınca animasyon kaldırılır ve oturmuş ışık biter;
       geçiş o anı yumuşatır. 0,18'den 0'a inen 1px'lik bir çizgi zaten
       göze batmaz, bu yalnızca kibarlık. */
    transition: opacity 400ms var(--ease);
}

/* Klavye aynı geri bildirimi görüyor — seçici öteki üç kuralla birebir. */
.card--interactive:is(:hover, :focus-visible, :has(:focus-visible))::before {
    animation: kart-kenar-parilti 700ms var(--dalga) both;
}

/* Tepe 0,55 opaklıkta ve 1px yüksekliğinde: "tek kromatik aksan, sayfa
   alanının %2'sinden fazlasını kaplamaz" kuralı rahatça korunuyor —
   parlama sayfanın binde birinden küçük ve yalnızca imleç/odak kartın
   üstündeyken var. `both` son kareyi tutuyor: parlama söner ama kenarda
   hafif bir ışık OTURUR; parlamanın "bir kez" olmasını sağlayan da bu,
   döngü yok. */
@keyframes kart-kenar-parilti {
    from { --parilti-eni: 6%;  opacity: 0; }
    32%  { --parilti-eni: 58%; opacity: 0.55; }
    to   { --parilti-eni: 46%; opacity: 0.18; }
}

/* ── Nav: aktif bölüm çizgisi ───────────────────────────────────────────
   Aktif bağlantının altında kehribar çizgi kayarak belirir. */
.site-nav__links a {
    position: relative;
}

.site-nav__links a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -6px;
    height: 1px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: 0 50%;
    transition: transform 500ms var(--dalga);
}

.site-nav__links a:hover::after,
.site-nav__links a.is-aktif::after {
    transform: scaleX(1);
}

/* ── Buton ──────────────────────────────────────────────────────────────
   Birincil buton hafifçe yükselir, ışığı yoğunlaşır. */
.btn {
    transition: transform 400ms var(--dalga),
                background-color var(--dur) var(--ease),
                border-color var(--dur) var(--ease),
                box-shadow 400ms var(--dalga);
}

.btn:hover {
    transform: translateY(-2px);
}

.btn--primary:hover {
    box-shadow: 0 14px 36px -12px rgba(232, 162, 74, 0.65);
}

.btn:active {
    transform: translateY(0);
    transition-duration: 80ms;
}

/* ── Okuma ilerleme çubuğu ──────────────────────────────────────────────
   Makale sayfasında, üst kenarda. Süs değil: ne kadar kaldığını söyler. */
.ilerleme {
    position: fixed;
    inset: 0 0 auto 0;
    height: 2px;
    z-index: var(--z-nav);
    pointer-events: none;
}

.ilerleme::before {
    content: "";
    display: block;
    height: 100%;
    background: var(--accent);
    transform: scaleX(var(--ilerleme, 0));
    transform-origin: 0 50%;
    box-shadow: 0 0 14px 1px rgba(232, 162, 74, 0.5);
}

/* ── Okuma izi (makale kenarı) ──────────────────────────────────────────
   Aynı --ilerleme'nin İKİNCİ tüketicisi. Üstteki çubuk "ne kadar kaldı"
   der ama göz metnin ortasındayken ekranın tepesinde kalır; iz aynı bilgiyi
   satırın yanına, göz hizasına getirir.

   Kaydırmaya bağlı animasyon (animation-timeline) BİLEREK kullanılmıyor:
   Firefox stabilde yok, ama asıl sebep o değil — bu bir DURUM göstergesi.
   Değeri hareket.js hesaplıyor; ikinci bir kaynak açmak iki göstergenin
   birbirinden kaymasına yol açar.

   İz scaleY ile değil BOYUYLA uzuyor: scaleY ucundaki ışık noktasını da
   yassıltırdı (%10'da nokta 1/10 boyunda bir çizgiye dönerdi). Bedeli,
   içeriği olmayan tek bir mutlak konumlu kutunun yüksekliği; contain onun
   dışarı düzen hesabı taşımayacağını garantiliyor. Aynı karede zaten
   getBoundingClientRect() okunuyor, bunun yanında ölçülemez. */
[data-makale] {
    position: relative;
}

/* Ray: hep tam boy, hep sönük. JS hiç çalışmazsa geriye yalnızca bu kalır —
   kenarda ince bir çizgi. Gizlenen hiçbir şey yok.
   Mutlak konumlu kutunun kapsayan bloğu makalenin PADDING kutusu; makale
   aynı zamanda .container ve padding-inline: var(--page-pad) taşıyor, yani
   inset-inline-start: calc(var(--page-pad) / 2) tam kenar boşluğunun
   ortasına düşüyor — metnin ölçüsüne dokunmuyor. */
[data-makale]::before {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: calc(var(--page-pad) / 2);
    width: 1px;
    background: var(--line);
    pointer-events: none;
}

/* Okunan pay: rayın üstünde uzayan ışık, ucunda nokta.
   Yüzde yükseklik makale kutusuna göre çözülür; hareket.js ilerlemeyi AYNI
   kutudan hesapladığı için nokta, makale boyunca ekranın tepesinden dibine
   düzgün iner — ilerleme 1'ken makalenin alt kenarındadır, o da tam o anda
   ekranın alt kenarındadır. Kutu 13px geniş ki noktanın halesine yer olsun;
   1px'lik ışık çizgisi ortada, rayın tam üstünde durur. */
[data-makale]::after {
    content: "";
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: calc(var(--page-pad) / 2 - 6px);
    width: 13px;
    height: calc(var(--ilerleme, 0) * 100%);
    background:
        radial-gradient(circle closest-side,
                        var(--accent), var(--accent-soft) 50%, transparent)
            center bottom / 11px 11px no-repeat,
        linear-gradient(to bottom, var(--accent-line), var(--accent))
            center top / 1px 100% no-repeat;
    /* Her karede değişen tek ölçü bu kutunun boyu; contain onu kendi içinde
       tutar, belgeye bir reflow olarak sızmaz. */
    contain: strict;
    pointer-events: none;
}

/* Kısa makalede çubuk gizleniyor (hareket.js: toplam <= 0); iz de aynı
   karara uyar. Çubuk makalenin ÖNCESİNDE kardeşi (Detay.cshtml satır 5 ve
   8, ikisi de _Layout'un <main id="main"> içinde) olduğu için JS'e tek
   satır eklemeden aynı kaynaktan besleniyor.
   DİKKAT: bu kural işaretleme sırasına bağlı — çubuk makalenin İÇİNE
   taşınırsa ya da sırası değişirse sessizce ölür. */
[data-ilerleme][hidden] ~ [data-makale]::before,
[data-ilerleme][hidden] ~ [data-makale]::after {
    display: none;
}

/* Dar ekranda kenar boşluğu yok. .container 768px'in altında --page-pad
   yerine --page-pad-sm (20px) kullanıyor: hem izin yeri kalmıyor hem de
   dayandığı hesap yanlışlıyor. 400px'te ekran kenarına yapışırdı. */
@media (max-width: 768px) {
    [data-makale]::before,
    [data-makale]::after {
        display: none;
    }
}

/* prefers-reduced-motion: iz KALIR — çubukla aynı gerekçe, kendi kendine
   oynayan bir animasyon değil, kullanıcının kendi kaydırmasının durumu.
   Geçiş (transition) bilerek yok: olsaydı hem dosyanın altındaki blokta
   kapatmak gerekirdi hem de gösterge kaydırmanın bir tık gerisinde
   kalırdı. Yazdırma dalı dosyanın altındaki TEK print bloğunda. */

/* Çapayla atlanan bölüm ekranın tepesine yapışmasın. */
[id] {
    scroll-margin-top: var(--sp-8);
}

/* Çapa hedefi odak alır (hareket.js odagiTasi) ki klavye ve ekran okuyucu
   oradan devam etsin. Bölümün tamamını çevreleyen bir halka bilgi
   vermez, yalnızca gürültü: bu kaplarda halka yok. Odaklanabilir
   öğelerin halkası (base.css :focus-visible) olduğu gibi kalır. */
:where(main, section)[tabindex="-1"]:focus {
    outline: none;
}

/* ── Yazdırma ───────────────────────────────────────────────────────────
   Kâğıtta hareket yok. Henüz belirmemiş bölümler ve kaymış katmanlar
   yerine oturur; yoksa ekranda görülmemiş bölümler boş basılırdı. */
@media print {
    .belirme-acik [data-belir],
    .belirme-acik [data-dalga] > *,
    .belirme-acik [data-belir] .section-head__rule,
    .hero__parca,
    [data-paralaks] {
        opacity: 1 !important;
        transform: none !important;
        translate: none !important;
        scale: none !important;
        animation: none !important;
        transition: none !important;
    }

    /* Kâğıtta ışık da tıklama işareti de yok. Bu liste yukarıdakinin TERSİ
       iş yapıyor: üstteki gizli kalmış İÇERİĞİ görünür kılar, bu ise
       yalnızca ekrana ait katmanları kaldırır. İkisini birleştirmek
       (opacity: 1) her kartın tepesine kahverengi bir çubuk basardı —
       tokens.css'in print bloğunda --rim/--rim-strong transparent olurken
       --accent #8A5214, --accent-line #C9B79E gibi OPAK renklere dönüyor.

       Gizlenenlerin hiçbiri içerik değil: "oku →" / "incele →" ipucunun
       hedefini başlık bağlantısı taşıyor ve o basılıyor (eskiden de aynı
       metni taşıyan bir <a> vardı, yani gerileme değil); ilerleme çubuğu
       ile okuma izi ise ekran göstergesi.
       YAN FAYDA: .ilerleme position:fixed ve bugüne dek hiçbir print
       kuralında gizli değildi — çoğu motorda HER sayfanın tepesine 2px
       kehribar bir şerit basılıyordu. Bu satır onu da kapatıyor. */
    .card__ipucu,
    .card--interactive::before,
    .ilerleme,
    [data-makale]::before,
    [data-makale]::after {
        display: none !important;
    }
}

/* ── Azaltılmış hareket ─────────────────────────────────────────────────
   Tüm hareket katmanları kapanır. hareket.js de bu durumda Lenis'i,
   paralaksı, belirmeyi ve imleç ışığını hiç kurmuyor; burası JS'e
   rağmen bir şey sızarsa diye ikinci emniyet. İlerleme çubuğu ve aktif
   bölüm KALIR — onlar animasyon değil, durum göstergesi. */
@media (prefers-reduced-motion: reduce) {
    @view-transition {
        navigation: none;
    }

    .belirme-acik [data-belir],
    .belirme-acik [data-dalga] > *,
    .belirme-acik [data-belir] .section-head__rule {
        opacity: 1 !important;
        transform: none !important;
        translate: none !important;
        scale: none !important;
        transition: none !important;
    }

    /* Aşağıdaki genel "animation-duration: 0.01ms" kaydırmaya bağlı
       animasyonu durdurmaz — süresi zamana değil kaydırmaya bağlı. Açıkça
       kapatılıyor. */
    .hero__parca,
    .page-ground__isik {
        animation: none !important;
    }

    [data-paralaks] {
        translate: none !important;
    }

    .site-nav__links a::after {
        transition: none !important;
    }

    .card--interactive:hover,
    .btn:hover {
        transform: none;
    }

    /* Kart üst kenarının parlaması. Bu kural SÜS DEĞİL, zorunlu: aşağıdaki
       genel "animation-duration: 0.01ms" animasyonu DURDURMUYOR, bir karede
       SONUNA atlatıyor — `both` ile birlikte bu, oturmuş parıltıyı (opacity
       0,18) kalıcı olarak yakardı; azaltılmış hareket isteyen kullanıcı
       animasyonu görmediği gibi bir de sabit kehribar çizgiyle kalırdı.
       `animation: none` animation-name'i de sıfırlar; seçici `*::before`den
       daha özgül olduğu için !important yarışını da kazanır.
       Geri bildirim kaybolmuyor: kenar rengi (--rim-strong/--border-strong)
       ve :focus-visible halkası olduğu gibi duruyor. */
    .card--interactive::before {
        animation: none !important;
        opacity: 0 !important;
    }

    /* Zemin ışığının hız katmanı. hareket.js azaltılmış harekette Lenis'i
       hiç kurmadığı için --hiz zaten hiç yazılmıyor; bu iki satır ikinci
       emniyet. Opaklığı değil --hiz'i sabitliyoruz: değer 0 olunca
       base.css'teki calc(0.9 + 0 * 0.1) normal dinlenme haliyle BİREBİR
       aynı sonucu verir — iki mod arasında %10'luk bir fark açılmaz.
       !important zorunlu: değeri JS satır içi stille yazıyor ve satır içi
       stil !important'sız kural sayfasını ezer. Genel 0.01ms kuralı
       GEÇİŞLERİ kapatmadığı için transition ayrıca yazılıyor (dosyada
       .site-nav__links a::after da bu yüzden ayrıca yazılmış). */
    .page-ground__isik {
        --hiz: 0 !important;
        transition: none !important;
    }

    /* Paylaşılan başlık geçişi. Bloğun başındaki `@view-transition {
       navigation: none }` geçişin TAMAMINI zaten hiç başlatmıyor ve
       hareket.js de azHareket'te adı hiç vermiyor; bu satır ad bir yerden
       sızarsa elemanın kendi geçiş katmanına çıkmasını engeller — ileride
       aynı adı Razor'dan basmaya kalkan biri olursa da tutar.
       !important şart: adı JS satır içi stille yazıyor. */
    [data-gecis] {
        view-transition-name: none !important;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
    }
}
