/* ==========================================================
   Sayfa bazlı bileşen stilleri. Tüm sayfalar tek css dosyasını
   paylaşır (SPA, tek index.html üzerinden çalışıyor).
   Renk/boşluk/tipografi için her zaman variables.css tokenleri
   kullanılır, burada büyülü (magic) değer yok.
   ========================================================== */

/* ---------- Auth (login / register) ---------- */
.login-page {
  min-height: 100vh;
  display: flex;
}

.brand-panel {
  position: relative;
  flex: 1.1;
  background: var(--color-topbar);
  color: var(--color-topbar-text);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-8) var(--space-7);
  overflow: hidden;
}

/* Sadece giriş ekranındaki "ilk izlenim" panelinde kullanılan hafif ışık efekti;
   uygulamanın gerçek çalışma ekranlarında (tablo/liste) kullanılmıyor. */
.brand-panel::before,
.brand-panel::after {
  content: '';
  position: absolute;
  width: 480px;
  height: 480px;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
}

.brand-panel::before {
  background: rgba(132, 103, 232, 0.35);
  top: -160px;
  right: -160px;
}

.brand-panel::after {
  background: rgba(132, 103, 232, 0.18);
  bottom: -180px;
  left: -140px;
}

.brand-panel > * {
  position: relative;
  z-index: 1;
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

/* Marka kutusu: düz kare yerine "squircle" form + accent renginden diyagonal
   degrade, üstte ışık huzmesi ve dışa doğru yayılan iki soluk halka - kutunun
   kendisi de "nabız yayılıyor" hissini taşısın diye. */
.brand-mark {
  width: 58px;
  height: 58px;
  background:
    linear-gradient(145deg, var(--color-accent-hover) 0%, var(--color-accent) 55%, #4A2FB8 100%);
  border-radius: 34%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  position: relative;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    0 6px 18px rgba(109, 79, 224, 0.38);
}

/* Kutunun dışına yayılan sinyal halkaları. */
.brand-mark::after {
  content: '';
  position: absolute;
  inset: -8px;
  border-radius: 38%;
  border: 1px solid rgba(255, 255, 255, 0.16);
  animation: brand-mark-ring 3.2s ease-out infinite;
  pointer-events: none;
}

/* Sol üstten geçen yumuşak ışık huzmesi (SVG'nin altında kalıyor). */
.brand-mark::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at 28% 18%, rgba(255, 255, 255, 0.42), transparent 62%);
  pointer-events: none;
}

.brand-mark svg {
  width: 38px;
  height: 38px;
  position: relative;
  z-index: 1;
  overflow: visible;
}

/* Sidebar'daki logoyla aynı davranış: imleç marka kilidinin üstüne gelince
   EKG çizgisi soldan sağa yeniden çiziliyor. */
.brand-lockup:hover .brand-ekg {
  animation: brand-ekg-sweep 1.1s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .brand-lockup:hover .brand-ekg {
    animation: none;
  }
}

@keyframes brand-mark-ring {
  0% {
    transform: scale(0.92);
    opacity: 0.9;
  }
  70% {
    transform: scale(1.12);
    opacity: 0;
  }
  100% {
    transform: scale(1.12);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .brand-mark::after {
    animation: none;
    opacity: 0.35;
    transform: none;
  }
}

.brand-name {
  font-family: var(--font-heading);
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  letter-spacing: 0.04em;
  color: var(--color-topbar-text);
}

.slogan-title {
  font-family: var(--font-heading);
  font-weight: var(--weight-bold);
  font-size: var(--text-4xl);
  line-height: 1.3;
  margin: 0 0 var(--space-4);
  white-space: nowrap;
}

.slogan-body {
  font-size: var(--text-md);
  line-height: 1.65;
  color: rgba(248, 250, 252, 0.72);
  max-width: 380px;
  margin: 0;
}

.form-panel {
  flex: 1;
  background: var(--color-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
}

.login-card {
  width: 100%;
  max-width: 360px;
}

.login-title {
  font-family: var(--font-heading);
  font-weight: var(--weight-bold);
  font-size: var(--text-2xl);
  margin: 0 0 4px;
}

.login-subtitle {
  color: var(--color-text-muted);
  font-size: var(--text-base);
  margin: 0 0 var(--space-5);
}

.form-group {
  margin-bottom: var(--space-4);
}

.form-group label,
.login-card label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  margin-bottom: 6px;
}

.login-card input,
.login-card select,
.login-card textarea {
  width: 100%;
  padding: 10px var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background-color: var(--color-surface);
  color: var(--color-text);
}

.login-card select {
  padding-right: 32px;
}

.login-card input:focus {
  outline: none;
  border-color: var(--color-accent);
}

.login-card button[type="submit"] {
  width: 100%;
  padding: 10px var(--space-3);
  background: var(--color-accent);
  color: #FFFFFF;
  border: none;
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  font-family: var(--font-body);
}

.login-card button[type="submit"]:hover {
  background: var(--color-accent-hover);
}

.login-card button[type="submit"]:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.error-message {
  background: var(--priority-critical-bg);
  color: var(--priority-critical-fg);
  font-size: var(--text-sm);
  padding: 10px var(--space-3);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-4);
  display: none;
}

.form-footer {
  margin-top: var(--space-5);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.form-footer a {
  color: var(--color-accent);
  font-weight: var(--weight-semibold);
  text-decoration: none;
}

.form-footer a:hover {
  text-decoration: underline;
}

@media (max-width: 900px) {
  .login-page {
    flex-direction: column;
  }
  .brand-panel {
    padding: var(--space-6) var(--space-5);
  }
  .slogan-title {
    font-size: var(--text-2xl);
    white-space: normal;
  }
}

/* Telefonda marka paneli ekranın yarısını yiyordu; giriş formu ilk
   görünende olmalı, marka bloğu ona başlık gibi eşlik etmeli. */
@media (max-width: 560px) {
  .brand-panel {
    padding: var(--space-5) var(--space-4);
  }

  .brand-lockup {
    margin-bottom: var(--space-3);
  }

  .brand-mark {
    width: 44px;
    height: 44px;
  }

  .brand-mark svg {
    width: 28px;
    height: 28px;
  }

  .brand-name {
    font-size: var(--text-2xl);
  }

  .slogan-title {
    font-size: var(--text-lg);
    margin-bottom: var(--space-2);
  }

  /* Slogan metni telefonda formu aşağı itmekten başka iş görmüyor. */
  .slogan-body {
    display: none;
  }
}

/* ---------- Tickets list ---------- */
.filter-bar {
  display: flex;
  align-items: flex-end;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.filter-group-search {
  flex: 1;
  min-width: 200px;
}

.search-box {
  position: relative;
}

/* Doğrudan çocuk: temizleme düğmesinin içindeki ikon bu kuralın mutlak
   konumunu almasın (bkz. .search-clear svg). */
.search-box > svg {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--color-text-muted);
  pointer-events: none;
  transition: color var(--transition-fast);
}

/* Yalnızca soldaki arama ikonu; temizleme düğmesinin içindeki çarpı
   kendi rengini koruyor (aksi halde odaktayken o da morarıyordu). */
.search-box:focus-within > svg {
  color: var(--color-accent);
}

.search-box input {
  width: 100%;
  padding: 9px 12px 9px 36px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background: var(--color-surface);
  color: var(--color-text);
}

/* Kutuda metin varken sağ tarafta yer açılıyor, yoksa temizleme düğmesi
   yazının üstüne biniyor. */
.search-box.has-value input {
  padding-right: 34px;
}

/* Temizleme (×) düğmesi - bkz. js/searchBox.js. Yalnızca kutuda metin
   varken görünüyor: boş bir kutuda temizlenecek bir şey yok. */
.search-clear {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  display: none;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  transition:
    color var(--transition-fast),
    background-color var(--transition-fast);
}

.search-box.has-value .search-clear {
  display: inline-flex;
}

.search-clear svg {
  /* .search-box svg kuralı arama ikonunu konumlandırıyor; buradaki ikon
     düğmenin içinde akışta durmalı, o kuralın mutlak konumunu iptal
     ediyoruz. */
  position: static;
  transform: none;
  width: 14px;
  height: 14px;
  color: inherit;
}

.search-clear:hover {
  color: var(--color-text);
  background: var(--color-accent-bg);
}

.search-clear:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

.filter-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Flex çocuğunun varsayılan min-width'i "auto": içindeki select uzun bir
     seçenek adı yüzünden gerildiğinde grup da onunla geriliyor ve çubuk
     taşıyordu. */
  min-width: 0;
}

