/**
 * RestoAI portal shell — sidebar + topbar chrome (Faz 1)
 *
 * Sınıf öneki `ps-`. Kabuk kapsayıcısı `.ps-shell` — `.portal-shell` DEĞİL:
 * o ad css/main.css:1156'da eski açık temalı portal düzeninde kullanılıyor
 * (bugün bu sayfalar main.css link etmiyor ama ad çakışması bırakmayalım).
 * Slotun id'si `#portal-shell` olarak kalır; id seçicisi o kuralla çakışmaz.
 *
 * dashboard.html ve reports.html aynı floating nav'ı kopyalayıp farklı kolon
 * genişlikleri (6xl / 7xl) kullanıyordu; sayfalar arası geçişte içerik zıplıyordu.
 * Chrome artık tek yerde: js/portal-shell.js bu sınıfları enjekte eder.
 *
 * Tailwind utility'si KULLANILMIYOR — shell, css/tailwind.css yeniden derlenmeden
 * de doğru görünsün diye düz CSS. Sayfa İÇERİĞİ Tailwind kullanmaya devam eder.
 *
 * ──────────────────────────────────────────────────────────────────────────
 * 2026-08-20 · "Kontrast + hat" geçişi
 *
 * ÖNCE: pazarlama sayfasının kuralı panele de uygulanıyordu — zemin beyaz,
 * kart neredeyse beyaz (#F8FAFC→#FAFBFC), kenarlık soluk. Kart ile zemin
 * arasındaki fark 1.05:1 olduğu için hiçbir kutunun sınırı görünmüyordu; ekran
 * "belirgin hatları olmayan" bir bulanıklığa dönüşüyordu. Üstüne `.ps-mesh-*`
 * lekeleri 0.40/0.30 opaklıkla (pazarlama sayfasındaki değerin ~5 katı) leylak
 * bir sis basıyordu. Bir de a694a2e'deki toplu `#E2E8F0 → #CBD5E1` değişimi
 * yalnız KENARLIKLARI değil sidebar/topbar ZEMİNLERİNİ de vurduğu için kabuk
 * düz gri bir levhaya dönmüştü (kenarlığıyla aynı renk = görünmez kenarlık).
 *
 * ŞİMDİ yüzey ilişkisi TERSİNE çevrildi — panelin tamamının dayandığı fikir bu:
 *   uygulama zemini  → hafif soğuk gri (`--ps-canvas`)
 *   kart / kabuk     → SAF BEYAZ (`--ps-surface`)
 *   ayrım            → 1px net hat (`--ps-line`) + dar gölge
 * Kartı artık dolgu farkı + hat + gölge birlikte ayırıyor; kenarlığı zorlamaya
 * (koyu çerçeve çizmeye) gerek kalmıyor. Pazarlama sayfaları BEYAZ zeminde
 * kalır — bu ters çevirme yalnız uygulama yüzeyi (portal + admin) içindir.
 *
 * Yarıçap ölçeği daraltıldı (24/28px → 12px): "belirgin hat" isteği yuvarlaklık
 * azaltmayı gerektirir; balon köşe hattı yok eder. Ölçek üç kademe:
 *   kart 12px · kart içi panel 10px · kontrol (buton/pill) 8px
 * Rozet ve durum etiketleri tam yuvarlak kalır — onlar zaten "pill" formudur.
 *
 * Mor artık HER küçük etikette değil: eskiden her `dt`, her eyebrow violet-700
 * idi ve aksan hiçbir şey söylemiyordu. Mor şimdi üç yerde: marka işareti,
 * aktif gezinme öğesi, birincil eylem. Etiketler nötr mürekkep tonlarında.
 * ────────────────────────────────────────────────────────────────────────── */

/* [hidden] HER ŞEYİ yener.
   Bileşen sınıflarımız display: flex/grid/inline-flex atıyor; bunlar tarayıcının
   `[hidden] { display: none }` kuralını özgüllükte geçtiği için `el.hidden = true`
   yapılan bloklar ekranda kalıyordu (boş uyarı kartı 104px yer kaplıyor, topbar'da
   içi boş bir sync rozeti duruyordu). Bu kural tek satırda kapatır. */
[hidden] { display: none !important; }

/* ── Tasarım jetonları ───────────────────────────────────────────────────── */
/* TEK KAYNAK. Yeni bir yüzey/hat rengi yazmadan önce buraya bak; sabit hex'i
   kuralın içine gömmek bu paletin bir sonraki ayarında dosyayı tekrar taramak
   demek. `.ps-shell` üzerinde tanımlı çünkü `.pcard`/`.pkpi` gibi kart
   bileşenleri daima kabuğun içinde yaşar (admin paneli dahil).

   KONTRAST (WCAG, beyaz #FFFFFF yüzeye karşı — panelin metni artık mesh
   üstünde değil BEYAZ kart üstünde duruyor, bütçe bu yüzden rahatladı):
     --ps-ink    #0F172A → 17.9:1   birincil metin
     --ps-ink-2  #334155 → 10.9:1   etiket / güçlü ikincil
     --ps-ink-3  #475569 →  7.5:1   ikincil metin, meta (EN SOLUK BU)
   slate-500 (#64748B) ve daha açığı hâlâ YASAK: 4.76:1 saf beyazda sınırı
   ancak geçiyor, gri zeminde (`--ps-canvas`) altına düşüyor.

   `:root` ŞART, süs değil: modal ve toast host'ları `document.body`ye
   eklenir, yani `.ps-shell`in DIŞINDADIR. Jetonlar yalnız `.ps-shell`de
   tanımlıyken modal içindeki her `var(--ps-*)` çözümsüz kalıyor ve CSS
   kuralı komple düşüyordu — `.as-btn-primary` zeminsiz (saydam) kalıp
   beyaz yazısıyla görünmez oluyor, `.as-btn`in kenarlığı ve yarıçapı
   siliniyordu. Jetonları `:root`ta tanımlamak kabuğun içindeki hiçbir
   şeyi değiştirmez (bu dosya yalnız portal/admin sayfalarında yüklü). */