/* Telefonda filtreler yan yana sığmıyor; her biri tam genişlik alıp alt
   alta diziliyor. Ara genişliklerde .filter-bar'ın kendi flex-wrap'i
   zaten yeterli. */
@media (max-width: 560px) {
  .filter-bar {
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-4);
    gap: var(--space-3);
  }

  /* Arama kutusunun tuttuğu 200px'lik alt sınır tek kolonda gereksiz. */
  .filter-group-search {
    min-width: 0;
  }

  /* Filtreleri temizle gibi tek başına duran butonlar satırı doldurmasın,
     kendi boyunda kalsın. */
  .filter-bar > .btn-secondary,
  .filter-bar > .btn-primary {
    align-self: flex-start;
  }
}

.filter-group label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
}

.filter-group select {
  padding: 8px 32px 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background-color: var(--color-surface);
  color: var(--color-text);
  min-width: 160px;
}

.filter-group select:focus {
  outline: none;
  border-color: var(--color-accent);
}

.filter-group > input[type="date"],
.filter-group > input[type="text"] {
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background-color: var(--color-surface);
  color: var(--color-text);
  color-scheme: light dark;
}

.filter-group > input[type="date"]:focus,
.filter-group > input[type="text"]:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: var(--focus-ring);
}

/* Tablo satır-içi düzenleme (Gruplar, Projeler vb.) için ortak input stili.
   .filter-group > input[type="text"] kuralı bu input'ları kapsamıyor çünkü
   bunlar bir hücre (<td>) içinde oluşturuluyor, .filter-group içinde değil -
   sonuç native/stilsiz bir kutu oluyordu. Hücreyi doldursun diye width: 100%. */
.table-edit-input {
  width: 100%;
  box-sizing: border-box;
  padding: 6px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background-color: var(--color-surface);
  color: var(--color-text);
}

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

/* Native <select> ve tarih popup'ında olduğu gibi, number input'un
   yukarı/aşağı ok spinner'ı da tarayıcı/OS çiziyor ve CSS ile temaya
   uydurulamıyor. Kendi ok ikonlarımızı çizmek yerine (değeri elle
   yazmak zaten yeterli) native spinner'ı tamamen gizliyoruz. */
input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  padding: 8px var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  font-family: var(--font-body);
  height: 37px;
}

/* İkon-only kare buton - .btn-secondary'nin yüksekliğini (37px) koruyup
   sadece genişliği/padding'i kareye eşitler. Filtre çubuğunda input/select
   ile aynı hizada durması için .pagination-btn (34px) yerine bunu kullan. */
.btn-icon-only {
  width: 37px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.btn-secondary:hover {
  background: var(--color-surface-alt);
}

/* Admin panelinde tablolar düzenle/sil/kaldır gibi .btn-secondary
   butonlarıyla dolu - şeffaf arkaplan + ince kenarlık burada "buton" gibi
   okunmuyordu. .btn-primary'yle aynı solid mor + hover'da hafif yukarı
   kalkma efektini kullanıyoruz, sadece admin sayfasında (bkz. admin.js'in
   kendi .admin-view sarmalayıcısı) - diğer sayfalardaki .btn-secondary'lere
   dokunmuyor. */
.admin-view .btn-secondary {
  background: var(--color-accent);
  color: #FFFFFF;
  border-color: var(--color-accent);
  box-shadow: var(--shadow-card);
  transition: background-color var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}

.admin-view .btn-secondary:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
  transform: translateY(-2px);
  box-shadow: var(--shadow-elevated);
}

.admin-view .btn-secondary:active {
  transform: translateY(0);
}

/* Silme/kaldırma gibi geri alınamaz işlemler için kırmızı varyant - Düzenle
   ile aynı satırda dururken renk farkı hangisinin yıkıcı olduğunu netleştiriyor.
   Admin paneline bağlı değil: proje detayındaki "üyeyi çıkar" gibi yıkıcı
   işlemler de aynı görünümü kullanıyor, o yüzden rengi kendisi tanımlıyor. */
.btn-secondary.btn-danger {
  background: var(--color-danger);
  color: #FFFFFF;
  border-color: var(--color-danger);
}

.btn-secondary.btn-danger:hover {
  background: var(--color-danger-hover);
  border-color: var(--color-danger-hover);
}

/* Tablo kendi içinde DİKEY kaydırılmaz (tasarım dili §1): sayfa başına satır
   sayısı zaten sabit, sayfanın kendi scroll'u yeterli. İç scroll ayrıca
   sayfayı iki ayrı kaydırma alanına bölüp tekerleğin hangisini süreceğini
   belirsizleştiriyordu.

   Yatay kaydırma ise kalıyor: dar ekranda çok kolonlu tablolar (yönetim
   paneli, proje detayı) hiçbir şekilde sığmıyor ve sayfanın tamamının yana
   kayması §10'a aykırı olurdu. Taşma tablonun kendi içinde kalıyor. */
.ticket-table-wrap {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow-x: auto;
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

/* Telefonda tablolar kendi içinde yana kayıyor (bkz. .ticket-table-wrap).
   Kaydırmayı büsbütün ortadan kaldırmak mümkün değil - yedi kolonlu bir
   talep tablosu 360px'e sığmıyor - ama hücre boşluklarını daraltarak kaç
   kolonun aynı anda görüneceğini artırıyoruz, böylece kaydırma mesafesi
   kısalıyor. Kolon gizlemiyoruz: hangi kolonun kime gereksiz olduğuna
   burada karar verilemez. */
@media (max-width: 560px) {
  thead th,
  tbody td {
    padding: var(--space-2) var(--space-3);
  }

  tbody td {
    font-size: var(--text-sm);
  }

  /* Kaydırılabilir olduğu belli olsun: kenarda kesilen içerik, tablonun
     devamı olduğunu kendiliğinden anlatmıyor. */
  .ticket-table-wrap {
    background-image: linear-gradient(to left, var(--color-surface-alt), transparent);
    background-size: 24px 100%;
    background-position: right center;
    background-repeat: no-repeat;
  }

  .pagination-bar {
    flex-wrap: wrap;
    gap: var(--space-3);
  }
}

.col-right {
  text-align: right;
}

.col-center {
  text-align: center;
}

.table-static tbody tr {
  cursor: default;
}

.admin-tabs {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--color-border);
  /* Sekme sayısı yetkiye göre altıya kadar çıkabiliyor; dar ekranda tek
     satıra sığmayınca sayfayı yana kaydırıyorlardı. Şeridin kendi içinde
     kayıyorlar, sekmeler de daralıp okunmaz hale gelmiyor. */
  overflow-x: auto;
  scrollbar-width: none;
}

.admin-tabs::-webkit-scrollbar {
  display: none;
}

.admin-tab {
  flex-shrink: 0;
}

/* Kullanıcı satırındaki grup değiştirme kutusu. Hücre konumlanma bağlamı
   oluyor, kutu da onun üstünde mutlak duruyor: satır yüksekliği düzenleme
   açılınca değişmiyor ve sonuç listesi tablo satırlarının üstüne binebiliyor
   (aksi halde tablo hücresi tarafından kırpılırdı). */
.group-cell {
  position: relative;
}

.group-picker-wrap {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: var(--space-4);
  right: var(--space-4);
  z-index: 5;
}

/* Telefonda hücre yatay boşluğu --space-3'e iniyor (bkz. tablo kuralları);
   kutu da hücreyle aynı hizada dursun diye onunla birlikte daralıyor. */
@media (max-width: 560px) {
  .group-picker-wrap {
    left: var(--space-3);
    right: var(--space-3);
  }
}

/* Proje Ayarları'nda düzenlenen projenin adı. Sekmenin içinde proje
   değiştirilemediği için (bkz. admin.js) hangi projede olunduğunu tek
   söyleyen şey bu başlık. */
.ps-project-heading {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-text);
  margin: 0 0 var(--space-4);
}

.admin-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.admin-tab:hover {
  color: var(--color-text);
}

.admin-tab.is-active {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

table {
  width: 100%;
  border-collapse: collapse;
}

/* Başlık satırı bir zamanlar sticky idi; anlamı vardı, çünkü tablo kendi
   içinde dikey kayıyordu. İç scroll kalkınca (bkz. .ticket-table-wrap)
   yapışma referansı sayfa oluyor ve başlıklar, üstlerindeki topbar yukarı
   kayıp gittikten sonra ekranın tepesinde havada asılı kalıyordu. */
thead th {
  text-align: left;
  font-size: 11px;
  font-weight: var(--weight-bold);
  color: var(--color-accent);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-alt);
  border-bottom: 2px solid var(--color-border);
}

.th-inner {
  display: flex;
  align-items: center;
  gap: 4px;
}

.col-center .th-inner {
  justify-content: center;
}

/* .col-right'ta text-align tek başına yetmiyor: başlık içeriği .th-inner
   flex kutusu, hizasını justify-content belirliyor. Sağa dayalı hücresi
   olan kolonun başlığı da sağa dayansın diye. */
.col-right .th-inner {
  justify-content: flex-end;
}

/* Sağa dayalı son kolonda başlık metni ile hücre metni aynı hizada dursun:
   hücrede tarihin sağında satır ok'u var (16px ikon + 8px gap = 24px),
   başlıkta ise sıralama ok'u (12px ikon + 4px gap = 16px). Aradaki 8px'lik
   farkı başlığa ekliyoruz. */
.table-fixed thead th.col-right .th-inner {
  padding-right: 8px;
}

/* Kolon genişlikleri th'lerdeki width'lerden gelsin diye (bkz.
   projectDetail.js TICKET_COLUMNS): otomatik yerleşimde uzun bir hücre
   ("Gecikti · 15.07.2026") kolonu orantısız genişletiyordu. */
.table-fixed {
  table-layout: fixed;
}

/* Sabit genişlikte uzun metin satırı ikiye katlayıp satır yüksekliklerini
   bozardı; tek satırda tutup üç noktayla kırpıyoruz. Hücrede title
   attribute'u var, tam metin hover'da görünüyor.
   :not([colspan]) - yükleniyor/boş/hata satırları tüm genişliği kaplayan
   ortalanmış kutular, onların metni sarmalı. */
.table-fixed tbody td:not([colspan]) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.col-sortable {
  cursor: pointer;
  user-select: none;
}

.col-sortable:hover {
  color: var(--color-accent-hover);
}

.sort-icon {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  opacity: 0.35;
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}

.col-sortable.is-active .sort-icon {
  opacity: 1;
}

.col-sortable.is-asc .sort-icon {
  transform: rotate(180deg);
}

/* ---------- Sayfalama ---------- */
.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-4);
  gap: var(--space-3);
  flex-wrap: wrap;
}

.pagination-info {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.pagination-btn {
  width: 34px;
  height: 34px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-lg);
  line-height: 1;
}

.pagination-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pagination-btn:disabled:hover {
  background: transparent;
}

.page-indicator {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  min-width: 48px;
  text-align: center;
}

tbody td {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-base);
  border-bottom: 1px solid var(--color-border);
  vertical-align: middle;
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr {
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

tbody tr:hover {
  background: var(--color-surface-alt);
}

.ticket-title {
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  transition: color var(--transition-fast);
}

tbody tr:hover .ticket-title {
  color: var(--color-accent);
}

.assignee-cell {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.assignee-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--color-accent-bg);
  color: var(--color-accent);
  font-size: 10px;
  font-weight: var(--weight-bold);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.ticket-id {
  display: inline-flex;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  background: var(--color-surface-alt);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  margin-right: var(--space-2);
}

.status-dot {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--color-text);
}

.status-dot::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--dot-color, var(--color-text-muted));
}

.row-end {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
}

.row-chevron {
  opacity: 0;
  color: var(--color-text-muted);
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}

tbody tr:hover .row-chevron {
  opacity: 1;
  transform: translateX(2px);
}

.due-cell {
  font-weight: var(--weight-semibold);
}

.due-overdue { color: var(--sla-overdue); }
.due-soon { color: var(--sla-urgent); }
.due-ok { color: var(--sla-ok); }
.due-done { color: var(--sla-done); font-weight: var(--weight-medium); }

/* ---------- Notifications ---------- */
.notification-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.notification-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.notification-unread {
  border-left: 3px solid var(--color-accent);
}

.notification-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.notification-message {
  color: var(--color-text);
  font-size: var(--text-base);
}

.notification-meta {
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.state-message {
  padding: var(--space-7);
  text-align: center;
  color: var(--color-text-muted);
  font-size: var(--text-base);
}

/* ---------- Ticket detail ---------- */
/* Geri linki, proje ve makale detayındaki .project-back-link ile aynı
   görünüyor: nötr gri metin, hover'da mor. Daha önce mor zeminli bir
   düğme gibi duruyordu ve aynı işi yapan iki bağlantı iki farklı şeye
   benziyordu. */
.back-link,
.project-back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--transition-fast);
}

.back-link:hover,
.project-back-link:hover {
  color: var(--color-accent);
}