:root,
.ps-shell {
  --ps-canvas: #EDEFF5;          /* uygulama zemini — kartın altındaki gri */
  --ps-surface: #FFFFFF;         /* kart, sidebar, topbar */
  --ps-surface-sunk: #F5F7FB;    /* kart İÇİNDE gömme panel (lisans kutusu vb.) */
  --ps-surface-hover: #F1F4F9;

  --ps-line: #D8DDE9;            /* ana hat: kart kenarı, ayraç, tablo çizgisi */
  --ps-line-soft: #E5E9F1;       /* kart içi ince ayraç */
  --ps-line-strong: #94A3B8;     /* form kontrolü kenarı (theme.css ile aynı) */

  --ps-ink: #0F172A;
  --ps-ink-2: #334155;
  --ps-ink-3: #475569;

  --ps-brand: #6D28D9;           /* metin/ikon moru (violet-700) */
  --ps-brand-solid: #4F46E5;     /* dolgu moru (indigo-600) — beyaz yazı taşır */
  --ps-brand-soft: #F2EFFE;      /* aktif gezinme zemini */
  --ps-brand-line: #C9BCF7;

  --ps-ok: #047857;
  --ps-warn: #B45309;
  --ps-crit: #BE123C;

  --ps-r-card: 12px;
  --ps-r-panel: 10px;
  --ps-r-ctl: 8px;

  /* Gölge DAR ve KOYU tutuluyor: geniş yumuşak gölge kartı yüzdürür ve kenarı
     yine belirsizleştirir; 1-2px'lik sıkı gölge hattı KUVVETLENDİRİR. */
  --ps-shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 1px 1px rgba(15, 23, 42, .04);
  --ps-shadow-lift: 0 6px 16px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .06);
}

/* ── Kabuk ızgarası ──────────────────────────────────────────────────────── */
.ps-shell {
  --ps-sidebar-w: 252px;
  --ps-drawer-w: 272px;
  /* Tam genişlik: içerik kolonu 1180px'e sabitlenince geniş ekranlarda
     sidebar'ın sağında 400px+ ölü alan kalıyordu. Dar isteyen sayfa
     `.ps-shell` üzerinde bu değişkeni ezebilir (ör. 80rem). */
  --ps-content-max: 100%;
  --ps-topbar-h: 60px;

  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--ps-canvas);
  color: var(--ps-ink);

  /* Yatay taşma koruması kabukta tutuluyor, body'de değil: body'ye yazılan
     overflow değeri görüntü alanına yayılır ve sayfanın geri kalanını da
     etkiler; burada etkisi yerel kalıyor. `clip` seçildi çünkü `hidden`in
     aksine kaydırma bağlamı yaratmaz — sticky sidebar/topbar'ın viewport'a
     göre takılması garanti altında kalır. */
  overflow-x: clip;
}

@media (min-width: 1024px) {
  .ps-shell { grid-template-columns: var(--ps-sidebar-w) minmax(0, 1fr); }
}

/* Panel yüzeyi pazarlama sayfasının dekorundan ARINIK olmalı: sürüklenen mesh
   ve film grain'i veri okunurken gürültü yapıyor, ayrıca ikisi de zemini aşağı
   çekip yeni kontrast bütçesini yiyor. `.ps-mesh-*` öğeleri DOM'da KALIR
   (portal-shell.js onları theme.js'ten önce koyar; theme.js `.mesh` görünce
   kendi animasyonlusunu eklemez) ama görünmez — kancayı kaldırma. */
.ps-mesh-a, .ps-mesh-b { display: none; }
body:has(.ps-shell)::before { content: none; }   /* .grain overlay'i panelde kapat */

/* Chrome enjekte edilene kadar ham içeriği gösterme (kısa FOUC engeli).
   portal-shell.js mount bitince .ps-booting kaldırır.
   Emniyet supabı: script hiç çalışmazsa (ağ hatası / JS kapalı) içerik 2 sn
   sonra yine de görünür — gizli kalmış bir sayfa, biçimsiz sayfadan kötüdür. */
.ps-booting { opacity: 0; animation: ps-failsafe-reveal 0s linear 2s forwards; }
@keyframes ps-failsafe-reveal { to { opacity: 1; } }
.ps-shell { transition: opacity .2s ease; }

/* Klavye odağı: tarayıcı varsayılanı beyaz kart üstünde ince kalıyor.
   Tek kural tüm kabuk + kart bileşenlerini kapsar. */
.ps-shell :focus-visible {
  outline: 2px solid var(--ps-brand-solid);
  outline-offset: 2px;
  border-radius: var(--ps-r-ctl);
}

/* ── Sidebar ─────────────────────────────────────────────────────────────── */
/* < 1024px: off-canvas drawer. ≥ 1024px: sticky kolon (fixed DEĞİL — grid
   hücresi olarak kalınca theme.css'in `body > *` z-index kuralıyla
   çakışmaz ve içerik kolonu otomatik daralır). */