.back-link svg,
.project-back-link svg {
  width: 16px;
  height: 16px;
}

.detail-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--space-5);
  align-items: start;
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  box-shadow: var(--shadow-card);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.card + .card {
  margin-top: var(--space-5);
}

/* Dashboard */
.dashboard-kpi-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

/* Genel ".card + .card { margin-top }" kuralı (kart yığınları için) burada
   da eşleşip grid'deki 2., 3., 4. ... kartları aşağı kaydırıp sıraları
   "kayık" gösteriyordu - grid içindeki kartlarda bunu iptal ediyoruz. */
.dashboard-kpi-grid > .card,
.dashboard-chart-grid > .card {
  margin-top: 0;
}

/* Etiket üstte, rakam altta ve altçizgi her kartta aynı hizada: eskiden
   kartlar yalnızca içeriklerine göre diziliyordu, etiket iki satıra taşan
   kartın rakamı komşularından aşağıda kalıyordu. margin-top:auto altçizgiyi
   kartın dibine sabitliyor. */
.kpi-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.kpi-tile .kpi-underline {
  margin-top: auto;
}

/* Kritik ve SLA riski sıfırdan büyükken kendi rengini alıyor; sıfırken
   diğer kartlardan ayrışmıyor (bkz. dashboard.js kpiCard). */
.kpi-tile.is-alerting .kpi-value {
  color: var(--kpi-color);
}

.kpi-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.kpi-value {
  font-family: var(--font-heading);
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  color: var(--color-text);
}

.kpi-underline {
  display: block;
  width: 32px;
  height: 3px;
  border-radius: 999px;
  margin-top: var(--space-1);
  background: var(--kpi-color, var(--color-accent));
}

.dashboard-chart-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  /* align-items varsayılanı (stretch) bilinçli olarak korunuyor - durum ve
     öncelik kartlarının satır sayısı farklı olsa bile (ör. biri 2, diğeri 5
     satır) her ikisi de aynı sıradaki en uzun kartın yüksekliğine uzanıp alt
     kenarları hizalı kalsın diye. */
}

.dashboard-chart-grid > .card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.dashboard-card-title {
  font-family: var(--font-heading);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  margin: 0 0 var(--space-4);
}

.bar-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.bar-row {
  display: grid;
  grid-template-columns: 100px 1fr 32px 40px;
  align-items: center;
  gap: var(--space-3);
}

.bar-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bar-track {
  height: 8px;
  border-radius: var(--radius-sm);
  background: var(--color-surface-alt);
  overflow: hidden;
}

.bar-fill {
  height: 100%;
  border-radius: var(--radius-sm);
  transition: width var(--transition-base);
}

.bar-count {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-align: right;
}

/* Sayının yanındaki pay oranı. Sayıdan daha soluk: asıl bilgi adet, oran
   onu bağlama oturtan ikincil bilgi. */
.bar-percent {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.dashboard-recent-card {
  margin-top: var(--space-5);
}

/* Panelde en çok okunan üç makale, bilgi bankasındaki kartların aynısıyla
   yan yana duruyor. Sayı üçle sınırlı (bkz. DashboardService), o yüzden
   auto-fill yerine sabit üç kolon: dördüncü bir kart gelmeyeceği için
   esnek ızgaraya gerek yok. */
.dashboard-article-grid {
  display: grid;
  /* minmax(0, 1fr), düz "1fr" değil: 1fr aslında minmax(auto, 1fr) demek ve
     o auto alt sınırı, kolonun içeriğinden dar olmasını engelliyor. Tek
     satıra alınan başlıklar (white-space: nowrap) bu yüzden kırpılmak
     yerine kolonu kendi genişliklerine kadar açıp ızgarayı taşırıyordu. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  /* Izgara satırı en uzun kartın boyunu alıyor; stretch (varsayılan) ile
     diğer kartlar da o boya uzuyor, yani üç kartın alt kenarı hizalı
     kalıyor. */
  align-items: stretch;
}

/* Kart bir "card" içinde duruyor; kendi gölgesi o zeminde fazladan bir
   katman gibi görünüyordu. Çerçeve kalıyor, gölge sadece hover'da. */
.dashboard-article-card {
  box-shadow: none;
}

/* Panel kartı üç kolona sığdığı için bilgi bankasındakinden dar: önizleme
   üç satır yerine iki satır gösteriliyor, alt sınırı da ona göre. */
.dashboard-article-card .project-card-description {
  -webkit-line-clamp: 2;
  line-clamp: 2;
  min-height: 3em;
}

@media (max-width: 1100px) {
  .dashboard-article-grid {
    grid-template-columns: 1fr;
  }
}

.recent-ticket-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  /* Yatay iç boşluk hover zemininin satırı boydan boya kaplaması için;
     negatif margin ile kartın kendi hizasına geri çekiliyor, yani
     yazılar eskisi gibi kartın kenarıyla hizalı duruyor. */
  padding: var(--space-3);
  margin: 0 calc(-1 * var(--space-3));
  border-bottom: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

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

/* Talep tablosundaki satırla aynı geri bildirim: zemin renkleniyor,
   başlık moralıyor, sağdaki ok beliriyor. Panel satırları tıklanabilir
   olmasına rağmen zemini değişmediği için tablodan farklı davranıyordu. */
.recent-ticket-row:hover {
  background: var(--color-surface-alt);
}

.recent-ticket-row:hover .ticket-title {
  color: var(--color-accent);
}

.recent-ticket-row:hover .row-chevron {
  opacity: 1;
  transform: translateX(2px);
}

.recent-ticket-title-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.recent-ticket-title-wrap .ticket-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Meta bloğu flex iken her hücre kendi içeriği kadar yer kaplıyordu:
   "Kritik"/"Düşük", "Açık"/"Beklemede" gibi farklı uzunluktaki rozetler
   yüzünden öncelik, durum ve son tarih hiçbir satırda aynı hizada
   başlamıyor, liste sütunsuz ve dağınık görünüyordu. Sabit genişlikli
   ızgara üçünü de her satırda aynı yere oturtuyor. */
.recent-ticket-meta {
  display: grid;
  grid-template-columns: 92px 118px 148px 16px;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
}

/* Rozetler kendi hücrelerinin soluna yaslanıyor; ortalanınca hücre
   genişliği sabit olsa bile metinler yine kaymış görünüyordu. */
.recent-ticket-meta .badge,
.recent-ticket-meta .status-dot {
  justify-self: start;
}

/* Uzun bir rozet metni hücresini gerip ızgarayı bozmasın. */
.recent-ticket-meta .badge {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Genişliği artık ızgara kolonu belirliyor; min-width ikisi birden
   uygulanınca hücreyi kolonundan taşırıyordu. */
.recent-ticket-meta .due-cell {
  text-align: right;
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Panel listelerinde (son talepler, en çok okunanlar) satır başlık + meta
   olarak yan yana duruyor. Telefonda meta bloğu (rozet, durum, son tarih,
   ok) başlığa yer bırakmıyordu; alt satıra alıp başlığı tam genişliğe
   kavuşturuyoruz. */
@media (max-width: 560px) {
  .recent-ticket-row {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
  }

  /* Telefonda sabit kolonlar sığmıyor: ızgaradan çıkıp içeriğe göre
     sarmalanan bir satıra dönüyor. */
  .recent-ticket-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    width: 100%;
    justify-content: flex-start;
  }

  .recent-ticket-meta .due-cell {
    text-align: left;
  }

  /* Satır ok'u yalnızca hover'da beliriyor; dokunmatikte hover olmadığı
     için yer kaplamaktan başka iş görmüyor. */
  .recent-ticket-meta .row-chevron {
    display: none;
  }
}

/* Beş KPI kartı 1100px altında sığmıyor. Doğrudan 2 kolona düşmek yerine
   3'e uğruyoruz: 5 kart 2 kolonda 3 satır ediyor ve son satırda tek başına
   kalan kart yarım kutu gibi duruyordu. */
@media (max-width: 1100px) {
  .dashboard-kpi-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .dashboard-chart-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 900px) {
  .dashboard-kpi-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 560px) {
  /* Telefonda iki KPI yan yana okunabiliyor - tek kolona indirmek beş kartı
     beş ekrana yayıp özet olma amacını bozardı. Rakam bir tık küçülüyor. */
  .kpi-value {
    font-size: var(--text-2xl);
  }

  /* Etiket, sayı ve oran için 100px'lik sabit etiket kolonu telefonda
     çubuğa yer bırakmıyordu. */
  .bar-row {
    grid-template-columns: 84px 1fr auto;
    gap: var(--space-2);
  }

  /* Oran yüzdesi telefonda düşüyor: sayının kendisi zaten orada ve
     çubuğun uzunluğu payı gösteriyor. */
  .bar-percent {
    display: none;
  }
}

.ticket-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

/* Talep listesindeki .ticket-id rozetiyle aynı görsel dil: kaydın kısa
   teknik kimliği düz metin yerine gri kutucukta durunca başlıktan ayrıştığı
   hemen anlaşılıyor (proje kodu rozeti de aynı desende). */
.ticket-id-large {
  display: inline-block;
  color: var(--color-text-muted);
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 2px 8px;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

.ticket-title-large {
  font-family: var(--font-heading);
  font-weight: var(--weight-bold);
  font-size: var(--text-2xl);
  margin: 4px 0 0;
}

.badge-row {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

.section-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin: 0 0 var(--space-2);
}

.description-text {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--color-text);
  white-space: pre-wrap;
}

.meta-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.meta-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.meta-row .meta-label {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.meta-row .meta-value {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
}

.action-form {
  display: flex;
  align-items: stretch;
  gap: var(--space-2);
}

/* enhanceSelect native select'i gizleyip yanına kendi tetikleyicisini
   koyuyor; aşağıdaki ".action-form select" kuralları o katmana geçmediği
   için açılır liste ile Kaydet butonu farklı yüksekliklerde kalıyordu.
   Sarmalayıcı satırı doldurup tetikleyici de yüksekliği devralıyor. */
.action-form .custom-select {
  flex: 1;
  min-width: 0;
}

.action-form .custom-select-trigger {
  height: 100%;
}

.action-form select {
  flex: 1;
  padding: 8px 32px 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background-color: var(--color-surface);
  color: var(--color-text);
}

.action-form select:focus {
  outline: none;
  border-color: var(--color-accent);
}

/* Talep detayındaki eylem düğmeleri (Kaydet, Ata, Gönder, Yükle).
   Yorum ve ek yükleme düğmelerinin hiçbir kuralı yoktu; tarayıcının
   varsayılan gri düğmesi olarak çiziliyor ve aktif olmalarına rağmen
   devre dışıymış gibi duruyorlardı.

   Seçici DOĞRUDAN çocukla (>) sınırlı: enhanceSelect, native select'i
   gizleyip yerine <button class="custom-select-trigger"> koyuyor.
   Sınırsız "button" seçicisi o tetikleyiciyi de yakalayıp açılır
   listeyi kapalıyken dolu mor bir düğmeye çeviriyordu. */
.action-form > button,
.comment-form-footer > button,
.upload-row > button {
  background: var(--color-accent);
  color: #FFFFFF;
  border: none;
  padding: 8px var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  font-family: var(--font-body);
  white-space: nowrap;
  transition:
    background-color var(--transition-fast),
    transform var(--transition-fast);
}

.action-form > button:hover,
.comment-form-footer > button:hover,
.upload-row > button:hover {
  background: var(--color-accent-hover);
}

/* Basılı tutulurken hafif içeri gitme: tıklamanın kaydedildiği belli olsun. */
.action-form > button:active,
.comment-form-footer > button:active,
.upload-row > button:active {
  transform: translateY(1px);
}

.action-form > button:focus-visible,
.comment-form-footer > button:focus-visible,
.upload-row > button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.action-form > button:disabled,
.comment-form-footer > button:disabled,
.upload-row > button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

/* Kart içi mesaj kutusu. Talep detayı sabit şeride (.toast-stack) geçti
   ama yönetim, bilgi bankası, projeler ve yeni talep sayfaları hâlâ bu
   kutuyu kullanıyor - kural onlar için duruyor. */
.toast {
  font-size: var(--text-sm);
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  margin-top: 10px;
  display: none;
}

.toast.success {
  background: var(--status-resolved-bg);
  color: var(--status-resolved-fg);
}

.toast.error {
  background: var(--priority-critical-bg);
  color: var(--priority-critical-fg);
}

/* ---------- Bildirim şeridi (toast) ----------
   Bkz: js/toast.js. Mesajlar eskiden ilgili kartın altındaki bir kutuda
   gösteriliyordu; kart sayfanın aşağısında kaldığı için mesaj çoğu zaman
   ekranın dışında kalıyor ve hiç kaybolmuyordu. Artık sayfaya sabit,
   kendiliğinden kayboluyor. */
.toast-stack {
  position: fixed;
  /* Yatayda ortalı: sağ üst köşede gözden kaçıyordu, ekranın ortası ise
     okunan içeriğin üstünü kapatıyor. Üstte ortalı ikisini de çözüyor.
     left/transform yerine left+right+margin:auto: transform kullanılırsa
     mesajların kendi giriş animasyonundaki transform ile çakışıyor. */
  top: var(--space-5);
  left: 0;
  right: 0;
  margin: 0 auto;
  width: fit-content;
  z-index: 1100;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  /* Şeridin kendisi tıklamayı yutmasın, yalnızca mesajlar tıklanabilir. */
  pointer-events: none;
  max-width: min(360px, calc(100vw - var(--space-6)));
}

.toast-item {
  pointer-events: auto;
  padding: 10px var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  box-shadow: var(--shadow-elevated);
  border: 1px solid transparent;
  cursor: pointer;
  text-align: center;
  /* Giriş/çıkış: yukarıdan inerek gelir - şerit üstte olduğu için
     hareket yönü geldiği yerle aynı. is-visible sınıfını JS ekliyor. */
  opacity: 0;
  transform: translateY(-12px);
  transition:
    opacity var(--transition-fast),
    transform var(--transition-fast);
  word-break: break-word;
}

.toast-item.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.toast-success {
  background: var(--status-resolved-bg);
  color: var(--status-resolved-fg);
  border-color: var(--status-resolved-fg);
}

.toast-error {
  background: var(--priority-critical-bg);
  color: var(--priority-critical-fg);
  border-color: var(--priority-critical-fg);
}

.toast-warning {
  background: var(--priority-medium-bg);
  color: var(--priority-medium-fg);
  border-color: var(--priority-medium-fg);
}

/* Telefonda şerit iki yana yayılıyor: 360px'lik sabit genişlik ekranın
   büyük kısmını kaplayıp sağa taşıyordu. */
@media (max-width: 560px) {
  /* Telefonda şerit alta geçiyor ve iki yana yayılıyor: üstte ortalı
     sabit genişlik, dar ekranda başlığın üstüne biniyordu.
     width'i fit-content'ten auto'ya çevirmek şart - miras kalırsa
     left/right ile verilen genişlik uygulanmıyor. */
  .toast-stack {
    top: auto;
    bottom: var(--space-4);
    left: var(--space-4);
    right: var(--space-4);
    width: auto;
    margin: 0;
    max-width: none;
  }

  /* Alttan geldiği için hareket yönü de tersine dönüyor. */
  .toast-item {
    transform: translateY(12px);
  }

  .toast-item.is-visible {
    transform: translateY(0);
  }
}

/* Hareketi azalt tercihi açıkken kaydırma animasyonu yapılmıyor,
   yalnızca görünürlük değişiyor. */
@media (prefers-reduced-motion: reduce) {
  .toast-item {
    transform: none;
    transition: opacity var(--transition-fast);
  }

  .toast-item.is-visible {
    transform: none;
  }
}

/* ---------- Onay diyaloğu (native window.confirm() yerine) ----------
   Bkz: js/confirmDialog.js - native confirm() adres çubuğu gösterip
   stillenemediği için, aynı customSelect/customDatePicker mantığıyla kendi
   overlay + kart bileşenimizi kullanıyoruz. */
.confirm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(11, 14, 20, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 1000;
  animation: confirm-fade-in var(--transition-fast) ease;
}

@keyframes confirm-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.confirm-dialog {
  width: 100%;
  max-width: 380px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-elevated);
  padding: var(--space-5);
  text-align: center;
  animation: confirm-pop-in var(--transition-base) ease;
}

@keyframes confirm-pop-in {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.confirm-dialog-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto var(--space-4);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-accent-bg);
  color: var(--color-accent);
}

.confirm-dialog-icon.is-danger {
  background: var(--priority-critical-bg);
  color: var(--priority-critical-fg);
}

.confirm-dialog-icon svg {
  width: 22px;
  height: 22px;
}

.confirm-dialog-message {
  font-size: var(--text-md);
  color: var(--color-text);
  line-height: 1.5;
  margin: 0 0 var(--space-5);
}

.confirm-dialog-actions {
  display: flex;
  gap: var(--space-3);
}

.confirm-dialog-actions button {
  flex: 1;
}

.confirm-dialog-actions .btn-primary.btn-danger {
  background: var(--color-danger);
}

.confirm-dialog-actions .btn-primary.btn-danger:hover {
  background: var(--color-danger-hover);
}

.comment-list, .attachment-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: var(--space-4);
}