.ps-sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--ps-drawer-w);
  max-width: 86vw;
  z-index: 60;
  display: flex;
  flex-direction: column;
  background: var(--ps-surface);
  border-right: 1px solid var(--ps-line);
  transform: translateX(-100%);
  transition: transform .28s cubic-bezier(0.16, 1, 0.3, 1);
}

.ps-shell.is-drawer-open .ps-sidebar { transform: translateX(0); }

@media (min-width: 1024px) {
  .ps-sidebar {
    position: sticky;
    top: 0;
    bottom: auto;
    height: 100vh;
    height: 100dvh;
    width: auto;
    max-width: none;
    z-index: 20;
    align-self: start;   /* stretch kalırsa yükseklik satırı doldurur, sticky kımıldamaz */
    transform: none;
  }
}

.ps-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(15, 23, 42, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity .28s cubic-bezier(0.16, 1, 0.3, 1);
}
.ps-shell.is-drawer-open .ps-backdrop { opacity: 1; pointer-events: auto; }
@media (min-width: 1024px) { .ps-backdrop { display: none; } }

/* Sidebar başlık (logo) — topbar ile AYNI yükseklikte ve alt hattı ortak:
   iki kutunun alt kenarı aynı piksele oturunca kabuk tek bir "L" çerçeveye
   dönüşüyor, iki ayrı çubuk gibi durmuyor. */
.ps-brand {
  display: flex;
  align-items: center;
  gap: .625rem;
  min-height: var(--ps-topbar-h);
  padding: 0 1.125rem;
  border-bottom: 1px solid var(--ps-line);
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  font-weight: 700;
  font-size: 1.1875rem;
  letter-spacing: -0.025em;
  color: var(--ps-ink);
  text-decoration: none;
}
.ps-brand-mark {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: var(--ps-r-ctl);
  background: linear-gradient(135deg, #7c3aed 0%, #4f46e5 100%);
  /* Neon "glow" (0 0 20px) beyaz zeminde mor bir leke bırakıyordu; yerine
     markanın kendi renginde sıkı bir gölge. */
  box-shadow: 0 1px 2px rgba(79, 70, 229, .35);
  color: #fff;
}

/* Gezinme */
.ps-nav {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: .875rem .625rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ps-nav-label {
  padding: .25rem .625rem .5rem;
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ps-ink-3);
}

.ps-nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: .6875rem;
  padding: .5625rem .6875rem;
  border-radius: var(--ps-r-ctl);
  font-size: .875rem;
  font-weight: 500;
  color: var(--ps-ink-2);
  text-decoration: none;
  transition: background-color .15s ease, color .15s ease;
}
.ps-nav-link svg { flex: none; opacity: .7; }
.ps-nav-link:hover { background: var(--ps-surface-hover); color: var(--ps-ink); }

.ps-nav-link[aria-current="page"] {
  background: var(--ps-brand-soft);
  color: #4C1D95;
  font-weight: 600;
}
.ps-nav-link[aria-current="page"] svg { opacity: 1; color: var(--ps-brand); }
/* Aktif işaretçi ÖĞENİN İÇİNDE. Eskiden `left: -.75rem` ile nav'ın padding'ine
   taşıyordu; `.ps-nav` overflow-y: auto olduğu için çubuk kırpılıyor ve
   ekranın sol kenarında asılı kalmış 3px'lik bir çizgi olarak görünüyordu. */
.ps-nav-link[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 18px;
  border-radius: 0 2px 2px 0;
  background: var(--ps-brand-solid);
}

/* "Yakında" öğesi — layout Faz 5'te değişmesin diye şimdiden yerinde durur. */
.ps-nav-link.is-soon { color: var(--ps-ink-3); opacity: .6; cursor: default; }
.ps-nav-link.is-soon:hover { background: none; color: var(--ps-ink-3); }
.ps-soon-tag {
  margin-left: auto;
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ps-brand);
  border: 1px solid var(--ps-brand-line);
  border-radius: 9999px;
  padding: 2px .5rem;
}

/* Dokunmatikte 44px kuralı — theme.css yalnız button/a.inline-flex'i
   büyütüyor, sidebar linkleri o seçicilere girmiyor. */
@media (pointer: coarse) {
  .ps-nav-link { min-height: 44px; }
}

/* Sidebar alt bloğu — abonelik her ekranda görünür kalsın */
.ps-foot {
  flex: none;
  padding: .875rem 1rem 1rem;
  border-top: 1px solid var(--ps-line);
}