.comment-item {
  padding-bottom: 14px;
  border-bottom: 1px solid var(--color-border);
}

.comment-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.comment-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 4px;
}

.comment-author {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.comment-date {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.comment-message {
  font-size: var(--text-base);
  line-height: 1.5;
  white-space: pre-wrap;
}

.internal-badge {
  font-size: 11px;
  font-weight: var(--weight-semibold);
  padding: 2px var(--space-2);
  border-radius: 999px;
  background: var(--status-pending-bg);
  color: var(--status-pending-fg);
}

.comment-form textarea {
  width: 100%;
  padding: 10px var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background: var(--color-surface);
  color: var(--color-text);
  resize: vertical;
  min-height: 70px;
  margin-bottom: var(--space-2);
}

.comment-form textarea:focus {
  outline: none;
  border-color: var(--color-accent);
}

.comment-form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* "Dahili not" işareti: tarayıcının varsayılan onay kutusu her işletim
   sisteminde başka türlü görünüyor ve sayfanın geri kalanındaki mor/nötr
   dile hiç uymuyordu. Kutuyu kendimiz çiziyoruz (customSelect ve
   customDatePicker'daki yaklaşımın aynısı). */
.checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  cursor: pointer;
  user-select: none;
  transition: color var(--transition-fast);
}

.checkbox-label:hover {
  color: var(--color-text);
}

.checkbox-label input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  cursor: pointer;
  position: relative;
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast);
}

.checkbox-label:hover input[type="checkbox"] {
  border-color: var(--color-accent);
}

.checkbox-label input[type="checkbox"]:checked {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

/* Tik, border-box içine çizilen bir "L" harfinin döndürülmüş hâli:
   ayrı bir SVG/ikon dosyası gerekmiyor. */
.checkbox-label input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid #FFFFFF;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Klavyeyle gezinenler için görünür odak halkası. */
.checkbox-label input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.attachment-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.attachment-meta {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.attachment-link {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-accent);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--font-body);
}

.attachment-link:hover {
  text-decoration: underline;
}

.upload-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* Dosya seçici: native input'un "Choose file / Dosya seçilmedi" parçası
   tarayıcıdan tarayıcıya değişiyor, stillenemiyor ve sayfadaki diğer
   alanlara hiç benzemiyordu. ::file-selector-button ile input'un kendi
   düğmesini sayfanın diline çekiyoruz - JS'e veya gizli input +
   sahte düğme kurgusuna gerek kalmıyor. */
.upload-row input[type="file"] {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-family: var(--font-body);
  color: var(--color-text-muted);
  padding: 6px 8px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  cursor: pointer;
  transition:
    border-color var(--transition-fast),
    background-color var(--transition-fast);
}

.upload-row input[type="file"]:hover {
  border-color: var(--color-accent);
}

.upload-row input[type="file"]:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.upload-row input[type="file"]::file-selector-button {
  margin-right: var(--space-3);
  padding: 6px var(--space-3);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: var(--color-accent-bg);
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-family: var(--font-body);
  cursor: pointer;
  transition:
    background-color var(--transition-fast),
    color var(--transition-fast);
}

.upload-row input[type="file"]:hover::file-selector-button {
  background: var(--color-accent);
  color: #FFFFFF;
}

@media (max-width: 900px) {
  .detail-grid {
    grid-template-columns: 1fr;
  }
}

/* Talep detayı telefonda: yan yana duran her şey alt alta iniyor.
   Ayrı ayrı küçük kurallar yerine tek blok, çünkü hepsi aynı sayfanın
   aynı daralma anındaki davranışı. */
@media (max-width: 560px) {
  /* Başlık ile durum/öncelik rozetleri: uzun bir başlık rozetleri ezip
     kendi de iki-üç satıra bölünüyordu. */
  .ticket-header {
    flex-direction: column;
    gap: var(--space-3);
  }

  .ticket-title-large {
    font-size: var(--text-xl);
  }

  /* Durum güncelleme / atama: açılır liste ile buton yan yana sığmıyor. */
  .action-form {
    flex-direction: column;
    align-items: stretch;
  }

  /* Dosya seçici zaten geniş bir kontrol; butonla yan yana kalınca
     ikisi de kullanılamayacak kadar daralıyordu. */
  .upload-row {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }

  /* Dahili not kutusu ile Gönder düğmesi arasına boşluk girmezse
     düğme kutunun dibine yapışıyor. */
  .comment-form-footer {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }
}