.ps-plan-card {
  border: 1px solid var(--ps-line);
  background: var(--ps-surface-sunk);
  border-radius: var(--ps-r-panel);
  padding: .625rem .75rem .6875rem;
}
.ps-plan-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
}
.ps-plan-name {
  font-size: .875rem;
  font-weight: 600;
  color: var(--ps-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ps-plan-days {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: .6875rem;
  color: var(--ps-ink-3);
  flex: none;
}
.ps-plan-bar {
  margin-top: .5rem;
  height: 5px;
  border-radius: 3px;
  background: #E2E7F0;
  overflow: hidden;
}
.ps-plan-fill {
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: var(--ps-brand-solid);
  transition: width .5s cubic-bezier(0.16, 1, 0.3, 1);
}
/* Durum renkleri TEK anlam taşır: kehribar = uyarı, gül = kritik. */
.ps-plan-card.is-warn { border-color: rgba(180, 83, 9, .38); background: rgba(245, 158, 11, .10); }
.ps-plan-card.is-warn .ps-plan-fill { background: #B45309; }
.ps-plan-card.is-critical { border-color: rgba(190, 18, 60, .38); background: rgba(244, 63, 94, .09); }
.ps-plan-card.is-critical .ps-plan-fill { background: #BE123C; }

.ps-account {
  margin-top: .75rem;
  display: flex;
  align-items: center;
  gap: .5rem;
}
.ps-account-mail {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .75rem;
  color: var(--ps-ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ps-logout {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  font-size: .75rem;
  font-weight: 600;
  color: var(--ps-crit);
  background: var(--ps-surface);
  border: 1px solid rgba(190, 18, 60, .28);
  border-radius: var(--ps-r-ctl);
  padding: .3125rem .625rem;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.ps-logout:hover { background: rgba(244, 63, 94, .08); border-color: rgba(190, 18, 60, .45); }

.ps-site-link {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  margin-top: .75rem;
  font-size: .75rem;
  color: var(--ps-ink-3);
  text-decoration: none;
  transition: color .15s ease;
}
.ps-site-link:hover { color: var(--ps-ink); }

/* ── Ana kolon ───────────────────────────────────────────────────────────── */
.ps-main { min-width: 0; display: flex; flex-direction: column; }

.ps-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: .875rem;
  min-height: var(--ps-topbar-h);
  /* İçerik kolonuyla aynı clamp — topbar öğeleri altındaki kartlarla hizalı kalır. */
  padding: .5rem clamp(1.25rem, 2.4vw, 3rem);
  background: var(--ps-surface);
  border-bottom: 1px solid var(--ps-line);
}
@media (min-width: 768px) { .ps-topbar { padding: .5rem clamp(2rem, 2.4vw, 3rem); } }

.ps-burger {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--ps-r-ctl);
  color: var(--ps-ink-2);
  background: var(--ps-surface);
  border: 1px solid var(--ps-line);
  cursor: pointer;
  transition: background-color .15s ease;
}
.ps-burger:hover { background: var(--ps-surface-hover); }
@media (min-width: 1024px) { .ps-burger { display: none; } }

/* Topbar'daki dişli: hesap ayarlarına (şifre/e-posta) her sayfadan tek tıkla
   erişim — sidebar'daki "Hesap" linkiyle aynı hedefe gider, burası yalnızca
   sık kullanılan bir kısayoldur. ps-burger'la aynı ölçüde kare kontrol. */
.ps-settings-btn {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--ps-r-ctl);
  color: var(--ps-ink-2);
  background: var(--ps-surface);
  border: 1px solid var(--ps-line);
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.ps-settings-btn:hover { background: var(--ps-surface-hover); color: var(--ps-ink); }
.ps-settings-btn[aria-current="page"] { color: var(--ps-brand); border-color: var(--ps-brand); }

.ps-topbar-meta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: .375rem;
  flex: none;
}

/* Pill artık tam yuvarlak DEĞİL: topbar'daki üç öğe yan yana durduğunda
   yuvarlak uçlar birbirine akıyordu; 8px köşe onları ayrı "kontrol" gibi
   okutuyor ve kabuğun kare hattına uyuyor. */
.ps-pill {
  display: inline-flex;
  align-items: center;
  gap: .4375rem;
  font-size: .75rem;
  font-weight: 500;
  color: var(--ps-ink-2);
  background: var(--ps-surface);
  border: 1px solid var(--ps-line);
  border-radius: var(--ps-r-ctl);
  padding: .375rem .625rem;
  white-space: nowrap;
}
.ps-pill svg { flex: none; opacity: .65; }
/* Tarih ve "son sync" dar ekranda başlıkla yarışmasın */
@media (max-width: 640px) { .ps-pill.ps-pill-date { display: none; } }

/* Kullanıcı rozeti ad soyad taşıyor: uzun isim başlığı ekrandan itmesin. */
.ps-pill.ps-pill-user { min-width: 0; max-width: min(220px, 45vw); }
.ps-pill.ps-pill-user > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* Sync göstergesi — nokta rengi TEK anlam: yeşil taze, kehribar bayat, gri bilinmiyor.
   Halka (0 0 0 3px) kullanılıyor, parlama (blur) değil: beyaz zeminde blur noktayı
   bulandırıp lekeye çeviriyor. */
.ps-dot { width: 7px; height: 7px; border-radius: 9999px; background: #64748B; flex: none; }
.ps-pill.is-fresh .ps-dot { background: #059669; box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.16); }
.ps-pill.is-stale .ps-dot { background: #d97706; box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.16); }

.ps-content {
  width: 100%;
  max-width: var(--ps-content-max);
  margin: 0 auto;
  /* Kenar boşluğu viewport ile ölçeklenir; içerik ekran kenarına yapışmaz. */
  padding: 1.5rem clamp(1.25rem, 2.4vw, 3rem) 4rem;
}
@media (min-width: 768px) { .ps-content { padding: 1.75rem clamp(2rem, 2.4vw, 3rem) 5rem; } }

@media (prefers-reduced-motion: reduce) {
  .ps-sidebar, .ps-backdrop, .ps-plan-fill { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Faz 2 — kart ağırlıkları + renk disiplini

   ÖNCE: 6 kart, 6 farklı gradient rozet (emerald, violet, fuchsia, indigo,
   sky) ve hepsinde aynı rounded-3xl/p-7. Renk hiçbir şey anlatmıyordu, her
   kart eşit derecede bağırdığı için hiçbiri öne çıkmıyordu.

   ŞİMDİ renk TEK anlam taşır:
     violet/indigo → marka, gezinme, nötr  (rozetlerin varsayılanı)
     emerald       → YALNIZ olumlu/canlı   (lisans geçerli, cihaz aktif)
     amber         → YALNIZ uyarı          (doğrulanmamış e-posta, süre bitiyor)
     rose          → YALNIZ kritik         (süre doldu, cihaz kaldır)
   fuchsia ve sky kullanılmaz.

   GRAFİK SERİLERİ AYRI BİR SİSTEMDİR (raporlar sayfası). Orada renk bir veri
   serisini ayırt eder, durum bildirmez:
     ciro   → violet→indigo  |  gider → amber→orange
     kâr    → emerald→teal   |  fire/iptal → rose
   Bu yüzden gider çubuklarının amber olması yukarıdaki "amber = uyarı"
   kuralını çiğnemez; ikisi farklı bağlamlarda tutarlı biçimde uygulanır.
   KPI kutuları grafik DEĞİL chrome'dur — oradaki sayılar nötr mürekkeptir.

   Ağırlık üç kademedir; display başlık YALNIZ birinci kademede ve sayfa
   h1'inde kullanılır — beş eşit display başlık hiyerarşiyi yok ediyordu.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Kademe 2 (varsayılan): lisans, cihazlar ───────────────────────────── */
.pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 1.25rem;
  border-radius: var(--ps-r-card);
  border: 1px solid var(--ps-line);
  background: var(--ps-surface);
  box-shadow: var(--ps-shadow);
  transition: border-color .15s ease, box-shadow .15s ease;
}
@media (min-width: 768px) { .pcard { padding: 1.375rem 1.5rem; } }
.pcard:hover { border-color: #C4CCDD; }

/* Kademe 2 başlığı: sans, küçük. Display'i birinci kademeye bırakır. */
.pcard-title {
  font-size: 1rem;
  font-weight: 650;
  color: var(--ps-ink);
  letter-spacing: -0.011em;
}

/* Kart başlık satırı — ikon + başlık + sağda rozet.
   Alt hattı kartın tam genişliğine taşınır (negatif margin): "belirgin hat"
   isteğinin en ucuz karşılığı budur, kartı gerçek bir başlık/gövde bölmesine
   ayırır. */
.pcard-head {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin: -1.25rem -1.25rem 1.125rem;
  padding: .875rem 1.25rem;
  border-bottom: 1px solid var(--ps-line);
}
@media (min-width: 768px) {
  .pcard-head { margin: -1.375rem -1.5rem 1.25rem; padding: .9375rem 1.5rem; }
}

/* ── Kademe 1: sayfanın birincil eylemi (Canlı Raporlar) ───────────────── */
/* Eskiden mor bir radial wash ile öne çıkıyordu; beyaz kart sisteminde o wash
   kartı yeniden bulanıklaştırıyor. Vurgu artık ÜST KENARDAKİ 2px'lik marka
   hattı + biraz daha güçlü gölge: renk lekesi değil, hat. */
.pcard-primary {
  border-color: #CBD2E2;
  box-shadow: var(--ps-shadow-lift);
  overflow: hidden;
}
.pcard-primary::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #7c3aed, #4f46e5);
}
.pcard-primary:hover { border-color: var(--ps-brand-line); }

/* ── Kademe 3: dipnot şeridi (indirme + destek) ────────────────────────── */
/* Bu ikisi eskiden lisansla aynı boyutta iki tam karttı; ikisi de bir
   "bilgi"den ibaret olduğu için sayfanın ağırlık dengesini bozuyorlardı. */
.pcard-foot {
  padding: .875rem 1.125rem;
  border-radius: var(--ps-r-card);
  border: 1px solid var(--ps-line);
  background: var(--ps-surface);
  box-shadow: var(--ps-shadow);
}
/* Izgara öğelerinin varsayılan `min-width: auto` değeri, içindeki rozet+buton+metin
   min-content genişliğinin altına inmeyi reddediyor; dar ekranda şerit kartın
   dışına taşıyordu (üstteki overflow-x: clip taşmayı gizlediği için fark
   edilmesi de zor). `truncate`ın çalışabilmesi için de bu şart. */
.pcard-foot > * { min-width: 0; }

/* ── Rozetler ──────────────────────────────────────────────────────────── */
/* Varsayılan rozet DÜZ ve nötr: parlama yok, gradient yok. Tek parlayan
   rozet birincil karttaki olunca "önemli olan bu" mesajı gerçekten geçiyor. */
.pbadge {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: var(--ps-r-panel);
  background: var(--ps-brand-soft);
  border: 1px solid var(--ps-brand-line);
  color: var(--ps-brand);
}
.pbadge-sm { width: 30px; height: 30px; border-radius: var(--ps-r-ctl); }
.pbadge-brand {
  width: 38px;
  height: 38px;
  border-color: transparent;
  background: linear-gradient(135deg, #7c3aed 0%, #4f46e5 100%);
  box-shadow: 0 1px 2px rgba(79, 70, 229, .35);
  color: #fff;
}

/* ── Sayılar ───────────────────────────────────────────────────────────── */
/* Panel kendini tazeliyor; orantılı rakamlarda her tazelemede sayılar
   yana oynar ve ekran ucuz görünür. tabular-nums bunu sabitler. */
.num {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

/* ── Kontroller ────────────────────────────────────────────────────────── */
/* Kart içindeki eylemler için ortak buton. Tailwind ile sayfa sayfa yazılan
   `inline-flex ... rounded-full bg-gradient-to-r ...` zincirleri her sayfada
   birazcık kayıyordu; tek sınıf tek görünüm.
   Yarıçap 8px: tam yuvarlak buton yumuşaklık üretir, istenen keskinlik değil. */
.pbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4375rem;
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1;
  padding: .625rem .875rem;
  border-radius: var(--ps-r-ctl);
  border: 1px solid var(--ps-line);
  background: var(--ps-surface);
  color: var(--ps-ink-2);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.pbtn:hover { background: var(--ps-surface-hover); border-color: #C4CCDD; color: var(--ps-ink); }
.pbtn svg { flex: none; }

/* Birincil: DÜZ renk, gradient değil. Gradient beyaz yazının kontrastını
   uçtan uca değiştirir (violet-500 ucunda 3.6:1'e düşüyordu); düz indigo-600
   her pikselde 7.0:1. */
.pbtn-primary {
  background: var(--ps-brand-solid);
  border-color: var(--ps-brand-solid);
  color: #fff;
  box-shadow: 0 1px 2px rgba(79, 70, 229, .30);
}
.pbtn-primary:hover { background: #4338CA; border-color: #4338CA; color: #fff; }
.pbtn-sm { font-size: .75rem; padding: .5rem .6875rem; }

@media (pointer: coarse) { .pbtn { min-height: 44px; } }

/* ── Form kontrolleri ──────────────────────────────────────────────────────
   Portal + admin formları aynı Tailwind zincirini (`mt-1.5 w-full bg-white
   border border-slate-400 rounded-lg px-3 py-2.5 ...`) sayfadan sayfaya
   kopyalıyordu: 9 utility × her alan. `.pbtn` neyse bu da odur — kontrol
   kenarı `--ps-line-strong`, yani hat rengi tek yerden ayarlanır.

   Kenar NEDEN ana hat (`--ps-line`) değil: kart kenarı ile giriş kutusu
   kenarı aynı tonda olduğunda form, kartın içinde bir kutu gibi DEĞİL kartın
   deseni gibi okunuyor. Tıklanabilir yüzey daha koyu bir hat ister. */
.pfield { display: block; }
.plabel {
  display: block;
  font-size: .75rem;
  font-weight: 600;
  color: var(--ps-ink-2);
  margin-bottom: .375rem;
}
.pinput {
  width: 100%;
  font: inherit;
  font-size: .875rem;
  color: var(--ps-ink);
  background: var(--ps-surface);
  border: 1px solid var(--ps-line-strong);
  border-radius: var(--ps-r-ctl);
  padding: .625rem .75rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.pinput::placeholder { color: #64748B; }
.pinput:focus {
  outline: none;
  border-color: var(--ps-brand-solid);
  /* Halka, kalınlaşan kenarlık DEĞİL: kenarlık kalınlaşırsa kutu 2px büyür ve
     odak sırasında satır zıplar. */
  box-shadow: 0 0 0 3px rgba(79, 70, 229, .16);
}
.pinput:disabled { background: var(--ps-surface-sunk); color: var(--ps-ink-3); cursor: not-allowed; }
.pinput.is-error { border-color: var(--ps-crit); }
.pinput.is-error:focus { box-shadow: 0 0 0 3px rgba(190, 18, 60, .14); }
@media (pointer: coarse) { .pinput { min-height: 44px; } }

/* Alanın altındaki açıklama/hata satırı. Yükseklik REZERVE edilmez: bu satır
   yalnız gerektiğinde çıkar, boşken yer kaplamaz (`:empty`). */
.phelp { font-size: .75rem; color: var(--ps-ink-3); margin-top: .375rem; }
.phelp:empty { display: none; }
.phelp.is-error { color: var(--ps-crit); }
.phelp.is-ok { color: var(--ps-ok); }

/* Şifre alanı + "göster" düğmesi. Düğme kutunun İÇİNDE durur; ayrı bir
   kontrol olarak yanına konduğunda ızgarayı bozuyordu. */
.ppass { position: relative; }
.ppass .pinput { padding-right: 2.75rem; }
.ppass-toggle {
  position: absolute;
  top: 50%;
  right: .375rem;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ps-ink-3);
  cursor: pointer;
}
.ppass-toggle:hover { background: var(--ps-surface-hover); color: var(--ps-ink); }

/* Şifre gücü şeridi. Üç kademe; renk kuralı kartlarınkiyle aynı
   (rose = kritik, amber = uyarı, emerald = olumlu). */
.pstrength { display: flex; gap: .25rem; margin-top: .5rem; }
.pstrength span {
  height: 4px;
  flex: 1;
  border-radius: 999px;
  background: #E2E8F0;
  transition: background-color .15s ease;
}
.pstrength[data-level="1"] span:nth-child(1) { background: #E11D48; }
.pstrength[data-level="2"] span:nth-child(-n+2) { background: #D97706; }
.pstrength[data-level="3"] span { background: #059669; }

/* Form sonu eylem satırı: buton + satır içi durum mesajı. */
.pform-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; }
.pmsg { font-size: .8125rem; color: var(--ps-ink-3); }
.pmsg.is-ok { color: var(--ps-ok); font-weight: 600; }
.pmsg.is-error { color: var(--ps-crit); font-weight: 600; }

/* ══════════════════════════════════════════════════════════════════════════
   Faz 3 — canlı veri blokları
   ═══════════════════════════════════════════════════════════════════════ */

/* ── İskelet yükleme ───────────────────────────────────────────────────── */
/* "Yükleniyor…" metni yerine yüksekliği REZERVE eden bir parıltı. Öğe kendi
   yer tutucu metnini ("—") taşımaya devam ettiği için veri gelince satır
   yüksekliği değişmez; içerik zıplaması olmaz. */
.skel {
  position: relative;
  overflow: hidden;
  color: transparent !important;
  border-radius: 4px;
  background: #E8ECF3;
}
.skel::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, #F4F6FA, transparent);
  animation: skel-shimmer 1.4s ease-in-out infinite;
}
@keyframes skel-shimmer { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .skel::after { animation: none; } }

/* ── KPI kutusu ────────────────────────────────────────────────────────── */
/* Tek başına (admin sayfalarındaki gibi) kendi kenarlıklı kutusudur. */
.pkpi {
  background: var(--ps-surface);
  border: 1px solid var(--ps-line);
  border-radius: var(--ps-r-card);
  box-shadow: var(--ps-shadow);
  padding: .875rem 1rem;
}
.pkpi dt {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ps-ink-3);
}
.pkpi dd {
  margin-top: .3125rem;
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--ps-ink);
  line-height: 1.1;
}
.pkpi-sub {
  display: block;
  margin-top: .3125rem;
  font-size: .6875rem;
  color: var(--ps-ink-3);
}

/* ── KPI şeridi ────────────────────────────────────────────────────────── */
/* Dört ayrı yuvarlak kutu yerine TEK kutu, içi 1px hatlarla bölünmüş.
   İstenen "belirgin hat" görünümünün ana taşıyıcısı bu: kutular arası boşluk
   yerine gerçek bir çizgi var, şerit bir ölçüm aleti gibi okunuyor.

   Hatlar `box-shadow` ile çiziliyor, `border` ile değil: sütun sayısı ekran
   genişliğine göre 2 ↔ 4 değişiyor ve hangi hücrenin sol/üst komşusu olduğu
   media query yazmadan bilinemez. İçe doğru 1px gölge her hücreye sol+üst
   hattı verir; şeridin `overflow: hidden` kırpması dış kenarlardakileri
   siler. Sütun sayısı değişince kendiliğinden doğru kalır. */
.pkpi-strip {
  border: 1px solid var(--ps-line);
  border-radius: var(--ps-r-card);
  background: var(--ps-surface);
  box-shadow: var(--ps-shadow);
  overflow: hidden;
}
.pkpi-strip > .pkpi {
  border: 0;
  border-radius: 0;
  box-shadow: -1px 0 0 var(--ps-line), 0 -1px 0 var(--ps-line);
  background: transparent;
  padding: .9375rem 1.125rem 1rem;
}
.pkpi-strip > .pkpi dd { font-size: 1.625rem; letter-spacing: -0.03em; }
@media (min-width: 1280px) {
  .pkpi-strip > .pkpi { padding: 1rem 1.25rem 1.125rem; }
  .pkpi-strip > .pkpi dd { font-size: 1.75rem; }
}

/* ── Sparkline ─────────────────────────────────────────────────────────── */
/* Kutu, SVG gelmeden de yüksekliği tutar — veri düşünce kart zıplamaz.
   "Veri yok" hâli de AYNI yüksekliği kullanır: aksi halde iskelet (84px)
   boş duruma (≈40px) düşerken kart bir kez sıçrıyordu. */
.pspark-box { min-height: 84px; }
/* Başlık satırı: delta rozeti sonradan geldiğinde satır büyüyüp kartı
   uzatmasın diye yükseklik baştan rezerve. */
.pspark-head {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  min-height: 1.625rem;
}
/* Sağa yaslama BURADA, HTML'de `ml-auto` ile değil: portal-live.js delta
   rozetini güncellerken `deltaEl.className = 'pdelta ...'` ile sınıf listesini
   TAMAMEN yeniden yazıyor ve HTML'den gelen utility'yi siliyordu — ilk veri
   turunda rozet sola atlıyordu. */
.pspark-head .pdelta { margin-left: auto; }
.pspark-empty {
  min-height: 84px;
  display: flex;
  align-items: center;
}
/* Yükseklik SABİT: veri gelmeden de yer kaplar, geldiğinde kart zıplamaz. */
.pspark { height: 84px; width: 100%; display: block; }
/* preserveAspectRatio="none" ile viewBox yatayda esner; çizgi kalınlığının
   esnemeden sabit kalması için vector-effect şart. */
.pspark path, .pspark line, .pspark circle { vector-effect: non-scaling-stroke; }

/* Grafik gövdesi gömme panelde: beyaz kart içinde beyaz grafik alanı
   "nerede bitiyor" sorusunu bırakıyordu. */
.pspark-panel {
  border: 1px solid var(--ps-line-soft);
  border-radius: var(--ps-r-panel);
  background: var(--ps-surface-sunk);
  padding: .75rem .875rem .5rem;
}

.pdelta {
  display: inline-flex;
  align-items: center;
  gap: .3125rem;
  font-size: .75rem;
  font-weight: 600;
  border-radius: 9999px;
  padding: .1875rem .5rem;
  background: #EEF1F7;
  color: var(--ps-ink-3);
}
.pdelta.is-up   { background: rgba(16, 185, 129, 0.14); color: #065F46; }
.pdelta.is-down { background: rgba(244, 63, 94, 0.14);  color: #BE123C; }

/* ── Uyarı satırları ───────────────────────────────────────────────────── */
/* ÖNCE: her satır ayrı yuvarlak, tinted, kenarlıklı bir kutuydu — üç sticker
   alt alta. ŞİMDİ tek liste, satırlar 1px hatla ayrılıyor ve şiddet SOL
   KENARDAKİ 3px'lik çubukla veriliyor. Renk yine tek anlam: amber = dikkat,
   rose = kritik. */
.palert {
  position: relative;
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .6875rem .875rem .6875rem 1.0625rem;
  border-top: 1px solid var(--ps-line-soft);
  font-size: .875rem;
}
.palert:first-child { border-top: 0; }
.palert::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 22px;
  border-radius: 2px;
  background: #CBD5E1;
}
.palert-name { min-width: 0; flex: 1 1 auto; color: var(--ps-ink); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palert-tag {
  flex: none;
  font-size: .6875rem;
  font-weight: 600;
  border-radius: 9999px;
  padding: .1875rem .5rem;
  white-space: nowrap;
}
.palert.is-warn::before { background: #D97706; }
.palert.is-warn .palert-tag { background: rgba(217, 119, 6, 0.14); color: var(--ps-warn); }
.palert.is-critical::before { background: #E11D48; }
.palert.is-critical .palert-tag { background: rgba(225, 29, 72, 0.12); color: var(--ps-crit); }
.palert-value { flex: none; font-size: .75rem; color: var(--ps-ink-3); }

/* Uyarı listesi kartın gövde boşluğunu kenardan kenara kullansın —
   satır ayraçları kartın iç kenarına kadar uzayınca "liste" hissi doğuyor. */
.palert-list { margin: 0 -1.25rem -1.25rem; }
/* Liste doğrudan başlık satırının altındaysa aradaki boşluk kalkar: başlığın
   alt kenarlığı listenin İLK AYRACI olur. Aksi halde header çizgisi ile ilk
   satır arasında 20px'lik sahipsiz bir bant kalıyordu. */
.pcard-head + .palert-list { margin-top: -1.25rem; }
.palert-list > .palert { padding-left: 2.125rem; padding-right: 1.25rem; }
.palert-list > .palert::before { left: 1.25rem; }
@media (min-width: 768px) {
  .palert-list { margin: 0 -1.5rem -1.375rem; }
  .palert-list > .palert { padding-left: 2.375rem; padding-right: 1.5rem; }
  .palert-list > .palert::before { left: 1.5rem; }
}

/* ── Veri satırı (etiket → değer) ──────────────────────────────────────── */
/* Lisans kartındaki "Plan / Geçerlilik" gibi ikili bilgiler için. İki sütun,
   satır arası 1px hat: kartın içinde de aynı hat dili sürsün. */
.prow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: .5625rem 0;
  border-top: 1px solid var(--ps-line-soft);
  font-size: .8125rem;
}
.prow:first-child { border-top: 0; padding-top: 0; }
.prow-label { color: var(--ps-ink-3); }
.prow-value { color: var(--ps-ink); font-weight: 600; text-align: right; }

/* ── İlerleme çubuğu ───────────────────────────────────────────────────── */
.pbar {
  height: 6px;
  border-radius: 3px;
  background: #E2E7F0;
  overflow: hidden;
}
.pbar-fill {
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: var(--ps-brand-solid);
  transition: width .5s cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) { .pbar-fill { transition: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   Faz 4 — kurulum (onboarding) adımları

   Yeni müşterinin ilk gördüğü şey sıfırlarla dolu bir dashboard olmasın:
   ne yapması gerektiğini sırayla söyleyen bir kart görsün. Üç adımın da
   tamamlandığı hesapta kart HİÇ render edilmez.
   ═══════════════════════════════════════════════════════════════════════ */
.pstep {
  display: flex;
  align-items: flex-start;
  gap: .875rem;
  padding: .875rem 0;
  border-top: 1px solid var(--ps-line-soft);
}
.pstep:first-child { border-top: 0; padding-top: 0; }
.pstep:last-child { padding-bottom: 0; }

.pstep-num {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 9999px;
  font-size: .75rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: #EEF1F7;
  border: 1px solid var(--ps-line);
  color: var(--ps-ink-3);
}
/* Tamamlanan adım emerald — "olumlu" anlamıyla tutarlı. */
.pstep.is-done .pstep-num {
  background: rgba(16, 185, 129, 0.16);
  border-color: rgba(4, 120, 87, 0.34);
  color: var(--ps-ok);
}
.pstep.is-done .pstep-title { color: var(--ps-ink-3); }

.pstep-body { min-width: 0; flex: 1 1 auto; }
.pstep-title { font-size: .9375rem; font-weight: 600; color: var(--ps-ink); }
.pstep-desc { margin-top: .1875rem; font-size: .8125rem; color: var(--ps-ink-3); }
.pstep-action {
  flex: none;
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  font-size: .75rem;
  font-weight: 600;
  color: #fff;
  background: var(--ps-brand-solid);
  border: 1px solid var(--ps-brand-solid);
  border-radius: var(--ps-r-ctl);
  padding: .4375rem .75rem;
  text-decoration: none;
  transition: background-color .15s ease;
}
.pstep-action:hover { background: #4338CA; }