/* ---------- New ticket form ---------- */
.form-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  max-width: 640px;
  box-shadow: var(--shadow-card);
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.form-card .form-group {
  margin-bottom: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-card label {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.form-card input,
.form-card select,
.form-card textarea {
  padding: 10px var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  background-color: var(--color-surface);
  color: var(--color-text);
}

.form-card select {
  padding-right: 32px;
}

.form-card textarea {
  resize: vertical;
  min-height: 100px;
}

.form-card input:focus,
.form-card select:focus,
.form-card textarea:focus {
  outline: none;
  border-color: var(--color-accent);
}

.form-card select:disabled {
  background-color: var(--color-surface-alt);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

/* Formdaki gönder butonu artık .btn-primary kullanıyor (uygulamanın geri
   kalanıyla aynı buton dili); burada yalnızca kart içindeki hizası veriliyor.
   Eskiden button[type="submit"]'e özel bir görünüm vardı, .btn-primary'yi
   eziyordu - kaldırıldı. */
.form-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

/* Form içindeki bölüm başlığı: alanları anlamsal gruplara ayırıyor
   (kapsam / sınıflandırma / detaylar) - uzun formda gözü yönlendiriyor. */
.form-section-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--color-accent);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: var(--space-5) 0 var(--space-3);
}

.form-section-title:first-child {
  margin-top: 0;
}

.form-hint {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* Talep formu iki kolonlu satırlar ve uzun bir açıklama alanı taşıyor;
   varsayılan 640px'te açıklama kutusu dar kalıyordu. */
.form-card-wide {
  max-width: 760px;
}

.form-card button[type="submit"]:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

@media (max-width: 560px) {
  .form-row {
    grid-template-columns: 1fr;
  }

  /* Form kartının iç boşluğu telefonda alanın önemli bir kısmını yiyordu. */
  .form-card {
    padding: var(--space-4);
  }
}

/* ---------- Projeler sayfası (kart grid) ----------
   Talepler tablo olarak listeleniyor; projeler ise sayıca az ve her biri
   özet sayaç taşıdığı için kart olarak gösteriliyor. */

/* min(300px, 100%): 300px'ten dar bir alanda sabit 300px'lik kolon sığmayıp
   ızgarayı taşırıyordu. min() ile kolon, alan daraldığında onunla birlikte
   daralıyor. */
.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: var(--space-4);
}

/* Yükleme/boş/hata kutusu grid'in tamamını kaplasın. */
.project-grid-state {
  grid-column: 1 / -1;
}

.project-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: inherit;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}

.project-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-elevated);
  border-color: var(--color-accent);
}

/* Pasif projeler soluk görünüyor ama tıklanabilir kalıyor. */
.project-card.is-inactive {
  opacity: 0.65;
}

.project-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Yüksekliği, yanındaki ad + kod bloğuyla aynı hizada bitecek şekilde
   seçildi (ad satırı + boşluk + kod rozeti ≈ 44px). */
.project-card-mark {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--color-accent);
  color: #FFFFFF;
  font-family: var(--font-heading);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  letter-spacing: 0.5px;
}

.project-card-title-wrap {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  flex: 1;
}

.project-card-name {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Proje kodu, talep listesindeki #12 rozetiyle (.ticket-id) aynı görsel dili
   kullanıyor: ikisi de kaydın kısa, teknik kimliği - düz metin yerine gri
   kutucuk içinde durunca addan ayrıştığı hemen anlaşılıyor. */
.project-card-code {
  display: inline-flex;
  align-self: flex-start;
  /* --text-xs (12px) rozet için bir tık iri kalıyordu; ölçek değişkenlerinin
     altında bir kademe olduğu için doğrudan yazıldı. */
  font-size: 11px;
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  background: var(--color-surface-alt);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  letter-spacing: 0.6px;
  text-transform: uppercase;
}

.project-card-status {
  flex-shrink: 0;
}

.project-card-status.is-active {
  background: var(--status-resolved-bg);
  color: var(--status-resolved-fg);
  border: 1px solid var(--status-resolved-fg);
}

.project-card-status.is-passive {
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.project-card-description {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: 1.5;
  /* İki satırdan uzun açıklamalar kartları farklı boylara sokmasın. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em;
}

.project-card-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-2);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.project-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: center;
}

.project-stat-value {
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-text);
}

.project-stat-label {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* Alt band kartın iki kenarına kadar uzanıyor: kartın kendi yatay padding'i
   negatif margin ile geri alınıp bandın kendi padding'i veriliyor. Gri zemin
   bandı gövdeden ayırdığı için ayrıca üst çizgi yok - üstündeki sayaç
   bloğunun border-top'u zaten orada. Alt köşeler kartın yuvarlaklığını
   izliyor, yoksa zemin köşelerden taşardı. */
.project-card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0 calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-alt);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.project-card-footer-date {
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

/* ---------- Proje detay sayfası ---------- */

.project-detail-loading {
  padding: var(--space-6) 0;
}

/* .project-back-link stilleri .back-link ile birleştirildi
   (bkz. "Ticket detail" bölümü) - iki bağlantı aynı işi yapıyor. */

.project-detail-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}


/* Detay başlığında kod rozeti, yanındaki durum rozetiyle (.badge) yan yana
   duruyor - kartta olduğu gibi daha küçük kalınca ikisinin üst/alt kenarları
   tutmuyor ve hiza bozuk görünüyordu. Burada .badge'in ölçülerini eşliyoruz:
   aynı font, aynı dikey padding, aynı yuvarlak köşe. Şeffaf kenarlık,
   durum rozetindeki 1px'lik kenarlığın yüksekliğini telafi ediyor. */
.project-detail-head .project-card-code {
  font-size: var(--text-xs);
  padding: var(--space-1) var(--space-3);
  border: 1px solid transparent;
  border-radius: 999px;
}


.clickable-row {
  cursor: pointer;
}


.member-cell {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.member-avatar {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}

/* ---------- Yeni proje modalı ----------
   Onay diyaloğuyla (confirm-overlay) aynı görsel dil, ama form içerdiği
   için daha geniş ve sola hizalı. */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(11, 14, 20, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: 1000;
  animation: confirm-fade-in var(--transition-fast) ease;
}

.modal-card {
  width: 100%;
  max-width: 440px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-elevated);
  padding: var(--space-5);
  animation: confirm-pop-in var(--transition-base) ease;
  /* Alçak ekranda (telefon yatay, küçük dizüstü) uzun bir modal ekranı
     taşırıyor ve alttaki Kaydet/Vazgeç düğmelerine ulaşılamıyordu. Kart
     görünen alanı aşmayıp kendi içinde kayıyor. */
  max-height: calc(100vh - 2 * var(--space-4));
  overflow-y: auto;
}

.modal-title {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
}

.modal-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

/* Aktivite Kaydı "Detay" sütunu: birden çok alan değiştiyse metin uzun
   olabiliyor ve tabloyu yatay scroll'a sokuyordu. Tek satırda kırpılıyor,
   tam hâli title'da (bkz. admin.js). */
.audit-details-cell {
  max-width: 320px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ---------- Alan bazlı doğrulama ----------
   Bkz: js/formValidation.js. Formlar eskiden tek bir genel mesaj
   gösteriyordu ("ad ve kod zorunlu"); hangi alanın eksik olduğu alanın
   kendisinden anlaşılmıyordu. */
.has-error,
.has-error:focus {
  border-color: var(--priority-critical-fg);
}

/* enhanceSelect native select'i gizleyip yerine kendi tetikleyicisini
   koyuyor; hata sınıfı gizli select'te kaldığı için çerçeveyi görünür
   olan tetikleyiciye taşıyoruz. */
.custom-select:has(.has-error) .custom-select-trigger {
  border-color: var(--priority-critical-fg);
}

.field-error {
  margin: 4px 0 0;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--priority-critical-fg);
}

/* ---------- Bilgi bankası ----------
   Kart ızgarası proje kartlarıyla aynı iskeleti (.project-grid /
   .project-card / .project-card-head …) kullanıyor; burada yalnızca
   makaleye özgü farklar tanımlı: etiket satırı, yazar satırı ve okuma
   görünümü. */

/* Başlık tek satır: iki satıra izin verildiğinde kısa başlıklı kartlarda
   ikinci satır boş kalıyor ve blok kartın tepesine yapışıyordu. Sığmayan
   başlık "…" ile kırpılıyor, tam hâli title attribute'unda. */
.article-card .project-card-name {
  min-height: 0;
}

/* Ad + yazar bloğu 44px'lik avatarla aynı yüksekliği tutup içeriğini
   ortalıyor, böylece iki satırlık metin avatarla dikeyde hizalı duruyor. */
.article-card .project-card-title-wrap {
  min-height: 44px;
  justify-content: center;
}

/* Makale içeriği düz metin ve satır sonları anlam taşıyor (numaralı adımlar,
   maddeler). pre-wrap onları koruyor; aksi halde "1. ... 2. ..." tek bir
   paragrafa dönüşüp okunmaz hale geliyordu. */
.article-card .project-card-description {
  -webkit-line-clamp: 3;
  line-clamp: 3;
  min-height: 4.5em;
  white-space: pre-wrap;
}

/* Başlık tek satırda kalıp sığmayan kısmı "…" ile kırpılıyor. İki satıra
   izin verilmesi denendi ama kartların çoğunda ikinci satır boş kalıyor,
   dolu olanla arasında dengesiz bir görüntü oluşuyordu. Tam başlık
   title attribute'unda duruyor (bkz. knowledgeBase.js / dashboard.js). */
.article-card-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
}

.article-card-author {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Kartın alt şeridi: solda proje/kategori etiketleri, sağda tarih.
   Kart yüksekliklerini eşitlemek için üst boşluğu otomatik. */
.article-card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

/* Etiketler tek satırda kalıyor: sarmalarına izin verilince uzun proje +
   kategori adı olan kart (ör. "Monitoring Platformu" + "Nöbet & Eskalasyon")
   iki satıra çıkıp ızgaradaki diğer kartlardan yüksek duruyordu. Sığmayan
   ad, etiketin kendi içinde "…" ile kırpılıyor. */
.article-card-tags {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2);
  min-width: 0;
  overflow: hidden;
}

/* Tek etiket varsa tüm şeridi kullanabilsin, iki etiket varsa alanı
   paylaşsınlar: ikisi de kırpılabilir ama kategori önce daralıyor
   (proje adı, makalenin nereye ait olduğunu anlatan asıl bilgi). */
.article-card-tags .article-tag {
  flex: 0 1 auto;
  min-width: 0;
}

/* Görüntülenme sayısı ikincil bilgi: satırın neden bu sırada olduğunu
   söylüyor ama başlığın önüne geçmemeli. */
.article-view-count {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.article-card-tags .article-tag.is-muted {
  flex-shrink: 2;
}

.article-card-date {
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* Proje/kategori etiketi. Proje kodu rozetiyle (.project-card-code) aynı
   görsel dil, ama büyük harfe çevrilmiyor: burada gösterilen şey bir kod
   değil, insan tarafından okunan bir ad. */
/* display: block (inline-flex değil) - inline-flex'te text-overflow: ellipsis
   çalışmıyor, metin kırpılmak yerine taşıyordu. */
.article-tag {
  display: block;
  max-width: 100%;
  font-size: 11px;
  font-weight: var(--weight-semibold);
  color: var(--color-accent);
  background: var(--color-surface-alt);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.article-tag.is-muted {
  color: var(--color-text-muted);
}

/* ---------- Makale okuma görünümü ---------- */

.article-detail {
  max-width: 760px;
  padding: var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.article-detail-head {
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.article-detail-title {
  margin: 0 0 var(--space-3);
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  line-height: 1.3;
}

.article-detail-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.article-detail-author,
.article-detail-date {
  color: var(--color-text-muted);
}

/* İçerik düz metin olarak saklanıyor (Markdown/HTML değil). pre-wrap,
   yazarın koyduğu satır sonlarını ve adım numaralarının hizasını koruyor;
   metin textContent ile basıldığı için HTML yorumlanmıyor. */
.article-detail-content {
  white-space: pre-wrap;
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--color-text);
  overflow-wrap: anywhere;
}

/* Makalenin altındaki aksiyon şeridi. İçerikten bir ayraçla ayrılıyor ve
   sağa yaslanıyor - formlardaki .modal-actions ile aynı hizalama dili. */
.article-detail-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.article-detail-actions .btn-secondary {
  gap: 6px;
}

.article-detail-actions .btn-secondary svg {
  width: 15px;
  height: 15px;
}

/* ---------- Makale formu (yeni makale modalı + satır içi düzenleme) ---------- */

.article-modal-card {
  max-width: 640px;
}

.article-edit-form {
  max-width: 760px;
  padding: var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Proje ve kategori yan yana: ikisi birlikte tek bir seçim (hangi projenin
   hangi kategorisi) oluşturuyor, alt alta konunca form gereksiz uzuyordu. */
.article-edit-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}

/* .filter-group içinde textarea için bir kural yoktu; select/input ile aynı
   kutu görünümünü veriyoruz ki form karışık görünmesin. */
.article-content-input {
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: var(--font-body);
  line-height: 1.6;
  background-color: var(--color-surface);
  color: var(--color-text);
  resize: vertical;
  min-height: 140px;
}

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

.article-publish-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text);
  cursor: pointer;
}

.article-publish-toggle input {
  width: 16px;
  height: 16px;
  accent-color: var(--color-accent);
  cursor: pointer;
}

@media (max-width: 560px) {
  .project-grid {
    grid-template-columns: 1fr;
  }

  .project-card-stats {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3);
  }

  /* Dar ekranda proje/kategori yan yana sığmıyor. */
  .article-edit-row {
    grid-template-columns: 1fr;
  }

  .article-detail {
    padding: var(--space-4);
  }

  /* Makale üst bilgisindeki etiketler (proje, kategori, yazar, tarih,
     okunma) tek satırda taşıyordu. */
  .article-detail-meta {
    flex-wrap: wrap;
    gap: var(--space-2);
  }
}
