[
 {
  "surface": "Admin home redirect",
  "route": "/[organizationSlug]/admin (page.tsx)",
  "titleTR": "(yok — anında yönlendirir)",
  "purpose": "The admin root has NO overview screen of its own; it immediately redirects to /admin/courses. There is no standalone analytics/dashboard home — the analytics live inside the Orders page.",
  "layout": "No visual layout; RedirectToPiHref to `/{slug}/admin/courses`.",
  "states": [
   "redirect-only"
  ],
  "priority": "edge",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [],
  "notes": "app/[organizationSlug]/admin/page.tsx. Important for the designer: the 'overview' canvas is realized as the Orders page's analytics section, not a separate dashboard.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders page — shell (tabs + analytics toggle)",
  "route": "/[organizationSlug]/admin/orders",
  "titleTR": "Siparişler",
  "purpose": "Main commerce landing: onboarding checklist (pre-first-sale), then a revenue analytics section and the orders table. For PI_PAYTR orgs with OWNER/ADMIN role, adds a Payouts (Ödemeler) tab.",
  "layout": "Page title 'Siparişler'. If onboarding incomplete AND no first sale → only the onboarding card shows. Once hasFirstSale/onboardingComplete: either a plain single-column (Orders content) OR a PageTabs with two triggers [Siparişler | Ödemeler]. An icon-only eye/eye-off toggle is overlaid top-right to show/hide the analytics section. Below: analytics section then orders data-table.",
  "tabs": [
   "Siparişler",
   "Ödemeler"
  ],
  "actions": [
   "Analitikleri Göster / Analitikleri Gizle (eye toggle)"
  ],
  "gating": "Page requires ORG_ORDERS_VIEW (else NoAccessMessage). Payouts tab requires activePaymentMethods includes PI_PAYTR AND isOwnerOrAdmin.",
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "keyComponents": [
   "PageTabs",
   "Tabs",
   "Tooltip",
   "Button(icon ghost)",
   "Skeleton",
   "Collapsible"
  ],
  "priority": "primary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "OrdersPageQuery (organization: id, slug, onboardingStatus{hasFirstSale, onboardingComplete}, activePaymentMethods{provider})",
   "OnboardingFlow_organization fragment"
  ],
  "notes": "Analytics visibility persisted in localStorage key admin:orders:show-analytics. Tab state synced to URL via useTabsUrlSync (orders|payouts). Skeletons: RevenueAnalyticsSkeleton, OrdersTableSkeleton, AdminContentSkeleton.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Onboarding checklist (Görevler)",
  "route": "/[organizationSlug]/admin/orders (top of page, before first sale)",
  "titleTR": "Görevler",
  "purpose": "7-step guided setup checklist shown until onboarding complete; gates the orders/analytics view (they only appear after hasFirstSale or onboardingComplete).",
  "layout": "Card titled 'Görevler' with description 'Aşağıdaki adımları tamamladıktan sonra satışlarınızı görüntüleyebilirsiniz', an X/Y tamamlandı counter, a Progress bar, then 7 step rows (numbered circle or green check). Each row: title, description, and an outline action button (external-link icon); the domain step also has a ghost 'Mevcut alt alan adını koru' dismiss button.",
  "actions": [
   "Profili Tamamla / Profili Güncelle",
   "Ürün Oluştur / Ürünleri Yönet",
   "Website Oluştur / Web Sitesini Yönet",
   "Alan Adı Ayarla / Alan Adını Yönet",
   "Mevcut alt alan adını koru (dismiss)",
   "Ödeme Ayarla / Ödemeleri Yönet",
   "Plan Seç"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Card",
   "Progress",
   "Button(outline/ghost)",
   "CheckIcon",
   "PiLink",
   "Toast"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "OnboardingFlow_organization (onboardingStatus{hasCustomDomain,hasFirstProduct,hasFirstSale,hasPaymentSetup,hasPlan,onboardingComplete,profileComplete,websiteCreated,domainStepDismissed})",
   "OnboardingFlowDismissStepMutation (dismissOnboardingStep)"
  ],
  "notes": "Steps: profile (Organizasyonunuzu tamamlayın.), product (İlk ürününüzü oluşturun.), website (Web sayfanızı tasarlayın ve yayına alın.), domain (Özel alan adınızı bağlayın.), payment (Ödeme altyapısını kurun.), plan (Planınızı seçin.), sale (İlk satışınızı gerçekleştirin.). Completed rows turn green. Dismiss failure toast: 'Adım kapatılamadı. Lütfen tekrar deneyin.'",
  "cluster": "overview-orders"
 },
 {
  "surface": "Revenue analytics section (Gelir Analizi)",
  "route": "/[organizationSlug]/admin/orders (analytics section, toggle-able)",
  "titleTR": "Gelir Analizi",
  "purpose": "The overview/analytics dashboard: revenue + student KPI cards, revenue time-series chart, and product/subscription-tier/promotion breakdown charts for a selected date preset.",
  "layout": "Header row: title 'Gelir Analizi' + description 'Seçili dönem için gelir ve satış metrikleri', and a right-aligned date-preset Select (w-180). Then RevenueOverviewCards (4-up KPI grid), StudentOverviewCards, a full-width RevenueTimeSeriesChart, then a responsive 1/2/3-column grid of ProductPerformanceChart + SubscriptionTierPerformanceChart (only if subscriptions) + PromotionEffectivenessChart (only if promotions).",
  "filters": [
   "Tarih Aralığı preset select: Bu Hafta, Son 7 Gün, Son 14 Gün, Son 28 Gün, Son 3 Ay, Son 6 Ay, Son 12 Ay, Tüm Zamanlar"
  ],
  "keyComponents": [
   "Select",
   "Card",
   "Recharts charts (bar/line/area)",
   "Skeleton",
   "Stat/KPI tiles with % change badges"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "priority": "primary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "RevenueAnalytics_organization fragment / RevenueAnalyticsRefetchQuery",
   "revenueOverview{grossRevenue,netRevenue,totalDiscounts,totalRefunds,orderCount,averageOrderValue,refundRate,subscriptionRevenue,activeSubscriptionCount,mrr}",
   "studentOverview{totalStudents,newStudents,activeStudents,newEnrollments,...}",
   "revenueTimeSeries{dataPoints}",
   "productPerformance{products{product,revenue,unitsSold,revenueShare}}",
   "promotionEffectiveness{promotions{promotion,usageCount,totalDiscountGiven,roi}}",
   "subscriptionTierPerformance{tiers{tier,revenue,subscriberCount}}"
  ],
  "notes": "Revenue cards: Toplam Ödenen Fiyat (grossRevenue), Toplam Net Kazanç (netRevenue), Sipariş Sayısı, Sipariş Başına Net Kazanç (AOV); subscription: Aktif Abonelik, Abonelik Geliri, Aylık Yinelenen Gelir (MRR). Each with 'önceki döneme göre' % change. Charts: Gelir Trendi (Bu Dönem/Önceki Dönem, Sipariş Gelirleri/Abonelik Gelirleri), En Çok Satan Ürünler (Gelire göre sıralama), En Popüler Abonelik Paketleri, Promosyon Performansı (Kod/Kullanım/Verilen İndirim/Üretilen Gelir/ROI). Empty: 'Seçili dönemde veri bulunamadı'. Charts are lazy-loaded (LazyRevenueAnalytics).",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders table (transactions list)",
  "route": "/[organizationSlug]/admin/orders (below analytics)",
  "titleTR": "Siparişler",
  "purpose": "Filterable, infinite-scroll table of all order line items AND subscription payments (unified 'transactions'), with per-row navigation to detail and a bulk export.",
  "layout": "Filter toolbar (faceted filters + date range + product popover + reset) with a header kebab (column visibility + export) pinned right; data-table with right-pinned actions column; infinite scroll with 'load more' + loaded/total count.",
  "tableColumns": [
   "Tür",
   "Tarih",
   "Öğrenci",
   "E-posta",
   "Durum",
   "Ürün",
   "Satış Fiyatı",
   "Ödenen",
   "Ödeme Sağlayıcı Komisyonu",
   "Teachfluence Komisyonu",
   "Net Fiyat",
   "İşlemler"
  ],
  "filters": [
   "İşlem Türü (Sipariş/Abonelik)",
   "Sipariş Durumu (11 statuses)",
   "Abonelik Ödeme Durumu (5 statuses)",
   "Ürün (product popover)",
   "Tarih Aralığı (+ quick: Son Gün/Son Hafta/Son 14 Gün/Son Ay)"
  ],
  "actions": [
   "Filtreleri Temizle",
   "Detaylar (row → order detail)",
   "Detaylar (subscription row → subscriber)",
   "Dışa Aktar (kebab)",
   "Daha fazla / infinite scroll"
  ],
  "gating": "ORG_ORDERS_VIEW.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "keyComponents": [
   "DataTable",
   "DataTableToolbar",
   "DataTableFacetedFilter",
   "DateRangePicker",
   "TableHeaderActionsMenu",
   "Badge",
   "Avatar",
   "Tooltip",
   "Popover/Command"
  ],
  "priority": "primary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "OrganizationOrders fragment / OrganizationOrdersPaginationQuery (transactions connection: OrderLineItem + StudentOrgSubscriptionPayment union)",
   "filters: transactionTypes, orderStatus, subscriptionPaymentStatus, dateFilter, relatedIds"
  ],
  "notes": "orderStatus/subscriptionPaymentStatus columns are hidden (used only as filter facets). Empty: 'Sonuç bulunamadı.' Net Fiyat has an info tooltip 'Komisyonlar düşüldükten sonra...' + link 'Detaylı bilgi için incele.'. Order status labels TR: Ödeme Bekleniyor, Öğrenci Kaydı Bekleniyor, Faturalandırma Bekleniyor, Ödeme Onayı Bekleniyor, Tamamlandı, Süresi Doldu, Başarısız, İade Talebi, Kısmi İade, İade Edildi, İade Reddedildi. Filters synced to URL.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders — product filter popover (Ürün)",
  "route": "/[organizationSlug]/admin/orders (toolbar filter)",
  "titleTR": "Ürün",
  "purpose": "Popover to filter the orders table by one or more products (courses, bundles, coaching sessions) with per-product sale counts respecting current status/date filters.",
  "layout": "Outline button 'Ürün' with 'Tümü' badge (or count / selected titles); popover with Command search input, grouped checkable items showing 'Title (count)' for course academic terms, bundles, coaching sessions; a 'Filtreleri temizle' footer when selections exist.",
  "filters": [
   "search input",
   "product checkboxes"
  ],
  "states": [
   "empty"
  ],
  "keyComponents": [
   "Popover",
   "Command",
   "CommandInput",
   "Badge",
   "CheckIcon"
  ],
  "priority": "edge",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "RelatedIdsFilterQuery (organization.courseAcademicTerms/coachingSessions/bundles with orderLineItems totalCount)"
  ],
  "notes": "Empty state 'Sonuç bulunamadı.', default badge 'Tümü', >3 selected → 'N seçildi'. Only products with >0 matching orders are listed.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders — bulk export modal (Dışa Aktar)",
  "route": "/[organizationSlug]/admin/orders (header kebab → export)",
  "titleTR": "Dışa Aktar",
  "purpose": "Column-picker driven bulk export of order line items to XLSX/CSV honoring the table's live filters, with a floating job-status/progress display.",
  "layout": "Kebab menu opens ExportColumnMenu: 'Sütunları Seç' with a column checklist (25 columns), Tümünü Seç / Tümünü Kaldır, count label, and two export buttons Excel (.xlsx) / CSV (.csv). A floating status shows Başlatılıyor…, {processed}/{total} satır işlendi, Dışa aktarma tamamlandı, or Dışa aktarma başarısız oldu.",
  "actions": [
   "Excel (.xlsx)",
   "CSV (.csv)",
   "Tümünü Seç",
   "Tümünü Kaldır"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "TableHeaderActionsMenu",
   "DropdownMenu",
   "ExportColumnMenu",
   "Checkbox",
   "ExportJobStatusDisplay"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "OrdersHeaderActionsMenuMutation (requestOrderLineItemsExport → OrderLineItemsExportJob)",
   "OrdersHeaderActionsMenuPollQuery (poll job status)"
  ],
  "notes": "Export columns TR: Sipariş ID, Sipariş Durumu, Sipariş Tarihi, Öğrenci ID/Adı/Soyadı/E-posta, Ürün Tipi/Adı, Orijinal/Satış/İndirimli/Ödenen Fiyat, Para Birimi, Ödeme İşlemci Ücreti, Platform Ücreti, Fatura Adı/Soyadı/Adresi, Vergi Numarası, Şirket, Telefon, Uygulanan Promosyonlar, Toplam İndirim, Vergi Kalemleri.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Payouts dashboard (Ödemeler tab)",
  "route": "/[organizationSlug]/admin/orders?tab=payouts",
  "titleTR": "Ödemeler",
  "purpose": "Financial payouts view: upcoming/transferred/pending KPI cards, an accumulated-net-earnings chart, and a transfers list; only for PI_PAYTR orgs and OWNER/ADMIN.",
  "layout": "PayoutsDashboard (KPI cards: Bankaya geçen, Yolda (bekleyen), Toplam net, Brüt satış, Sıradaki ödeme; accumulated net-earnings area chart with currency select; 'Tüm işlemler' transfers table with load-more) followed by a Collapsible 'Kesintiler' (Deductions) trigger button that reveals the deductions table.",
  "tableColumns": [
   "(Transfers) type / status / net",
   "(Deductions) Tür, Durum, Tutar, İade Edilen, Kesilen, Sebep, Oluşturulma Tarihi, Oluşturan, İlişkili"
  ],
  "filters": [
   "(Transfers) Durum, Tür, Yurt Dışı Kart",
   "(Deductions) Durum, Tür",
   "date preset (analytics)"
  ],
  "actions": [
   "Dışa Aktar (CSV)",
   "Kesintiler (collapse toggle)",
   "Detaylar",
   "Daha fazla yükle",
   "Analizi Göster/Gizle"
  ],
  "gating": "hasPiPaytr && isOwnerOrAdmin (payout backend requires OWNER/ADMIN).",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "keyComponents": [
   "Card",
   "Collapsible",
   "DataTable",
   "Recharts area chart",
   "Select",
   "Button"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "LazyPayoutsDashboard",
   "LazyPayoutDeductions",
   "payout transfers + deductions connections"
  ],
  "notes": "Cards from Admin.Payouts.Dashboard: Bankaya geçen, Yolda (bekleyen), Toplam net, Brüt satış (Kesinti: {fees}), Sıradaki ödeme (Yaklaşan ödeme yok). Chart 'Biriken net kazanç'. periodInfo note about period being sale-date based. Deductions statuses: Beklemede/Kesildi/Silindi. Transfers statuses: Beklemede/Hazır/Transfer Edildi/Başarısız. Detailed component files under src/admin/payouts (outside the given hint paths but part of this tab).",
  "cluster": "overview-orders"
 },
 {
  "surface": "Order detail page",
  "route": "/[organizationSlug]/admin/orders/[slug]",
  "titleTR": "Sipariş {slug}",
  "purpose": "Full single-order view: KPI cards, line items, transactions, refunds, activity, gifts, customer, custom fields, billing address, order summary, and invoices.",
  "layout": "Breadcrumb 'Siparişler / Sipariş {slug}' with an OrderStatusBadge + currency code on the right. Then OrderKpiCards (4-up). Two-column grid: left (2/3) = Ürünler, Ödemeler ve işlemler, İadeler, Etkinlik, Hediyeler, Müşteri Bilgileri, custom fields, Fatura Bilgileri; right (1/3) = Sipariş Özeti, Faturalar.",
  "actions": [
   "breadcrumb back to Siparişler"
  ],
  "gating": "Reachable from orders list; ORG_ORDERS_VIEW.",
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "Breadcrumb",
   "StatusBadge",
   "Card",
   "KPI cards"
  ],
  "priority": "primary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "AdminOrderPageQuery (order by slug) with fragments OrderKpiCards_order, AdminOrderTransactions_order, AdminOrderRefunds_order, AdminOrderActivity_order, AdminOrderLineItems_order, AdminOrderSummary_order, AdminOrderStudent_order, AdminOrderCustomFields_order, AdminOrderBillingAddress_order, AdminOrderInvoice_order, AdminOrderGifts_order"
  ],
  "notes": "KPI cards: Ödenen, Kesintiler (İşlemci {processor} · Platform {platform} / Henüz ödenmedi), Net kazancınız (Kesintiler sonrası / Henüz ödenmedi), Durum. Missing order → notFound(). Loading via AdminContentSkeleton.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Order detail — Sipariş Özeti + line items + transactions + refunds",
  "route": "/[organizationSlug]/admin/orders/[slug] (cards)",
  "titleTR": "Sipariş Özeti / Ürünler / Ödemeler ve işlemler / İadeler",
  "purpose": "Read-only financial breakdown cards on the order detail page.",
  "layout": "Ürünler card (line items with per-item 'Ödenen:', 'Form ödemesi'). Ödemeler ve işlemler card (payment attempts list: 'Aktif' badge, 'Ödenen:', external 'Ödeme sağlayıcısında görüntüle' link; empty 'Henüz ödeme denemesi kaydedilmedi.'). İadeler card ('Tahsil edilecek net:', 'Tahsil edilen:', '{name} tarafından'). Sipariş Özeti card (Ara Toplam, Toplam, Toplam İndirim, Ödenen, Ödeme işlemci ücreti, Platform ücreti, Net kazancınız; 'Sipariş zamanı:').",
  "states": [
   "empty"
  ],
  "keyComponents": [
   "Card",
   "Badge",
   "dl/dt/dd rows",
   "external link"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "AdminOrderLineItems_order",
   "AdminOrderTransactions_order",
   "AdminOrderRefunds_order",
   "AdminOrderSummary_order"
  ],
  "notes": "Purely read-only cards.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Order detail — Müşteri Bilgileri (edit email)",
  "route": "/[organizationSlug]/admin/orders/[slug] (customer card)",
  "titleTR": "Müşteri Bilgileri",
  "purpose": "Shows customer/student info; the order email is editable inline.",
  "layout": "Card 'Müşteri Bilgileri' with Email (inline editable field + save), Kayıt Tarihi. Inline edit form with validation.",
  "actions": [
   "edit email / save"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Card",
   "Input",
   "Form",
   "Toast"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "AdminOrderStudent_order",
   "AdminOrderStudentUpdateOrderMutation"
  ],
  "notes": "Success toast 'Email başarıyla güncellendi'; invalid 'Geçerli bir email adresi girin'; error 'Email güncellenemedi. Lütfen tekrar deneyin.'",
  "cluster": "overview-orders"
 },
 {
  "surface": "Order detail — Fatura Bilgileri (billing address add/edit dialog)",
  "route": "/[organizationSlug]/admin/orders/[slug] (billing card + modal)",
  "titleTR": "Fatura Bilgileri",
  "purpose": "View and add/edit the order's billing address via a form.",
  "layout": "Card 'Fatura Bilgileri' with an Ekle or Düzenle button (empty: 'Fatura bilgisi bulunmuyor.'). Opens a form/dialog with fields: Ad, Soyad, Adres, Adres Devamı, Şehir, İlçe, Ülke Kodu (TR), Posta Kodu, Telefon, Kimlik Numarası (TC Kimlik No), Şirket Adı, Vergi Numarası, Vergi Dairesi.",
  "actions": [
   "Ekle",
   "Düzenle",
   "save"
  ],
  "dialogs": [
   "Fatura Bilgileri form (add/edit)"
  ],
  "states": [
   "empty",
   "error"
  ],
  "keyComponents": [
   "Card",
   "Form",
   "Input",
   "Dialog/inline form",
   "Toast"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "AdminOrderBillingAddress_order",
   "AdminOrderBillingAddressUpdateMutation"
  ],
  "notes": "Validation: Ad gereklidir / Soyad gereklidir / Adres gereklidir. Success 'Fatura bilgileri başarıyla güncellendi.', error 'Fatura bilgileri güncellenemedi. Lütfen tekrar deneyin.'",
  "cluster": "overview-orders"
 },
 {
  "surface": "Order detail — Faturalar / Fatura Oluştur (invoices)",
  "route": "/[organizationSlug]/admin/orders/[slug] (invoices card)",
  "titleTR": "Faturalar",
  "purpose": "View/download issued invoices and trigger invoice generation.",
  "layout": "Card 'Faturalar' listing invoices with a 'Faturayı Görüntüle' download button (loading 'Yükleniyor…'). TriggerOrderBilling area: 'Fatura Oluştur' button (or 'İşlemin Bitmesini Bekleyin'), 'Tetiklenen Fatura Oluşturma İşlemleri' history; when no billing integration → 'Hesabınıza tanımlı aktif bir faturalandırma entegrasyonu bulunmamaktadır. Lütfen destek ekibiyle iletişime geçin.'",
  "actions": [
   "Faturayı Görüntüle",
   "Fatura Oluştur"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "keyComponents": [
   "Card",
   "Button",
   "Toast"
  ],
  "priority": "secondary",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "AdminOrderInvoice_order",
   "OrderInvoiceDownloadButtonGetInvoiceUrlMutation",
   "TriggerOrderBillingMutation"
  ],
  "notes": "Create success 'Fatura Oluşturma İşlemi Sıraya Alındı'. URL error 'Fatura açılamadı. Lütfen tekrar deneyin.' TriggerOrderBilling uses Admin.Billing namespace.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Order detail — Hediyeler / Etkinlik / özel alanlar",
  "route": "/[organizationSlug]/admin/orders/[slug] (cards)",
  "titleTR": "Hediyeler / Etkinlik",
  "purpose": "Gift delivery details, order activity timeline (emails/automations), and checkout custom-field answers.",
  "layout": "Hediyeler card (gift recipients: 'Email ile gönderim' / 'Link ile paylaşım', recipientName/email). Etkinlik card (email/automation log; empty 'Bu sipariş için henüz e-posta veya otomasyon kaydı yok.', 'Alıcı: {recipient}'). Custom fields card (checkout page settings orderPanelTitle).",
  "states": [
   "empty"
  ],
  "keyComponents": [
   "Card",
   "timeline rows",
   "Badge"
  ],
  "priority": "edge",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "AdminOrderGifts_order (namespace AdminOrderGifts + GiftCard)",
   "AdminOrderActivity_order",
   "AdminOrderCustomFields_order (Admin.CheckoutPageSettings)"
  ],
  "notes": "Gift line items are excluded from the main Ürünler list and shown here instead (useGiftLineItemIds).",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders/overview — permission denied",
  "route": "/[organizationSlug]/admin/orders (no ORG_ORDERS_VIEW)",
  "titleTR": "Siparişler",
  "purpose": "Shown when a member lacks ORG_ORDERS_VIEW — role-aware access gate instead of the orders view.",
  "layout": "NoAccessMessage: ShieldX icon, AccessGate.section copy naming the section ('Siparişler') and the viewer's role.",
  "gating": "!hasOrgPermission('ORG_ORDERS_VIEW').",
  "states": [
   "permission-denied"
  ],
  "keyComponents": [
   "ErrorLayout",
   "ShieldX icon"
  ],
  "priority": "edge",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "usePermissions (role, hasOrgPermission)"
  ],
  "notes": "AccessGate.section.reasonWithRole / reasonWithSection copy. Payouts data further gated to OWNER/ADMIN (tab simply hidden, not an error).",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders/overview — error boundary",
  "route": "/[organizationSlug]/admin/* (admin error.tsx)",
  "titleTR": "(AccessGate.serverError.title)",
  "purpose": "Segment-level error boundary for the admin tree (e.g. a failed useLazyLoadQuery on the orders/analytics/order-detail pages) rendered in place while the sidebar/navbar stay mounted.",
  "layout": "ErrorLayout inline, AlertTriangle icon, warning tone, description + 'Tekrar Dene' button (RefreshCw), optional reference id.",
  "actions": [
   "Tekrar Dene"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "ErrorLayout",
   "Button",
   "AlertTriangle"
  ],
  "priority": "edge",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [
   "Sentry.captureException"
  ],
  "notes": "Shared across all admin pages; applies to orders list, analytics, payouts, and order detail. reset() retries.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Orders/overview — loading skeletons",
  "route": "/[organizationSlug]/admin/orders (Suspense fallbacks)",
  "titleTR": "Siparişler",
  "purpose": "Loading placeholders while org/analytics/orders/order-detail queries resolve.",
  "layout": "AdminContentSkeleton (page), RevenueAnalyticsSkeleton (header + preset select + 4 KPI card skeletons + 400px chart + two 350px chart skeletons), OrdersTableSkeleton (3 filter chips + 400px table), TableSkeleton (payouts).",
  "states": [
   "loading"
  ],
  "keyComponents": [
   "Skeleton"
  ],
  "priority": "edge",
  "suggestedCanvas": "01-overview-orders",
  "dataSources": [],
  "notes": "showAnalytics===null renders RevenueAnalyticsSkeleton until localStorage read resolves.",
  "cluster": "overview-orders"
 },
 {
  "surface": "Product catalog hub (Kurslar)",
  "route": "/[organizationSlug]/admin/courses (CoursesPage.tsx → hash sections #courses / #meetings / #digital-products / #live-events / #bundles)",
  "titleTR": "Kurslar",
  "purpose": "Single scrolling hub that lists all product families of an org (courses, birebir görüşmeler/coaching, digital products, live events, bundles) plus an upcoming-events calendar. Each family is a <section> with its own heading, description, toolbar (search + tag filter + reorder + create) and infinite card grid. Hash links (#courses etc.) smooth-scroll to a section.",
  "layout": "Vertical stack of <section>s separated by top borders. Each section: h2 heading (white-label NAV label + AdminHelpMenu '?' icon) + muted description; a CoursesToolbar row (search input, Etiketler tag filter popover, 'Sıralamayı Düzenle' outline button, primary create button, and for courses an extra gradient 'AI ile Oluştur' button); then a Tabs strip (Tümü/Yayında/Taslak/Arşivlenmiş via PublicationStatusFilterTabs) over a responsive card grid (VerticalCourseCard/VerticalDigitalProductCard/VerticalLiveEventCard/VerticalBundleCard), with InfiniteListFooter 'showingCount'. CalendarEventsSection sits at the very top. Bundles section only if ORG_BUNDLES_VIEW.",
  "states": [
   "loading",
   "empty",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Tümü",
   "Yayında",
   "Taslak",
   "Arşivlenmiş"
  ],
  "filters": [
   "Kurs ara... (search)",
   "Etiketler (tag include/exclude popover: Dahil et / Hariç tut, Gruplanmamış)",
   "Sıfırla"
  ],
  "actions": [
   "Kurs Oluştur",
   "AI ile Oluştur",
   "Birebir Görüşme Oluştur",
   "Dijital Ürün Oluştur",
   "Canlı Etkinlik Oluştur",
   "Paket Oluştur",
   "Sıralamayı Düzenle"
  ],
  "dialogs": [
   "CourseCreationWizard (4-step sheet)",
   "CreateCourseWithAIDialogContent (AI Prompt dialog)",
   "CoachingCreationWizard",
   "DigitalProductCreationWizard",
   "LiveEventCreationWizard",
   "BundleCreationWizard",
   "ReorderCoursesSheet",
   "ReorderCoachingSessionsSheet",
   "ReorderDigitalProductsSheet",
   "ReorderLiveEventsSheet",
   "ReorderBundlesSheet",
   "AdminOrganizationOnboardingAlert"
  ],
  "keyComponents": [
   "Tabs/TabsList",
   "PublicationStatusFilterTabs",
   "CoursesToolbar",
   "VerticalCourseCard",
   "VerticalImageCardSkeleton",
   "SectionCardsSkeleton",
   "InfiniteListFooter",
   "Button",
   "Dialog",
   "AdminHelpMenu"
  ],
  "dataSources": [
   "CoursesPageQuery (organization: publishedCoursesCount, draftCoursesCount, publishedCoachingSessionsCount, draftCoachingSessionsCount, enabledBundlesCount, disabledBundlesCount, publishedDigitalProductsCount, draftDigitalProductsCount, publishedLiveEventsCount, draftLiveEventsCount, tagGroups)",
   "OrganizationCourses_courses fragment (courses connection, OBJECT_INDEX ASC, sortBy/tagIds/excludeTagIds/query)",
   "OrganizationCoachingSessions_coachingSessions",
   "OrganizationDigitalProducts_digitalProducts",
   "OrganizationLiveEvents_liveEvents",
   "OrganizationBundles_organization",
   "CoursesOnboarding_organization",
   "useOrganizationTags_organization"
  ],
  "gating": "Courses create gated on COURSE_EDIT; coaching on COACHING_EDIT; digital products & live events on COURSE_EDIT; bundles section on ORG_BUNDLES_VIEW. Non-editors still see published cards (read-only, no toolbar).",
  "notes": "White-label labels via useCustomLabel (NAV_MY_COURSES = 'Kurslarım', NAV_COACHING_SESSIONS = 'Birebir Görüşmeler'). Section descriptions: coursesDescription 'Kurslarınızı görüntüleyin ve yönetin.', sectionTitleDigitalProducts 'Dijital Ürünleriniz', sectionTitleLiveEvents 'Canlı Etkinlikleriniz'. ?openWizard= deep-link opens matching creation wizard.",
  "cluster": "catalog"
 },
 {
  "surface": "Catalog hub — empty state (Onboarding)",
  "route": "/[organizationSlug]/admin/courses (CoursesOnboarding, when org has 0 of every product type)",
  "titleTR": "Ürünlerinize hoş geldiniz",
  "purpose": "Two-step onboarding shown when the org has no products at all: intro (what you can create) then product-type picker that launches the matching creation wizard.",
  "layout": "Stepper (Tanıtım / Ürün tipi). Intro screen: heading 'Ürünlerinize hoş geldiniz', description, feature list (Kurslar, Koçluk seansları, Dijital ürünler, Canlı etkinlikler, Paketler each with title+description), 'Başla' button. Select screen: 'Ne oluşturmak istersiniz?' grid of product-type cards, 'Geri' back button. AdminOrganizationOnboardingAlert below.",
  "states": [
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Başla",
   "Geri"
  ],
  "keyComponents": [
   "Stepper",
   "Card",
   "Button"
  ],
  "dataSources": [
   "CoursesOnboarding_organization"
  ],
  "notes": "Turkish: stepIntro 'Tanıtım', stepSelect 'Ürün tipi', selectTitle 'Ne oluşturmak istersiniz?'. Feature titles/descs in Admin.Courses.onboarding.*",
  "cluster": "catalog"
 },
 {
  "surface": "Calendar events section (Takvim Etkinlikleri)",
  "route": "/[organizationSlug]/admin/courses (CalendarEventsSection at top of hub)",
  "titleTR": "Takvim Etkinlikleri",
  "purpose": "Upcoming reservations (coaching bookings) and live course sessions across the org, in a table view or calendar view. Admin vs instructor variants.",
  "layout": "Section header 'Takvim Etkinlikleri' + description 'Organizasyonunuzdaki yaklaşan rezervasyonlar ve canlı oturumlar.' Toolbar: Tablo/Takvim segmented toggle, Tarih aralığı date range, Durum status filter, Sıfırla. Table columns: Tür / Başlık / Başlangıç / Bitiş / Detay (Detaya Git). Calendar view = month grid with day-detail panel.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Tablo",
   "Takvim"
  ],
  "filters": [
   "Tarih aralığı",
   "Durum",
   "Sıfırla"
  ],
  "tableColumns": [
   "Tür",
   "Başlık",
   "Başlangıç",
   "Bitiş",
   "Detay"
  ],
  "keyComponents": [
   "Tabs/SegmentedViewToggle",
   "Table",
   "Calendar day grid",
   "StatusFilter"
  ],
  "dataSources": [
   "useCalendarEvents (reservations + live course items)"
  ],
  "notes": "typeReservation 'Rezervasyon', typeLiveCourseItem 'Canlı Oturum', noEvents 'Etkinlik bulunamadı.', calendarEventsError 'Takvim etkinlikleri yüklenemedi.'",
  "cluster": "catalog"
 },
 {
  "surface": "Course creation wizard",
  "route": "/[organizationSlug]/admin/courses (CourseCreationWizard dialog/sheet)",
  "titleTR": "Kurs Detayları",
  "purpose": "4-step wizard to create a course: Details → Görsel → Fiyat → İçerik (with AI-generate or manual branch at content step).",
  "layout": "Stepper: Detaylar / Görsel / Fiyat / İçerik. Step 1 Details: Kurs Başlığı, Kurs URL'si, Açıklama. Step 2 Image upload (Atla/Devam Et/Görseli Değiştir). Step 3 Pricing: Para Birimi, Satış Fiyatı, Orijinal Fiyat, Vergi Oranı, Aktif toggle. Step 4 Content: two cards 'Yapay Zeka ile Oluştur' vs 'Manuel Oluştur'.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Devam Et",
   "Geri",
   "Kapat",
   "Tekrar Dene"
  ],
  "keyComponents": [
   "Dialog/Sheet",
   "Stepper",
   "Form fields",
   "ImageUploader"
  ],
  "notes": "Admin.CourseCreationWizard.*. loadError 'Bu adım yüklenirken bir hata oluştu.', comingSoon exists.",
  "cluster": "catalog"
 },
 {
  "surface": "Create course with AI dialog",
  "route": "/[organizationSlug]/admin/courses (CreateCourseWithAIDialogContent)",
  "titleTR": "AI ile Oluştur",
  "purpose": "Single-field dialog: enter an AI prompt to auto-generate a full course draft.",
  "layout": "Dialog: title 'AI ile Oluştur', description 'Yapay zeka yardımıyla hızlıca kurs içeriği oluşturun', AI Prompt textarea (placeholder 'Örneğin: İspanyolca cümle kalıpları ve deyimler üzerine bir kurs oluştur'), in-flight message 'Yaklaşık 20 saniye içerisinde kursunuz oluşmuş olacak. Ne kadar heyecan verici!'",
  "states": [
   "loading",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "02-catalog",
  "keyComponents": [
   "Dialog",
   "Textarea",
   "Button"
  ],
  "notes": "Gradient purple→pink CTA style. aiPromptMaxLengthError 2000 chars.",
  "cluster": "catalog"
 },
 {
  "surface": "Course detail (admin course + academic term)",
  "route": "/[organizationSlug]/admin/courses/[courseSlug]/[academicTermSlug] (AdminCoursePage.tsx)",
  "titleTR": "Kurs",
  "purpose": "Full course/term management workspace with 9 tabs. Header shows term title, publish status badge, 'Öğrenme Deneyimini Görüntüle' external link, GeneratedPageLinks, and a 'search this page' box.",
  "layout": "Optional banners: PublishDraftBanner (draft), payment-methods-missing warning Alert ('Ödeme Bilgilerin Eksik'), archived Alert ('Bu kurs arşivlendi'). ProductDetailHeader (back 'Kurslar', title, PublishStatusBadge, view-as-student, page links, ProductDetailSearch). Scrollable TabsList: Kurs İçeriği / Görevler (with count badge) / Öğrenciler / Eğitmenler / Ayarlar / Satışlar / Öneriler / Sertifika / Dönemler(if >1 term). Settings tab has SegmentedViewToggle: Genel / Fiyatlandırma / Görünüm / Özel Alanlar / Kritik İşlemler.",
  "states": [
   "loading",
   "empty",
   "error",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Kurs İçeriği",
   "Görevler",
   "Öğrenciler",
   "Eğitmenler",
   "Ayarlar",
   "Satışlar",
   "Öneriler",
   "Sertifika",
   "Dönemler"
  ],
  "actions": [
   "Öğrenme Deneyimini Görüntüle",
   "Yayınla (banner)",
   "Ödeme Bilgilerini Ekle"
  ],
  "dialogs": [
   "UnsavedChangesConfirmDialog",
   "(within tabs) course item create/edit/delete dialogs, instructor invite, term settings, delete course"
  ],
  "keyComponents": [
   "ProductDetailHeader",
   "ScrollableTabsList",
   "Tabs",
   "SegmentedViewToggle",
   "PublishStatusBadge",
   "PublishDraftBanner",
   "Alert",
   "Badge",
   "ProductDetailSearch"
  ],
  "dataSources": [
   "AdminCoursePageQuery (course: title, publishStatus, tags, customFieldValues, generatedPageLinks, academicTerms, academicTerm{sections, viewerInstructor.role, instructorTasksRequiringAction}, organization.paymentMethods)",
   "AdminCoursePagePublishMutation (updateCourse status PUBLISHED)",
   "fragments: CourseAdminSections_sections, CourseAdminInstructors_*, CourseAcademicTermSettings_*, CourseAcademicTermPricing_course, CourseAdminAcademicTerms_course"
  ],
  "gating": "Editing gated on COURSE_EDIT resource permission OR viewerInstructor.role ADMIN (hasAdminAccess). Settings/Öneriler/Sertifika/Dönemler locked (lockedNoEditAccess) for non-admins. Öğrenciler examResults sub-view only if term has exams.",
  "notes": "Students tab sub-views: Kayıtlılar / Davetler / İlerleme / Sınav Sonuçları (Admin.Course.StudentsTab). Settings groups labels in Admin.Course. Detail covered by sibling clusters for contents/students/orders/instructors; here mapped as the shell + settings.",
  "cluster": "catalog"
 },
 {
  "surface": "Organization academic terms (Akademik Dönemler)",
  "route": "/[organizationSlug]/admin/courses/academic-terms (OrganizationAcademicTerms.tsx)",
  "titleTR": "Akademik Dönemler",
  "purpose": "Org-level list of shared academic terms (e.g. 2026 Bahar) that can be linked to multiple courses. CRUD table.",
  "layout": "Back button 'Kurslar'. Header 'Akademik Dönemler' + description. 'Yeni Dönem' primary button. Table: Dönem / Tarihler / Bağlı kurslar / (actions edit+delete icons). Empty state card 'Henüz akademik dönem yok'.",
  "states": [
   "empty",
   "permission"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Dönem",
   "Tarihler",
   "Bağlı kurslar",
   "İşlemler"
  ],
  "actions": [
   "Yeni Dönem",
   "Düzenle",
   "Sil"
  ],
  "dialogs": [
   "CreateAcademicTermDialogContent (Yeni Akademik Dönem: Ad, Başlangıç, Bitiş)",
   "UpdateAcademicTermDialogContent (Akademik Dönemi Düzenle)",
   "DeleteAcademicTermDialogContent ('{label}' silinsin mi? with linked-course warning)"
  ],
  "keyComponents": [
   "Table",
   "Dialog",
   "Button (icon ghost)"
  ],
  "dataSources": [
   "OrganizationAcademicTermsQuery (organization.academicTerms: id, label, startDate, endDate, courseAcademicTermCount)"
  ],
  "gating": "Requires COURSE_EDIT permission; otherwise notFound().",
  "notes": "Admin.AcademicTerms.*. deleteWithLinkedWarning warns linked courses get unlinked (not deleted).",
  "cluster": "catalog"
 },
 {
  "surface": "Digital product detail",
  "route": "/[organizationSlug]/admin/digital-products/[slug] (AdminDigitalProductPage.tsx)",
  "titleTR": "Dijital Ürün",
  "purpose": "Manage one digital product: settings, attachments/files, students, orders, recommendations.",
  "layout": "PublishDraftBanner if DRAFT. ProductDetailHeader (back 'Dijital ürünlere dön', title, PublishStatusBadge, 'Öğrenci Görünümü' external, page links, search). Tabs: Ayarlar / Öğrenciler / Siparişler / Öneriler. Settings tab SegmentedViewToggle: Genel / Fiyatlandırma / Etiketler & Alanlar / Kritik İşlemler. Genel: product-page preview, settings card (Başlık/URL/Durum/Fiyat + Ayarları Düzenle + Ürünü Çoğalt), OrderableSalesPauseCard, DigitalProductAttachments (Dosyalar). Pricing: OrderablePricing + CheckoutPageSettingsCard. Tags&Fields: TagsSettingsCard + ProductAccessPlansCard(if sub products) + EntityCustomFieldsCard. Kritik: Kursa Dönüştür + Dijital Ürünü Sil.",
  "states": [
   "loading",
   "empty",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Ayarlar",
   "Öğrenciler",
   "Siparişler",
   "Öneriler"
  ],
  "actions": [
   "Öğrenci Görünümü",
   "Yayınla (banner)",
   "Ayarları Düzenle",
   "Ürünü Çoğalt",
   "Kursa Dönüştür",
   "Dijital Ürünü Sil"
  ],
  "dialogs": [
   "UpdateDigitalProductDialogContent (Dijital Ürünü Güncelle)",
   "CloneDigitalProductDialogContent (Ürünü Çoğalt)",
   "ConvertDigitalProductToCourseDialogContent (typed-confirm)",
   "DeleteDigitalProductDialogContent (typed-confirm)",
   "UnsavedChangesConfirmDialog"
  ],
  "keyComponents": [
   "ProductDetailHeader",
   "Tabs",
   "SegmentedViewToggle",
   "Card",
   "OrderableSalesPauseCard",
   "DigitalProductAttachments",
   "ProductAccessPlansCard",
   "EntityCustomFieldsCard",
   "PublishStatusBadge"
  ],
  "dataSources": [
   "AdminDigitalProductPageQuery (digitalProduct: title, slug, publishStatus, image, sellingPrice, originalPrice, tags, grantingOrgSubscriptionTiers, customFieldValues, generatedPageLinks, organization.orgSubscriptionProducts.totalCount)",
   "AdminDigitalProductPagePublishMutation (updateDigitalProduct status PUBLISHED)",
   "fragments: CheckoutPageSettingsCard_orderable, OrderableSalesPauseCard_orderable, UpdateDigitalProductDialogContent_digitalProduct, DigitalProductAttachments_digitalProduct, ProductAccessPlansCard_organization"
  ],
  "gating": "canEdit via hasResourcePermission(COURSE, id, COURSE_EDIT); non-editors see read-only settings card only.",
  "notes": "Attachments (Dosyalar): 'Dosya Yükle' maks 1 GB, önizle/sil per file. Convert-to-course is one-way typed confirmation.",
  "cluster": "catalog"
 },
 {
  "surface": "Digital product creation wizard",
  "route": "/[organizationSlug]/admin/courses (DigitalProductCreationWizard)",
  "titleTR": "Dijital Ürün Detayları",
  "purpose": "Create a digital product: Details → Oluştur → (then) Görsel/Fiyat/Dosyalar.",
  "layout": "Stepper: Detaylar / Oluştur / Görsel / Fiyat / Dosyalar. Details: Ürün Başlığı, Ürün URL. Create step: review + 'Oluştur ve Dosya Ekle'. Then image, pricing, files upload (maks 1 GB, 'Dosyasız Tamamla' / 'Tamamla').",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Devam",
   "Oluştur ve Dosya Ekle",
   "Dosyasız Tamamla",
   "Tamamla"
  ],
  "keyComponents": [
   "Dialog/Sheet",
   "Stepper",
   "ImageUploader",
   "FileUploader"
  ],
  "notes": "Admin.DigitalProductCreationWizard.*",
  "cluster": "catalog"
 },
 {
  "surface": "Live event detail",
  "route": "/[organizationSlug]/admin/live-events/[slug] (AdminLiveEventPage.tsx)",
  "titleTR": "Canlı Etkinlik",
  "purpose": "Manage one live event: settings, students, orders, certificates, recommendations.",
  "layout": "PublishDraftBanner if DRAFT. ProductDetailHeader (back 'Canlı etkinliklere dön', 'Öğrenci Görünümü', page links, search). Tabs: Ayarlar / Öğrenciler / Siparişler / Öneriler / Sertifikalar. Settings SegmentedViewToggle: Genel / Fiyatlandırma / Etiketler & Alanlar / Kritik İşlemler. Genel settings card shows Başlık/URL/Durum/Başlangıç Tarihi/Bitiş Tarihi/Platform/Kapasite/Fiyat + Ayarları Düzenle + Etkinliği Çoğalt + OrderableSalesPauseCard. Kritik: Kursa Dönüştür + Canlı Etkinliği Sil.",
  "states": [
   "loading",
   "empty",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Ayarlar",
   "Öğrenciler",
   "Siparişler",
   "Öneriler",
   "Sertifikalar"
  ],
  "actions": [
   "Öğrenci Görünümü",
   "Yayınla (banner)",
   "Ayarları Düzenle",
   "Etkinliği Çoğalt",
   "Kursa Dönüştür",
   "Canlı Etkinliği Sil"
  ],
  "dialogs": [
   "UpdateLiveEventDialogContent (Canlı Etkinliği Güncelle: startDate/endDate/platform/capacity)",
   "CloneLiveEventDialogContent",
   "ConvertLiveEventToCourseDialogContent (typed-confirm)",
   "DeleteLiveEventDialogContent (typed-confirm)",
   "UnsavedChangesConfirmDialog"
  ],
  "keyComponents": [
   "ProductDetailHeader",
   "Tabs",
   "SegmentedViewToggle",
   "Card",
   "OrderableSalesPauseCard",
   "ProductAccessPlansCard",
   "EntityCustomFieldsCard",
   "LiveEventCertificateTab",
   "PublishStatusBadge"
  ],
  "dataSources": [
   "AdminLiveEventPageQuery (liveEvent: title, slug, publishStatus, image, startDate, endDate, platform, capacity, sellingPrice, originalPrice, tags, grantingOrgSubscriptionTiers, customFieldValues, generatedPageLinks, organization.orgSubscriptionProducts.totalCount)",
   "AdminLiveEventPagePublishMutation",
   "fragments: CheckoutPageSettingsCard_orderable, OrderableSalesPauseCard_orderable, UpdateLiveEventDialogContent_liveEvent, ProductAccessPlansCard_organization"
  ],
  "gating": "canEdit via hasResourcePermission(COURSE, id, COURSE_EDIT).",
  "notes": "Distinct from DP: extra Sertifikalar tab (LiveEventCertificateTab) + schedule/platform/capacity fields. Admin.LiveEvent.*",
  "cluster": "catalog"
 },
 {
  "surface": "Live event creation wizard",
  "route": "/[organizationSlug]/admin/courses (LiveEventCreationWizard)",
  "titleTR": "Canlı Etkinlik Detayları",
  "purpose": "Create a live event: Details → Takvim (schedule) → Oluştur → Görsel → Fiyat.",
  "layout": "Stepper: Detaylar / Takvim / Oluştur / Görsel / Fiyat. Details: Etkinlik Başlığı, Etkinlik URL. Schedule: Başlangıç Tarihi ve Saati, Bitiş, Platform, Toplantı URL'si, Kapasite (boş = sınırsız). Create: review + 'Canlı Etkinlik Oluştur'. Then image, pricing.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Devam",
   "Canlı Etkinlik Oluştur",
   "Atla",
   "Devam Et"
  ],
  "keyComponents": [
   "Dialog/Sheet",
   "Stepper",
   "DateTimePicker",
   "ImageUploader"
  ],
  "notes": "zoomSyncWarning shown if Zoom meeting sync fails. Admin.LiveEventCreationWizard.*",
  "cluster": "catalog"
 },
 {
  "surface": "Live event certificates tab",
  "route": "/[organizationSlug]/admin/live-events/[slug]?tab=certificates (LiveEventCertificateTab)",
  "titleTR": "Sertifika Şablonları",
  "purpose": "Create certificate templates and view/issue/revoke certificates for a live event's participants.",
  "layout": "Certificate prefix info card, 'Sertifika Şablonları' list with 'Yeni Şablon Oluştur', empty state 'Sertifika şablonu oluşturun'. Template cards show Kazanım Kriteri + issued count. Editor: drag-drop certificate canvas (Önizleme/Ayarlar tabs), fields (Öğrenci Adı/Kurs Adı/Tarih/Sertifika ID/Özel Metin). Issued certificates table: Öğrenci/Sertifika Şablonu/Veriliş Tarihi/Durum/İşlemler. Sertifika Ver dialog.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Öğrenci",
   "Sertifika Şablonu",
   "Veriliş Tarihi",
   "Durum",
   "İşlemler"
  ],
  "actions": [
   "Yeni Şablon Oluştur",
   "Sertifika Ver",
   "Sertifikayı Görüntüle",
   "İptal Et",
   "Sil"
  ],
  "dialogs": [
   "Certificate editor (create/edit)",
   "Issue certificate (Sertifika Ver)",
   "Revoke (Sertifikayı İptal Et)",
   "Delete template / Delete certificate"
  ],
  "keyComponents": [
   "Card",
   "Table",
   "Certificate canvas editor",
   "Dialog"
  ],
  "dataSources": [
   "Live event certificate templates + issued certificates queries"
  ],
  "notes": "Shared Admin.Certificates namespace (same as course certificate tab).",
  "cluster": "catalog"
 },
 {
  "surface": "Bundle detail",
  "route": "/[organizationSlug]/admin/bundles/[slug] (AdminBundlePage.tsx)",
  "titleTR": "Paket",
  "purpose": "Manage a bundle: its contents, settings, and recommendations. Content editor holds pending add/remove until a top-bar Save.",
  "layout": "PublishDraftBanner if not enabled. ProductDetailHeader (back 'Paketlere dön', 'Görüntüle' external to /siparis?bundle=, page links, 'Değişiklikleri Kaydet' save button when content dirty, StatusBadge Yayında/Taslak). Tabs: Paket İçeriği (İçerik) / Ayarlar / Öneriler (locked for non-managers). Content tab: BundleContentManager (Mevcut İçerikler list + İçerik Ekle picker with product-type sub-tabs Kurslar/Koçluk Seansları/Dijital Ürünler/Canlı Etkinlikler). Settings SegmentedViewToggle: Genel / Fiyatlandırma / Etiketler & Alanlar / Kritik İşlemler. Genel: preview + BundleUpdateForm (title/slug/image/enabled) + OrderableSalesPauseCard. Pricing: BundlePricing + CheckoutPageSettingsCard. Kritik: Paketi Sil.",
  "states": [
   "loading",
   "empty",
   "error",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Paket İçeriği",
   "Ayarlar",
   "Öneriler"
  ],
  "actions": [
   "Görüntüle",
   "Yayınla (banner)",
   "Değişiklikleri Kaydet",
   "İçerik Ekle",
   "Paketi Sil"
  ],
  "dialogs": [
   "DeleteBundleDialogContent (typed-confirm 'Paketi silmek istediğime eminim')",
   "UnsavedChangesConfirmDialog",
   "creationWarning toast on partial-create"
  ],
  "keyComponents": [
   "ProductDetailHeader",
   "Tabs (PageTabsTrigger locked)",
   "SegmentedViewToggle",
   "BundleContentManager",
   "BundlePricing",
   "BundleUpdateForm",
   "OrderableSalesPauseCard",
   "ProductAccessPlansCard",
   "StatusBadge",
   "ErrorBoundary"
  ],
  "dataSources": [
   "AdminBundlePageQuery (organization.bundle: title, slug, enabled, tags, grantingOrgSubscriptionTiers, customFieldValues, generatedPageLinks; orgSubscriptionProducts.totalCount)",
   "AdminBundlePagePublishMutation (updateBundle enabled:true)",
   "fragments: BundlePricing_bundle, BundleUpdateForm_bundle, BundleContentManager_bundle, CheckoutPageSettingsCard_orderable, OrderableSalesPauseCard_orderable"
  ],
  "gating": "hasOrgPermission(ORG_BUNDLES_MANAGE) for all tab content; tabs locked otherwise.",
  "notes": "Publish = flip enabled bit. Content changes are batched and saved via header Save. Admin.BundleSettings.* + Admin.Bundle.*",
  "cluster": "catalog"
 },
 {
  "surface": "Bundle creation wizard",
  "route": "/[organizationSlug]/admin/courses (BundleCreationWizard)",
  "titleTR": "Paket Detayları",
  "purpose": "Create a bundle: Details → Fiyat → İçerik.",
  "layout": "Stepper: Detaylar / Fiyat / İçerik. Details: Paket Başlığı, Paket URL'si. Pricing: Para Birimi, Satış Fiyatı, Vergi Oranı, Yayında toggle. Content: multi-selects for Kurs Seçin / Koçluk Seansı Seçin / Dijital Ürünler / Canlı Etkinlikler, then 'Paketi Oluştur'.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Devam Et",
   "Paketi Oluştur"
  ],
  "keyComponents": [
   "Dialog/Sheet",
   "Stepper",
   "Combobox/multi-select"
  ],
  "notes": "Admin.BundleCreationWizard.*. Partial-create surfaces creationWarning on the detail page.",
  "cluster": "catalog"
 },
 {
  "surface": "Subscriptions list (Abonelik Ürünleri)",
  "route": "/[organizationSlug]/admin/subscriptions (SubscriptionsPage.tsx)",
  "titleTR": "Abonelik Ürünleri",
  "purpose": "List org subscription products (recurring membership products), each as a card with metrics; create via template or wizard. On the 'pi' org, also shows Teachfluence platform subscriptions table below.",
  "layout": "PageHeader 'Abonelik Ürünleri' + 'Yeni Ürün Oluştur' primary button. SubscriptionTemplates quick-start row ('Şablonla hızlı başla': Üyelik / Kademeli Plan / Koçluk Programı / İçerik Üreticisi). Status Tabs: Tümü / Aktif / Taslak / Arşivlenmiş + search 'Ürün ara...' + Filtreleri temizle. OrgSubscriptionProducts grid of product cards (each: name, slug, subscriber count 'abone', tier count, status badge). If org=pi: Separator + PiEducationSubscriptions table.",
  "states": [
   "loading",
   "empty",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Tümü",
   "Aktif",
   "Taslak",
   "Arşivlenmiş"
  ],
  "filters": [
   "Ürün ara...",
   "Filtreleri temizle"
  ],
  "actions": [
   "Yeni Ürün Oluştur"
  ],
  "dialogs": [
   "SubscriptionCreationWizard (4-step)",
   "SubscriptionTemplates picker"
  ],
  "keyComponents": [
   "PageHeader",
   "SubscriptionTemplates",
   "Tabs",
   "AdminSearchInput",
   "OrgSubscriptionProductCard",
   "NoAccessMessage",
   "Separator"
  ],
  "dataSources": [
   "SubscriptionsPageQuery (organization.name, OrgSubscriptionProducts_organization; PiEducationSubscriptions_query @include(isPiOrg))"
  ],
  "gating": "ORG_SUBSCRIPTIONS_VIEW to view (else NoAccessMessage 'Abonelik Ürünlerini Yönetme Yetkin Yok'); ORG_SUBSCRIPTIONS_MANAGE to create.",
  "notes": "Admin.OrgSubscriptions.*. noProducts 'Henüz abonelik ürünü oluşturulmadı.'",
  "cluster": "catalog"
 },
 {
  "surface": "Subscription creation wizard",
  "route": "/[organizationSlug]/admin/subscriptions (SubscriptionCreationWizard)",
  "titleTR": "Detaylar",
  "purpose": "Create a subscription product: Details → Aralıklar (intervals) → Kademeler (tiers) → Oluştur.",
  "layout": "Stepper: Detaylar / Aralıklar / Kademeler / Oluştur. Details: name, slug, description. Intervals: allow Monthly/Yearly/Lifetime toggles. Tiers: seed tier(s). Create: review + submit. Prefillable from template presets (Üyelik/Kademeli Plan/Koçluk/İçerik Üreticisi).",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Devam",
   "Oluştur"
  ],
  "keyComponents": [
   "Dialog/Sheet",
   "Stepper",
   "Switch",
   "Form fields"
  ],
  "notes": "Admin.SubscriptionCreationWizard.*",
  "cluster": "catalog"
 },
 {
  "surface": "Subscription product detail",
  "route": "/[organizationSlug]/admin/subscriptions/[productSlug] (AdminSubscriptionProductPage.tsx)",
  "titleTR": "Abonelikler",
  "purpose": "Manage one subscription product: overview metrics + tiers, subscribers, gifted subscriptions.",
  "layout": "ProductDetailHeader (back 'Abonelik ürünlerine dön', title, status Badge Taslak/Aktif/Arşivlenmiş, 'Canlı Sayfayı Aç' external, Update dialog). Overview Card: description, allowed-interval badges (Aylık/Yıllık/Ömür Boyu), slug, metrics strip: Kademe count / Aktif Aboneler / Aylık Tekrarlayan Gelir (MRR, may show '—' with tooltip when >100 subscribers). PageTabs: Abonelik Kademeleri / Aboneler / Hediye Abonelikler. Tiers tab toolbar: 'Yeni Kademe Ekle' + 'Sıralamayı Düzenle'; tier cards grid.",
  "states": [
   "loading",
   "empty",
   "permission"
  ],
  "priority": "primary",
  "suggestedCanvas": "02-catalog",
  "tabs": [
   "Abonelik Kademeleri",
   "Aboneler",
   "Hediye Abonelikler"
  ],
  "actions": [
   "Canlı Sayfayı Aç",
   "Yeni Kademe Ekle",
   "Sıralamayı Düzenle",
   "(Update product dialog)"
  ],
  "dialogs": [
   "UpdateOrgSubscriptionProductDialog",
   "TierCreationWizard (6-step)",
   "ReorderTiersSheet",
   "DeleteOrgSubscriptionProductDialog",
   "DeleteOrgSubscriptionTierDialog",
   "UpdateOrgSubscriptionTierDialog"
  ],
  "keyComponents": [
   "ProductDetailHeader",
   "Card",
   "Badge",
   "PageTabs",
   "OrgSubscriptionTiers",
   "OrgSubscriptionTierCard",
   "ProductSubscribers",
   "ProductGiftedSubscriptions",
   "Tooltip"
  ],
  "dataSources": [
   "AdminSubscriptionProductPageQuery (orgSubscriptionProduct: name, slug, description, status, allowMonthly/Yearly/Lifetime, tiers{name,pricing{currency,interval,intervalCount,enabled,sellingPrice}}, activeSubscribers sample first:100)",
   "OrgSubscriptionTiers_organization/_product fragments"
  ],
  "gating": "ORG_SUBSCRIPTIONS_VIEW (else NoAccessMessage); ORG_SUBSCRIPTIONS_MANAGE to create tiers/edit.",
  "notes": "MRR computed client-side, capped at 100-subscriber sample; over cap → mrrUnavailable '—' + tooltip. metrics.tiers 'Kademe', metrics.activeSubscribers 'Aktif Aboneler', metrics.mrr 'Aylık Tekrarlayan Gelir'.",
  "cluster": "catalog"
 },
 {
  "surface": "Subscription tiers tab",
  "route": "/[organizationSlug]/admin/subscriptions/[productSlug]?tab=tiers (OrgSubscriptionTiers)",
  "titleTR": "Abonelik Kademeleri",
  "purpose": "List/manage the product's tiers (pricing, features, granted tags, unlocked content).",
  "layout": "Grid of OrgSubscriptionTierCard: tier name, Aktif/Devre Dışı badge, pricing per interval, Özellikler list (+N daha), Verilen Etiketler, Erişim Sağlanan İçerikler counts (Kurs/Paket/Dijital ürün/Canlı etkinlik). Empty: 'Bu ürün için henüz kademe oluşturulmadı.' Card actions: edit/delete/manage content+tags.",
  "states": [
   "loading",
   "empty",
   "permission"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Yeni Kademe Ekle",
   "Özellik Ekle",
   "(edit / delete tier)"
  ],
  "dialogs": [
   "TierCreationWizard",
   "UpdateOrgSubscriptionTierDialog",
   "DeleteOrgSubscriptionTierDialog",
   "TierUnlockedContentManager",
   "TierTagsManager",
   "AccessibleContentPicker"
  ],
  "keyComponents": [
   "OrgSubscriptionTierCard",
   "TierPricingForm",
   "TierTagsManager",
   "TierUnlockedContentManager",
   "UnlockedContentPreview",
   "Badge"
  ],
  "dataSources": [
   "OrgSubscriptionTiers_product / _organization fragments (tiers, pricing, grantedTags, unlockedCourses/Bundles/DigitalProducts/LiveEvents)"
  ],
  "notes": "Admin.OrgSubscriptions.tiers.*",
  "cluster": "catalog"
 },
 {
  "surface": "Tier creation wizard",
  "route": "/[organizationSlug]/admin/subscriptions/[productSlug] (TierCreationWizard)",
  "titleTR": "Detaylar",
  "purpose": "Create a subscription tier: Details → Özellikler → Erişim (content) → Ayarlar → Fiyatlandırma → Oluştur.",
  "layout": "Stepper: Detaylar / Özellikler / Erişim / Ayarlar / Fiyatlandırma / Oluştur. Details: name/slug/description. Features: bullet list. Content(Erişim): pick accessible content. Settings: trial/grace period days, enabled. Pricing: per-interval selling prices. Create: submit.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "actions": [
   "Devam",
   "Oluştur"
  ],
  "keyComponents": [
   "Dialog/Sheet",
   "Stepper",
   "TierPricingForm"
  ],
  "notes": "Admin.TierCreationWizard.*",
  "cluster": "catalog"
 },
 {
  "surface": "Subscription product — Subscribers tab",
  "route": "/[organizationSlug]/admin/subscriptions/[productSlug]?tab=subscribers (ProductSubscribers)",
  "titleTR": "Aboneler",
  "purpose": "Table of the product's subscribers with bulk-cancel; per-row payments/details/cancel.",
  "layout": "Toolbar: search 'Abone ara...', Durum filter, Filtreleri Temizle; selection with 'Seçilenleri iptal et ({count})'. Table columns: Abone / Kademe / Durum / Periyot / Dönem Sonu / Abone Olma. Row actions menu: Ödemeleri Görüntüle / Detaylar / Aboneliği iptal et. Status badges: Beklemede/Aktif/Deneme/Ödeme Gecikmiş/İptal Edildi/Süresi Doldu/Duraklatıldı/Eksik.",
  "states": [
   "loading",
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Abone",
   "Kademe",
   "Durum",
   "Periyot",
   "Dönem Sonu",
   "Abone Olma"
  ],
  "filters": [
   "Abone ara...",
   "Durum",
   "Filtreleri Temizle"
  ],
  "actions": [
   "Seçilenleri iptal et",
   "Ödemeleri Görüntüle",
   "Detaylar",
   "Aboneliği iptal et"
  ],
  "dialogs": [
   "BulkCancelStudentOrgSubscriptionsDialog (timing: Dönem sonunda / Şimdi; reason; progress; partial-failure retry)"
  ],
  "keyComponents": [
   "DataTable",
   "data-table-toolbar",
   "SubscribersBulkActions",
   "Badge",
   "DropdownMenu"
  ],
  "dataSources": [
   "ProductSubscribers subscribers connection (student, tier, status, paymentInterval, periodEnd, subscribedAt)"
  ],
  "notes": "Admin.OrgSubscriptions.Subscribers.* + BulkCancel.*",
  "cluster": "catalog"
 },
 {
  "surface": "Subscription product — Gifted subscriptions tab",
  "route": "/[organizationSlug]/admin/subscriptions/[productSlug]?tab=gifted (ProductGiftedSubscriptions)",
  "titleTR": "Hediye Abonelikler",
  "purpose": "List gifted subscriptions; create single or bulk gifts; revoke; resend notification.",
  "layout": "Header actions: 'Abonelik Hediye Et' + 'Toplu Hediye'. Search 'Alıcı ara...', Durum filter. Table columns: Alıcı / Kademe / Durum / Süre / Son Kullanma / Oluşturulma / Hediye Eden. Status: Beklemede/Uygulandı/Süresi Doldu/İptal Edildi. Row actions: İptal Et / Bildirimi Tekrar Gönder. Empty 'Henüz hediye abonelik oluşturulmadı.'",
  "states": [
   "loading",
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Alıcı",
   "Kademe",
   "Durum",
   "Süre",
   "Son Kullanma",
   "Oluşturulma",
   "Hediye Eden"
  ],
  "filters": [
   "Alıcı ara...",
   "Durum",
   "Filtreleri Temizle"
  ],
  "actions": [
   "Abonelik Hediye Et",
   "Toplu Hediye",
   "İptal Et",
   "Bildirimi Tekrar Gönder"
  ],
  "dialogs": [
   "CreateGiftedSubscriptionDialog (Abonelik Hediye Et: tier, recipient email/name, lifetime/duration, personal message, expiry days, directEnroll)",
   "BulkCreateGiftedSubscriptionDialog (Toplu Abonelik Hediye Et: recipient emails textarea)",
   "RevokeGiftedSubscriptionDialog"
  ],
  "keyComponents": [
   "GiftedSubscriptionsDataTable",
   "data-table-toolbar",
   "Badge",
   "DropdownMenu",
   "Dialog"
  ],
  "dataSources": [
   "gifted subscriptions connection"
  ],
  "notes": "Admin.OrgSubscriptions.GiftedSubscriptions.* + GiftForms.*",
  "cluster": "catalog"
 },
 {
  "surface": "Subscriber detail (student subscription)",
  "route": "/[organizationSlug]/admin/subscriptions/subscriber/[subscriptionId] (AdminSubscriptionPage.tsx)",
  "titleTR": "Abonelik Detayları",
  "purpose": "Detail of one student's subscription: payments, promotions, student info, summary.",
  "layout": "Breadcrumb (product name → student name) + status Badge (Aktif/İptal Edildi/Süresi Doldu/Ödeme Gecikmiş/Bekliyor/Deneme). Two-column layout: left = StudentSubscriptionPayments (Ödemeler table: Tarih/Tutar/Tür/Durum/Kart/Fatura + Faturayı İndir), StudentSubscriptionStudent (Öğrenci, Profili Görüntüle), StudentSubscriptionPromotions (Promosyonlar); right = StudentSubscriptionSummary (Özet: Kademe/Ödeme Periyodu/Deneme Süresi/Mevcut Dönem/Sonraki Fatura/İptal, scheduled-change alerts).",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Tarih",
   "Tutar",
   "Tür",
   "Durum",
   "Kart",
   "Fatura"
  ],
  "actions": [
   "Faturayı İndir",
   "Profili Görüntüle",
   "Ödemeleri Görüntüle"
  ],
  "keyComponents": [
   "Breadcrumb",
   "Badge",
   "StudentSubscriptionPayments",
   "StudentSubscriptionSummary",
   "StudentSubscriptionStudent",
   "StudentSubscriptionPromotions"
  ],
  "dataSources": [
   "AdminSubscriptionPageQuery node(StudentOrgSubscription): status, tier{name,product}, student, fragments StudentSubscriptionSummary/Payments/Student/Promotions"
  ],
  "notes": "Admin.StudentSubscription.*. Payment types: İlk Ödeme/Yinelenen/Yükseltme/Yeniden Deneme.",
  "cluster": "catalog"
 },
 {
  "surface": "Teachfluence platform subscriptions (pi org only)",
  "route": "/[organizationSlug]/admin/subscriptions (PiEducationSubscriptions, only when slug='pi')",
  "titleTR": "Teachfluence Abonelikleri",
  "purpose": "Platform-level table of Teachfluence SaaS subscriptions across organizations (Starter/Growth/Scale/Enterprise tiers). Internal-only.",
  "layout": "Section below a Separator. Search 'Organizasyon adı veya e-posta ile ara...', filters Durum / Kademe / Başarısız Ödeme / İptal Edilecek, Filtreleri Temizle. Table columns: Organizasyon / Kademe / Durum / Plan / Sonraki Fatura / Dönem Sonu. Row actions: Detayları Gör / Ödeme Geçmişi / Promosyon Kullanımları. Detail/Payments/PromotionUsages sheets.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Organizasyon",
   "Kademe",
   "Durum",
   "Plan",
   "Sonraki Fatura",
   "Dönem Sonu"
  ],
  "filters": [
   "Organizasyon adı veya e-posta ile ara...",
   "Durum",
   "Kademe",
   "Başarısız Ödeme",
   "İptal Edilecek",
   "Filtreleri Temizle"
  ],
  "actions": [
   "Detayları Gör",
   "Ödeme Geçmişi",
   "Promosyon Kullanımları"
  ],
  "dialogs": [
   "PiEducationSubscriptionPaymentsSheet (Ödeme Geçmişi)",
   "Subscription detail sheet",
   "Promotion usages"
  ],
  "keyComponents": [
   "DataTable",
   "Sheet",
   "Badge",
   "PiEducationSubscriptionsSkeleton"
  ],
  "dataSources": [
   "PiEducationSubscriptions_query fragment"
  ],
  "gating": "Only rendered for organizationSlug === 'pi' (Teachfluence internal ops).",
  "notes": "Admin.PiEducationSubscriptions.*. Tiers STARTER/GROWTH/SCALE/ENTERPRISE.",
  "cluster": "catalog"
 },
 {
  "surface": "Digital product / Live event — Students tab",
  "route": "/[organizationSlug]/admin/digital-products/[slug]?tab=students (and live-events)",
  "titleTR": "Öğrenciler",
  "purpose": "Table of students who own the product with search/sort.",
  "layout": "data-table-toolbar (search 'Öğrenci ara...') over a table. Columns: Öğrenci / Email / Kaydolma Tarihi / Erişim Sonu Tarihi. Sortable.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Öğrenci",
   "Email",
   "Kaydolma Tarihi",
   "Erişim Sonu Tarihi"
  ],
  "filters": [
   "Öğrenci ara..."
  ],
  "keyComponents": [
   "DataTable",
   "data-table-toolbar"
  ],
  "dataSources": [
   "digital product / live event students connection"
  ],
  "notes": "Admin.Students + Admin.Orderable.StudentsTab. loadError 'Öğrenciler yüklenemedi...'",
  "cluster": "catalog"
 },
 {
  "surface": "Digital product / Live event / Bundle — Orders tab",
  "route": "/[organizationSlug]/admin/digital-products/[slug]?tab=orders (and live-events)",
  "titleTR": "Siparişler",
  "purpose": "Orders table for the product (sales, fees, net earnings).",
  "layout": "data-table with columns: Öğrenci / Email / Tarih / Satış Fiyatı / Ödenen Fiyat / Ödeme Sağlayıcı Komisyonu / Teachfluence Komisyonu / Net Kazanç / Durum / (Detaylı bilgi için incele). Sortable.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "02-catalog",
  "tableColumns": [
   "Öğrenci",
   "Email",
   "Tarih",
   "Satış Fiyatı",
   "Ödenen Fiyat",
   "Ödeme Sağlayıcı Komisyonu",
   "Teachfluence Komisyonu",
   "Net Kazanç",
   "Durum"
  ],
  "keyComponents": [
   "DataTable",
   "orders-table columns"
  ],
  "dataSources": [
   "orderable orders connection (Admin.TableColumns.*)"
  ],
  "notes": "Shared orders table (also used by course orders). Net earnings tooltip present.",
  "cluster": "catalog"
 },
 {
  "surface": "Product recommendations tab (Öneriler)",
  "route": "detail pages ?tab=recommendations (OrderableRecommendationsTab — course/DP/LE/bundle)",
  "titleTR": "Öneriler",
  "purpose": "Configure cross-sell recommendations shown when a customer views/buys this product.",
  "layout": "Recommendation configuration panel listing other orderables to recommend; add/remove.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "02-catalog",
  "keyComponents": [
   "OrderableRecommendationsTab",
   "ErrorBoundary",
   "Skeleton"
  ],
  "dataSources": [
   "orderable recommendations query (organizationId, triggerOrderableId)"
  ],
  "notes": "Shared across all product detail pages; gated on edit access.",
  "cluster": "catalog"
 },
 {
  "surface": "Sales pause card (Satışı Durdur)",
  "route": "detail pages settings → Genel (OrderableSalesPauseCard, course/DP/LE/bundle)",
  "titleTR": "(Orderable sales pause)",
  "purpose": "Toggle to pause sales of a product without unpublishing; order gate blocks purchases while paused.",
  "layout": "Card with a switch/toggle to pause/resume sales, shown in the Genel settings group.",
  "states": [
   "loading"
  ],
  "priority": "edge",
  "suggestedCanvas": "02-catalog",
  "keyComponents": [
   "OrderableSalesPauseCard",
   "Card",
   "Switch"
  ],
  "dataSources": [
   "OrderableSalesPauseCard_orderable fragment"
  ],
  "notes": "Shared orderable component; salesStatus derived + salesPausedAt bit (PR #437).",
  "cluster": "catalog"
 },
 {
  "surface": "Course / Academic-Term editor shell",
  "route": "/[organizationSlug]/admin/courses/[courseSlug]/[academicTermSlug]",
  "titleTR": "<Kurs adı> — <Dönem adı> (fallback: \"Kurs\")",
  "purpose": "Top-level admin editor for one course academic term. Hosts all editing tabs, publish/status banners, and the product detail header.",
  "layout": "ProductDetailHeader (back link 'Kurslar', term title, PublishStatusBadge, actions: 'Öğrenme Deneyimini Görüntüle' external link + GeneratedPageLinks dropdown, ProductDetailSearch 'search this page'). Below: scrollable TabsList then TabsContent. Tabs: Kurs İçeriği, Görevler (with count badge), Öğrenciler, Eğitmenler, Ayarlar (lock icon if no edit access), Satışlar, Öneriler, Sertifika, Dönemler (only if >1 term). Top banners stack: PublishDraftBanner (DRAFT), payment-methods-missing warning Alert, course-archived warning Alert.",
  "tabs": [
   "Kurs İçeriği",
   "Görevler",
   "Öğrenciler",
   "Eğitmenler",
   "Ayarlar",
   "Satışlar",
   "Öneriler",
   "Sertifika",
   "Dönemler"
  ],
  "actions": [
   "Öğrenme Deneyimini Görüntüle",
   "Yayına Al (publish banner)",
   "Ödeme Bilgilerini Ekle"
  ],
  "dialogs": [
   "UnsavedChangesConfirmDialog (Kaydedilmemiş değişiklikler)",
   "GeneratedPageLinks dropdown",
   "ProductDetailSearch command palette"
  ],
  "states": [
   "loading",
   "error",
   "permission-denied",
   "empty"
  ],
  "gating": "Admin tabs (Ayarlar/Öneriler/Sertifika/Dönemler) gated on hasResourcePermission(COURSE, COURSE_EDIT) OR viewerInstructor.role==='ADMIN'; locked tabs show tooltip 'lockedNoEditAccess'. notFound() when course/academicTerm missing.",
  "dataSources": [
   "AdminCoursePageQuery (course{title,publishStatus,tags,customFieldValues,generatedPageLinks,academicTerms,academicTerm{...}}, organization{paymentMethods})",
   "AdminCoursePagePublishMutation (updateCourse)"
  ],
  "keyComponents": [
   "Tabs",
   "ScrollableTabsList",
   "PageTabsTrigger",
   "Alert",
   "Badge",
   "ProductDetailHeader",
   "ProductDetailSearch",
   "PublishStatusBadge",
   "PublishDraftBanner",
   "SegmentedViewToggle"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "notes": "Route [courseSlug] with no term redirects to currentAcademicTerm.slug (RedirectToPiHref). Suspense fallback = AdminContentSkeleton. Per-tab ErrorBoundary fallback shows AlertTriangle + 'tabLoadError'.",
  "cluster": "course-editor"
 },
 {
  "surface": "Course Content tab (sections + items)",
  "route": ".../[academicTermSlug]?tab=contents",
  "titleTR": "Kurs İçeriği",
  "purpose": "Build course structure: drag-and-drop sections (bölüm), each an accordion holding draggable content-item rows of every type.",
  "layout": "Toolbar row: 'Tüm bölümleri aç/kapat' (expand/collapse all), 'Yeni Bölüm Oluştur', 'AI ile Oluştur'. DragDropContext > Droppable list of CourseAdminSection accordions. Each section header: title, visibility/hidden toggle, drag handle, actions menu (Bölümü Düzenle, Kopyasını Oluştur, Bölümü Gizle/Göster, Bölümü Sil). Inside: content item rows. Empty: 'Henüz bölüm yok' / 'Kursunu bölümlere ayırıp...'. Autosave status ('Kaydedildi {time}').",
  "tabs": [],
  "filters": [],
  "actions": [
   "Yeni Bölüm Oluştur",
   "AI ile Oluştur",
   "Yeni İçerik Oluştur",
   "Tüm bölümleri aç",
   "Tüm bölümleri kapat",
   "Öğrencinin Gözünden Gör"
  ],
  "dialogs": [
   "CreateCourseSectionDialogContent",
   "CreateCourseSectionWithAIDialogContent",
   "UpdateCourseSectionDialog",
   "DeleteCourseSectionDialogContent",
   "CreateCourseItemDialogContent"
  ],
  "states": [
   "empty",
   "error",
   "loading"
  ],
  "gating": "Read-only when course ARCHIVED (isCourseArchived) — editing disabled.",
  "dataSources": [
   "CourseAdminSections_sections fragment on CourseAcademicTerm",
   "CourseAdminSectionsMoveCourseItemMutation",
   "CourseAdminSectionsMoveCourseSectionMutation"
  ],
  "keyComponents": [
   "Accordion",
   "DragDropContext/Droppable (@hello-pangea/dnd)",
   "Button",
   "Dialog",
   "ContentSaveStatusContext"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "notes": "Section badges: Gizli, Yayınlanma Tarihi/Yakında. Item completeness ratio '{ready}/{total} hazır' and 'X eksik içerik'.",
  "cluster": "course-editor"
 },
 {
  "surface": "Content item row (collapsed)",
  "route": ".../[academicTermSlug]?tab=contents (per item)",
  "titleTR": "<İçerik Adı>",
  "purpose": "A single lesson/content row inside a section, showing type + status badges and quick actions; expands to inline editor.",
  "layout": "Row: drag handle, ItemTypeBadge (Video/Ses/Soru Çözümü/Quiz/Sınav/Ödev/Zengin Metin/Belge/Embed/Canlı Ders/Forum/SCORM/cmi5), item title, badges (ReleaseDateBadge, HiddenBadge 'Gizli', FreeAccessBadge 'Ücretsiz Erişim', IncompleteItemBadge, StudentVisibilityBadge 'Öğrenciye görünür'/'Kurs taslak'/'Kurs arşivlendi'). Detay göster/gizle toggle. Actions: İçeriği Düzenle (edit), İçeriği Sil, Öğrencinin Gözünden Gör, İçeriği Gizle/Göster, and 'Daha fazla işlem' dropdown (Kopyasını Oluştur etc.).",
  "actions": [
   "İçeriği Düzenle",
   "İçeriği Sil",
   "İçeriği Gizle/Göster",
   "Kopyasını Oluştur",
   "Öğrencinin Gözünden Gör"
  ],
  "dialogs": [
   "UpdateCourseItemDialog (İçeriği Güncelle)",
   "DeleteCourseItemDialogContent"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "DropdownMenu",
   "Tooltip",
   "Badge",
   "ItemTypeBadge"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "notes": "Update dialog fields: İçerik Adı, İçerik Türü, Yayınlanma Tarihi, Gizli, Ücretsiz Erişim, İçerik Zamanlama (drip: Zamanlama Yok/Sabit Tarih/Kayıttan Sonra Gün/İçerik Tamamlandıktan Sonra), Ön Koşul İçerik, Açıldığında Bildirim Gönder, Dahili Notlar.",
  "cluster": "course-editor"
 },
 {
  "surface": "Create Content Item dialog",
  "route": ".../[academicTermSlug]?tab=contents (modal)",
  "titleTR": "İçerik Oluştur",
  "purpose": "Create a new content item; pick name, type, hidden flag.",
  "layout": "Dialog form: İçerik Adı input; İçerik Türü Select (Video, Ses, Soru, Sınav (Birden Fazla Soru), Ödev, Belge, Zengin Metin, Webinar (Zoom vb.), Forum, Embed, İnteraktif Soru (Çoktan Seçmeli vb.), Soru Çözümü, SCORM Paketi, cmi5 Paketi); conditional Video Türü / Soru Türü sub-select; 'Gizli içerik' switch; submit 'İçerik Oluştur'.",
  "dialogs": [],
  "states": [
   "error"
  ],
  "dataSources": [
   "CreateCourseItem create mutation",
   "createAfterItem fragment"
  ],
  "keyComponents": [
   "Dialog",
   "Select",
   "Input",
   "Switch",
   "zod form"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Create / Update / Delete Section dialogs",
  "route": ".../[academicTermSlug]?tab=contents (modals)",
  "titleTR": "Yeni Bölüm Oluştur / Bölümü Güncelle / \"<title>\" bölümünü silmek istediğine emin misin?",
  "purpose": "Section CRUD; AI variant generates a section from a prompt.",
  "layout": "Create/Update: Bölüm Adı, Bölüm Açıklaması (rich toggle), Yayınlanma Tarihi + description, Gizli switch. AI create: 'AI Prompt' textarea (placeholder 'Örneğin: Atatürk dönemi kalkınma politikaları', max 2000). Delete confirm: warning about cascade delete of all items ('kalıcı olarak silinecektir'), lists items, tip to hide instead.",
  "dialogs": [],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Textarea",
   "DatePicker",
   "Switch"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — Video item",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded)",
  "titleTR": "Video Ayarları",
  "purpose": "Upload/manage a lesson video with chapters and subtitles.",
  "layout": "Inline panel: 'Video yükle' (VideoUploader) or 'Dış kaynaktan video ekle' (external URL YouTube/Vimeo). Processing states 'İşleniyor'/'Hazır'. 'Videoyu Görüntüle{duration}', 'Videoyu İndir'. Sub-actions: Video Bölümlerini Güncelle (chapters), Altyazılar (subtitles). İçerik Açıklaması rich text below player.",
  "actions": [
   "Video yükle",
   "Dış kaynaktan video ekle",
   "Videoyu İndir",
   "Video Bölümlerini Güncelle",
   "Altyazılar"
  ],
  "dialogs": [
   "UpdateVideoChaptersDialog (Video Bölümlerini Güncelle: Bölüm Adı/Bölüm Bitiş Zamanı/İşlemler table)",
   "SubtitleUploadDialog (Altyazıları Yönet: Dil Seçin, Altyazı Dosyası .srt/.vtt)"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "VideoUploader",
   "Dialog",
   "Table",
   "Progress"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — Audio / Article / Embed / Document items",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded)",
  "titleTR": "Ses / Zengin Metin / Embed / Belge",
  "purpose": "Inline editors for simple content types.",
  "layout": "Audio: 'Ses dosyası yükle' / 'Dış kaynaktan ses ekle' (Spotify/SoundCloud/Mixcloud), İçerik Açıklaması. Article: 'Zengin Metin İçeriği' rich editor. Embed: 'Embed URL/Kod Bloğu' textarea + description about copyright. Document/attachments: AttachmentUploader 'Ek doküman yükle' (max N files, .zip suggestion), 'X Ek Dokümanı görüntüle', per-file update/delete.",
  "actions": [
   "Ses dosyası yükle",
   "Dış kaynaktan ses ekle",
   "Ek doküman yükle",
   "Embed'i Güncelle"
  ],
  "dialogs": [
   "UpdateAttachmentDialog",
   "DeleteCourseItemAttachmentDialogContent (\"<title>\" Ek Dosyasını Silmek İstediğine Emin Misin?)"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "AudioUploader",
   "AttachmentUploader",
   "RichTextEditor",
   "Textarea"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — Question (Soru Çözümü) & Quiz (İnteraktif Soru)",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded)",
  "titleTR": "Soru / Quiz",
  "purpose": "Author a solved-question (question text + answer + hints + solution video) or an interactive quiz (multiple-choice / free-response).",
  "layout": "Question: Soru İçeriği, Cevap, İpuçları (add 'Yeni İpucu Ekle'), Soruya Ücretsiz Erişim, plus QuizSolutionVideo panel ('Çözüm videosu yükle'). Quiz create: Quiz Adı, Quiz Türü (Çoktan Seçmeli/Açık Uçlu). Multiple-choice: Soru, per-choice 'Şık {index}' + 'Doğru Cevap Olarak Seç' + optional açıklama, 'Yeni Şık Ekle' (min 2, single correct). Free-response: Soru + Örnek Cevap.",
  "actions": [
   "Quiz Oluştur",
   "Yeni Şık Ekle",
   "Yeni İpucu Ekle",
   "Doğru Cevap Olarak Seç",
   "Çözüm videosu yükle"
  ],
  "dialogs": [],
  "states": [
   "error"
  ],
  "keyComponents": [
   "RadioGroup",
   "Input",
   "RichTextEditor",
   "VideoUploader"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — Exam item (multi-question)",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded)",
  "titleTR": "Sınav",
  "purpose": "Configure an exam and manage its bank of quiz questions.",
  "layout": "Settings summary: Talimatlar, öğrenciler boş bırakabilir, geri dönebilir, kaç kere çözebilir (Sınırsız/# defa), tamamlananı tekrar çözebilir, geçme puanı %, Önkoşul, Soru sayısı (Tüm sorular/#), soruların sırasını karıştır. 'Sınavı Görüntüle ({count} Soru)'. Add questions: 'Soru Ekle', 'AI ile Sınav Sorusu Oluştur', Excel yükleme (ExcelQuestionsUploader). Each exam quiz row editable (Puan Değeri, Süre).",
  "actions": [
   "Soru Ekle",
   "AI ile Sınav Sorusu Oluştur",
   "Sınavı Güncelle",
   "Excel yükle"
  ],
  "dialogs": [
   "CreateExamQuizDialogContent",
   "UpdateExamQuiz (Quizi Güncelle)",
   "DeleteExamQuiz (\"<title>\" Sorusunu Silmek İstediğine Emin Misin?)",
   "UpdateCourseItemExam (İçerik Sınav Ayarlarını Güncelle)",
   "AIExamQuizGeneratorDialog"
  ],
  "states": [
   "error",
   "loading"
  ],
  "keyComponents": [
   "Dialog",
   "Tabs",
   "Input",
   "Switch"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "AI Exam Question Generator dialog",
  "route": ".../[academicTermSlug]?tab=contents (modal)",
  "titleTR": "AI ile Sınav Sorusu Oluştur",
  "purpose": "Generate multiple-choice questions from an uploaded file or pasted text via AI, then review/edit before adding.",
  "layout": "Dialog: Soru Sayısı, Soru Dili (Türkçe/İngilizce), tabs 'Dosya Yükle' (PDF/Word/TXT max 10MB) / 'Metin Yapıştır' (transcript, min 100 chars). Progress 'Sorular oluşturuluyor... (current/total)'. Then AIGeneratedQuestionsEditor: collapsible per-question list (Soru Başlığı, Soru, Şıklar, Doğru Cevap, Açıklama), 'Sınava Ekle ({count} Soru)'.",
  "actions": [
   "{count} Soru Oluştur",
   "Sınava Ekle ({count} Soru)",
   "İptal Et"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Tabs",
   "FileUpload",
   "Textarea",
   "Accordion"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — Live/Webinar item",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded)",
  "titleTR": "Canlı Ders Detayları",
  "purpose": "Configure a webinar/live session (manual URL or auto-managed Zoom).",
  "layout": "Fields: Canlı Ders Platformu, Katılım Linki (or 'Link her katılımcıya özel olarak üretilir'), Başlangıç/Bitiş Tarihi, 'Zoom Görüşmesini Otomatik Oluştur' switch + description, Gelişmiş Katılımcı Doğrulaması (Pro required), Buluta Otomatik Kaydet (Pro required), Kayıt mevcut, Zoom Toplantısını Başlat, Canlı Ders Açıklaması.",
  "actions": [
   "Canlı Dersi Güncelle",
   "Zoom Toplantısını Başlat"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Switch",
   "DatePicker",
   "Select",
   "Input"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — Forum item",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded)",
  "titleTR": "Forum Oluştur",
  "purpose": "Create/manage a discussion forum content item.",
  "layout": "CreateForum card: Forum Başlığı, Forum Adresi (slug + description), Forum Açıklaması. UpdateForum edits same.",
  "actions": [
   "Forumu Görüntüle",
   "Forum Oluştur"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Input",
   "RichTextEditor"
  ],
  "priority": "edge",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Content editor — SCORM / cmi5 item + reports",
  "route": ".../[academicTermSlug]?tab=contents (inline expanded / report modal)",
  "titleTR": "SCORM Raporu / cmi5 Raporu",
  "purpose": "Upload a SCORM/cmi5 package and view completion/interaction reports.",
  "layout": "Upload panel: 'SCORM Paketi Yükle' / 'cmi5 Paketi Yükle', processing/failed states, metadata (Başlık, Sürüm, Tanımlayıcı, Giriş Noktası / Kurs IRI, Atanabilir Birimler), 'Yeni SCORM Paketi Yükle'. 'Raporu görüntüle' opens ScormItemReportContent / Cmi5ItemReportContent (ReportStatCard tiles + ScormQuestionDistributionContent).",
  "actions": [
   "SCORM Paketi Yükle",
   "cmi5 Paketi Yükle",
   "Raporu görüntüle"
  ],
  "dialogs": [
   "SCORM/cmi5 report modal"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "FileUpload",
   "ReportStatCard",
   "Dialog",
   "Charts"
  ],
  "priority": "edge",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Tasks tab (instructor action queue)",
  "route": ".../[academicTermSlug]?tab=tasks",
  "titleTR": "Görevler",
  "purpose": "Queue of items needing instructor action: assignment grading, open-ended quiz grading, help requests, error reports.",
  "layout": "List of task cards. Empty state: 'Bekleyen görev yok' / description. Assignment submission card: Öğrenci Cevabı, Puan (100 üzerinden), Feedback, 'Ödevi Puanla'. Quiz submission card: Örnek Cevap, Öğrenci Cevabı, Puan, Feedback, 'Puanla'. Tab trigger shows count badge.",
  "actions": [
   "Ödevi Puanla",
   "Puanla"
  ],
  "dialogs": [],
  "states": [
   "empty",
   "loading",
   "error"
  ],
  "dataSources": [
   "CourseAcademicTermTasks query (instructorTasksRequiringAction)"
  ],
  "keyComponents": [
   "Card",
   "TaskCardSkeleton",
   "Textarea",
   "Input"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "notes": "TaskCardSkeleton x3 during Suspense.",
  "cluster": "course-editor"
 },
 {
  "surface": "Students tab — Enrolled list",
  "route": ".../[academicTermSlug]?tab=students&view=enrolled",
  "titleTR": "Öğrenciler",
  "purpose": "Table of students enrolled in this term with row actions.",
  "layout": "Radiogroup sub-tabs: Kayıtlılar, Davetler, İlerleme, Sınav Sonuçları (only if exams). Enrolled DataTable columns: Öğrenci (avatar+name), Email, Kaydolma Tarihi, Erişim Sonu Tarihi, actions. Toolbar: search by email + 'Öğrenci Davet Et'. Row actions menu, column show/hide.",
  "tableColumns": [
   "Öğrenci",
   "Email",
   "Kaydolma Tarihi",
   "Erişim Sonu Tarihi"
  ],
  "filters": [
   "Öğrenci ara (email)"
  ],
  "actions": [
   "Öğrenci Davet Et",
   "Detayları Görüntüle",
   "Erişim tarihini güncelle"
  ],
  "dialogs": [
   "InviteCourseAcademicTermStudentDialogContent",
   "UpdateStudentAccessDateDialogContent",
   "BulkImportCourseStudents"
  ],
  "states": [
   "empty",
   "loading",
   "error"
  ],
  "dataSources": [
   "CourseAcademicTermStudentsQuery",
   "dataTableCourseAcademicTermStudents fragment"
  ],
  "keyComponents": [
   "DataTable",
   "Avatar",
   "DropdownMenu",
   "DataTableColumnHeader",
   "StudentsTableSkeleton"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Students tab — Invitations list",
  "route": ".../[academicTermSlug]?tab=students&view=invitations",
  "titleTR": "Davetler",
  "purpose": "Pending/accepted student invitations table.",
  "layout": "DataTable columns: Öğrenci/Email, Davet Tarihi, Durum (InvitationStatus), Davet Eden. Toolbar search by email.",
  "tableColumns": [
   "Email",
   "Davet Tarihi",
   "Durum",
   "Davet Eden"
  ],
  "filters": [
   "E-posta ile ara"
  ],
  "actions": [
   "Öğrenci Davet Et"
  ],
  "dialogs": [
   "InviteCourseAcademicTermStudentDialogContent (tek tek / toplu içe aktar modes; Doğrudan Kayıt option)"
  ],
  "states": [
   "empty",
   "loading",
   "error"
  ],
  "dataSources": [
   "studentInvitations on CourseAcademicTerm"
  ],
  "keyComponents": [
   "DataTable",
   "Badge (InvitationStatus)"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "notes": "Invite dialog: modeSingle 'Tek tek' vs modeBulk 'Toplu içe aktar' (paste emails/CSV, {valid} geçerli {invalid} geçersiz); Davet Gönder vs Doğrudan Kayıt.",
  "cluster": "course-editor"
 },
 {
  "surface": "Students tab — Progress (gradebook)",
  "route": ".../[academicTermSlug]?tab=students&view=progresses",
  "titleTR": "İlerleme",
  "purpose": "Per-student completion + score gradebook across sections/items.",
  "layout": "Progresses table with section filter ('Tüm bölümler'), completion % ('%X tamamlandı'), score cells (GradebookCellScoreDetail: Geçti/Kaldı/Tamamlandı, {raw}/{max}, attempts). Row expands to answer detail (Öğrenci Cevabı, Feedback, exam points breakdown).",
  "tableColumns": [
   "Öğrenci",
   "Bölüm/İçerik ilerleme",
   "Puan"
  ],
  "filters": [
   "Bölüme göre filtrele"
  ],
  "states": [
   "empty",
   "loading",
   "error"
  ],
  "dataSources": [
   "CourseAcademicTermStudentProgresses fragment",
   "columns_progressTableCourseAcademicTerm"
  ],
  "keyComponents": [
   "Table",
   "Select",
   "Popover",
   "StatusBadge"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Students tab — Exam Results",
  "route": ".../[academicTermSlug]?tab=students&view=examResults",
  "titleTR": "Sınav Sonuçları",
  "purpose": "Exam attempt results per student with question-level breakdown.",
  "layout": "Filters: Öğrenci ara, Tüm Bölümler, Tüm Sınavlar, Tarih Aralığı, Sıfırla. Columns: Öğrenci, Sınav, Durum (Geçti/Kaldı/Değerlendiriliyor/Devam Ediyor/Duraklatıldı), Doğru/Yanlış/Beklemede/Boş, Skor (%), Süre, Çözüm Tarihi. Expandable question list with Tümü/Yanlış/Boş filter. 'Daha fazla yükle'.",
  "tableColumns": [
   "Öğrenci",
   "Sınav",
   "Durum",
   "Doğru",
   "Yanlış",
   "Beklemede",
   "Boş",
   "Skor",
   "Süre",
   "Çözüm Tarihi"
  ],
  "filters": [
   "Öğrenci ara",
   "Tüm Bölümler",
   "Tüm Sınavlar",
   "Tarih Aralığı"
  ],
  "actions": [
   "Daha fazla yükle",
   "Sıfırla"
  ],
  "states": [
   "empty",
   "loading"
  ],
  "dataSources": [
   "examResultsTable_students",
   "examResultsTable_courseAcademicTerm"
  ],
  "keyComponents": [
   "Table",
   "Select",
   "DateRangePicker",
   "Badge"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "notes": "Only rendered when term has ExamCourseItem; invalid ?view=examResults normalizes to enrolled.",
  "cluster": "course-editor"
 },
 {
  "surface": "Instructors tab",
  "route": ".../[academicTermSlug]?tab=instructors",
  "titleTR": "Eğitmenler",
  "purpose": "Manage course instructors and pending instructor invitations.",
  "layout": "Two tables. Instructors: İsim, Soyisim, Email, Rol (Admin/Eğitmen/Asistan), Görünürlük (Gizli/Görünür), row actions (Eğitmeni Güncelle, Eğitmeni Kurstan Çıkar). Invitations ('Bekleyen Davetler'): Email, Davet Tarihi, Durum, Davet Eden. Toolbar: 'Email ile ara', 'Eğitmen Davet Et'.",
  "tableColumns": [
   "İsim",
   "Soyisim",
   "Email",
   "Rol",
   "Görünürlük"
  ],
  "filters": [
   "Email ile ara"
  ],
  "actions": [
   "Eğitmen Davet Et",
   "Eğitmeni Güncelle",
   "Eğitmeni Kurstan Çıkar"
  ],
  "dialogs": [
   "InviteInstructorDialogContent (Eğitmen Davet Et / Doğrudan Kayıt)",
   "UpdateCourseInstructorDialogContent",
   "RemoveCourseInstructorDialogContent"
  ],
  "states": [
   "empty",
   "error"
  ],
  "gating": "Mutations gated on hasAdminAccess (COURSE_EDIT or role ADMIN).",
  "dataSources": [
   "CourseAdminInstructors_instructors",
   "CourseAdminInstructors_invitations"
  ],
  "keyComponents": [
   "DataTable",
   "Select (role)",
   "Switch (visibility)",
   "Dialog"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Settings tab — General",
  "route": ".../[academicTermSlug]?tab=settings&settingsView=general",
  "titleTR": "Ayarlar › Genel",
  "purpose": "Course + term general settings; product page preview.",
  "layout": "SegmentedViewToggle: Genel, Fiyatlandırma, Görünüm, Özel Alanlar, Kritik İşlemler. General: ProductPagePreviewSection, CourseAcademicTermSettings card (Kurs Akademik Dönem Ayarları — slug, title, Kapasite, resim, Sipariş Ekranı Açıklaması Göster/Gizle), CourseSettings card (Kurs adresi, Yayınlanma Durumu). Single-term merges wording (Kurs Bilgileri).",
  "tabs": [
   "Genel",
   "Fiyatlandırma",
   "Görünüm",
   "Özel Alanlar",
   "Kritik İşlemler"
  ],
  "actions": [
   "Güncelle",
   "Görseli Değiştir",
   "Kurs Akademik Dönemini Güncelle"
  ],
  "dialogs": [
   "UpdateCourseDialogContent (Kursu Güncelle)",
   "UpdateCourseAcademicTermDialogContent",
   "UpdateCourseAcademicTermImageDialog",
   "TagsSettingsCard"
  ],
  "states": [
   "permission-denied"
  ],
  "gating": "Whole tab body only rendered when hasAdminAccess.",
  "keyComponents": [
   "SegmentedViewToggle",
   "SettingsCard",
   "Dialog",
   "ImageCropper"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Settings tab — Pricing",
  "route": ".../[academicTermSlug]?tab=settings&settingsView=pricing",
  "titleTR": "Ayarlar › Fiyatlandırma",
  "purpose": "Manage term price list and checkout page settings.",
  "layout": "CourseAcademicTermPricing card: list of pricings (Aktif/Taslak badge, %indirim, %KDV, 'Sipariş Linkini Kopyala'), 'Fiyat Ekle' / 'Güncelle'. Empty: 'Henüz fiyat eklenmemiş.'. Below: CheckoutPageSettingsCard.",
  "actions": [
   "Fiyat Ekle",
   "Güncelle",
   "Sipariş Linkini Kopyala"
  ],
  "dialogs": [
   "SetCourseAcademicTermPricingDialogContent"
  ],
  "states": [
   "empty",
   "loading",
   "error"
  ],
  "dataSources": [
   "CourseAcademicTermPricing_course"
  ],
  "keyComponents": [
   "Card",
   "Badge",
   "Dialog"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Settings tab — Appearance (UI settings)",
  "route": ".../[academicTermSlug]?tab=settings&settingsView=appearance",
  "titleTR": "Görünüm Ayarları",
  "purpose": "Override org default theme/colors and quiz/exam UI for this term.",
  "layout": "CourseAcademicTermUISettings: 'Görünüm ayarlarını özelleştir' switch; Tema (Açık/Koyu/Sistem); Renkler (Ana/Arka Plan/Yazı/Kenarlık + dark variants) with live Önizleme; Kurs İçerikleri menü konumu (Sol/Sağ); video bölümlerini göster; Sınav Görünümü (Quiz/Sınav Arayüz Modu Varsayılan/Resmi, Hesap Makinesi, Referans Sayfası, Geri Bildirim Modu Anlık/Sınav Sonunda). 'Görünüm Ayarlarını Kaydet'.",
  "actions": [
   "Görünüm Ayarlarını Kaydet"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Switch",
   "ColorPicker",
   "RadioGroup",
   "Preview"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Settings tab — Custom Fields",
  "route": ".../[academicTermSlug]?tab=settings&settingsView=customFields",
  "titleTR": "Özel Alanlar",
  "purpose": "Manage course- and term-scoped custom field values.",
  "layout": "Multi-term: two EntityCustomFieldsCard (scopeLabel 'Bu döneme özel' + 'Kurs geneli — tüm dönemlerde geçerli'). Single-term: one MergedCourseCustomFieldsCard.",
  "states": [
   "empty"
  ],
  "keyComponents": [
   "EntityCustomFieldsCard",
   "Card"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Settings tab — Danger Zone",
  "route": ".../[academicTermSlug]?tab=settings&settingsView=danger",
  "titleTR": "Kritik İşlemler",
  "purpose": "Duplicate course, create new term/cohort, delete course.",
  "layout": "DangerousCourseSettings: 'Kursu Kopyala' (Yeni Kurs Adı/Adresi), 'Yeni Dönem (Kohort) Oluştur' (CreateAcademicTermDialog: Dönem Adı, Dönem Adresi, içeriği kopyala, güncel yap), 'Bu kursu sil' (type-to-confirm 'Kursu silmek istediğime eminim').",
  "actions": [
   "Kursu Kopyala",
   "Yeni Dönem Oluştur",
   "Kursu Sil"
  ],
  "dialogs": [
   "CloneCourseDialogContent",
   "CreateCourseAcademicTermDialogContent",
   "DeleteCourseDialogContent"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Card",
   "Dialog",
   "Input (confirm)"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Orders tab",
  "route": ".../[academicTermSlug]?tab=orders",
  "titleTR": "Satışlar",
  "purpose": "Orders/sales table for this term.",
  "layout": "Orders DataTable columns: Tarih, Öğrenci, Email, Durum (OrderStatus), Satış Fiyatı, Ödenen Tutar (+tooltip), Ödeme Sağlayıcı Ücreti, Teachfluence Ücreti, Net Kazanç (+tooltip 'Learn more'). OrdersTableSkeleton fallback.",
  "tableColumns": [
   "Tarih",
   "Öğrenci",
   "Email",
   "Durum",
   "Satış Fiyatı",
   "Ödenen Tutar",
   "Ödeme Sağlayıcı Ücreti",
   "Teachfluence Ücreti",
   "Net Kazanç"
  ],
  "states": [
   "loading",
   "error",
   "empty"
  ],
  "dataSources": [
   "CourseAcademicTermOrders query"
  ],
  "keyComponents": [
   "DataTable",
   "Tooltip",
   "OrdersTableSkeleton"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Recommendations tab",
  "route": ".../[academicTermSlug]?tab=recommendations",
  "titleTR": "Öneriler",
  "purpose": "Configure cross-sell/upsell orderable recommendations triggered by this term.",
  "layout": "OrderableRecommendationsTab (shared component; admin-only, AdminContentSkeleton fallback).",
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "hasAdminAccess only.",
  "keyComponents": [
   "OrderableRecommendationsTab"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Certificate tab",
  "route": ".../[academicTermSlug]?tab=certificate",
  "titleTR": "Sertifika",
  "purpose": "Design certificate templates, view/issue/revoke issued certificates.",
  "layout": "Prefix info alert (Sertifika ID Ön Eki). 'Sertifika Şablonları' with template cards (Kazanım Kriteri, issued count, Düzenle/Sil) + 'Yeni Şablon Oluştur'. Empty: 'Sertifika şablonu oluşturun'. IssuedCertificatesTable columns: Öğrenci, Sertifika Şablonu, Veriliş Tarihi, Durum (Aktif/İptal Edildi), İşlemler (Sertifikayı Görüntüle, İptal Et, Sil). 'Sertifika Ver' issue dialog.",
  "tableColumns": [
   "Öğrenci",
   "Sertifika Şablonu",
   "Veriliş Tarihi",
   "Durum",
   "İşlemler"
  ],
  "actions": [
   "Yeni Şablon Oluştur",
   "Sertifika Ver",
   "Düzenle",
   "İptal Et",
   "Sil"
  ],
  "dialogs": [
   "CertificateTemplateEditor (Sertifika Şablonu Oluştur/Düzenle: name, LinkedIn org id, Arkaplan Görseli, Kazanım Kriteri, Sertifika Alanları drag-canvas)",
   "IssueCertificateDialog",
   "RevokeCertificateDialog",
   "DeleteCertificateDialog",
   "DeleteCertificateTemplateDialog"
  ],
  "states": [
   "empty",
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "hasAdminAccess only.",
  "keyComponents": [
   "CertificateCanvas",
   "CertificateTemplateCard",
   "CertificateFieldToolbar",
   "Table",
   "Dialog",
   "CertificateTabSkeleton"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "notes": "Editor has Önizleme/Ayarlar tabs, draggable fields (Öğrenci Adı/Kurs Adı/Dönem Adı/Kurum Adı/Tarih/Sertifika ID/Özel Metin), undo/redo, unsaved-changes guard.",
  "cluster": "course-editor"
 },
 {
  "surface": "Certificate Template Editor",
  "route": ".../[academicTermSlug]?tab=certificate (full editor)",
  "titleTR": "Sertifika Şablonu Oluştur / Düzenle",
  "purpose": "Visual editor placing text fields on a certificate background image.",
  "layout": "Two panes/tabs: Önizleme (CertificateCanvas — draggable/resizable fields, arrow-key nudge, corner resize) and Ayarlar (Şablon Adı, LinkedIn Kuruluş ID, Arkaplan Görseli upload/URL, Kazanım Kriteri: Tümünü tamamla/Yüzde tamamla/Belirli içerikler/Koşulsuz, CourseItemsSelector, Sertifika Alanları list with per-field fontSize/fontFamily/fontColor/fontWeight/textAlign). Save/Oluştur.",
  "tabs": [
   "Önizleme",
   "Ayarlar"
  ],
  "actions": [
   "Kaydet",
   "Oluştur",
   "Geri al",
   "Yinele",
   "Alanı sil"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "CertificateCanvas",
   "CertificateFieldToolbar",
   "CourseItemsSelector",
   "Slider",
   "ColorPicker"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Terms tab (multi-term / cohort management)",
  "route": ".../[academicTermSlug]?tab=terms",
  "titleTR": "Dönemler",
  "purpose": "Manage all cohorts (dönemler) of a multi-term course.",
  "layout": "Description + 'Akademik dönemler' link. Table columns: Dönem (with 'Güncel Dönem' badge), Akademik Dönem, Öğrenci (count/capacity), Satış (CourseAcademicTermSalesStatusBadge), İşlemler. 'Yeni Dönem Oluştur'. Row menu: Güncel yap, Ayarları düzenle, Satışı Aç/Kapat, Takvimi Düzenle, Sil.",
  "tableColumns": [
   "Dönem",
   "Akademik Dönem",
   "Öğrenci",
   "Satış",
   "İşlemler"
  ],
  "actions": [
   "Yeni Dönem Oluştur",
   "Güncel yap",
   "Ayarları düzenle",
   "Satışı Kapat",
   "Satışı Aç",
   "Takvimi Düzenle",
   "Sil"
  ],
  "dialogs": [
   "SetCurrentCourseAcademicTermDialogContent",
   "SetSalesPausedCourseAcademicTermDialogContent (Satışı Kapat/Aç)",
   "DeleteCourseAcademicTermDialogContent (type SİL to confirm)",
   "Dönem Takvimi edit (label/start/end)",
   "CreateCourseAcademicTermDialogContent"
  ],
  "states": [
   "error"
  ],
  "gating": "Only shown when hasMultipleTerms (>1); hasAdminAccess for actions. Redirects off when term count drops to 1.",
  "dataSources": [
   "CourseAdminAcademicTerms_course"
  ],
  "keyComponents": [
   "Table",
   "Badge",
   "DropdownMenu",
   "Dialog"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Organization Academic Terms (org-level)",
  "route": "/[organizationSlug]/admin/courses/academic-terms",
  "titleTR": "Akademik Dönemler",
  "purpose": "Org-wide catalog of academic terms (e.g. 2026 Bahar) that courses/terms can be linked to.",
  "layout": "Back link 'Kurslar'. Header 'Akademik Dönemler' + description. 'Yeni Dönem' button. Table columns: Dönem, Tarihler, Bağlı kurslar (count), İşlemler (Düzenle pencil, Sil trash). Empty: 'Henüz akademik dönem yok' / 'İlk döneminizi oluşturun (ör. 2026 Bahar)...'.",
  "tableColumns": [
   "Dönem",
   "Tarihler",
   "Bağlı kurslar",
   "İşlemler"
  ],
  "actions": [
   "Yeni Dönem",
   "Düzenle",
   "Sil"
  ],
  "dialogs": [
   "CreateAcademicTermDialogContent (Yeni Akademik Dönem: Ad, Başlangıç, Bitiş)",
   "UpdateAcademicTermDialogContent (Akademik Dönemi Düzenle)",
   "DeleteAcademicTermDialogContent (force-unlink warning '{count} kurs bağlı')"
  ],
  "states": [
   "empty",
   "loading",
   "permission-denied"
  ],
  "gating": "notFound() unless hasPermission('COURSE_EDIT').",
  "dataSources": [
   "OrganizationAcademicTermsQuery (organization.academicTerms{label,startDate,endDate,courseAcademicTermCount})"
  ],
  "keyComponents": [
   "Table",
   "Dialog",
   "Button",
   "AdminContentSkeleton"
  ],
  "priority": "primary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Open-ended submissions grading",
  "route": ".../[academicTermSlug] (open-ended sections within items / tasks)",
  "titleTR": "Açık Uçlu",
  "purpose": "Grade open-ended quiz/exam question submissions per item.",
  "layout": "OpenEndedQuizItemSection / OpenEndedExamItemSection: filter (Tümü/Notlandırılmayı Bekliyor/Notlandırıldı), collapsible submissions table columns: Öğrenci, Soru, Durum (Bekliyor/Notlandırıldı/Cevap Verilmedi), Puan, actions (Not Ver/Düzenle). Grade sheet 'Notlandır'. 'Daha fazla yükle'. Empty: 'Bu kursta açık uçlu soru bulunmuyor.'",
  "tableColumns": [
   "Öğrenci",
   "Soru",
   "Durum",
   "Puan"
  ],
  "filters": [
   "Tümü",
   "Notlandırılmayı Bekliyor",
   "Notlandırıldı"
  ],
  "actions": [
   "Not Ver",
   "Düzenle",
   "Daha fazla yükle"
  ],
  "states": [
   "empty",
   "loading",
   "error"
  ],
  "keyComponents": [
   "Collapsible",
   "Table",
   "Sheet",
   "Select"
  ],
  "priority": "secondary",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Loading skeleton (page + tab)",
  "route": ".../[academicTermSlug] (Suspense)",
  "titleTR": "—",
  "purpose": "Placeholder while the course/term query or a tab query resolves.",
  "layout": "AdminContentSkeleton for the page; per-tab fallbacks: StudentsTableSkeleton, OrdersTableSkeleton, TaskCardSkeleton x3, CertificateTabSkeleton, AdminContentSkeleton.",
  "states": [
   "loading"
  ],
  "keyComponents": [
   "Skeleton"
  ],
  "priority": "edge",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Not-found / archived / payment-missing states",
  "route": ".../[academicTermSlug] (variants)",
  "titleTR": "—",
  "purpose": "Non-happy-path banners and 404.",
  "layout": "notFound() when course.academicTerm missing. Warning Alerts stacked at top: 'Bu kurs arşivlendi' (edit disabled), 'Ödeme Bilgilerin Eksik' (Ödeme Bilgilerini Ekle link), PublishDraftBanner for DRAFT courses. Tab-level ErrorBoundary: AlertTriangle + 'tabLoadError'.",
  "states": [
   "error",
   "empty",
   "permission-denied"
  ],
  "keyComponents": [
   "Alert",
   "PublishDraftBanner",
   "ErrorBoundary"
  ],
  "priority": "edge",
  "suggestedCanvas": "03-course-editor",
  "cluster": "course-editor"
 },
 {
  "surface": "Campaigns list (Kampanyalar tab)",
  "route": "/[organizationSlug]/admin/campaigns",
  "titleTR": "E-posta Kampanyaları",
  "purpose": "Landing page for all email-marketing tooling; default tab lists the org's email campaigns plus an email-quota usage card.",
  "layout": "PageTabs with 4 triggers: Kampanyalar / Şablonlar / Sistem E-postaları / Listeler. Campaigns tab: EmailUsageCard at top, then H2 'Kampanyalarım' + AdminHelpMenu (?) + 'Kampanya Oluştur' button; grid of CampaignAdminCard; 'Geçmiş Kampanyalar' (PastCampaigns) section below.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "tabs": [
   "Kampanyalar",
   "Şablonlar",
   "Sistem E-postaları",
   "Listeler"
  ],
  "actions": [
   "Kampanya Oluştur"
  ],
  "dialogs": [
   "CreateCampaignDialogContent (Kampanya Oluştur)"
  ],
  "filters": [],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_CAMPAIGNS_VIEW to view (else NoAccessMessage); 'Kampanya Oluştur' only with ORG_CAMPAIGNS_MANAGE",
  "keyComponents": [
   "PageTabs",
   "EmailUsageCard",
   "CampaignAdminCard",
   "Button",
   "Dialog",
   "AdminHelpMenu",
   "AdminOrganizationOnboardingAlert"
  ],
  "dataSources": [
   "CampaignsPageQuery",
   "OrganizationCampaigns_campaigns",
   "CreateCampaignDialogContent_organization",
   "EmailUsageCard_organization"
  ],
  "tableColumns": [],
  "notes": "Loading fallback text 'Kampanyalar yükleniyor...'; empty 'Geçmiş kampanya bulunamadı.' The Create dialog offers 'Şablondan başla' (start from template) select.",
  "cluster": "marketing"
 },
 {
  "surface": "Create campaign modal",
  "route": "/[organizationSlug]/admin/campaigns (Dialog)",
  "titleTR": "Kampanya Oluştur",
  "purpose": "Create a new email campaign, optionally seeded from a saved template.",
  "layout": "Dialog: 'Kampanya Adı' input (nameRequiredError/max 200), 'Şablondan başla' select ('Bir şablon seçin (isteğe bağlı)' / 'Şablon yok'), 'Kampanya Oluştur' submit.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Kampanya Oluştur"
  ],
  "states": [
   "error"
  ],
  "gating": "ORG_CAMPAIGNS_MANAGE",
  "keyComponents": [
   "Dialog",
   "Input",
   "Select",
   "Button"
  ],
  "dataSources": [
   "CreateCampaignDialogContent_organization",
   "useSavedEmailTemplates"
  ],
  "notes": "On network error shows 'Bağlantı hatası. Lütfen tekrar dene.'",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign templates tab",
  "route": "/[organizationSlug]/admin/campaigns?tab=templates",
  "titleTR": "Kampanya Şablonları",
  "purpose": "List reusable campaign templates (saved subject/content/sender) used to seed new campaigns.",
  "layout": "H2 'Kampanya Şablonları' + hint 'Kampanya menüsündeki \"Şablon olarak kaydet\" seçeneğiyle...'; grid of CampaignTemplateAdminCard (fields: Konu, Gönderen, Oluşturuldu) each with dots dropdown (Düzenle / Sil).",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [],
  "dialogs": [
   "EditCampaignTemplateDialogContent (Kampanya Şablonunu Düzenle)",
   "delete confirm 'Şablon silinsin mi?'"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "gating": "canManage (ORG_CAMPAIGNS_MANAGE) enables edit/delete",
  "keyComponents": [
   "CampaignTemplateAdminCard",
   "CampaignTemplateDotsDropdown",
   "DropdownMenu",
   "AlertDialog"
  ],
  "dataSources": [
   "OrganizationCampaignTemplates_organization"
  ],
  "notes": "Empty 'Henüz şablon yok.'; loading 'Şablonlar yükleniyor...'",
  "cluster": "marketing"
 },
 {
  "surface": "System emails tab",
  "route": "/[organizationSlug]/admin/campaigns?tab=systemEmails",
  "titleTR": "Sistem E-postaları",
  "purpose": "Analytics + searchable log of transactional/system emails the org has sent.",
  "layout": "H2 'Sistem E-postaları'; SystemEmailStatsCards row (Toplam E-posta, Açılma Oranı, Tıklama Oranı, Teslim Edilen, Durum Dağılımı with Beklemede/Gönderildi/Teslim Edildi/Geri Döndü/Başarısız/Engellendi); data-table toolbar (search 'Alıcı ara...', filters Durum + E-posta Türü); table.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "filters": [
   "Durum",
   "E-posta Türü"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "keyComponents": [
   "SystemEmailStatsCards",
   "DataTable",
   "DataTableToolbar",
   "Select",
   "Input",
   "Badge"
  ],
  "dataSources": [
   "OrganizationSystemEmails_organization",
   "system-emails-filters"
  ],
  "tableColumns": [
   "E-posta Türü",
   "Alıcı E-postası",
   "Alıcı Adı",
   "Konu",
   "Durum",
   "Gönderim Tarihi",
   "Oluşturma Tarihi"
  ],
  "notes": "Empty 'Sonuç bulunamadı.'; loading 'Sistem e-postaları yükleniyor...'. Suppressed count shown separately (excluded from rates).",
  "cluster": "marketing"
 },
 {
  "surface": "Lists tab (mailing lists + exclusion + suppressions)",
  "route": "/[organizationSlug]/admin/campaigns?tab=lists",
  "titleTR": "E-posta Listelerim",
  "purpose": "Manage mailing lists, exclusion lists, and the global suppression list from one tab.",
  "layout": "Three stacked sections: (1) 'E-posta Listelerim' H2 + 'E-posta Listesi Oluştur' button + MailingListAdminCard grid; (2) OrganizationExclusionLists ('Hariç Tutma Listeleri' + 'Liste Oluştur'); (3) OrganizationGlobalSuppressions ('Global Engelleme Listesi' + 'E-posta Ekle' + reason filter + table).",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "E-posta Listesi Oluştur",
   "Liste Oluştur",
   "E-posta Ekle"
  ],
  "dialogs": [
   "CreateMailingListDialogContent",
   "CreateExclusionListDialogContent",
   "AddGlobalSuppressionsDialogContent"
  ],
  "filters": [
   "Sebebe göre filtrele (Global suppressions: Tümü/Kalıcı Hata/Geçici Hata/Spam Şikayeti/Manuel)"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "gating": "ORG_MAILING_LISTS_MANAGE / ORG_EXCLUSION_LISTS_MANAGE gate create buttons",
  "keyComponents": [
   "MailingListAdminCard",
   "ExclusionListCard",
   "GlobalSuppressionRow",
   "Table",
   "Card",
   "Button",
   "Badge"
  ],
  "dataSources": [
   "OrganizationMailingLists_mailingLists",
   "OrganizationExclusionLists_organization",
   "OrganizationGlobalSuppressions_organization"
  ],
  "tableColumns": [
   "E-posta",
   "Sebep",
   "Kaynak",
   "Eklenme Tarihi"
  ],
  "notes": "Exclusion empty: 'Henüz hariç tutma listesi yok.' Suppression empty: 'Global engelleme yok'. entriesCount badge pluralized.",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign detail — İçerik tab",
  "route": "/[organizationSlug]/admin/campaigns/[campaignSlug]",
  "titleTR": "E-posta Kampanyası",
  "purpose": "Edit a single campaign's settings, email body/template and attachments; hub for sending.",
  "layout": "Breadcrumb (Kampanyalarım > name) + status Badge (CampaignStatus enum). Tabs: İçerik / Alıcılar / Analizler. İçerik shows CampaignSettings card, CampaignTemplate preview/editor, CampaignAttachments dropzone.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "tabs": [
   "İçerik",
   "Alıcılar",
   "Analizler"
  ],
  "actions": [
   "Şablonu Düzenle",
   "Şablonu Önizle",
   "Test E-postası Gönder",
   "Değişiklikleri Kaydet"
  ],
  "dialogs": [
   "CampaignPreviewDialog",
   "SendTestEmailDialog",
   "CampaignDotsDropdown menu"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "Tabs",
   "Breadcrumb",
   "Badge",
   "CampaignSettings",
   "CampaignTemplate",
   "CampaignAttachments",
   "Card"
  ],
  "dataSources": [
   "CampaignPageQuery",
   "CampaignTemplate_campaign",
   "CampaignSettings_campaign",
   "CampaignAttachments_campaign",
   "useCampaignOrgEmailSettings_organization"
  ],
  "notes": "Status Badge variants: destructive (CANCELLED/FAILED), default (SENDING/COMPLETED), secondary (SCHEDULED), outline (DRAFT). Settings fields: Kampanya Adı, E-posta Konusu, Gönderen Adı, Gönderen E-postası, Yanıtlama E-postası. Attachments max 1MB, 5 files.",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign email template editor (full-screen edit mode)",
  "route": "/[organizationSlug]/admin/campaigns/[campaignSlug] (İçerik, editing)",
  "titleTR": "Şablonu Düzenle",
  "purpose": "WYSIWYG email body editor; when active it hides breadcrumb/tabs/settings for focus.",
  "layout": "Full-width email editor replacing page chrome (isEmailEditing hides breadcrumb, tabs, settings card, attachments).",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "states": [
   "loading"
  ],
  "keyComponents": [
   "EmailEditor",
   "Button"
  ],
  "dataSources": [
   "CampaignTemplate_campaign"
  ],
  "notes": "Chrome hidden via conditional render (not css) per code comment.",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign detail — Alıcılar tab (recipients editor + emails table)",
  "route": "/[organizationSlug]/admin/campaigns/[campaignSlug]?tab=emails",
  "titleTR": "Alıcılar",
  "purpose": "Build the recipient audience (included/excluded sources) and inspect the per-recipient email send log.",
  "layout": "CampaignRecipients: 'Dahil edilenler' vs 'Hariç tutulanlar' sections with audience chips; 'Alıcı Ekle' opens source pickers (E-posta Listesi, Kurs Dönemi, Hariç Tutma Listesi, Abonelik planları, Kurs/ürün hedefleri). Below: 'Mailleri Gönder' (SendCampaignButton) + CampaignEmails data-table.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Alıcı Ekle",
   "E-posta Listesi Ekle",
   "Kurs Dönemi Ekle",
   "Hariç Tutma Listesi Ekle",
   "Abonelik planı ekle",
   "Kurs veya ürün ekle",
   "Mailleri Gönder"
  ],
  "dialogs": [
   "AddMailingListToCampaignDialogContent",
   "AddCourseAcademicTerm (CourseAcademicTermSelector)",
   "AddExclusionListToCampaignDialogContent",
   "AddOrgSubscriptionPlanToCampaignDialogContent",
   "AddOrderableTargetToCampaignDialogContent",
   "remove confirms"
  ],
  "filters": [],
  "states": [
   "loading",
   "empty"
  ],
  "keyComponents": [
   "CampaignRecipients",
   "CampaignAudienceChip",
   "CampaignEmails",
   "DataTable",
   "Button",
   "AlertDialog"
  ],
  "dataSources": [
   "CampaignRecipients_campaign",
   "campaign.emails connection"
  ],
  "tableColumns": [
   "Email",
   "(öğrenci adı)",
   "Durum",
   "Tarih",
   "Açılma Tarihi"
  ],
  "notes": "Empty 'Alıcı yok' / 'İlk alıcıları eklemek için aşağıdan bir kaynak seçin.'; each item toggles Dahil et/Hariç tut. Skeleton = CampaignEmailsTableSkeleton. Send success 'Kampanya gönderime alındı...'.",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign detail — Analizler tab",
  "route": "/[organizationSlug]/admin/campaigns/[campaignSlug]?tab=analytics",
  "titleTR": "Analizler",
  "purpose": "Show delivery/engagement metrics for a sent campaign.",
  "layout": "CampaignAnalytics: rate cards (Teslimat Oranı, Açılma Oranı, Tıklama Oranı, Geri Dönme Oranı) + 'E-posta Durum Dağılımı' (Toplam/Beklemede/Gönderildi/Teslim Edildi/Geri Döndü/Başarısız) + 'Etkileşim Dağılımı' (Açıldı/Tıklandı/Abonelikten Çıkıldı) + Engellendi note.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "states": [
   "empty"
  ],
  "keyComponents": [
   "Card",
   "Stat tiles",
   "Progress/breakdown"
  ],
  "dataSources": [
   "CampaignAnalytics_campaign"
  ],
  "notes": "Suppressed emails excluded from rates (suppressedDescription note).",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign preview dialog",
  "route": "/[organizationSlug]/admin/campaigns/[campaignSlug] (Önizleme)",
  "titleTR": "E-posta önizlemesi",
  "purpose": "Inbox-style preview of how the campaign email renders including from/reply-to/subject/attachments.",
  "layout": "Dialog: 'Gelen kutusu görünümü' + 'E-posta detayı' (Gönderen, Yanıt adresi, Konu, Ekler / 'Ek yok').",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "states": [],
  "keyComponents": [
   "Dialog"
  ],
  "dataSources": [
   "extractEmailPreview"
  ],
  "notes": "Empty subject shows '(Konu yok)'.",
  "cluster": "marketing"
 },
 {
  "surface": "Send test email dialog",
  "route": "/[organizationSlug]/admin/campaigns/[campaignSlug] (Test E-postası Gönder)",
  "titleTR": "Test E-postası Gönder",
  "purpose": "Send a one-off test email to verify rendering before sending the campaign.",
  "layout": "Dialog with description, 'E-posta Adresi' input (placeholder test@ornek.com), 'Test Gönder' submit.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Test Gönder"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "Button"
  ],
  "dataSources": [],
  "notes": "Success 'Test e-postası başarıyla gönderildi.'",
  "cluster": "marketing"
 },
 {
  "surface": "Campaign actions dropdown",
  "route": "/[organizationSlug]/admin/campaigns (card / detail)",
  "titleTR": "Menüyü aç",
  "purpose": "Per-campaign overflow actions.",
  "layout": "DropdownMenu items: Düzenle, Kopyasını Oluştur, Şablon olarak kaydet, Mailleri Gönder, Zamanlamayı iptal et, Sil (with confirm 'Emin misiniz?').",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Düzenle",
   "Kopyasını Oluştur",
   "Şablon olarak kaydet",
   "Sil",
   "Zamanlamayı iptal et"
  ],
  "dialogs": [
   "delete confirm",
   "cancel-schedule confirm"
  ],
  "states": [],
  "keyComponents": [
   "DropdownMenu",
   "AlertDialog"
  ],
  "dataSources": [
   "CampaignDotsDropdown"
  ],
  "notes": "Cancel-schedule reverts SCHEDULED campaign to DRAFT.",
  "cluster": "marketing"
 },
 {
  "surface": "Promotions list (İndirim Kodları)",
  "route": "/[organizationSlug]/admin/promotions",
  "titleTR": "İndirim Kodları",
  "purpose": "List and filter discount-code promotions; entry point to the create wizard.",
  "layout": "PageHeader 'İndirim Kodları' + AdminHelpMenu; PromotionsFilterToolbar (search + filters); grid of PromotionAdminCard; 'Geçmiş İndirim Kodları' section; pi-org only: Separator + 'Abonelik Promosyonları' section below.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "İndirim Kodu Oluştur",
   "İlk indiriminizi oluşturun",
   "Pasif indirimleri görüntüle"
  ],
  "dialogs": [
   "PromotionOnboarding wizard (inline)",
   "UpdatePromotionDialog"
  ],
  "filters": [
   "Durum (Aktif/Pasif/Tümü)",
   "İndirim Türü",
   "Birleştirme Türü",
   "Başlangıç Tarihi Aralığı",
   "Bitiş Tarihi Aralığı",
   "Ürün İçerir",
   "Ürün Hariç"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_PROMOTIONS_VIEW to view (else NoAccessMessage 'İndirim Kodlarını Yönetme Yetkin Yok'); create requires ORG_PROMOTIONS_MANAGE",
  "keyComponents": [
   "PageHeader",
   "PromotionsFilterToolbar",
   "PromotionAdminCard",
   "Badge",
   "Separator",
   "AdminHelpMenu"
  ],
  "dataSources": [
   "PromotionsPageQuery",
   "OrganizationPromotions_promotions",
   "PiEducationSubscriptionPromotions_promotions (pi only, @include)"
  ],
  "notes": "Card fields: Kupon Kodu / 'Otomatik Uygulanır', İndirim Türü, İndirim Tutarı, Kullanım Sayısı, Başlangıç/Bitiş; status pills Aktif/Pasif/Başlamadı/Süresi Doldu/Maksimum kullanıma ulaşıldı. Empty routes to onboarding EmptyState.",
  "cluster": "marketing"
 },
 {
  "surface": "Promotions empty state",
  "route": "/[organizationSlug]/admin/promotions (no promotions)",
  "titleTR": "İlk indirim kampanyanızı başlatın",
  "purpose": "First-run onboarding prompt when the org has no promotions.",
  "layout": "OrganizationPromotionsEmptyState: title + subtitle + benefit bullets, 'İlk indiriminizi oluşturun' CTA and 'Pasif indirimleri görüntüle'.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "İlk indiriminizi oluşturun",
   "Pasif indirimleri görüntüle"
  ],
  "states": [
   "empty"
  ],
  "keyComponents": [
   "EmptyState"
  ],
  "dataSources": [
   "OrganizationPromotionsEmptyState"
  ],
  "notes": "",
  "cluster": "marketing"
 },
 {
  "surface": "Create promotion wizard",
  "route": "/[organizationSlug]/admin/promotions (PromotionOnboarding inline, replaces list)",
  "titleTR": "İndirim Kodunuzu Oluşturun",
  "purpose": "Guided multi-step creation of a discount-code promotion, optionally from a template.",
  "layout": "Full-page wizard with step rail: Şablon / Temel Bilgiler / İndirim / Koşullar / Ürünler / Özet. Nav buttons Geri/Devam/Atla/Vazgeç; exit-confirm 'Değişiklikler kaybolacak'. Templates: welcome/coupon/cart + 'Boş Başla'.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Devam",
   "Geri",
   "Atla",
   "Vazgeç",
   "İndirim Kodunu Oluştur"
  ],
  "dialogs": [
   "exit confirm dialog"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_PROMOTIONS_MANAGE",
  "keyComponents": [
   "Wizard",
   "Stepper",
   "Card",
   "Input",
   "Select",
   "Switch",
   "DatePicker",
   "Product selector"
  ],
  "dataSources": [
   "promotion-templates",
   "WizardContext"
  ],
  "tableColumns": [],
  "notes": "Discount step: type + amount + max-discount ceil. Conditions: validity dates, combination type help (UNIQUE/MAJOR/MINOR), max uses. Products: Tüm ürünler / dahil / hariç. Summary shows created toast 'İndirim kodu oluşturuldu!'",
  "cluster": "marketing"
 },
 {
  "surface": "Promotion detail",
  "route": "/[organizationSlug]/admin/promotions/[id]",
  "titleTR": "İndirim Kodu",
  "purpose": "Show one promotion's full config plus the orders that used it.",
  "layout": "Breadcrumb (İndirim Kodları > title) + PromotionAdminCard (all config fields, edit via UpdatePromotionDialog) + PromotionOrders data-table (status + date filters synced to URL).",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "dialogs": [
   "UpdatePromotionDialog",
   "PromotionPreviewBanner"
  ],
  "filters": [
   "Durum (OrderStatus)",
   "Tarih aralığı"
  ],
  "states": [
   "loading"
  ],
  "keyComponents": [
   "Breadcrumb",
   "PromotionAdminCard",
   "PromotionOrders",
   "DataTable"
  ],
  "dataSources": [
   "AdminPromotionPageQuery (node ... on Promotion)",
   "PromotionAdminCard_promotion",
   "PromotionOrders"
  ],
  "tableColumns": [
   "Tarih",
   "Email",
   "Orijinal Fiyat",
   "Satış Fiyatı",
   "İndirimli Fiyat",
   "Durum"
  ],
  "notes": "Promotion fields: couponCode, discountType, discountAmount, combinationType, priceForDiscountedItemsBasedOn, percentageDiscountCeil, isActive, start/endDate, usageCount, maxUses, currency.",
  "cluster": "marketing"
 },
 {
  "surface": "Update promotion dialog",
  "route": "/[organizationSlug]/admin/promotions (UpdatePromotionDialog)",
  "titleTR": "\"{title}\" İndirim Kodunu Güncelle",
  "purpose": "Edit an existing promotion including product scope.",
  "layout": "Large form dialog with sections: Temel Bilgiler, İndirim Ayarları, Kullanım Koşulları, Geçerlilik Süresi, Ürün Yönetimi (Tüm ürünlere uygula / Belirli ürünlere / Belirli ürünler hariç with product pickers by category).",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Kaydet"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "FormSection",
   "Input",
   "Select",
   "Switch",
   "PromotionOrderablesList",
   "PromotionAllProductsSelector"
  ],
  "dataSources": [
   "promotion-filter-types"
  ],
  "notes": "Product categories: Tüm Ürünler/Kurslar/Etkinlikler/Birebir Görüşmeler/Paketler/Dijital Ürünler. İndirim Özeti preview banner.",
  "cluster": "marketing"
 },
 {
  "surface": "Subscription promotions section (pi org)",
  "route": "/[organizationSlug]/admin/promotions (pi only)",
  "titleTR": "Abonelik Promosyonları",
  "purpose": "Platform-level (pi-org) recurring-subscription promotions list.",
  "layout": "PageSection 'Abonelik Promosyonları' + 'Abonelik Promosyonu Oluştur' button; grid of SubscriptionPromotionAdminCard (Promosyon Türü, İndirim Tutarı, Süre, Geçerli Seviyeler, Kullanım).",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Abonelik Promosyonu Oluştur"
  ],
  "dialogs": [
   "CreateSubscriptionPromotionDialogContent",
   "UpdateSubscriptionPromotionDialog",
   "DeleteSubscriptionPromotionDialog"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "gating": "Only rendered for organizationSlug==='pi'; manage requires ORG_PROMOTIONS_MANAGE",
  "keyComponents": [
   "PageSection",
   "SubscriptionPromotionAdminCard",
   "Button"
  ],
  "dataSources": [
   "PiEducationSubscriptionPromotions_promotions"
  ],
  "notes": "Empty 'Henüz abonelik promosyonu yok'; loading 'Abonelik promosyonları yükleniyor...'. Duration enum İlk Ödeme/Sınırlı Dönem/Süresiz.",
  "cluster": "marketing"
 },
 {
  "surface": "Create/Edit subscription promotion dialog",
  "route": "/[organizationSlug]/admin/promotions (subscription create/edit)",
  "titleTR": "Abonelik Promosyonu Oluştur",
  "purpose": "Create or edit a subscription-tier promotion (percentage/fixed/free-trial-extension).",
  "layout": "Form dialog sections: Temel Bilgiler, İndirim Ayarları, Süre ve Kapsam, Kullanım Limitleri ve Geçerlilik; fields incl. Promosyon Türü, Süre, Fatura Döngüsü Limiti, Deneme Uzatma Günü, Geçerli Seviyeler, Sadece Yeni Abonelikler, Davet eden kodu (ReferralCodeSelect). Promosyon Özeti preview.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Promosyon Oluştur",
   "Promosyonu Güncelle"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "FormSection",
   "Select",
   "Switch",
   "ReferralCodeSelect",
   "DatePicker"
  ],
  "dataSources": [
   "subscriptionPromotionValidation"
  ],
  "notes": "Referral code is write-only on edit ('Mevcut değer gösterilemez'). Owner types Kullanıcı/Ortak.",
  "cluster": "marketing"
 },
 {
  "surface": "Subscription promotion detail",
  "route": "/[organizationSlug]/admin/promotions/subscription/[id]",
  "titleTR": "Abonelik Promosyonu",
  "purpose": "One subscription promotion's card + its usage log by organization.",
  "layout": "Breadcrumb (Abonelik Promosyonları > title) + SubscriptionPromotionAdminCard + SubscriptionPromotionUsages data-table with search.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "filters": [
   "İsim veya e-posta ile ara"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "pi org only (else notFound); ORG_PROMOTIONS_VIEW (else NoAccessMessage)",
  "keyComponents": [
   "Breadcrumb",
   "SubscriptionPromotionAdminCard",
   "DataTable"
  ],
  "dataSources": [
   "SubscriptionPromotionUsages",
   "subscription-promotion-usages-table"
  ],
  "tableColumns": [
   "Organizasyon",
   "Kullanıcı",
   "Uygulanma Tarihi",
   "İndirimli Dönem Sayısı",
   "Toplam İndirim"
  ],
  "notes": "Empty 'Promosyon kullanımı bulunmuyor.'",
  "cluster": "marketing"
 },
 {
  "surface": "Automations list (Otomasyonlar tab)",
  "route": "/[organizationSlug]/admin/automations",
  "titleTR": "Otomasyonlar",
  "purpose": "List event-driven automations and launch the create wizard / template gallery.",
  "layout": "PageTabs: Otomasyonlar / Otomasyon E-postaları. Automations tab: PageHeader 'Otomasyonlar' + AdminHelpMenu + 'Sıfırdan Başla' button + subtitle; TemplateGallery of AutomationCard templates; 'Aktif (n)' and 'Aktif Değil (n)' grouped automation cards each with status badge + dots menu.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "tabs": [
   "Otomasyonlar",
   "Otomasyon E-postaları"
  ],
  "actions": [
   "Sıfırdan Başla",
   "Otomasyon Şablonu Kullan"
  ],
  "dialogs": [
   "AutomationWizardDialog",
   "UpdateAutomationDialog",
   "DeleteAutomationDialog"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_AUTOMATIONS_VIEW to view (else NoAccessMessage); ORG_AUTOMATIONS_MANAGE to create/edit",
  "keyComponents": [
   "PageTabs",
   "PageHeader",
   "TemplateGallery",
   "AutomationCard",
   "AutomationStatusBadge",
   "AutomationLockedCapabilitiesHint",
   "Button"
  ],
  "dataSources": [
   "AutomationsPageQuery",
   "OrganizationAutomations_automations"
  ],
  "notes": "Empty 'Henüz otomasyon yok'. LockedCapabilities hint for Instagram/WhatsApp triggers. Cards show lastRun/neverRun, totalExecutions, webhook last-delivery, delay summary.",
  "cluster": "marketing"
 },
 {
  "surface": "Create automation wizard",
  "route": "/[organizationSlug]/admin/automations (AutomationWizardDialog)",
  "titleTR": "Otomasyon Oluştur",
  "purpose": "Step-by-step builder for a single-trigger automation from scratch or a template.",
  "layout": "Dialog wizard, steps: Şablon (choose) / Tetikleyici / Koşullar / Eylemler / Gözden Geçir. Adım {current}/{total}. Trigger step = big categorized picker (TriggerTypes); Actions step = ActionTypePicker + per-action config; Conditions step (VE/VEYA operator + condition rows); Review = flow preview + name field.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "İleri",
   "Geri",
   "Otomasyon Oluştur"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_AUTOMATIONS_MANAGE",
  "keyComponents": [
   "AutomationWizardDialog",
   "TriggerStep",
   "ConditionsStep",
   "ActionsStep",
   "ReviewStep",
   "ActionTypePicker",
   "EntitySelect",
   "AutomationFlowPreview",
   "WizardDelayConfig"
  ],
  "dataSources": [
   "useCreateAutomationWizard",
   "wizardEntities",
   "automationTemplates"
  ],
  "notes": "~50 trigger types (studentSignedUp, examCompletion, orderAbandoned, coachingSessionBooked, subscriptionCreated, tagAdded, formSubmitted, promotionUsed...); ~30 action types (addTag, enrollInAcademicTerm, sendEmailToStudent, sendWebhook, subscribeMailingList, grantCertificate, sendPushNotification...); conditions (HAS_SPECIFIC_TAG, IS_PAYING_USER, IS_ENROLLED_IN_COURSE, USER_EMAIL_DOMAIN_IS...). FormAutomationWizardDialog is a form-scoped variant.",
  "cluster": "marketing"
 },
 {
  "surface": "Automation detail (flow builder view)",
  "route": "/[organizationSlug]/admin/automations/[automationId]",
  "titleTR": "Otomasyonlar",
  "purpose": "View one automation's trigger→conditions→actions flow and its execution history; edit/delete.",
  "layout": "Breadcrumb (Admin > Otomasyonlar > name); header H1 + AutomationStatusBadge + 'Düzenle' / 'Sil' buttons + description. AutomationFlowCard = visual AutomationFlowPreview (clickable nodes, 'Düzenlemek için tıklayın'); ExecutionsTable below.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Düzenle",
   "Sil"
  ],
  "dialogs": [
   "UpdateAutomationDialog (focus section)",
   "DeleteAutomationDialog"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_AUTOMATIONS_MANAGE for edit/delete",
  "keyComponents": [
   "Breadcrumb",
   "AutomationStatusBadge",
   "AutomationFlowPreview",
   "Card",
   "Button",
   "ExecutionsTable"
  ],
  "dataSources": [
   "AutomationPageQuery",
   "AutomationPage_executions",
   "UpdateAutomationDialog_automation",
   "DeleteAutomationDialog_automation"
  ],
  "tableColumns": [
   "E-posta",
   "Başlangıç",
   "Bitiş",
   "Durum"
  ],
  "notes": "Execution status enum PENDING/PROCESSING/COMPLETED/FAILED/SKIPPED (ExecutionStatusBadge). Executions table paginated (Sayfa x/y, Önceki/Sonraki). Clicking a flow node opens the edit dialog focused on that section.",
  "cluster": "marketing"
 },
 {
  "surface": "Edit automation dialog (full editor)",
  "route": "/[organizationSlug]/admin/automations/[automationId] (UpdateAutomationDialog)",
  "titleTR": "Otomasyonu Düzenle",
  "purpose": "Full editor supporting multiple triggers, conditions and ordered actions.",
  "layout": "Large dialog: name + description + status switch; TriggersBuilder (add/remove multiple triggers), TriggerConditionsBuilder (VE/VEYA), ActionsBuilder (ordered list, Yukarı/Aşağı Taşı, delay config per action via ActionDelayConfig), action config forms per type.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Otomasyonu Güncelle",
   "Eylem Ekle",
   "Tetikleyici Ekle"
  ],
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "TriggersBuilder",
   "ConditionsBuilder",
   "ActionsBuilder",
   "TriggerConfigForm",
   "ActionConfigForm",
   "ActionDelayConfig",
   "Switch"
  ],
  "dataSources": [
   "UpdateAutomationDialog_automation",
   "useUpdateAutomationDialogPrefetch"
  ],
  "notes": "signingPartialFailure toast for webhook signing. Delete confirm 'Otomasyonu Sil' with name.",
  "cluster": "marketing"
 },
 {
  "surface": "Automation emails tab (event campaigns list)",
  "route": "/[organizationSlug]/admin/automations?tab=automation-emails",
  "titleTR": "Otomasyon E-postaları",
  "purpose": "List reusable automation-triggered email campaigns (formerly 'event campaigns').",
  "layout": "H2 'Otomasyon E-postaları' + 'Otomasyon E-postası Oluştur' button + hint; grid of EventCampaignAdminCard (status badge ACTIVE/ARCHIVED/PAUSED/DRAFT, dots menu Çoğalt/Arşivle). Own query so authz failure degrades only this tab (ErrorBoundary).",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Otomasyon E-postası Oluştur"
  ],
  "dialogs": [
   "CreateEventCampaignDialogContent",
   "EventCampaignDotsDropdown (Çoğalt/Arşivle)"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "gating": "ORG_AUTOMATIONS_MANAGE to create",
  "keyComponents": [
   "EventCampaignAdminCard",
   "EventCampaignDotsDropdown",
   "ErrorBoundary",
   "Dialog",
   "Button"
  ],
  "dataSources": [
   "AutomationEmailsTabQuery",
   "OrganizationEventCampaigns_eventCampaigns",
   "CreateEventCampaignDialogContent_organization"
  ],
  "notes": "Error fallback 'Otomasyon e-postaları yüklenemedi...'; loading 'Otomasyon e-postaları yükleniyor...'. /event-campaigns routes permanently redirect here.",
  "cluster": "marketing"
 },
 {
  "surface": "Automation email (event campaign) detail",
  "route": "/[organizationSlug]/admin/automation-emails/[eventCampaignSlug]",
  "titleTR": "Otomasyon E-postası",
  "purpose": "Edit an automation email's content and see the automations that use it plus its analytics.",
  "layout": "Breadcrumb (Otomasyon E-postaları > name) + EventCampaignStatus Badge. Tabs: İçerik / E-postalar / Otomasyonlar / Analizler. İçerik = EventCampaignSettings + EventCampaignTemplate editor + EventCampaignAttachments.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "tabs": [
   "İçerik",
   "E-postalar",
   "Otomasyonlar",
   "Analizler"
  ],
  "actions": [
   "Şablonu Düzenle",
   "Test E-postası Gönder",
   "Değişiklikleri Kaydet"
  ],
  "dialogs": [
   "SendTestEmailDialog",
   "EventCampaign settings delete-attachment confirm"
  ],
  "states": [
   "loading"
  ],
  "keyComponents": [
   "Tabs",
   "Breadcrumb",
   "Badge",
   "EventCampaignSettings",
   "EventCampaignTemplate",
   "EventCampaignAttachments"
  ],
  "dataSources": [
   "EventCampaignPageQuery",
   "EventCampaignTemplate_eventCampaign",
   "EventCampaignSettings_eventCampaign",
   "EventCampaignAttachments_eventCampaign"
  ],
  "notes": "Status Badge: destructive PAUSED, default ACTIVE, outline else. Settings fields Kampanya Adı, E-posta Konusu, Açıklama, Yanıtlama E-postası. Reached from Automations > Otomasyon E-postaları.",
  "cluster": "marketing"
 },
 {
  "surface": "Automation email — Otomasyonlar sub-tab",
  "route": "/[organizationSlug]/admin/automation-emails/[slug]?tab=automations",
  "titleTR": "Otomasyonlar",
  "purpose": "List/create automations that send this automation email; quick templates.",
  "layout": "EventCampaignAutomations: 'Otomasyonlarınız' + activeCount/inactiveCount; 'Hızlı Şablonlar' cards (Kampanya E-postası Gönder, E-posta Gönder ve Etiketle, ...Kaydet, ...Abone Et); 'Otomasyon Oluştur'.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Otomasyon Oluştur"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "keyComponents": [
   "EventCampaignAutomations",
   "Card",
   "Skeleton"
  ],
  "dataSources": [
   "EventCampaignAutomations (own query)"
  ],
  "notes": "Empty 'Henüz otomasyon yok'.",
  "cluster": "marketing"
 },
 {
  "surface": "Automation email — Analizler sub-tab",
  "route": "/[organizationSlug]/admin/automation-emails/[slug]?tab=analytics",
  "titleTR": "Analizler",
  "purpose": "Delivery/engagement analytics for the automation email's sends.",
  "layout": "EventCampaignAnalytics: same metric cards as campaign analytics (Teslimat/Açılma/Tıklama/Geri Dönme Oranı, status + engagement breakdown).",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "states": [
   "loading",
   "empty"
  ],
  "keyComponents": [
   "Card",
   "Skeleton"
  ],
  "dataSources": [
   "EventCampaignAnalytics (own query)"
  ],
  "notes": "Empty 'Henüz analiz verisi bulunmuyor'.",
  "cluster": "marketing"
 },
 {
  "surface": "Create automation email dialog",
  "route": "/[organizationSlug]/admin/automations (CreateEventCampaignDialogContent)",
  "titleTR": "Otomasyon E-postası Oluştur",
  "purpose": "Create a new reusable automation email template.",
  "layout": "Dialog: 'Otomasyon E-postası Adı' input + optional binding selectors (Kurs Akademik Dönemi / Koçluk Seansı / E-posta Listesi); 'Otomasyon E-postası Oluştur' submit.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Otomasyon E-postası Oluştur"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "Select"
  ],
  "dataSources": [
   "CreateEventCampaignDialogContent_organization"
  ],
  "notes": "",
  "cluster": "marketing"
 },
 {
  "surface": "Tags list (Etiketler + Etiket Grupları)",
  "route": "/[organizationSlug]/admin/tags",
  "titleTR": "Etiketler",
  "purpose": "Manage organization tags and tag groups used to categorize students/content.",
  "layout": "Two PageSections: 'Etiketler' (description + 'Yeni Etiket' + OrganizationTags table + ArchivedTags 'Arşivlenmiş Etiketler') and Separator + 'Etiket Grupları' (+ 'Etiket Grubu Oluştur' + OrganizationTagGroups).",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Yeni Etiket",
   "Etiket Grubu Oluştur"
  ],
  "dialogs": [
   "CreateTagDialog",
   "CreateTagGroupDialog",
   "UpdateTagDialog",
   "DeleteTagDialog"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_TAGS_VIEW to view (else NoAccessMessage 'Etiketleri Yönetme Yetkiniz Yok'); ORG_TAGS_MANAGE to create/edit",
  "keyComponents": [
   "PageSection",
   "Table",
   "Badge",
   "ArchivedTags",
   "Separator",
   "Button"
  ],
  "dataSources": [
   "TagsPageQuery",
   "OrganizationTags_organization",
   "OrganizationTagGroups_organization"
  ],
  "tableColumns": [
   "Ad",
   "Slug",
   "Renk",
   "Gruplar",
   "Durum",
   "Görünürlük",
   "Oluşturulma Tarihi",
   "İşlemler"
  ],
  "notes": "Row actions: Düzenle/Sil/Arşivle/Geri Yükle. Status Aktif/Arşivlenmiş; visibility Herkese Açık/Gizli. Empty 'Henüz etiket oluşturulmadı.'",
  "cluster": "marketing"
 },
 {
  "surface": "Create/Update tag dialog",
  "route": "/[organizationSlug]/admin/tags (Create/UpdateTagDialog)",
  "titleTR": "Yeni Etiket",
  "purpose": "Create or edit a tag (name, slug, color, emoji icon, visibility, group, status).",
  "layout": "Dialog form: Etiket Adı, Slug (format validation), Açıklama, Renk (TagIconFormField color picker + 'Temizle'), İkon (emoji), Herkese Açık switch, Durum.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Kaydet"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "ColorPicker",
   "EmojiPicker",
   "Switch",
   "Select"
  ],
  "dataSources": [],
  "notes": "Slug only lowercase/digits/hyphen. 'Açık etiketler öğrenciler tarafından görülebilir'.",
  "cluster": "marketing"
 },
 {
  "surface": "Delete tag dialog",
  "route": "/[organizationSlug]/admin/tags (DeleteTagDialog)",
  "titleTR": "Etiketi Sil",
  "purpose": "Confirm irreversible tag deletion.",
  "layout": "AlertDialog: '\"{name}\" etiketini silmek istediğinize emin misiniz?...' + İptal / Sil.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Sil",
   "İptal"
  ],
  "states": [],
  "keyComponents": [
   "AlertDialog"
  ],
  "dataSources": [],
  "notes": "",
  "cluster": "marketing"
 },
 {
  "surface": "Tag detail",
  "route": "/[organizationSlug]/admin/tags/[tagId]",
  "titleTR": "Etiketler",
  "purpose": "Show one tag's info and everywhere it is used (subscription tiers, courses, bundles, students, coaching sessions).",
  "layout": "Back arrow + icon/color + name + slug code + 'Düzenle' button. Cards: 'Etiket Bilgileri' (Açıklama, Durum badge, Herkese Açık/Gizli, Gruplar); 'Bu Etiketi Veren Abonelik Kademeleri (n)' table (Kademe/Ürün/Görüntüle) + coursesRequiring + bundlesRequiring tables; TagStudentsTable; TagCoursesTable; TagBundlesTable; TagCoachingSessionsTable.",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Düzenle"
  ],
  "dialogs": [
   "UpdateTagDialog"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_TAGS_VIEW; edit ORG_TAGS_MANAGE",
  "keyComponents": [
   "Card",
   "Table",
   "Badge",
   "Button"
  ],
  "dataSources": [
   "TagDetailsPageQuery",
   "TagCoursesTable_organization",
   "TagBundlesTable_organization",
   "TagStudentsTable_organization",
   "TagCoachingSessionsTable_organization",
   "orgSubscriptionProducts.tiers.grantedTags"
  ],
  "tableColumns": [
   "Kademe",
   "Ürün",
   "Öğrenci / E-posta",
   "Kurs Adı / Kurs Slug",
   "Paket Başlığı / Paket Slug",
   "Seans Başlığı"
  ],
  "notes": "Multiple related-entity tables each with own empty text (e.g. 'Bu etikete sahip öğrenci bulunmuyor.').",
  "cluster": "marketing"
 },
 {
  "surface": "Mailing list detail",
  "route": "/[organizationSlug]/admin/mailing-lists/[mailingListSlug]",
  "titleTR": "E-posta Listesi",
  "purpose": "Manage one mailing list: subscribers, campaigns using it, and settings.",
  "layout": "Breadcrumb (E-posta Listelerim > name) + status Badge (Aktif/Pasif/Herkese Açık/Özel) + 'Sil' / 'E-posta Listesini Güncelle' buttons (manage). Cards: Açıklama (if any); 'Kampanyalar' card ('Kampanya Oluştur') = MailingListCampaigns; 'Abone' card (Export + 'E-posta Ekle') = MailingListSubscriptions table; 'Detaylar' card (Durum, Görünürlük).",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "E-posta Listesini Güncelle",
   "Sil",
   "Kampanya Oluştur",
   "E-posta Ekle",
   "Dışa Aktar"
  ],
  "dialogs": [
   "UpdateMailingListDialogContent",
   "delete AlertDialog",
   "CreateCampaignWithMailingListDialogContent",
   "BulkAddEmailsDialogContent"
  ],
  "filters": [
   "Abone ara"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "gating": "ORG_MAILING_LISTS_MANAGE for edit/add; Export visible to all viewers (VIEW-level)",
  "keyComponents": [
   "Breadcrumb",
   "Badge",
   "Card",
   "AlertDialog",
   "Dialog",
   "DataTable",
   "ExportMailingListSubscriptionsButton"
  ],
  "dataSources": [
   "MailingListPageQuery",
   "MailingListCampaigns",
   "MailingListSubscriptions"
  ],
  "tableColumns": [
   "E-posta",
   "İsim",
   "Abone Olma Tarihi",
   "Abonelik İptal Tarihi",
   "Durum"
  ],
  "notes": "Export XLSX/CSV with progress. Subscriptions empty 'Henüz abone yok'; campaigns empty 'Henüz kampanya yok'.",
  "cluster": "marketing"
 },
 {
  "surface": "Create/Update mailing list dialog",
  "route": "/[organizationSlug]/admin/campaigns?tab=lists / mailing-list detail",
  "titleTR": "E-posta Listesi Oluştur",
  "purpose": "Create or edit a mailing list (name, description, active, public).",
  "layout": "Dialog: E-posta Listesi Adı, Açıklama, Aktif switch, Herkese Açık switch.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "E-posta Listesi Oluştur",
   "E-posta Listesini Güncelle"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "Switch"
  ],
  "dataSources": [
   "CreateMailingListDialogContent_organization"
  ],
  "notes": "'Özel olduğunda, sadece organizasyon üyeleri ve aboneler bu listeyi görebilir.'",
  "cluster": "marketing"
 },
 {
  "surface": "Bulk add emails dialog (mailing list)",
  "route": "/[organizationSlug]/admin/mailing-lists/[slug] (BulkAddEmailsDialogContent)",
  "titleTR": "E-posta Listesine E-posta Ekle",
  "purpose": "Paste many emails to add as subscribers.",
  "layout": "Dialog: 'E-posta Adresleri' textarea (comma/newline/space separated) + 'E-posta Önizlemesi' (n geçerli e-posta bulundu / ve n tane daha...) + 'E-postaları Ekle'.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "E-postaları Ekle"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Textarea",
   "Badge"
  ],
  "dataSources": [],
  "notes": "",
  "cluster": "marketing"
 },
 {
  "surface": "Create campaign from mailing list dialog",
  "route": "/[organizationSlug]/admin/mailing-lists/[slug] (CreateCampaignWithMailingListDialogContent)",
  "titleTR": "E-posta Listesi İçin Kampanya Oluştur",
  "purpose": "Create a campaign pre-targeted to this mailing list.",
  "layout": "Dialog: campaign name + info 'Bu kampanya otomatik olarak \"{mailingListName}\" listesindeki aboneleri içerecektir.'",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Kampanya Oluştur"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Input"
  ],
  "dataSources": [],
  "notes": "",
  "cluster": "marketing"
 },
 {
  "surface": "Exclusion list detail",
  "route": "/[organizationSlug]/admin/exclusion-lists/[exclusionListId]",
  "titleTR": "Hariç Tutma Listeleri",
  "purpose": "Manage the email addresses in one exclusion list used to suppress campaign recipients.",
  "layout": "Breadcrumb (Hariç Tutma Listeleri > name) + status Badge (Aktif/Pasif) + 'Sil' / 'Güncelle' (manage). Cards: Açıklama; '\"{name}\" E-postaları' = ExclusionListEntriesManager (search, Export, CSV import, bulk select/delete, 'E-posta Ekle'); 'Detaylar' (Durum).",
  "priority": "primary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Sil",
   "Güncelle",
   "E-posta Ekle",
   "Dışa Aktar",
   "CSV içe aktar",
   "Seçilenleri sil"
  ],
  "dialogs": [
   "AddEntriesDialogContent",
   "UpdateExclusionListDialogContent",
   "delete AlertDialog",
   "remove/bulk-delete confirms"
  ],
  "filters": [
   "E-posta ara"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied",
   "error"
  ],
  "gating": "ORG_EXCLUSION_LISTS_VIEW or ORG_CAMPAIGNS_VIEW to view; ORG_EXCLUSION_LISTS_MANAGE to manage; cross-org guard (Sentry + notFound)",
  "keyComponents": [
   "Breadcrumb",
   "Badge",
   "Card",
   "ExclusionListEntriesManager",
   "AlertDialog"
  ],
  "dataSources": [
   "ExclusionListPageQuery",
   "exclusion-entries-store (Relay)"
  ],
  "tableColumns": [
   "E-posta",
   "Eklenme Tarihi"
  ],
  "notes": "Empty 'Bu listede henüz e-posta yok.'; loadedHint for search-only-loaded caveat; import limits (5MB, max per import).",
  "cluster": "marketing"
 },
 {
  "surface": "Create/Update exclusion list dialog",
  "route": "/[organizationSlug]/admin/campaigns?tab=lists (Create/UpdateExclusionListDialogContent)",
  "titleTR": "Hariç Tutma Listesi Oluştur",
  "purpose": "Create or edit an exclusion list (name, description, active).",
  "layout": "Dialog: Liste Adı (placeholder 'Örn: Abonelikten çıkanlar'), Açıklama, Aktif switch.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "Oluştur",
   "Güncelle"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "Switch"
  ],
  "dataSources": [],
  "notes": "Delete dialog '\"{name}\" Listesini Sil' warns irreversible.",
  "cluster": "marketing"
 },
 {
  "surface": "Add entries dialog (exclusion list)",
  "route": "/[organizationSlug]/admin/exclusion-lists/[id] (AddEntriesDialogContent)",
  "titleTR": "E-posta Ekle",
  "purpose": "Bulk-paste emails into an exclusion list.",
  "layout": "Dialog: 'E-posta Adresleri' textarea + preview count + 'E-postaları Ekle'.",
  "priority": "edge",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "E-postaları Ekle"
  ],
  "states": [
   "error"
  ],
  "keyComponents": [
   "Dialog",
   "Textarea"
  ],
  "dataSources": [],
  "notes": "",
  "cluster": "marketing"
 },
 {
  "surface": "Global suppression list section + add dialog",
  "route": "/[organizationSlug]/admin/campaigns?tab=lists (OrganizationGlobalSuppressions)",
  "titleTR": "Global Engelleme Listesi",
  "purpose": "View/manage org-wide suppressed addresses (bounces, spam complaints, manual) blocked across all campaigns.",
  "layout": "Section header + description + 'E-posta Ekle'; reason filter (Tümü/Kalıcı Hata/Geçici Hata/Spam Şikayeti/Manuel); table of GlobalSuppressionRow with Kaldır. AddGlobalSuppressionsDialogContent = paste-emails dialog 'Global Engelleme Listesine E-posta Ekle'.",
  "priority": "secondary",
  "suggestedCanvas": "04-marketing",
  "actions": [
   "E-posta Ekle",
   "Kaldır"
  ],
  "dialogs": [
   "AddGlobalSuppressionsDialogContent",
   "remove confirm 'Engellemeyi Kaldır'"
  ],
  "filters": [
   "Sebebe göre filtrele"
  ],
  "states": [
   "empty"
  ],
  "keyComponents": [
   "Table",
   "Select",
   "Badge",
   "Dialog",
   "AlertDialog"
  ],
  "dataSources": [
   "OrganizationGlobalSuppressions_organization"
  ],
  "tableColumns": [
   "E-posta",
   "Sebep",
   "Kaynak",
   "Eklenme Tarihi"
  ],
  "notes": "Empty 'Global engelleme yok'.",
  "cluster": "marketing"
 },
 {
  "surface": "Forms list",
  "route": "/[organizationSlug]/admin/forms",
  "titleTR": "Formlar",
  "purpose": "List all of an organization's forms as cards, with search, status filter, sort, and create.",
  "layout": "PageHeader with title 'Formlar' + AdminHelpMenu (?) + guided-tour button and a numeric titleBadge (filter-aware total) + subtitle 'Organizasyonunuz için formlar oluşturun ve yönetin'. Toolbar row: AdminSearchInput ('Form ara...'), status Select ('Tüm durumlar'/'Herkese Açık'/'Özel'/'Arşivlenmiş') with a clear-X, SortSelect ('En yeni'/'Son güncellenen'/'Başlık (A-Z)'), and a primary 'Form Oluştur' button. Below: responsive card grid (sm:2 / lg:3 / xl:4) of FormAdminCard, infinite-scroll footer.",
  "priority": "primary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "Page body gated on ORG_FORMS_VIEW (else NoAccessMessage). Create/edit actions gated on ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [
   "Arama (form ara)",
   "Durum: Tüm durumlar / Herkese Açık / Özel / Arşivlenmiş",
   "Sırala: En yeni / Son güncellenen / Başlık (A-Z)"
  ],
  "actions": [
   "Form Oluştur",
   "Filtreleri temizle",
   "Aramayı temizle"
  ],
  "dialogs": [
   "CreateFormWizard (Form Oluştur)"
  ],
  "tableColumns": [],
  "keyComponents": [
   "PageHeader",
   "AdminSearchInput",
   "Select",
   "SortSelect",
   "Card grid",
   "FormAdminCard",
   "InfiniteListFooter",
   "Skeleton",
   "TourProvider",
   "AdminHelpMenu"
  ],
  "dataSources": [
   "FormsPageQuery { organization(slug) { ...OrganizationForms_organization ...CreateFormWizard_organization } }",
   "OrganizationForms_organization fragment -> forms(first,after,query,publishStatus,sortBy) connection { totalCount edges.node { slug ...FormAdminCard_form } }",
   "OrganizationFormsPaginationQuery",
   "websiteSettings.customDomain"
  ],
  "notes": "Filters persist to URL (useUrlFilterSync). 8-card skeleton fallback. When truly empty AND unfiltered, renders FormOnboardingHero instead (separate surface). 'Filtreyle eşleşen form yok' dashed empty box for zero filter results.",
  "cluster": "forms"
 },
 {
  "surface": "Forms list — empty onboarding hero",
  "route": "/[organizationSlug]/admin/forms (empty org state)",
  "titleTR": "Formlarla başlayın",
  "purpose": "First-run explainer shown when the org has no forms at all (no active filter).",
  "layout": "FormOnboardingHero: FileText icon, title 'Formlarla başlayın', body 'Formlar; kayıt, başvuru, anket ve geri bildirim toplamanızı sağlar...', three feature tiles (Etiketle/Toplama/Otomasyon icons ClipboardList/Inbox/Zap) and a primary CTA 'İlk formunu oluştur' (opens the wizard). Replaces the whole toolbar+grid.",
  "priority": "edge",
  "suggestedCanvas": "05-forms",
  "states": [
   "empty"
  ],
  "gating": "CTA only rendered if ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [],
  "actions": [
   "İlk formunu oluştur"
  ],
  "dialogs": [
   "CreateFormWizard"
  ],
  "tableColumns": [],
  "keyComponents": [
   "FormOnboardingHero",
   "feature tiles",
   "lucide icons"
  ],
  "dataSources": [
   "OrganizationForms_organization forms.totalCount == 0"
  ],
  "notes": "Header 'Form Oluştur' button + tour are hidden while this hero is the whole screen (onEmptyStateChange).",
  "cluster": "forms"
 },
 {
  "surface": "Form card (list item)",
  "route": "/[organizationSlug]/admin/forms (grid item)",
  "titleTR": "(form başlığı)",
  "purpose": "Per-form card summarizing status/type/response counts with an actions menu and a link into the builder.",
  "layout": "Card: title (line-clamp-2), a ⋯ actions DropdownMenu (label 'İşlemler'), status Badge (Herkese Açık/Özel/Arşivlenmiş), type Badge (Pazarlama/Kayıt/Öğrenme), an 'in progress' StatusBadge with Clock icon (# devam ediyor) when >0, a response count line (# yanıt / Yanıt yok), and a full-width 'Form Düzenleyiciyi Aç' outline button linking to the builder.",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [],
  "gating": "Copy link / Preview items only when publishStatus == PUBLIC.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Form Düzenleyiciyi Aç",
   "Düzenle",
   "Çoğalt",
   "Bağlantıyı kopyala",
   "Önizle",
   "Sil"
  ],
  "dialogs": [
   "UpdateFormDialog (Formu Güncelle)",
   "CloneFormDialog (Formu Çoğalt)",
   "DeleteFormDialog (Formu Sil)"
  ],
  "tableColumns": [],
  "keyComponents": [
   "Card",
   "DropdownMenu",
   "Badge",
   "StatusBadge",
   "Button"
  ],
  "dataSources": [
   "FormAdminCard_form fragment { title slug publishStatus type completedSessions.totalCount inProgressSessions.totalCount }"
  ],
  "notes": "'Bağlantı kopyalandı' / 'Bağlantı kopyalanamadı' toasts. Preview link opens org website /form/{slug}.",
  "cluster": "forms"
 },
 {
  "surface": "Create form wizard",
  "route": "/[organizationSlug]/admin/forms (modal)",
  "titleTR": "Form Oluştur",
  "purpose": "2-step modal to create a form either from a template or blank, then fill details.",
  "layout": "Dialog with OnboardingStepperUI 2 steps: 'Şablon' (choose) → 'Detaylar'. Choose step: 'Şablonsuz başla' card ('Boş bir formla başla...') + a searchable template gallery ('Hazır şablonlar', hint 'Hızlı başlamak için bir şablon seçin', TemplateCard grid with type-styled icons). Details step (BlankConfigStep/TemplateConfigStep): Başlık, Slug (form-slug, 'Bu, formunuzun web adresinin bir parçası olacak'), Form Tipi (Pazarlama/Kayıt/Öğrenme), Durum, with a 'Geri' back button and 'Oluştur' submit.",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "error"
  ],
  "gating": "Only mounted when ORG_FORMS_MANAGE.",
  "tabs": [
   "Şablon",
   "Detaylar"
  ],
  "filters": [
   "Şablon arama (gallery.searchPlaceholder)"
  ],
  "actions": [
   "Oluştur",
   "Geri",
   "Şablonsuz başla"
  ],
  "dialogs": [
   "UnsavedChangesConfirmDialog"
  ],
  "tableColumns": [],
  "keyComponents": [
   "Dialog",
   "OnboardingStepperUI",
   "TemplateCard grid",
   "Input",
   "Select",
   "AdminSearchInput"
  ],
  "dataSources": [
   "CreateFormWizard_organization fragment",
   "createForm mutation",
   "formTemplates catalog (info-request, course-evaluation, event-registration, course-gift, student-registration, contact-form, student-satisfaction, newsletter-signup, parent-information, course-enrollment, pre-assessment)"
  ],
  "notes": "12 built-in templates under FormTemplates messages; 'gallery.noResults' when search empty.",
  "cluster": "forms"
 },
 {
  "surface": "Form builder shell (tabbed editor)",
  "route": "/[organizationSlug]/admin/forms/[formSlug]",
  "titleTR": "(form başlığı)",
  "purpose": "The form editor page: header with title + view link, and a tab bar routing to Questions / Settings / Calculations / Result pages / Automations / Responses.",
  "layout": "PageContent maxWidth=none. Header: h1 form title, then either a 'Görüntüle' outline button (opens public form, OpenInNewWindow icon) when PUBLIC, or an info line 'Form {status}' (e.g. Form Özel) when not public; a FormBuilderTourButton on the right. ScrollableTabsList with triggers: 'Sorular', 'Ayarlar', 'Hesaplamalar', 'Sonuç Sayfaları', 'Otomasyonlar', 'Yanıtlar'. Each non-questions tab self-fetches (Suspense + Skeleton).",
  "priority": "primary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "permission-denied",
   "error"
  ],
  "gating": "Manage tabs (Sorular/Ayarlar/Hesaplamalar/Sonuç Sayfaları/Otomasyonlar) only shown with ORG_FORMS_MANAGE; without it the page force-shows only the Yanıtlar tab. Missing form -> notFound().",
  "tabs": [
   "Sorular",
   "Ayarlar",
   "Hesaplamalar",
   "Sonuç Sayfaları",
   "Otomasyonlar",
   "Yanıtlar"
  ],
  "filters": [],
  "actions": [
   "Görüntüle (public form)"
  ],
  "dialogs": [
   "UnsavedChangesConfirmDialog (Kaydedilmemiş değişiklikler / Sayfada kal / Değişiklikleri at)"
  ],
  "tableColumns": [],
  "keyComponents": [
   "Tabs",
   "ScrollableTabsList",
   "Button",
   "TourProvider",
   "UnsavedChangesProvider",
   "Skeleton"
  ],
  "dataSources": [
   "FormBuilderPageQuery { organization { websiteSettings.customDomain form(slug){ id slug title publishStatus ...FormAdminSections_form } ...FormAdminSections_organization } }",
   "each tab has its own useLazyLoadQuery"
  ],
  "notes": "Tab state in ?tab= query param. Tab-switch warns on unsaved settings edits via AlertDialog (not window.confirm). Query intentionally split per-tab to stay under backend complexity limit 2500.",
  "cluster": "forms"
 },
 {
  "surface": "Builder — Questions tab (section/question editor)",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=questions",
  "titleTR": "Sorular",
  "purpose": "Drag-and-drop builder for sections and their questions.",
  "layout": "List of sections (FormAdminSection), each with title/description and its questions (QuestionItem). DnD reordering of both sections and questions. Per-section and per-question row actions. Empty: 'Henüz bölüm yok' + 'Başlamak için ilk bölümünüzü oluşturun' + 'Bölüm Oluştur'. Inline add controls: 'Altına Bölüm Ekle', 'Soru Ekle', 'Altına Soru Ekle'.",
  "priority": "primary",
  "suggestedCanvas": "05-forms",
  "states": [
   "empty"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Bölüm Oluştur",
   "Soru Ekle",
   "Altına Bölüm Ekle",
   "Altına Soru Ekle",
   "Düzenle",
   "Çoğalt",
   "Sil",
   "Göster/Gizle"
  ],
  "dialogs": [
   "CreateSectionDialog (Bölüm Oluştur)",
   "UpdateSectionDialog (Bölümü Güncelle)",
   "DeleteSectionDialog (Bölümü Sil)",
   "CreateQuestionDialog (Soru Oluştur)",
   "UpdateQuestionDialog (Soruyu Güncelle)",
   "DeleteQuestionDialog (Soruyu Sil)"
  ],
  "tableColumns": [],
  "keyComponents": [
   "DndContext / Sortable",
   "FormAdminSection",
   "SectionItem",
   "QuestionItem",
   "Button",
   "Dialog"
  ],
  "dataSources": [
   "FormAdminSections_form fragment { sections { questions ...QuestionItem_question ...FormAdminSection_section } }",
   "FormAdminSections_organization",
   "moveFormQuestion / moveFormSection mutations",
   "CreateSectionDialog_organization"
  ],
  "notes": "Section reordering + question reorder within/across sections update the Relay store optimistically. 'Bölüm başarıyla çoğaltıldı' / 'Soru başarıyla çoğaltıldı' toasts.",
  "cluster": "forms"
 },
 {
  "surface": "Question editor dialog",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=questions (modal)",
  "titleTR": "Soru Oluştur / Soruyu Güncelle",
  "purpose": "Create/edit a single question: pick type and configure its type-specific data.",
  "layout": "Dialog: Soru Tipi select (16 types: Kısa Metin, Uzun Metin, İçerik Bloğu, İletişim Bilgisi, Çoktan Seçmeli, Birden Fazla Seçim, Seçim Listesi, Çoklu Seçim Listesi, Matris/Izgara, Tarih/Saat, Dosya Yükleme, Doğrusal Ölçek, Ödeme, Etiket Grubu Seçimi, Etiket Seçimi, Özel Alan), Soru Metni, a Zorunlu switch ('Bu soruyu zorunlu yap'), a Gizli switch ('Kullanıcılara gösterme'), and a QuestionDataForm rendering type-specific fields (options/rows/columns, min/max lengths, contact type, date format, file types & size/duration limits, linear-scale min/max/step/labels, payment currency/min/max/pay-what-you-want, tag group/tags, custom field, rich-text toggle, help placeholder).",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "error"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Oluştur",
   "Güncelle",
   "İptal"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "Dialog",
   "Select (question type)",
   "Input/Textarea",
   "Switch",
   "QuestionDataForm",
   "TagSelectionInput"
  ],
  "dataSources": [
   "createFormQuestion / updateFormQuestion mutations",
   "tag groups + custom field definitions for TAG/CUSTOM_FIELD types"
  ],
  "notes": "ContactFormQuestionType (Tam Ad/Ad/Soyad/E-posta/Telefon/URL) and DateFormQuestionType (Tarih/Saat/Tarih ve Saat) drive sub-selects. File types: Video/Ses/Resim/PDF/Döküman/Arşiv.",
  "cluster": "forms"
 },
 {
  "surface": "Builder — Settings tab",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=settings",
  "titleTR": "Ayarlar",
  "purpose": "Form-level settings: general info, navigation/display, and email notifications.",
  "layout": "FormBuilderSettings stacks three cards: (1) Form Ayarları / general (Başlık, Slug w/ 'URL'yi değiştirmek...' warning, Form Tipi, Durum w/ unpublish warning, 'Güncelle'/'Kaydedilecek değişiklik yok'); (2) Gezinme Ayarları / navigation (Gezinme Modu = Soru Soru/Bölüm Bölüm/Hepsi Bir Arada, Geri Gitmeye İzin Ver, Otomatik İlerle, Navbar'ı Göster, İlerleme Çubuğunu Göster, Bölüm Başlıklarını Göster, Bölüm Açıklamalarını Göster, Soru Numaralarını Göster; 'Akış'/'Görünüm' groups; inherited-from-org notice); (3) E-posta Bildirimleri (new-submission notify toggle + recipient multiselect, respondent-copy toggle, org-default inherit).",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Güncelle",
   "Bildirim ayarlarını kaydet"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "Card",
   "Input",
   "Select",
   "Switch",
   "InputMultiSelect (recipients)",
   "Button"
  ],
  "dataSources": [
   "FormBuilderSettings_form + FormBuilderSettings_organization fragments",
   "updateForm / update navigation settings / update email-notification settings mutations"
  ],
  "notes": "Navigation settings inherit org defaults until saved ('Bu ayarlar organizasyon varsayılanlarından devralınıyor'). 'Ayarlar kaydedildi' / 'Ayarlar kaydedilemedi' toasts. Back-navigation hint disabled in FORM mode.",
  "cluster": "forms"
 },
 {
  "surface": "Builder — Calculations & Grading tab",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=calculations",
  "titleTR": "Hesaplamalar",
  "purpose": "Sub-tabbed scoring config: auto Calculations and manual Grading questions.",
  "layout": "FormScoringContent nested Tabs: 'Hesaplamalar' and 'Değerlendirme' (?scoringTab=). Calculations sub-tab: list of calculations (name/type Badge) or onboarding hero ('Hesaplamalarla başlayın'); 'Hesaplama Oluştur'. Grading sub-tab (FormGradingQuestions): 'Manuel Değerlendirme Soruları' list or onboarding hero; 'Değerlendirme Sorusu Oluştur'; move up/down.",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "empty"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [
   "Hesaplamalar",
   "Değerlendirme"
  ],
  "filters": [],
  "actions": [
   "Hesaplama Oluştur",
   "Değerlendirme Sorusu Oluştur",
   "Yukarı Taşı",
   "Aşağı Taşı",
   "Düzenle",
   "Sil"
  ],
  "dialogs": [
   "CreateCalculationDialog",
   "EditCalculationDialog",
   "DeleteCalculationDialog",
   "CreateGradingQuestionDialog",
   "EditGradingQuestionDialog",
   "DeleteGradingQuestionDialog"
  ],
  "tableColumns": [],
  "keyComponents": [
   "Tabs",
   "Card",
   "FormOnboardingHero",
   "Dialog"
  ],
  "dataSources": [
   "FormCalculations_form fragment { calculations }",
   "FormGradingQuestions_form fragment { gradingQuestions }",
   "create/update/delete FormCalculation + FormGradingQuestion mutations"
  ],
  "notes": "Both sub-tabs have empty-onboarding heroes with feature tiles.",
  "cluster": "forms"
 },
 {
  "surface": "Calculation builder dialog",
  "route": "?tab=calculations (modal)",
  "titleTR": "Hesaplama Oluştur / Hesaplamayı Düzenle",
  "purpose": "Multi-step builder for a form calculation (math/conditional/string/comparison), optionally AI-generated.",
  "layout": "Method choice first ('Nasıl oluşturmak istersiniz?' — Manuel Oluştur vs AI ile Oluştur). Manual path steps: 'Şablon' → 'Yapılandır' → 'İfade' → 'Test & Kaydet'. Templates: Soruların Toplamı, Soruların Ortalaması, Geçti/Kaldı Eşiği, Sıfırdan Başla. Fields: Ad, Tür (Matematik/Koşullu/Metin/Karşılaştırma), an ExpressionBuilder (question-answer/constant/other-calculation/math/string/comparison/conditional operands with a flow preview) and a TestCalculation panel (Örnek Veri, Testi Çalıştır, Sonuç/Hata).",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "error"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [
   "Şablon",
   "Yapılandır",
   "İfade",
   "Test & Kaydet"
  ],
  "filters": [],
  "actions": [
   "Kaydet",
   "Testi Çalıştır",
   "İleri",
   "Geri",
   "Şablonu Uygula"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "Dialog",
   "OnboardingStepperUI",
   "ExpressionBuilder",
   "ExpressionFlowPreview",
   "TestCalculation",
   "AICalculationGenerator",
   "CreateMethodChoice"
  ],
  "dataSources": [
   "createFormCalculation / updateFormCalculation mutations",
   "AI generate-calculation mutation",
   "form questions for references"
  ],
  "notes": "Rich builder: MathOperationBuilder, StringOperationBuilder, ComparisonBuilder, ConditionalBuilder, QuestionReferenceBuilder, CalculationReferenceBuilder, ConstantValueBuilder. Flow-preview labels (Toplam/Ortalama/Eğer-İse-Değilse etc.).",
  "cluster": "forms"
 },
 {
  "surface": "Grading question builder dialog",
  "route": "?tab=calculations (Değerlendirme, modal)",
  "titleTR": "Değerlendirme Sorusu Oluştur / Düzenle",
  "purpose": "Create a manual-grading question hidden from respondents, of one of four types.",
  "layout": "Dialog 2 steps ('Detaylar' → 'Yapılandır & Kaydet'): Başlık, Açıklama, Tür (Sayısal Ölçek / Metin Geri Bildirimi / Rubrik / Geçti-Kaldı), Gerekli Değerlendirici Sayısı, then a type-specific builder + GradingQuestionPreview. NumericScale: min/max value + labels. TextFeedback: placeholder + max length. Rubric: criteria (name/description/required) each with scoring levels (score/label/description). PassFail: pass/fail labels.",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "error"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [
   "Detaylar",
   "Yapılandır & Kaydet"
  ],
  "filters": [],
  "actions": [
   "Kaydet",
   "İleri",
   "Geri",
   "Kriter Ekle",
   "Seviye Ekle"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "Dialog",
   "NumericScaleBuilder",
   "TextFeedbackBuilder",
   "RubricBuilder",
   "PassFailBuilder",
   "GradingQuestionPreview"
  ],
  "dataSources": [
   "create/update FormGradingQuestion mutations"
  ],
  "notes": "'Bu sorular formu dolduran kişiye gösterilmez.' Question types: NUMERIC_SCALE/TEXT_FEEDBACK/RUBRIC/PASS_FAIL.",
  "cluster": "forms"
 },
 {
  "surface": "Builder — Result Pages tab",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=resultPages",
  "titleTR": "Sonuç Sayfaları",
  "purpose": "Configure post-submission result pages (conditional) and the display mode.",
  "layout": "Display-mode selector card ('Gönderim sonrası görünüm': 'Sonuç sayfasına git' vs 'Satır içi göster'). Below: ordered list of result pages or empty ('Henüz sonuç sayfası yok') with 'Sonuç Sayfası Oluştur'. Each ResultPageItem shows title, a Varsayılan/condition-count badge, move up/down, and edit/delete. Editor (ResultPageEditor) has a Puck-based content editor + a ConditionsBuilder (Eşleşme Türü VE/VEYA, per-condition Hesaplama + Operatör + Değer).",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "empty",
   "error"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Sonuç Sayfası Oluştur",
   "Düzenle",
   "Önizleme",
   "Sil",
   "Koşul Ekle",
   "Yukarı taşı",
   "Aşağı taşı"
  ],
  "dialogs": [
   "ResultPageEditor (Sonuç Sayfası Oluştur/Güncelle)",
   "DeleteResultPageDialog"
  ],
  "tableColumns": [],
  "keyComponents": [
   "Card",
   "ResultPageItem",
   "ResultPageEditor",
   "ConditionsBuilder",
   "Puck editor",
   "Dialog"
  ],
  "dataSources": [
   "FormResultPages_form + FormResultPages_organization fragments",
   "create/update/delete/move FormResultPage mutations",
   "form calculations (for conditions)"
  ],
  "notes": "13 condition operators (eşittir, büyüktür, içerir, boştur, doğrudur, ...). Default page shown when no condition matches. 'Bu sonuç sayfası hata alıyor. Destek ile iletişime geçin.' preview error.",
  "cluster": "forms"
 },
 {
  "surface": "Builder — Automations tab",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=automations",
  "titleTR": "Otomasyonlar",
  "purpose": "Create automations that run actions when the form is submitted.",
  "layout": "List of automations with search ('Otomasyonlarınızda ara...') and status filter (Tümü/Aktif/Pasif); each row shows name, active/inactive, action count ('# eylem'), and a ⋯ menu (Düzenle / Çalıştırmaları Görüntüle / Sil). Empty: onboarding hero 'Otomasyonlarla başlayın' + 'Otomasyon Oluştur'. Quick templates: Göndereni Etiketle, Kursa Otomatik Kayıt, Listeye Abone Et, Sertifika Ver.",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "empty"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [
   "Arama",
   "Durum: Tümü / Aktif / Pasif"
  ],
  "actions": [
   "Otomasyon Oluştur",
   "Düzenle",
   "Çalıştırmaları Görüntüle",
   "Sil"
  ],
  "dialogs": [
   "Create/Edit Automation dialog",
   "Delete confirm (Otomasyonu Sil)",
   "Executions view (Çalıştırmalar)"
  ],
  "tableColumns": [],
  "keyComponents": [
   "Card/list",
   "AdminSearchInput",
   "DropdownMenu",
   "FormOnboardingHero",
   "automation builder"
  ],
  "dataSources": [
   "FormAutomations_form + FormAutomations_organization(@arguments formId) fragments",
   "create/update/delete automation mutations"
  ],
  "notes": "Automation builder has trigger conditions + an ordered action list across many action categories (Etiketler, E-posta, Kurs Erişimi, Kayıt, Paket Erişimi, Koçluk, Abonelik, İlerleme, E-posta Listesi, İletişim, Entegrasyon) with delay options (Süre sonra / Belirli zamanda). This subsystem is large; may warrant its own canvas but is reached via the form builder.",
  "cluster": "forms"
 },
 {
  "surface": "Builder — Responses tab (list)",
  "route": "/[organizationSlug]/admin/forms/[formSlug]?tab=responses",
  "titleTR": "Yanıtlar",
  "purpose": "Table of form sessions/responses with status filter, contact search, per-status counts, export, column toggling, and drill-in.",
  "layout": "DataTable with DataTableToolbar: contact-search input ('İletişim bilgisine göre ara...'), a DataTableFacetedFilter on Durum (Devam Ediyor/Duraklatıldı/Tamamlandı with server counts), column visibility toggle ('Sütunlar'/'Sütunları göster/gizle'), and a header actions menu with Export (Excel .xlsx / CSV .csv, progress + ExportJobStatusDisplay). Rows link to detail ('Detaylar'). Empty: 'Henüz yanıt yok' + 'Bir yanıt geldiğinde burada göreceksiniz.'",
  "priority": "primary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "gating": "Visible to ORG_FORMS_VIEW (only tab for users without ORG_FORMS_MANAGE).",
  "tabs": [],
  "filters": [
   "İletişim bilgisi araması",
   "Durum: Devam Ediyor / Duraklatıldı / Tamamlandı"
  ],
  "actions": [
   "Detaylar (satır)",
   "Dışa Aktar → Excel (.xlsx) / CSV (.csv)",
   "Filtreleri temizle"
  ],
  "dialogs": [
   "Export submenu + ExportJobStatusDisplay"
  ],
  "tableColumns": [
   "Kullanıcı",
   "Kurum (only 'pi' org)",
   "Gönderen (only 'pi' org)",
   "İletişim Bilgisi",
   "Durum",
   "Başlangıç",
   "Bitiş",
   "Cevaplar",
   "(actions)"
  ],
  "keyComponents": [
   "DataTable",
   "DataTableToolbar",
   "DataTableFacetedFilter",
   "DataTableColumnHeader",
   "FormResponsesHeaderActionsMenu",
   "StatusBadge",
   "Avatar"
  ],
  "dataSources": [
   "FormResponses fragment: sessions(status, contactSearch) connection + per-status counts (completedCount/inProgressCount/pausedCount)",
   "requestFormResultsExport mutation -> FormResultsExportJob { status processedSessions totalSessions downloadUrl }"
  ],
  "notes": "Status + contactSearch persist to URL and are seeded server-side (page.tsx) to avoid unfiltered flash. Anonymous respondents render 'Anonim'. Kurum/Gönderen columns only for org slug 'pi'.",
  "cluster": "forms"
 },
 {
  "surface": "Response detail + grading",
  "route": "/[organizationSlug]/admin/forms/[formSlug]/responses/[sessionId]",
  "titleTR": "Yanıt Detayı",
  "purpose": "Full detail of one submission: respondent, metadata, answers, contact info, calculation results, existing grades, and the manual grading form.",
  "layout": "Back button (→ ?tab=responses preserving status) + h1 'Yanıt Detayı' + subtitle '\"{form}\" formuna gönderilen yanıt'. 3-col grid: left sticky Card (respondent Avatar/name/email or 'Anonim', status Badge, MetaFields: Başlangıç, Bitiş, Cevaplar, Kurum/Gönderen for 'pi', extracted İletişim Bilgisi as mailto/tel/link, Hesaplama Sonuçları, and a 'Notlar' block listing existing grades per grading question incl. rubric criteria breakdown + feedback quote + grader avatar/date). Right (2-col): FormResponseDetail rendering each section's questions with the respondent's answers (+ payment status, file attachments), and FormSessionGrading form to submit/update grades.",
  "priority": "primary",
  "suggestedCanvas": "05-forms",
  "states": [
   "loading",
   "error"
  ],
  "gating": "notFound() if org/form/session missing. Grading requires appropriate manage permission.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Yanıtlara Dön",
   "Notu Kaydet",
   "Notu Güncelle"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "Card",
   "Avatar",
   "Badge",
   "MetaField",
   "FormResponseDetail",
   "FormSessionGrading",
   "grading-input builders (NumericScale/PassFail/Rubric/TextFeedback)",
   "FormSubmissionAttachment"
  ],
  "dataSources": [
   "FormResponseDetailPageQuery { form { sections(showHidden:true).questions(showHidden:true) [+ type-specific: options/rows/columns/min/max/labels/contactType/paymentSession] gradingQuestions[type-specific] session(sessionId){ startedAt finishedAt status submissions{answer attachments{fileType fileSize title fileName}} student user respondingOrganization calculationResults{result formCalculation} grades{grade feedback grader formGradingQuestion} } } }",
   "submitFormGrade / updateFormGrade mutations"
  ],
  "notes": "Grade value formatting per type (NUMERIC_SCALE number, PASS_FAIL Geçti/Kaldı, RUBRIC summed score, TEXT_FEEDBACK truncated). Contact links sanitized (isSafeUrl, encoded mailto/tel). Payment questions show 'Ödeme tamamlandı/bekleniyor/işleniyor'.",
  "cluster": "forms"
 },
 {
  "surface": "Manual grading panel (FormSessionGrading)",
  "route": "/[organizationSlug]/admin/forms/[formSlug]/responses/[sessionId] (right column)",
  "titleTR": "Değerlendirme",
  "purpose": "The grader-facing form to score a submission against each grading question.",
  "layout": "Card 'Değerlendirme' with one input per grading question by type: NumericScaleGradingInput (slider/number with min/max labels), PassFailGradingInput ('Seviye seçin' → Geçti/Kaldı), RubricGradingInput (per-criterion level pick), TextFeedbackGradingInput. Optional 'Geri Bildirim' textarea ('İsteğe bağlı geri bildirim...'), and a 'Notu Kaydet'/'Notu Güncelle' button. Shows 'Değerlendiren' + 'Değerlendirme tarihi' for existing grades.",
  "priority": "secondary",
  "suggestedCanvas": "05-forms",
  "states": [
   "error"
  ],
  "gating": "Grading permission.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Notu Kaydet",
   "Notu Güncelle"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "Card",
   "grading-input/*",
   "Textarea",
   "Button"
  ],
  "dataSources": [
   "gradingQuestions + existing grades from FormResponseDetailPageQuery",
   "submitFormGrade mutation"
  ],
  "notes": "'Not kaydedildi' success toast. Supports multiple required graders per question.",
  "cluster": "forms"
 },
 {
  "surface": "Forms — permission denied",
  "route": "/[organizationSlug]/admin/forms (no ORG_FORMS_VIEW)",
  "titleTR": "Formlar",
  "purpose": "Access-denied state when the member lacks form view permission.",
  "layout": "NoAccessMessage component with section label 'Formlar' — replaces the entire page body.",
  "priority": "edge",
  "suggestedCanvas": "05-forms",
  "states": [
   "permission-denied"
  ],
  "gating": "!hasOrgPermission('ORG_FORMS_VIEW').",
  "tabs": [],
  "filters": [],
  "actions": [],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "NoAccessMessage"
  ],
  "dataSources": [
   "usePermissions()"
  ],
  "notes": "Also 'Organizasyon bulunamadı' when org query returns null.",
  "cluster": "forms"
 },
 {
  "surface": "Delete form confirmation",
  "route": "/[organizationSlug]/admin/forms (modal)",
  "titleTR": "Formu Sil",
  "purpose": "Type-to-confirm destructive delete of a form.",
  "layout": "AlertDialog: 'Formu Sil', body '\"{title}\" formunu silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.', a confirm text input (label 'Onaylamak için \"Bu formu sil\" yazın', must type 'Bu formu sil'), cancel + destructive confirm.",
  "priority": "edge",
  "suggestedCanvas": "05-forms",
  "states": [
   "error"
  ],
  "gating": "ORG_FORMS_MANAGE.",
  "tabs": [],
  "filters": [],
  "actions": [
   "Sil",
   "İptal"
  ],
  "dialogs": [],
  "tableColumns": [],
  "keyComponents": [
   "AlertDialog",
   "Input"
  ],
  "dataSources": [
   "deleteForm mutation"
  ],
  "notes": "'\"{title}\" formu silindi' success / 'Form silinemedi.' error toasts. Clone dialog (Formu Çoğalt) has Başlık + URL Slug fields with 'Kopya' suffix.",
  "cluster": "forms"
 },
 {
  "surface": "Students roster list",
  "route": "/[organizationSlug]/admin/students",
  "titleTR": "Kayıtlı Kullanıcılar",
  "purpose": "Primary CRM roster: paginated, filterable, sortable table of all organization students with avatar, contact, tags, lifetime value and activity dates; row/whole-row click navigates to the Contact-360 detail page.",
  "layout": "PageHeader 'Kayıtlı Kullanıcılar' with an AdminHelpMenu '?' + page-tour trigger. Below, StudentsToolbar in two fixed rows: row 1 = search input (left) + action buttons 'Özel Alanlar' and 'Öğrenci Ekle' (right); row 2 = 'Filtreler' builder button + active-filter chips + 'Filtreleri sıfırla'. Then an infinite-scroll DataTable (TanStack) with left-pinned selection checkbox column and right-pinned actions kebab column. Bottom: 'Daha fazla yükle' / loaded-of-total count. A one-time guided tour (TourProvider) highlights search, actions, filters, columns and table.",
  "priority": "primary",
  "tabs": [],
  "filters": [
   "Arama (searchPlaceholder 'Öğrenci ara...')",
   "Etiketler (dahil/hariç)",
   "Kurs, ürün veya etkinlik erişimi",
   "Koçluk seansları",
   "Abonelik kademesi",
   "Paketler",
   "Erişim durumu (yalnızca şu an aktif erişim)",
   "Toplam harcama (en az/en fazla/arasında)",
   "Son etkinlik (tarih)",
   "Kayıt tarihi (tarih)"
  ],
  "actions": [
   "Öğrenci Ekle",
   "Özel Alanlar",
   "Filtreler",
   "Filtreleri sıfırla"
  ],
  "tableColumns": [
   "(seçim onay kutusu)",
   "Öğrenci",
   "E-posta",
   "Etiketler",
   "Toplam Harcama",
   "Kayıt Tarihi",
   "Son Giriş",
   "Son Aktivite",
   "(işlemler kebabı)"
  ],
  "dialogs": [
   "Filtreler popover",
   "Sütun görünürlüğü + Dışa Aktar kebabı",
   "Öğrenci Ekle dialog",
   "Kursa Davet Et dialog",
   "Etiketleri Yönet dialog",
   "Toplu işlem çubuğu",
   "Öğrenci Özel Alanları sheet"
  ],
  "keyComponents": [
   "PageHeader",
   "AdminHelpMenu",
   "AdminSearchInput",
   "DataTable",
   "Avatar",
   "Badge",
   "Tooltip",
   "Progress",
   "Button",
   "Skeleton",
   "TourProvider",
   "DataTableColumnHeader",
   "createSelectionColumn"
  ],
  "dataSources": [
   "StudentsPageQuery (organization(slug))",
   "fragment dataTableOrganizationStudents on Organization @refetchable(OrganizationStudentsTablePaginationQuery): students(first,after,filters: OrganizationStudentFilters) connection — edges.node: id, email, image, givenName, lastName, createdAt, lastSignInAt, lastActivityAt, lifetimeValue{amount,currency}, tags{id,name,color,icon}; totalCount",
   "useOrganizationTags_organization fragment",
   "OrganizationStudentSortField (GIVEN_NAME/EMAIL/CREATED_AT/LAST_ACTIVITY_AT/LIFETIME_VALUE)"
  ],
  "states": [
   "loading",
   "empty",
   "error",
   "permission-denied"
  ],
  "gating": "Requires ORG_STUDENTS_VIEW (else NoAccessMessage). 'Öğrenci Ekle' gated ORG_STUDENTS_ADD; 'Özel Alanlar' gated ORG_CUSTOM_FIELDS_MANAGE; export/bulk gated ORG_STUDENTS_EDIT.",
  "notes": "Lifetime value of 0 renders an em-dash with tooltip 'Henüz tamamlanmış bir ödemesi yok.' Rows without a name show '(isim girilmemiş)'. Tags cell shows first 2 + '+N'. Sort labels are per-column contextual (e.g. 'A–Z sırala', 'Çok harcayandan aza', 'Yeniden eskiye').",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Students list — loading skeleton",
  "route": "/[organizationSlug]/admin/students (Suspense fallback)",
  "titleTR": "Kayıtlı Kullanıcılar",
  "purpose": "Skeleton shown while the students connection is fetching / refetching.",
  "layout": "Bordered card with a muted header row and 8 skeleton rows, each = round avatar skeleton + two text-line skeletons + a status pill + date + kebab placeholder. Also AdminContentSkeleton at the route Suspense boundary before the page shell mounts.",
  "priority": "edge",
  "states": [
   "loading"
  ],
  "keyComponents": [
   "Skeleton",
   "AdminContentSkeleton"
  ],
  "notes": "During a filter-change refetch the table stays visible in a dimmed 'refetch' loading mode rather than swapping to the skeleton.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Students list — empty state",
  "route": "/[organizationSlug]/admin/students (no rows)",
  "titleTR": "Kayıtlı Kullanıcılar",
  "purpose": "Empty state, two variants: no students at all vs. no filter matches.",
  "layout": "Centered UsersIcon (40% opacity) + bold title + body text. No-students: 'Henüz öğrenci yok' / 'Yukarıdaki butonu kullanarak ilk öğrencinizi ekleyin.' Filtered: 'Eşleşme bulunamadı' / 'Filtrelerinizi değiştirmeyi veya temizlemeyi deneyin.' + 'Filtreleri sıfırla' button.",
  "priority": "secondary",
  "states": [
   "empty"
  ],
  "keyComponents": [
   "UsersIcon",
   "Button"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Students list — permission denied",
  "route": "/[organizationSlug]/admin/students (no ORG_STUDENTS_VIEW)",
  "titleTR": "Öğrenciler",
  "purpose": "Access-denied screen for viewers lacking ORG_STUDENTS_VIEW.",
  "layout": "NoAccessMessage component keyed to section name 'Öğrenciler'.",
  "priority": "edge",
  "states": [
   "permission-denied"
  ],
  "gating": "ORG_STUDENTS_VIEW absent",
  "keyComponents": [
   "NoAccessMessage"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Students list — load/refetch error",
  "route": "/[organizationSlug]/admin/students (fetch failure)",
  "titleTR": "Kayıtlı Kullanıcılar",
  "purpose": "Error banner + retry when the filtered refetch or a page load fails (network/5xx/permission-revoke mid-session).",
  "layout": "DataTable error banner with a retry affordance; a failed 'load more' also raises a destructive toast (title 'Hata', 'İşlem başarısız oldu'). Sentry-captured. Filter-facets failure degrades to a small inline destructive-tinted banner 'Filtre seçenekleri yüklenemedi.' + 'Tekrar dene'.",
  "priority": "edge",
  "states": [
   "error"
  ],
  "keyComponents": [
   "DataTable (error)",
   "ErrorBoundary",
   "Button",
   "toast"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Filters builder popover",
  "route": "/[organizationSlug]/admin/students → 'Filtreler' button",
  "titleTR": "Filtreler",
  "purpose": "Accordion rule-builder: a left field list + right per-field editor; edits apply live and surface as removable chips above the table.",
  "layout": "Popover: left column lists filter fields (Etiketler, Kurs/ürün/etkinlik erişimi, Koçluk seansları, Abonelik kademesi, Paketler, Toplam harcama, Son etkinlik, Kayıt tarihi) each with an active-count badge + chevron; picking one widens the popover to show its editor on the right. Editors: multi-select with Dahil/Hariç segmented toggle + searchable command list (per-item selected checkmarks, cross-tag indicator); harcama = gte/lte/between numeric inputs with a currency hint; date = vertical after/before/between operator toggle + inline single/two-month Calendar (capped at today). Footer: contextual 'Erişim durumu' (only-currently-active-access) checkbox that appears only when an access-type filter is set. Facet lists cap results and show a 'İlk N sonuç gösteriliyor' truncation note.",
  "priority": "secondary",
  "filters": [
   "Dahil/Hariç operatörleri",
   "en az / en fazla / arasında",
   "Bu tarihten sonra / önce / arasında"
  ],
  "dialogs": [
   "Inline Calendar",
   "Command search lists"
  ],
  "keyComponents": [
   "Popover",
   "Command",
   "Calendar",
   "Checkbox",
   "Input",
   "Badge",
   "OperatorToggle (custom segmented control)"
  ],
  "dataSources": [
   "useStudentsFilterFacets (accessOptions, coachingOptions, tierOptions, bundleOptions, ltvCurrencyHint, truncated flags) — Suspense + ErrorBoundary + retry",
   "tags from useOrganizationTags"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "notes": "Empty facet categories are hidden from the field list. Chips render as 'Erişim · içerir · <value +N>' with an X to remove.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Bulk-actions bar (selection active)",
  "route": "/[organizationSlug]/admin/students → select ≥1 row",
  "titleTR": "Toplu İşlemler",
  "purpose": "Actions available when rows are selected: bulk tag management, bulk course invite/enroll, and CSV export of the selection.",
  "layout": "Shared DataTable bulk bar shows selected-count ('N öğrenci seçildi') + clear; this slot adds outline buttons: 'Etiketleri Yönet' (TagIcon), 'Kursa Davet Et' (BookOpenIcon), 'Seçilenleri Dışa Aktar' (DownloadIcon). Selection persists across sort refetch (keyed by student id).",
  "priority": "secondary",
  "actions": [
   "Etiketleri Yönet",
   "Kursa Davet Et",
   "Seçilenleri Dışa Aktar"
  ],
  "dialogs": [
   "Etiketleri Toplu Yönet dialog",
   "Kursa Toplu Davet dialog"
  ],
  "gating": "All bulk actions require ORG_STUDENTS_EDIT.",
  "keyComponents": [
   "Button",
   "Dialog",
   "toast"
  ],
  "states": [],
  "notes": "Client-side CSV export only covers loaded rows; off-page selections trigger a partial-export warning toast ('Kısmi dışa aktarma' / 'Seçili N öğrenciden X tanesi dışa aktarıldı...').",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Table header kebab — column visibility + server export",
  "route": "/[organizationSlug]/admin/students → actions-column header kebab",
  "titleTR": "Sütunlar",
  "purpose": "Toggle column visibility (persisted to localStorage) and launch a full-list server-side export with a column picker (XLSX/CSV) plus a floating job-status indicator.",
  "layout": "TableHeaderActionsMenu kebab: column show/hide toggles ('Sütunları Göster/Gizle') + an export submenu. ExportColumnMenu: 'Sütunları seç' with Tümünü seç / Tümünü kaldır, per-column checkboxes (Kimlik, E-posta, Ad, Soyad, Kayıt Tarihi, Son Giriş, Son Etkinlik, Tercih Edilen Dil, Tercih Edilen Saat Dilimi, Etiketler, Toplam Harcama, Para Birimi), count label, then 'XLSX olarak dışa aktar' / 'CSV olarak dışa aktar'. ExportJobStatusDisplay shows Başlatılıyor…/progress '{n}/{total}'/Dışa aktarıldı/Uyarı ile dışa aktarıldı/Dışa aktarma başarısız.",
  "priority": "secondary",
  "actions": [
   "XLSX olarak dışa aktar",
   "CSV olarak dışa aktar",
   "Tümünü seç",
   "Tümünü kaldır"
  ],
  "gating": "Export gated ORG_STUDENTS_EDIT (column visibility ungated).",
  "keyComponents": [
   "TableHeaderActionsMenu",
   "ExportColumnMenu",
   "ExportJobStatusDisplay",
   "DropdownMenu",
   "Checkbox"
  ],
  "dataSources": [
   "useStudentsExport (server export job over the current filter set)"
  ],
  "states": [
   "loading",
   "error"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Row actions menu",
  "route": "/[organizationSlug]/admin/students → row kebab",
  "titleTR": "Menüyü Aç",
  "purpose": "Per-student quick actions from the table row.",
  "layout": "RowActions dropdown: primary link 'Detayları Görüntüle', plus 'Etiketleri Yönet' (TagIcon) and 'Kursa Davet Et' (BookOpenIcon).",
  "priority": "edge",
  "actions": [
   "Detayları Görüntüle",
   "Etiketleri Yönet",
   "Kursa Davet Et"
  ],
  "dialogs": [
   "Etiketleri Yönet dialog",
   "Kursa Davet Et dialog"
  ],
  "keyComponents": [
   "RowActions",
   "DropdownMenu",
   "Dialog"
  ],
  "states": [],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Add students dialog",
  "route": "/[organizationSlug]/admin/students → 'Öğrenci Ekle'",
  "titleTR": "Öğrenci Ekle",
  "purpose": "Bulk-add students by pasting email addresses (comma/newline/space separated); shows a parsed preview and a partial-success failed-emails report.",
  "layout": "Modal (UserPlusIcon title 'Öğrenci Ekle', desc 'E-posta adresi ile organizasyonunuza öğrenci ekleyin.'). Textarea 'E-posta Adresleri' + help text; a muted 'E-posta Önizleme' panel lists parsed emails as removable chips with 'N geçerli e-posta bulundu' count (caps visible chips at 50, '+N e-posta daha'). Submit 'Öğrenci Ekle'. Result view: green partial-success banner + destructive-tinted 'Aşağıdaki e-postalar eklenemedi:' chip list + 'Kapat'.",
  "priority": "secondary",
  "actions": [
   "Öğrenci Ekle",
   "Kapat"
  ],
  "keyComponents": [
   "Dialog",
   "Textarea",
   "Form (react-hook-form + zod)",
   "Button",
   "toast"
  ],
  "dataSources": [
   "AddStudentsDialogContentMutation → addOrganizationStudents (successCount, newlyCreatedCount, failedEmails, userErrors); @appendNode into OrganizationStudentsTableFragment_students connection + totalCount bump"
  ],
  "states": [
   "error"
  ],
  "gating": "Reachable only with ORG_STUDENTS_ADD.",
  "notes": "Validation errors: 'Lütfen en az bir e-posta adresi girin.' / 'Lütfen en az bir geçerli e-posta adresi girin.'",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Invite student to course dialog (single)",
  "route": "/[organizationSlug]/admin/students → row/detail 'Kursa Davet Et'",
  "titleTR": "Kursa Davet Et",
  "purpose": "Invite one student to a course academic term, optionally direct-enrolling instead of emailing an invitation.",
  "layout": "Modal (DialogSuspense fallback while org courses load). Fields: 'Kurs' combobox (searchable popover, 'Kurs seçin...'), 'Dönem' combobox (auto-selects current term / hides when a single term, 'Dönem seçin...'), and a bordered 'Doğrudan Kayıt' switch row with description. Footer button toggles by mode: 'Davet Gönder' / 'Öğrenciyi Kaydet' (or 'Davet gönderiliyor...'). Title/description swap between invite and 'Kursa Kaydet' when direct-enroll is on.",
  "priority": "secondary",
  "actions": [
   "Davet Gönder",
   "Öğrenciyi Kaydet"
  ],
  "keyComponents": [
   "DialogSuspense",
   "Popover",
   "Command",
   "Switch",
   "Button"
  ],
  "dataSources": [
   "InviteStudentToCourseDialogContentQuery (Organization.courses(first:100){academicTerms{isCurrentAcademicTerm}})",
   "inviteCourseAcademicTermStudent mutation (invitation{status,email}, courseStudent @appendNode, userErrors)"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "notes": "Success toast differs: 'Davet e-postası {email} adresine gönderildi.' vs '{name} kursa kaydedildi.'",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Bulk invite to course dialog",
  "route": "/[organizationSlug]/admin/students → bulk 'Kursa Davet Et'",
  "titleTR": "Kursa Toplu Davet",
  "purpose": "Invite/enroll the whole selection into a course term at once, with a partial-success result summary.",
  "layout": "Modal (BookOpenIcon). Same Kurs + Dönem comboboxes + 'Doğrudan Kayıt' switch as the single dialog, but title/desc are count-based ('N öğrenciyi kursa davet edin.'). Result block: yellow partial-success line ('X başarılı, Y başarısız') with a bulleted error list ('ve N hata daha...') or a green success line. Footer button 'N öğrenciyi davet et' / 'N öğrenciyi kaydet' / 'İşleniyor...', then 'Kapat' after a result.",
  "priority": "secondary",
  "actions": [
   "Davet et / Kaydet",
   "Kapat"
  ],
  "keyComponents": [
   "DialogSuspense",
   "Popover",
   "Command",
   "Switch",
   "Button"
  ],
  "dataSources": [
   "BulkInviteToCourseDialogContentQuery",
   "bulkInviteCourseAcademicTermStudents mutation (successCount, failedEmails, failedStudentIds, invitations, courseStudents @appendNode)"
  ],
  "states": [
   "loading",
   "error"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Manage tags dialog (single student)",
  "route": "/[organizationSlug]/admin/students → 'Etiketleri Yönet' (row or detail overview)",
  "titleTR": "Etiketleri Yönet",
  "purpose": "Add/remove tags on one student with optimistic per-tag pending spinners.",
  "layout": "Modal (TagIcon, desc '\"{name}\" öğrencisinin etiketlerini düzenleyin.'). 'Mevcut Etiketler' as colored removable badges (per-tag Loader2 while pending, 'Etiket yok' when none); 'Etiket Ekle' section = full-width outline button ('Etiket seçin...' / 'Tüm etiketler eklenmiş') opening a searchable Command popover of available tags (color swatch + icon).",
  "priority": "secondary",
  "actions": [
   "Etiket Ekle",
   "Etiketi Kaldır"
  ],
  "keyComponents": [
   "Dialog",
   "Badge",
   "Popover",
   "Command",
   "Loader2"
  ],
  "dataSources": [
   "useStudentTagMutations (add/remove tag mutations, optimistic)"
  ],
  "states": [
   "error"
  ],
  "notes": "Toasts '\"{name}\" etiketi başarıyla eklendi/silindi'.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Bulk manage tags dialog",
  "route": "/[organizationSlug]/admin/students → bulk 'Etiketleri Yönet'",
  "titleTR": "Etiketleri Toplu Yönet",
  "purpose": "Add or remove a set of tags across all selected students, with add/remove mode tabs and a partial-success summary.",
  "layout": "Modal (TagIcon, count desc). Segmented Tabs 'Etiket Ekle' / 'Etiket Kaldır'. 'Seçili Etiketler' staged-badge area (click badge to unstage, 'Etiket seçilmedi'); 'Etiket Seç' inline bordered Command list with color swatch + checkmark. Result block (yellow partial / green success). Footer 'İptal' + 'N öğrenciye etiket ekle' / 'N öğrenciden etiket kaldır' / 'İşleniyor...'. Closing with staged tags raises an unsaved-changes AlertDialog.",
  "priority": "secondary",
  "actions": [
   "Etiket Ekle (mode)",
   "Etiket Kaldır (mode)",
   "Uygula",
   "İptal"
  ],
  "dialogs": [
   "Kaydedilmemiş değişiklikler AlertDialog"
  ],
  "keyComponents": [
   "Dialog",
   "Tabs",
   "Command",
   "Badge",
   "AlertDialog"
  ],
  "dataSources": [
   "bulkAddTagsToStudents / bulkRemoveTagsFromStudents mutations (successCount, failedStudentIds, userErrors); optimistic Relay store updater"
  ],
  "states": [
   "error"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Custom field definitions manager sheet",
  "route": "/[organizationSlug]/admin/students → 'Özel Alanlar'",
  "titleTR": "Öğrenci Özel Alanları",
  "purpose": "Manage org-wide student custom-field definitions: list/reorder/edit existing fields (master-detail) and create new ones; unsaved-edit guarded.",
  "layout": "Large modal (85vh, Settings2Icon, desc 'Öğrenciler için özel bilgi alanları tanımlayın...'). Tabs 'Mevcut Alanlar (N)' and 'Alan Ekle'. Existing tab = left list of CustomFieldDefinitionItem rows (title + type/visibility badges, up/down reorder arrows 'Yukarı taşı'/'Aşağı taşı', edit/delete) + right form panel or hint 'Düzenlemek için soldan bir alan seçin.' Create tab = the same form panel with empty defaults. Navigations that would drop unsaved edits trigger an unsaved-changes AlertDialog. List empty state: 'Henüz özel alan tanımlanmamış'.",
  "priority": "secondary",
  "tabs": [
   "Mevcut Alanlar (N)",
   "Alan Ekle"
  ],
  "actions": [
   "Alanı Sil",
   "Kaydet",
   "Yukarı taşı",
   "Aşağı taşı"
  ],
  "dialogs": [
   "Alanı Sil confirm",
   "Kaydedilmemiş değişiklikler AlertDialog"
  ],
  "keyComponents": [
   "Dialog",
   "Tabs",
   "Skeleton",
   "AlertDialog",
   "CustomFieldDefinitionItem",
   "CustomFieldFormPanel"
  ],
  "dataSources": [
   "CustomFieldDefinitionsListQuery (Organization.customStudentFieldDefinitions{id,type,title,editability,validationSchema,visibility})",
   "reorder/create/update/delete OrganizationStudentCustomFieldDefinition mutations"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "gating": "Reachable only with ORG_CUSTOM_FIELDS_MANAGE.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Custom field create/edit form panel",
  "route": "Within Öğrenci Özel Alanları sheet (right pane / Alan Ekle tab)",
  "titleTR": "Alanı Düzenle",
  "purpose": "Type-aware form to define a custom field: name, field type, visibility, editability, and type-specific validation (options, min/max, aspect ratio, object properties, default country).",
  "layout": "Scrollable form: 'Alan Adı' input (placeholder 'Örn: Doğum Tarihi, TC Kimlik No...'), 'Alan Türü' selector (Kısa Metin/Uzun Metin/Sayı/Tarih/Tarih ve Saat/Tekli Seçim/Çoklu Seçim/Metin Listesi/Telefon/E-posta/URL/Resim/Nesne/Nesne Dizisi/Form), 'Görünürlük' (Herkese Açık/Özel/Gizli), 'Düzenleme Yetkisi' (Sadece Öğrenci/Sadece Yöneticiler/Öğrenci ve Yöneticiler), then type-specific controls: 'Seçenekler' editor, 'Maksimum Karakter', 'Minimum/Maksimum Değer', 'Maksimum/Minimum Seçim/Öğe', 'Nesne Özellikleri' (Ad/Tür/Zorunlu), 'En Boy Oranı', 'Varsayılan Ülke Kodu'. Footer: 'Alanı Sil' (edit only) + 'İptal' + 'Kaydet' (create shows 'Kaydet'/'Kaydediliyor...').",
  "priority": "secondary",
  "actions": [
   "Kaydet",
   "İptal",
   "Alanı Sil"
  ],
  "keyComponents": [
   "Form (react-hook-form + zod)",
   "FieldTypeSelector",
   "EnumOptionsEditor",
   "ObjectPropertiesEditor",
   "Select",
   "Input",
   "Button"
  ],
  "dataSources": [
   "CustomFieldFormPanelCreateMutation / CustomFieldFormPanelUpdateMutation (fieldDefinition + userErrors)"
  ],
  "states": [
   "error"
  ],
  "notes": "IMAGE and JSON_SCHEMA (FORM) types disable the type selector on edit. Validation msgs e.g. 'Alan adı gerekli', 'En az bir seçenek eklemelisiniz', 'Minimum değer, maksimum değerden büyük olamaz'.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Delete custom field confirm dialog",
  "route": "Within Öğrenci Özel Alanları sheet → 'Alanı Sil'",
  "titleTR": "Alanı Sil",
  "purpose": "Confirm destructive deletion of a custom-field definition (wipes that field's data on all students).",
  "layout": "AlertDialog: title 'Alanı Sil', description 'Bu alanı silmek istediğinizden emin misiniz? Tüm öğrencilerdeki bu alana ait veriler silinecektir.', 'İptal' + destructive 'Sil' ('Siliniyor...').",
  "priority": "edge",
  "actions": [
   "Sil",
   "İptal"
  ],
  "keyComponents": [
   "AlertDialog"
  ],
  "dataSources": [
   "deleteOrganizationStudentCustomFieldDefinition mutation"
  ],
  "states": [
   "error"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — Overview tab (Contact-360)",
  "route": "/[organizationSlug]/admin/students/[studentId] (?tab=overview, default)",
  "titleTR": "Genel Bakış",
  "purpose": "Primary contact profile: header identity, core student info card (with inline name edit, latest login OTP, tags), and the custom-fields card.",
  "layout": "Header: back arrow + large Avatar + name (or email) + email with mail icon. Tabs bar: Genel Bakış (UserIcon), Kayıtlar (BookOpenIcon +count), Abonelikler (CreditCardIcon +count), Satın Alımlar (ShoppingCartIcon +count). Overview: 'Öğrenci Bilgileri' Card in a 2-col grid — E-posta, Ad Soyad (inline pencil-edit → Ad/Soyad inputs + check/cancel), Kayıt Tarihi, Toplam Harcama, Son Giriş, Son Aktivite, 'Son Giriş Kodu' (OTP code chip + channel badge E-posta/SMS/WhatsApp + Geçerli/Süresi Dolmuş badge + 'Geçerlilik' timestamp), and 'Etiketler' (colored badges + pencil to open Manage Tags, 'Etiket yok'). Below: EditCustomFieldsCard.",
  "priority": "primary",
  "tabs": [
   "Genel Bakış",
   "Kayıtlar",
   "Abonelikler",
   "Satın Alımlar"
  ],
  "actions": [
   "Düzenle (isim)",
   "Etiketleri Yönet"
  ],
  "dialogs": [
   "Etiketleri Yönet dialog"
  ],
  "keyComponents": [
   "Tabs",
   "Card",
   "Avatar",
   "Badge",
   "Input",
   "Button",
   "Tooltip"
  ],
  "dataSources": [
   "StudentDetailPageQuery: node...on OrganizationStudent{ email, givenName, lastName, image(size:200), createdAt, lastSignInAt, lastActivityAt, lifetimeValue{amount,currency}, tags{id,name,color,icon}, enrollments{...}, subscriptions{...}, customFields{value, fieldDefinition{...}}, latestLoginOtp{otp,validUntil,isValid,channel}, orders(first:1){totalCount} }; organization{customStudentFieldDefinitions, viewerMembership{role}}",
   "StudentDetailPageNameMutation → updateOrganizationStudent (givenName/lastName)"
  ],
  "states": [
   "loading",
   "permission-denied"
  ],
  "gating": "Detail visible only to ADMIN/OWNER (viewerMembership.role); otherwise notFound(). Tab state synced to ?tab URL param.",
  "notes": "Tab counts render as secondary badges only when >0. Contact-360 tabs shipped are overview/enrollments/subscriptions/purchases — there is NO timeline/support/email/notes-tasks tab in the current code (src/crm is empty).",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — inline name edit",
  "route": "/[organizationSlug]/admin/students/[studentId] → Overview 'Ad Soyad' pencil",
  "titleTR": "Ad Soyad",
  "purpose": "Edit the student's given/last name inline in the info card.",
  "layout": "Two small inputs (placeholders 'Ad', 'Soyad') + ghost check (save) and X (cancel) icon buttons; disabled while the mutation is in flight. Success toast 'İsim güncellendi'.",
  "priority": "edge",
  "actions": [
   "Kaydet",
   "İptal"
  ],
  "keyComponents": [
   "Input",
   "Button",
   "toast"
  ],
  "dataSources": [
   "updateOrganizationStudent (givenName/lastName partial-update, userErrors)"
  ],
  "states": [
   "error"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — Enrollments tab",
  "route": "/[organizationSlug]/admin/students/[studentId]?tab=enrollments",
  "titleTR": "Kurs Kayıtları",
  "purpose": "List the courses/terms the student is enrolled in, with progress and access-expiry.",
  "layout": "Card 'Kurs Kayıtları' (desc 'Öğrencinin kayıtlı olduğu kurslar ve ilerleme durumu'). Table: Kurs (linked to course admin page) · Dönem · İlerleme (Progress bar + %) · Erişim Bitiş (date or '-'). Empty: 'Henüz kayıtlı kurs bulunmuyor.'",
  "priority": "secondary",
  "tableColumns": [
   "Kurs",
   "Dönem",
   "İlerleme",
   "Erişim Bitiş"
  ],
  "keyComponents": [
   "Card",
   "Table",
   "Progress",
   "Link"
  ],
  "dataSources": [
   "StudentDetailPageQuery enrollments{ createdAt, accessExpiresAt, progress{overallProgress,completedItemsCount,totalItemsCount}, courseAcademicTerm{title,slug,course{title,slug}} }"
  ],
  "states": [
   "empty"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — Subscriptions tab",
  "route": "/[organizationSlug]/admin/students/[studentId]?tab=subscriptions",
  "titleTR": "Aktif Abonelikler",
  "purpose": "Show the student's subscription tiers, status, billing dates, and a link to per-subscription payments.",
  "layout": "Card 'Aktif Abonelikler' (desc 'Öğrencinin mevcut abonelik durumu'). Each subscription = bordered row: tier name + status badge (Aktif/Deneme/Ödeme Gecikmiş/İptal Edildi/Süresi Doldu, color-coded) + optional 'Ömür Boyu' badge; 'Dönem sonunda iptal edilecek' note; 'Dönem Bitiş'/'Sonraki Ödeme' dates; outline button 'Ödemeleri Görüntüle' (CreditCardIcon). Empty: 'Aktif abonelik bulunmuyor.'",
  "priority": "secondary",
  "actions": [
   "Ödemeleri Görüntüle"
  ],
  "dialogs": [
   "Abonelik Ödemeleri sheet"
  ],
  "keyComponents": [
   "Card",
   "Badge",
   "Button"
  ],
  "dataSources": [
   "StudentDetailPageQuery subscriptions{ status, isLifetime, currentPeriodEnd, nextBillingDate, cancelAtPeriodEnd, tier{name}, ...StudentSubscriptionPaymentsSheet_subscription }"
  ],
  "states": [
   "empty"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Subscription payments sheet",
  "route": "/[organizationSlug]/admin/students/[studentId]?tab=subscriptions → 'Ödemeleri Görüntüle'",
  "titleTR": "Ödemeler",
  "purpose": "Side sheet listing a subscription's payment/invoice history with invoice download.",
  "layout": "Sheet 'Ödemeler' (desc 'Abonelik ödemeleri ve fatura geçmişi'): rows of Tutar / Ödenen Tutar / Ödeme Tarihi with a 'Faturayı İndir' action per invoice; empty 'Bu abonelik için ödeme bulunamadı.'",
  "priority": "secondary",
  "actions": [
   "Faturayı İndir"
  ],
  "keyComponents": [
   "Sheet",
   "Table/Cell",
   "Button"
  ],
  "dataSources": [
   "StudentSubscriptionPaymentsSheet_subscription fragment (payments + invoices)"
  ],
  "states": [
   "empty",
   "error"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — Purchases tab",
  "route": "/[organizationSlug]/admin/students/[studentId]?tab=purchases",
  "titleTR": "Satın Alma Geçmişi",
  "purpose": "Self-fetching orders/purchase history for the student (course terms, coaching plans, bundles) with links to each order.",
  "layout": "Card 'Satın Alma Geçmişi' (desc 'Öğrencinin tüm satın alma işlemleri'). Desktop DataTable: Tarih · Ürünler · Tutar · Durum (status badge) · external-link action to /admin/orders/{slug}. Mobile: stacked cards. Empty: 'Henüz satın alma bulunmuyor.'",
  "priority": "secondary",
  "tableColumns": [
   "Tarih",
   "Ürünler",
   "Tutar",
   "Durum",
   "(aç)"
  ],
  "keyComponents": [
   "Card",
   "DataTable",
   "Badge",
   "Link",
   "Skeleton"
  ],
  "dataSources": [
   "StudentPurchasesTabQuery: node...on OrganizationStudent.orders(first:50){ slug, createdAt, status, sellingPrice/paidPrice{presentmentMoney}, lineItems{orderable ...on CourseAcademicTerm/CoachingSessionPlan/Bundle} }"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "notes": "Order status badges: Ödeme Bekleniyor/Tamamlandı/Kısmen İade Edildi/İade Edildi/Başarısız etc. (color-coded).",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — Purchases tab loading / error",
  "route": "/[organizationSlug]/admin/students/[studentId]?tab=purchases (fetch pending/failed)",
  "titleTR": "Satın Alma Geçmişi",
  "purpose": "Localized Suspense skeleton and ErrorBoundary fallback so a purchases fetch failure doesn't crash the detail page.",
  "layout": "Skeleton: card with 4 skeleton rows. Error card: centered 'Satın almalar yüklenemedi. Lütfen sayfayı yenileyin.'",
  "priority": "edge",
  "states": [
   "loading",
   "error"
  ],
  "keyComponents": [
   "Card",
   "Skeleton",
   "ErrorBoundary"
  ],
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — Custom fields card (edit/empty)",
  "route": "/[organizationSlug]/admin/students/[studentId]?tab=overview (EditCustomFieldsCard)",
  "titleTR": "Özel Alanlar",
  "purpose": "View and edit this student's custom-field values inline; admins edit only fields whose editability allows it; owner-only fields are read-only.",
  "layout": "Card 'Özel Alanlar' with a right-aligned 'Düzenle'/'İptal' toggle. Read mode: label + formatted value per definition. Edit mode: per-field CustomFieldInput (typed inputs incl. image upload), 'Salt Okunur' badge + 'Bu alan sadece öğrenci tarafından düzenlenebilir.' for OWNER-only fields; footer 'İptal' + 'Kaydet'/'Kaydediliyor...'. No definitions: dashed empty panel 'Henüz özel alan tanımlanmamış.' + 'Özel Alan Tanımla' (opens the definitions sheet). Unsaved edits guarded by beforeunload + a discard AlertDialog.",
  "priority": "secondary",
  "actions": [
   "Düzenle",
   "Kaydet",
   "İptal",
   "Özel Alan Tanımla"
  ],
  "dialogs": [
   "Kaydedilmemiş değişiklikler AlertDialog",
   "Öğrenci Özel Alanları sheet"
  ],
  "keyComponents": [
   "Card",
   "Form",
   "CustomFieldInput",
   "Badge",
   "Tooltip",
   "AlertDialog"
  ],
  "dataSources": [
   "EditCustomFieldsCardMutation → updateOrganizationStudent (customFields[{fieldDefinitionId,value}], userErrors)"
  ],
  "states": [
   "empty",
   "error"
  ],
  "notes": "Success toast 'Özel alanlar güncellendi'; no-op save 'Değişiklik yapılmadı'.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Student detail — not found / permission denied",
  "route": "/[organizationSlug]/admin/students/[studentId] (non-ADMIN/OWNER or missing student)",
  "titleTR": "Öğrenciler",
  "purpose": "Guard: renders Next.js notFound() when the viewer is not ADMIN/OWNER or the node isn't an OrganizationStudent.",
  "layout": "Standard 404 not-found page (no bespoke UI).",
  "priority": "edge",
  "states": [
   "permission-denied",
   "error"
  ],
  "gating": "viewerMembership.role must be ADMIN or OWNER.",
  "suggestedCanvas": "06-students",
  "cluster": "students"
 },
 {
  "surface": "Coaching sessions list",
  "route": "/[organizationSlug]/admin/courses#meetings (OrganizationCoachingSessions section; cards link to /admin/coaching-sessions/[slug])",
  "titleTR": "Birebir Görüşmeler (rendered inside the Courses page as the \"meetings\" section)",
  "purpose": "Browse/manage all of an org's 1:1 coaching sessions (Birebir Görüşme) as a card grid, filterable by publication status, with a create entry point.",
  "layout": "PublicationStatusFilterTabs (Tümü / Yayında / Taslak / Arşiv with counts + totalCount) over a responsive card grid (sm:2 / lg:3 / xl:4 cols) of VerticalCoachingCard. InfiniteListFooter with 'showingCount' label (\"{total} birebir görüşmeden {loaded} tanesi gösteriliyor\") + load-more; VerticalImageCardSkeleton placeholders while paginating.",
  "states": [
   "loading",
   "empty",
   "populated"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "tabs": [
   "all",
   "published",
   "draft",
   "archived"
  ],
  "filters": [
   "Publication status tabs",
   "tag include/exclude (tagIds/excludeTagIds)",
   "search query"
  ],
  "actions": [
   "Birebir Görüşme Oluştur",
   "Seçili etiket filtresini temizle",
   "Daha Fazla Yükle"
  ],
  "keyComponents": [
   "Tabs",
   "PublicationStatusFilterTabs",
   "VerticalCoachingCard",
   "SectionEmptyState",
   "InfiniteListFooter",
   "VerticalImageCardSkeleton"
  ],
  "dataSources": [
   "OrganizationCoachingSessions_coachingSessions fragment",
   "coachingSessions(first,after,tagIds,excludeTagIds,query,sortBy:{field:OBJECT_INDEX,direction:ASC}) connection",
   "VerticalCoachingCard_coachingSession",
   "fields: id, publishStatus, totalCount"
  ],
  "notes": "Empty-with-filters: 'Filtrelere uygun birebir görüşme bulunamadı.' / tag variant 'İlgili etiket filtresine uygun...'. True-empty (canCreate): SectionEmptyState 'Öğrencilerinizle birebir görüşme randevusu planlayın'. Per-tab-empty: 'Bu kategoride içerik bulunamadı.' Default sort OBJECT_INDEX ASC.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Create coaching session dialog",
  "route": "modal opened from the coaching list empty-state / create button (CreateCoachingSessionDialogContent)",
  "titleTR": "Birebir Görüşme Oluştur",
  "purpose": "Wizard/form to create a new coaching session: name, URL slug, booking mode (in-house vs Calendly), and mode-specific scheduling defaults.",
  "layout": "Dialog with form fields: Birebir Görüşme Adı, Birebir Görüşme Adresi (slug), Randevu Modu (Dahili Sistem / Calendly). In-house: Seans Süresi (Dakika), Toplantı Platformu (Google Meet / Zoom), Tampon Süresi, Minimum Bildirim Süresi (Saat), Maksimum İleri Tarih (Gün). Calendly: Calendly Toplantısı select. Also a multi-step CoachingCreationWizard (DetailsStep, SettingsStep) variant exists.",
  "states": [
   "empty",
   "error",
   "loading"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Oluştur/submit",
   "Calendly toplantılarını yenile"
  ],
  "keyComponents": [
   "Dialog",
   "Form",
   "Select",
   "RadioGroup",
   "Input"
  ],
  "dataSources": [
   "CoachingSession.Create i18n namespace",
   "createCoachingSession mutation"
  ],
  "notes": "Slug validation TR strings (required/tooLong/invalidFormat/reserved/alreadyExists). bookingMode options: 'Dahili Sistem - Teachfluence üzerinden randevu al' / 'Calendly - Harici randevu sistemi kullan'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching session detail — page shell",
  "route": "/[organizationSlug]/admin/coaching-sessions/[slug]",
  "titleTR": "Birebir Düzenle (tab title becomes the session title once loaded)",
  "purpose": "Root detail/editor for one coaching session: publish state, config warnings, tabbed workspace (settings / sessions / instructors / students / orders / recommendations).",
  "layout": "ProductDetailHeader (back 'Birebir görüşmelere dön' → /admin/courses#meetings, PublishStatusBadge, GeneratedPageLinks 'Sayfayı Görüntüle', ProductDetailSearch 'search this page'). Top warning Alerts (payment missing / activate Calendly / configure availability). PublishDraftBanner when DRAFT. Scrollable Tabs: Ayarlar, Seanslar, Eğitmenler(IN_HOUSE only), Danışanlarım, Satışlarım, Öneriler. UnsavedChangesGuard confirm dialog.",
  "states": [
   "loading",
   "not-found",
   "permission-denied",
   "populated"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "tabs": [
   "Ayarlar (settings)",
   "Seanslar (reservations)",
   "Eğitmenler (instructors, IN_HOUSE)",
   "Danışanlarım (students)",
   "Satışlarım (orders)",
   "Öneriler (recommendations)"
  ],
  "actions": [
   "Yayınla (publish draft)",
   "Sayfayı Görüntüle",
   "Ayarları Düzenle (warning CTAs)"
  ],
  "dialogs": [
   "UnsavedChangesConfirmDialog",
   "ProductDetailSearch popover"
  ],
  "keyComponents": [
   "ProductDetailHeader",
   "PublishStatusBadge",
   "PublishDraftBanner",
   "Alert",
   "Tabs/ScrollableTabsList",
   "PageTabsTrigger (locked+lockedLabel for no-edit)",
   "Suspense skeletons"
  ],
  "gating": "Settings & Recommendations tabs locked unless hasResourcePermission('COACHING_SESSION', id, 'COACHING_EDIT'); non-editors on IN_HOUSE still see availability under settings; default tab = settings (editor/in-house) else reservations",
  "dataSources": [
   "AdminCoachingSessionPageQuery",
   "coachingSession(slug,organizationSlug): id,title,publishStatus,bookingMode,tags,customFieldValues,calendlyIntegrationEventType,inHouseAvailabilityRules,generatedPageLinks",
   "organization: calendlyIntegration, paymentMethods{status}",
   "AdminCoachingSessionPagePublishMutation",
   "fragments: CoachingSessionCheckoutSettings/SalesPause/Settings/Pricing/Dangerous_coachingSession"
  ],
  "notes": "Warning alerts: 'Ödeme Bilgilerin Eksik', 'Calendly Entegrasyonunu Aktive Et', 'Müsaitlik Ayarlarını Yapılandır' (each links to settings). Non-editor + non-IN_HOUSE sees locked settings/recommendations (lockedLabel 'Bu bölümü düzenleme erişiminiz yok').",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Settings › General sub-view",
  "route": ".../coaching-sessions/[slug]?tab=settings&settingsView=general",
  "titleTR": "Birebir Görüşme Ayarları",
  "purpose": "Core session configuration: promotional page preview, scheduling/booking settings, availability (in-house), and per-plan sales pause.",
  "layout": "SegmentedViewToggle (Genel / Fiyatlandırma / Etiketler ve Alanlar / Kritik). General: ProductPagePreviewSection + CoachingSessionSettings card (slug, Randevu Modu, Seans Süresi, Tampon Süresi, Toplantı Platformu, Min Bildirim, Max İleri Tarih, iptal süresi, description/order-description toggles, change image) + in-house WeeklyAvailability wrapper + CoachingSessionSalesPause cards (one per plan).",
  "states": [
   "populated",
   "permission-denied",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Ayarları Güncelle",
   "Etkinliği Calendly'de Gör",
   "Entegrasyonu Yapılandır",
   "Birebir görüşme resmini değiştir",
   "Önizleme toggles"
  ],
  "dialogs": [
   "UpdateCoachingSessionDialogContent",
   "UpdateCoachingSessionImageDialog",
   "Calendly event type select"
  ],
  "keyComponents": [
   "SegmentedViewToggle",
   "Card",
   "Switch",
   "ProductPagePreviewSection",
   "OrderableSalesPauseCard"
  ],
  "dataSources": [
   "CoachingSessionSettings_coachingSession",
   "CoachingSessionSalesPause_coachingSession (plans showDraft/showHidden)",
   "OrderableSalesPauseCard_orderable"
  ],
  "notes": "Config-warning cards inside: 'Eksik Randevu Yapılandırması', 'Google Takvim Bağlı Değil', 'Zoom Bağlı Değil'. bookingModeInHouse label 'Dahili Sistem'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Settings › Pricing sub-view",
  "route": ".../coaching-sessions/[slug]?tab=settings&settingsView=pricing",
  "titleTR": "Fiyatlandırma",
  "purpose": "Manage per-plan pricing (session credits, price, tax, visibility, active) and checkout settings.",
  "layout": "CoachingSessionPricing list of plan cards (each: {count} Randevu Hakkı, price, %{percent} indirim, %{rate} KDV, Aktif/Taslak/Özel badges, durationMinutes '{d} dk', bufferMinutes '{b} dk tampon', 'Sipariş Linkini Kopyala', 'Güncelle') + empty state 'Henüz fiyatlandırma eklenmedi...' + 'Yeni Fiyatlandırma Ekle'. Below: CoachingSessionCheckoutSettings.",
  "states": [
   "empty",
   "populated",
   "loading"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Yeni Fiyatlandırma Ekle",
   "Güncelle",
   "Sipariş Linkini Kopyala"
  ],
  "dialogs": [
   "SetCoachingSessionPlanPricingDialogContent (Fiyatı Güncelle: Seans Sayısı, Para Birimi, Satış Fiyatı, Orijinal Fiyat, Vergi Yüzdesi, Seans Süresi, Tampon Süresi, Gizli, Aktif)"
  ],
  "keyComponents": [
   "Card",
   "Badge",
   "Dialog",
   "Form"
  ],
  "dataSources": [
   "CoachingSessionPricing_coachingSession"
  ],
  "notes": "Private badge 'Özel (Sadece Sipariş Linki ile Alınabilir)'. Tax field can be locked by billing config.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Settings › Tags & Fields sub-view",
  "route": ".../coaching-sessions/[slug]?tab=settings&settingsView=tagsFields",
  "titleTR": "Etiketler",
  "purpose": "Assign organization tags and edit tag-scoped custom field values for the session.",
  "layout": "Card 'Etiketler' with EntityTagsManager + EntityCustomFieldsCard (custom field values gated by tagScopes/visibility).",
  "states": [
   "populated",
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "Card",
   "EntityTagsManager",
   "EntityCustomFieldsCard"
  ],
  "dataSources": [
   "coachingSession.tags{id,name,color,icon}",
   "customFieldValues{value,fieldDefinition{title,validationSchema,visibility,tagScopes}}",
   "useOrganizationTags_organization"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Settings › Danger (Kritik) sub-view + delete dialog",
  "route": ".../coaching-sessions/[slug]?tab=settings&settingsView=danger",
  "titleTR": "Bu birebir görüşmeyi sil",
  "purpose": "Destructive zone to permanently delete the coaching session.",
  "layout": "Destructive-bordered card: 'Bu birebir görüşmeyi sil' + description 'Birebir görüşmeyi sildiğinizde tüm ilişkili veriler silinecektir. Bu işlem geri alınamaz.' + 'Birebir Görüşmeyi Sil' button → DeleteCoachingSessionDialogContent (type-to-confirm 'Bu birebir görüşmeyi silmek istediğimi kabul ediyorum').",
  "states": [
   "populated",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Birebir Görüşmeyi Sil"
  ],
  "dialogs": [
   "DeleteCoachingSessionDialogContent (confirm-by-typing)"
  ],
  "keyComponents": [
   "Dialog",
   "Input confirm",
   "Button destructive"
  ],
  "dataSources": [
   "DangerousCoachingSessionSettings_coachingSession{id,title}",
   "deleteCoachingSession mutation"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Availability editor (in-house)",
  "route": ".../coaching-sessions/[slug]?tab=settings (IN_HOUSE) or availability card",
  "titleTR": "Müsaitliği Düzenle",
  "purpose": "Set weekly availability rules and date-specific overrides for in-house booking.",
  "layout": "CoachingSessionAvailability: WeeklyAvailabilityEditor + WeeklyCalendarPreview + AvailabilityOverridesEditor. When bookingMode != IN_HOUSE shows unavailable notice 'Müsaitlik Ayarları Kullanılamıyor' / description to switch to 'Dahili Sistem'.",
  "states": [
   "populated",
   "permission-denied",
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Müsaitliği Düzenle",
   "Kapat"
  ],
  "keyComponents": [
   "WeeklyAvailabilityEditor",
   "WeeklyCalendarPreview",
   "AvailabilityOverridesEditor"
  ],
  "dataSources": [
   "inHouseAvailabilityRules{dayOfWeek}",
   "AvailabilityOverridesEditor i18n"
  ],
  "notes": "Shown to non-editors too when bookingMode IN_HOUSE (read-only-ish). Config warning if no availability rules. Non-in-house shows unavailable-notice.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Sessions/Reservations tab",
  "route": ".../coaching-sessions/[slug]?tab=reservations (resView=table|calendar)",
  "titleTR": "Seanslar",
  "purpose": "View and manage upcoming/past reservations for the session in table or calendar form.",
  "layout": "ReservationsToolbar (öğrenci ara, tarih aralığı, Durum filter, Sıfırla). Tabs: Tablo / Takvim. Table columns; Calendar = ReservationsCalendarView + ReservationsDayDetail. Content skeleton (calendar grid) during load.",
  "states": [
   "loading",
   "empty",
   "populated"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "tabs": [
   "Tablo (table)",
   "Takvim (calendar)"
  ],
  "filters": [
   "Öğrenci ara...",
   "Tarih aralığı (date range)",
   "Durum (RESERVED/COMPLETED/CANCELED_BY_USER/CANCELED_BY_ORGANIZATION)"
  ],
  "tableColumns": [
   "Öğrenci (STUDENT_SINGULAR)",
   "Email",
   "Başlangıç Zamanı",
   "Bitiş Zamanı",
   "Plan",
   "Durum",
   "Link",
   "(actions)"
  ],
  "actions": [
   "Görüşme Linki Ekle",
   "Seansa Git",
   "Zoom Toplantısını Başlat",
   "Sıfırla"
  ],
  "dialogs": [
   "UpdateCoachingSessionReservationDialogContent (add/edit meeting link)",
   "row-actions kebab (reschedule/cancel/update)"
  ],
  "keyComponents": [
   "Tabs",
   "DataTable",
   "Badge (status)",
   "Calendar",
   "Avatar",
   "StartZoomMeetingButton"
  ],
  "dataSources": [
   "CoachingSessionUpcomingReservationsQuery",
   "useReservations_coachingSession (reservations connection)",
   "fields: student, startDate, endDate, coachingSessionPlan.name, status, url, zoomMeetingId"
  ],
  "notes": "Default status filter ['RESERVED'], default range from today. Status badge variants via getReservationStatusBadgeVariant. Empty-day: 'Bu gün için rezervasyon yok.'",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Instructors tab (in-house)",
  "route": ".../coaching-sessions/[slug]?tab=instructors (IN_HOUSE only)",
  "titleTR": "Eğitmenler",
  "purpose": "Manage instructors assigned to an in-house session and their Google Calendar connections.",
  "layout": "Header 'Eğitmenler' + 'Bu seansa atanmış eğitmenleri yönetin.' + 'Eğitmen Ekle'. List of instructors (Görünen Ad, Biyografi, Aktif/Pasif, Google Takvim status). Empty: 'Henüz eğitmen eklenmemiş.'",
  "states": [
   "empty",
   "populated",
   "loading"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Eğitmen Ekle",
   "Eğitmeni Düzenle",
   "Eğitmeni Kaldır",
   "Takvimimi Bağla",
   "Takvim Bağlantısını Kaldır"
  ],
  "dialogs": [
   "AddInstructorDialog (Üye seç, Görünen Ad, Biyografi)",
   "EditInstructorDialog",
   "RemoveInstructorDialog (confirm)",
   "DisconnectCalendarDialog (Google Takvim Bağlantısını Kaldır)"
  ],
  "keyComponents": [
   "Card",
   "Dialog",
   "Combobox (member select)",
   "GoogleCalendarIcon",
   "Switch (active)"
  ],
  "dataSources": [
   "CoachingSessionInstructors query",
   "instructor add/update/remove mutations",
   "Google Calendar connect/disconnect"
  ],
  "notes": "Calendar states: 'Google Takvim Bağlı' / 'Google Takvim bağlı değil' / 'Takvim bağlı (izinler eksik)'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Students tab",
  "route": ".../coaching-sessions/[slug]?tab=students (view=enrolled|invitations)",
  "titleTR": "Danışanlarım (tab) / Kayıtlılar & Davetler (sub-views)",
  "purpose": "Manage enrolled students (with remaining session credits) and pending invitations for the session.",
  "layout": "SegmentedViewToggle: Kayıtlılar (UsersIcon) / Davetler (MailIcon). Enrolled = StudentsDataTable; Invitations = InvitationsDataTable. Invite dialog reachable.",
  "states": [
   "loading",
   "empty",
   "populated",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "tabs": [
   "Kayıtlılar (enrolled)",
   "Davetler (invitations)"
  ],
  "actions": [
   "Öğrenci Davet Et",
   "Doğrudan Kayıt / Öğrenciyi Kaydet",
   "Kalan Görüşme Hakkını Güncelle"
  ],
  "dialogs": [
   "InviteCoachingSessionStudentDialogContent (Email; Doğrudan Kayıt toggle)",
   "UpdateCoachingSessionStudentDialogContent (update remaining sessions)"
  ],
  "tableColumns": [
   "(enrolled) Öğrenci, Email, Kalan Görüşme Hakkı, Toplam Görüşme Hakkı, İlk Satın Alma Tarihi, (actions)",
   "(invitations) Email, Durum, Davet Tarihi, Davet Eden, (actions)"
  ],
  "keyComponents": [
   "SegmentedViewToggle",
   "DataTable",
   "Dialog",
   "Badge (InvitationStatus)"
  ],
  "dataSources": [
   "CoachingSessionStudentsQuery",
   "studentInvitations{status,email,createdAt,acceptedAt,canceledAt,expiresAt,user,invitedBy}",
   "dataTableCoachingSessionStudents fragment"
  ],
  "notes": "Invitation status TR: Beklemede/Kabul Edildi/İptal Edildi/Süresi Doldu. loadError 'Öğrenciler yüklenemedi...'. UpdateRemaining dialog title '\"{email}\" Üyesinin Kalan Görüşme Hakkını Güncelle'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Orders tab",
  "route": ".../coaching-sessions/[slug]?tab=orders",
  "titleTR": "Satışlarım",
  "purpose": "View order line items (sales) for the coaching session with earnings breakdown.",
  "layout": "OrdersTable (data-table) with skeleton (OrdersTableSkeleton, ~10 cols) during load.",
  "states": [
   "loading",
   "empty",
   "populated"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "tableColumns": [
   "Tarih",
   "Öğrenci",
   "Email",
   "Durum",
   "Seans Sayısı",
   "Satış Fiyatı",
   "Ödenen Fiyat",
   "Ödeme Sağlayıcı Komisyonu",
   "Teachfluence Komisyonu",
   "Net Kazanç"
  ],
  "keyComponents": [
   "DataTable",
   "Avatar",
   "Tooltip (paidPrice/netPrice explainers)",
   "Badge (OrderStatus)"
  ],
  "dataSources": [
   "CoachingSessionOrders / dataTableCoachingSessionOrders (orderLineItems connection)",
   "OrderStatus enum labels"
  ],
  "notes": "Tooltips explain paid vs net earnings; net earnings tooltip carries a 'Detaylı bilgi için incele.' link.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Coaching detail — Recommendations tab",
  "route": ".../coaching-sessions/[slug]?tab=recommendations (edit-gated)",
  "titleTR": "Öneriler",
  "purpose": "Configure recommended/related orderables surfaced on the coaching session page.",
  "layout": "CoachingSessionRecommendations editor (only rendered when canEditCoaching).",
  "states": [
   "loading",
   "populated",
   "permission-denied"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "Suspense",
   "AdminContentSkeleton"
  ],
  "dataSources": [
   "CoachingSessionRecommendations (orderable-recommendations)"
  ],
  "notes": "Tab is locked/hidden for non-editors.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Organization Settings — page shell",
  "route": "/[organizationSlug]/admin/settings (?tab=&section=)",
  "titleTR": "Ayarlar",
  "purpose": "Root org settings workspace: permission-filtered top-level tabs, each with URL-synced sub-tabs, plus ⌘K search, guided tour, and help menu.",
  "layout": "Heading 'Ayarlar' + AdminHelpMenu + SettingsSearch (⌘K). ScrollableTabsList of visible tabs. Each tab renders SectionedTabContent (secondary chip sub-tab row) or a full component. TourProvider onboarding. UnsavedChangesConfirmDialog on tab/section switch.",
  "states": [
   "loading",
   "permission-denied",
   "populated"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "tabs": [
   "Organizasyon",
   "Tema",
   "Ekip",
   "İçerik Ayarları",
   "Yerelleştirme",
   "Ödeme",
   "Aboneliğim",
   "Entegrasyonlar",
   "Bildirimler",
   "Özel Alanlar",
   "Yasal Belgeler",
   "xAPI"
  ],
  "filters": [
   "SettingsSearch (tab/section jump with keyword synonyms)"
  ],
  "actions": [
   "Ayarlar arama (⌘K)",
   "Yardım menüsü / tur"
  ],
  "gating": "Each tab gated by hasAnyOrgPermission(tab.permissions) (ORG_SETTINGS_VIEW/EDIT, ORG_WEBSITE_VIEW, ORG_MEMBERS_VIEW, ORG_BILLING_VIEW, ORG_CUSTOM_FIELDS_VIEW, ORG_LEGAL_DOCUMENTS_VIEW); sub-sections gated individually; no visible tabs → NoAccessMessage",
  "dialogs": [
   "SettingsSearch command palette",
   "UnsavedChangesConfirmDialog",
   "AdminHelpMenu / TourProvider steps"
  ],
  "keyComponents": [
   "Tabs/ScrollableTabsList",
   "SectionedTabContent (chip sub-tabs)",
   "SettingsSearch",
   "TourProvider",
   "Badge (counts)",
   "AdminHelpMenu"
  ],
  "dataSources": [
   "SettingsPageQuery (organization) with ~20 spread fragments incl OrganizationMembers, OrganizationMemberInvitations, OrganizationRoles, OrganizationSettings, Payment/Subscription/Theme/Website/Localization/Legal etc.",
   "members{role,isPublic}",
   "memberInvitations{acceptedAt,canceledAt}"
  ],
  "notes": "Tab aliases + legacy redirects (roles→members#roles, website→organization#website, ui/videoWatermark/attachmentWatermark→content, checkoutFields→payment, lrsCredentials→xapi). Section labels: Organizasyon Ayarları/Websitesi Ayarları/Üyeler/Davetler/Roller/Ödeme Ayarları/Fatura ve İletişim Alanları etc. Many tabs (payment/subscription/theme/integrations/content/notifications/localization/legal/customFields/xapi) belong to other clusters — this record documents the shared shell + members/roles which are in-cluster.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — loading skeleton",
  "route": "/[organizationSlug]/admin/settings (Suspense fallback)",
  "titleTR": "Ayarlar (skeleton)",
  "purpose": "Loading placeholder for the settings page while the Relay query resolves.",
  "layout": "SettingsPageSkeleton: title Skeleton bar, wide tab-bar Skeleton, three text-line Skeletons.",
  "states": [
   "loading"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "Skeleton"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — no-access state",
  "route": "/[organizationSlug]/admin/settings (visibleTabs.length === 0)",
  "titleTR": "Ayarlar",
  "purpose": "Shown when the viewer has no permission for any settings tab.",
  "layout": "NoAccessMessage (section='Ayarlar').",
  "states": [
   "permission-denied"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "NoAccessMessage"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — Members (Ekip) section",
  "route": "/[organizationSlug]/admin/settings?tab=members&section=members",
  "titleTR": "Ekip Ayarları",
  "purpose": "Team roster management: view/sort members, edit tags, manage custom field definitions, invite, reorder.",
  "layout": "TeamSummaryCards (Toplam üye / Bekleyen davet / Görünür / Gizli, with per-role count chips). Header 'Ekip Ayarları' + description + 'Sıralamayı Düzenle'. MembersDataTable with toolbar (email search, role filter, invite, custom-fields button).",
  "states": [
   "empty",
   "populated"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "filters": [
   "Email ile ara...",
   "Role filter (Sahip/Yönetici/Üye/Eğitmen)"
  ],
  "tableColumns": [
   "Ad (givenName)",
   "Soyad (lastName)",
   "Email",
   "Rol",
   "Etiketler",
   "Profil Görünürlüğü (Herkese Açık/Gizli)",
   "Oluşturulma (createdAt, relative)",
   "(actions: view details, kebab)"
  ],
  "actions": [
   "Ekip Üyesi Davet Et",
   "Sıralamayı Düzenle",
   "Özel Alan Tanımları",
   "row: Üye detayına git, Etiketleri Düzenle, Özel alan değerleri, Rol güncelle, Üyeyi Kaldır"
  ],
  "dialogs": [
   "InviteOrganizationMemberDialogContent",
   "ManageMemberTagsDialogContent",
   "MemberCustomFieldDefinitionsSheet",
   "ReorderMembersSheet",
   "UpdateOrganizationMemberDialogContent",
   "RemoveOrganizationMemberDialogContent",
   "EditMemberCustomFieldValuesDialogContent"
  ],
  "gating": "Edit actions (invite/reorder/tags) require ORG_MEMBERS_EDIT; view requires ORG_MEMBERS_VIEW",
  "keyComponents": [
   "TeamSummaryCards",
   "DataTable",
   "Badge",
   "Dialog",
   "Sheet",
   "TableHeaderActionsMenu"
  ],
  "dataSources": [
   "OrganizationMembers fragment",
   "members{id,role,createdAt,isPublic,tags,customFields,givenName,lastName,image,member{email}}",
   "customMemberFieldDefinitions",
   "tags connection"
  ],
  "notes": "Deleted member email shows 'deletedUser'. isPublic badge Herkese Açık/Gizli. Default member sort OBJECT_INDEX ASC.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — Invite member dialog",
  "route": "modal from Members / Invitations section",
  "titleTR": "Ekip Üyesi Davet Et",
  "purpose": "Invite a new team member by email with a role.",
  "layout": "Dialog with email input + role select; submit sends invitation.",
  "states": [
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Davet gönder"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "Select (role)"
  ],
  "dataSources": [
   "InviteOrganizationMemberDialogContent_organization"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — Member Invitations (Davetler) section",
  "route": "/[organizationSlug]/admin/settings?tab=members&section=invitations",
  "titleTR": "Davetler",
  "purpose": "List and manage pending/accepted/canceled team member invitations.",
  "layout": "InvitationsDataTable (with invite toolbar button) or empty state: MailPlus icon + 'Henüz bekleyen davet yok' + 'Ekibine yeni üyeler davet ederek başla.' + 'Ekip Üyesi Davet Et'.",
  "states": [
   "empty",
   "populated"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "tableColumns": [
   "Email",
   "Rol",
   "Durum (Beklemede/Kabul Edildi/İptal Edildi/Süresi Doldu)",
   "Davet Tarihi",
   "(actions: cancel/resend)"
  ],
  "actions": [
   "Ekip Üyesi Davet Et",
   "Daveti iptal et"
  ],
  "dialogs": [
   "InviteOrganizationMemberDialogContent"
  ],
  "keyComponents": [
   "DataTable",
   "Badge (InvitationStatus)",
   "EmptyState"
  ],
  "dataSources": [
   "OrganizationMemberInvitations_organization",
   "memberInvitations{status,role,email,createdAt,acceptedAt,canceledAt,expiresAt,user}"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — Roles section",
  "route": "/[organizationSlug]/admin/settings?tab=members&section=roles",
  "titleTR": "Roller",
  "purpose": "Create/manage custom RBAC roles with granular permission scopes for org members.",
  "layout": "Header 'Roller' + 'Organizasyon üyeleriniz için ayrıntılı izinlere sahip özel roller oluşturun ve yönetin.' + 'Rol Oluştur'. Grid of role cards (color dot, name, description, '{count} izin'). Empty: ShieldCheck + 'Henüz rol yok' + 'Organizasyon üyelerinizin izinlerini yönetmek için özel roller oluşturun.'",
  "states": [
   "empty",
   "populated",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Rol Oluştur",
   "Rolü Düzenle",
   "Rolü Sil"
  ],
  "dialogs": [
   "CreateRoleDialog",
   "EditRoleDialog",
   "DeleteRoleDialog"
  ],
  "gating": "Read requires ORG_MEMBERS_VIEW (else NoAccessMessage 'Rol Yönetimi İzniniz Yok'); edit requires ORG_MEMBERS_EDIT",
  "keyComponents": [
   "Card",
   "Button",
   "Dialog",
   "ShieldCheck empty icon"
  ],
  "dataSources": [
   "OrganizationRoles_organization",
   "roles{id,name,description,color,permissions,createdAt,updatedAt}"
  ],
  "notes": "permissionCount plural '# izin'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — Create/Edit Role dialog",
  "route": "modal from Roles section",
  "titleTR": "Rol Oluştur / Rolü Düzenle",
  "purpose": "Define a role's name, description, color, and permission scopes.",
  "layout": "Dialog form: Ad (namePlaceholder 'ör. İçerik Yöneticisi'), Açıklama, Renk (ColorPickerField, hex; Renk Seç/Temizle), İzinler grid via PermissionScopeSelector (grouped permissionGroups; Tümünü Seç / Tümünü Kaldır). Save 'Kaydet' / İptal.",
  "states": [
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Kaydet",
   "İptal",
   "Tümünü Seç",
   "Tümünü Kaldır"
  ],
  "keyComponents": [
   "Dialog",
   "Input",
   "Textarea",
   "ColorPickerField",
   "PermissionScopeSelector (checkbox groups)"
  ],
  "dataSources": [
   "createOrganizationRole / updateOrganizationRole mutations",
   "useRoleFormSchema",
   "permissionGroups"
  ],
  "notes": "Validation TR: nameRequired/nameMaxLength(100), descriptionMaxLength(500), colorFormatError, permissionsRequiredError.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Settings — Delete Role dialog",
  "route": "modal from Roles section",
  "titleTR": "Rolü Sil",
  "purpose": "Confirm destructive deletion of a custom role.",
  "layout": "AlertDialog: '\"{name}\" rolünü silmek istediğinizden emin misiniz? Bu role sahip üyeler ilgili izinlerini kaybedecektir.' + Sil/İptal.",
  "states": [
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Sil",
   "İptal"
  ],
  "keyComponents": [
   "AlertDialog"
  ],
  "dataSources": [
   "deleteOrganizationRole mutation"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Member detail page",
  "route": "/[organizationSlug]/admin/settings/members/[memberId]",
  "titleTR": "Üye Detayları (title = member name)",
  "purpose": "Full profile of one org member: identity, org-specific profile overrides, description, custom fields, and role assignments.",
  "layout": "Header (back arrow to members list [edit-only], Avatar, name, email, GeneratedPageLinks). Cards: 'Üye Bilgileri' (Email, Rol badge, Unvan[inline edit], Slug[inline edit], Oluşturulma, Profil Görünürlüğü switch, Etiketler, Biyografi[inline]). 'Bu organizasyona özel profil' overrides (Görüntülenen Ad, Soyad, görsel override w/ original). MemberDescriptionCard. MemberCustomFieldsCard. MemberRoleAssignmentsCard.",
  "states": [
   "loading",
   "not-found",
   "populated",
   "permission-denied"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Kaydet/inline edit fields",
   "Profil görünürlüğü toggle",
   "Etiketleri Düzenle",
   "Rol Ata",
   "Görseli değiştir/kaldır (removeOverride)"
  ],
  "dialogs": [
   "ManageMemberTagsDialogContent",
   "AssignRoleDialog",
   "RevokeRoleAssignmentDialog",
   "ImageUploader"
  ],
  "gating": "canEdit = ORG_MEMBERS_EDIT OR own profile (viewerMembership.id === member.id); back button + isPublic switch require ORG_MEMBERS_EDIT",
  "keyComponents": [
   "Card",
   "InlineEditField",
   "Switch",
   "Badge",
   "Avatar",
   "Textarea",
   "ImageUploader",
   "MemberRoleAssignmentsCard"
  ],
  "dataSources": [
   "MemberDetailPageQuery (node → OrganizationMember)",
   "member{role,slug,title,bio,givenName,lastName,image,description,isPublic,tags,member{email,image},customFields}",
   "organization{roles,tags,customMemberFieldDefinitions}",
   "MemberDetailPageIsPublicMutation",
   "MemberRoleAssignmentsCard_member"
  ],
  "notes": "Not-found → Alert 'Üye Bulunamadı' + back. Override hints show 'originalValue'. Role assignments: org-wide vs resource-scoped, Geçerli İzinler summary. Section title 'Bu organizasyona özel profil'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Member — Reorder members sheet",
  "route": "sheet from Members section",
  "titleTR": "Sıralamayı Düzenle",
  "purpose": "Drag-and-drop reorder of team member display order.",
  "layout": "Sheet: 'Ekip üyelerinin görüntülenme sıralamasını değiştirin.' + 'Sıralamayı değiştirmek için sürükleyin.' draggable list.",
  "states": [
   "populated",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "Sheet",
   "Drag-and-drop list"
  ],
  "dataSources": [
   "ReorderMembersSheet (reorder mutation)"
  ],
  "notes": "reorderError 'Sıralama güncellenemedi'.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Member — Custom field definitions sheet",
  "route": "sheet from Members section",
  "titleTR": "Ekip Üyesi Özel Alanları",
  "purpose": "Master/detail manager to define custom fields shown on member profiles.",
  "layout": "Sheet with tabs 'Mevcut Alanlar ({count})' / 'Alan Ekle'. Form: Alan Adı, Alan Türü, Görünürlük (PUBLIC/PRIVATE/HIDDEN), Düzenleme Yetkisi (OWNER/ORGANIZATION_ADMINS/OWNER_AND_ORGANIZATION_ADMINS). List + reorder + delete.",
  "states": [
   "empty",
   "populated",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Kaydet",
   "Alanı Düzenle",
   "Alanı Sil"
  ],
  "dialogs": [
   "DeleteMemberFieldDefinitionDialog"
  ],
  "keyComponents": [
   "Sheet",
   "Tabs",
   "MemberCustomFieldFormPanel",
   "Select"
  ],
  "dataSources": [
   "customMemberFieldDefinitions",
   "field create/update/delete/reorder mutations"
  ],
  "notes": "Empty 'Henüz özel alan tanımlanmamış'. Delete warns all member data for the field is removed.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Profile Page editor (Profil Kartım)",
  "route": "/[organizationSlug]/admin/profile-page",
  "titleTR": "Profil Kartım",
  "purpose": "Visual editor for the org's public profile/landing card (banner, avatar, bio, metrics, CTA, social links, product sections) that serves as the site homepage.",
  "layout": "ProfileEditorLayout: live preview (Masaüstü/Tablet/Mobil), Önizleme/Düzenleme toggle, side controls for Kapak Görseli (Gradyan/Görsel), Profil Fotoğrafı, İsim, Başlık, Açıklama, Metrikler (Öğrenci/Kurs/Görüşme), Aksiyon Butonu, Sosyal Medya Bağlantıları, and product section toggles (Kurslar/Görüşmeler/Dijital Ürünler/Webinarlar/Paketler). Save/Yayınla/Yayından Kaldır/Sayfayı Sil. Draft-recovery AlertDialog. Conflict banner when a custom root page overrides it.",
  "states": [
   "loading",
   "empty",
   "populated",
   "permission-denied",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "07-coaching-settings",
  "actions": [
   "Kaydet",
   "Yayınla",
   "Yayından Kaldır",
   "Sayfayı Sil",
   "Gelişmiş Düzenleyici",
   "Sayfayı Görüntüle",
   "Bağlantı Ekle"
  ],
  "dialogs": [
   "Draft-found AlertDialog (Geri Yükle/Sil)",
   "Unpublish confirm 'Tanıtım Sayfasını Yayından Kaldır'",
   "Delete confirm 'Tanıtım Sayfasını Sil'",
   "SEO settings"
  ],
  "gating": "Requires ORG_WEBSITE_VIEW (else NoAccessMessage)",
  "keyComponents": [
   "ProfileEditorLayout",
   "AlertDialog",
   "ImageUploader",
   "Preview iframe",
   "Toggle/Switch",
   "ErrorBoundary"
  ],
  "dataSources": [
   "ProfilePageEditorQuery",
   "organization{name,slug,image,webPages(path),websiteSettings{customDomain,faviconUrl},activeWebPage(path:'')}",
   "ProfileEditorLayout_organization",
   "SEOWebPage_webPage",
   "update/publish/unpublish/delete web page mutations"
  ],
  "notes": "profilePageInfo explains it is the homepage on the custom domain. contentParseError toast on invalid stored content; unsaved-changes beforeunload guard; local draft autosave with recovery. conflictBanner when a custom Web Sitelerim page overrides the homepage.",
  "cluster": "coaching-settings"
 },
 {
  "surface": "Profile Page — onboarding",
  "route": "/[organizationSlug]/admin/profile-page (no profile page yet)",
  "titleTR": "Profil Kartım (onboarding)",
  "purpose": "First-run experience prompting the admin to create their profile card, with a skip-to-editor option.",
  "layout": "ProfileOnboarding intro/CTA with org avatar/name; 'skip to editor' path.",
  "states": [
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "ProfileOnboarding"
  ],
  "dataSources": [
   "organization{id,image,name,slug}"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Profile Page — editor error fallback",
  "route": "/[organizationSlug]/admin/profile-page (ErrorBoundary)",
  "titleTR": "Profil Kartım",
  "purpose": "Fallback when the profile editor crashes.",
  "layout": "Centered destructive message (editorError).",
  "states": [
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "07-coaching-settings",
  "keyComponents": [
   "ErrorBoundary"
  ],
  "cluster": "coaching-settings"
 },
 {
  "surface": "Web Pages list (Sayfalarım)",
  "route": "/[organizationSlug]/admin/web-pages?tab=pages",
  "titleTR": "Sayfalarım",
  "purpose": "Full-width website page manager: browse, search, filter, create, publish/unpublish/clone/delete every custom web page of the org website.",
  "layout": "Full-bleed page (own scroll container, virtualized). PageHeader 'Sayfalarım' + subtitle 'Web sitenizi oluşturun, düzenleyin ve yayınlayın.' with AdminHelpMenu '?'. Outer Tabs: 'Web Sayfaları' | 'Ürün Sayfaları'. Filter bar row: AdminSearchInput ('Sayfa adı veya URL ile ara...'), 'Filtrele' popover button with active-count badge, spacer, 'Tema Ayarları' link button (Palette icon), 'Yeni Sayfa Oluştur' primary button (PlusCircled). Body = virtualized responsive grid (1/2/3 cols) of WebPageAdminCard, each preceded by a page-type icon + mono normalizedPath (or 'Ana Sayfa').",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "tabs": [
   "Web Sayfaları",
   "Ürün Sayfaları"
  ],
  "filters": [
   "Search by name/URL",
   "Status: Tümü / Yayında / Taslak",
   "Page type: Tümü / Ana Sayfa / Blog / Hakkımızda / İletişim / Profil / Diğer"
  ],
  "actions": [
   "Yeni Sayfa Oluştur",
   "Tema Ayarları",
   "Filtrele"
  ],
  "dialogs": [
   "Filter popover (two radiogroup columns: Durum + Sayfa Türü, each with per-bucket counts and 'Filtreleri sıfırla')",
   "WebPageAdminCard row menu: Görüntüle / Yönet / Kopyasını Oluştur / Yayınla / Yayından Kaldır / Sil",
   "Publish confirm ('...sayfasını yayına almak istediğine emin misin?', 'Evet, Yayına Al')",
   "Unpublish confirm ('...Yayından Kaldırmak İstediğine Emin Misin?')",
   "Delete confirm ('...Silmek İstediğine Emin Misin?', geri alınamaz)",
   "Clone dialog ('Web Sayfasını Kopyala': Başlık, Web Sayfası Adresi, 'Ana sayfa için boş bırakın')"
  ],
  "keyComponents": [
   "Tabs",
   "Popover",
   "Badge",
   "AdminSearchInput",
   "Button",
   "useVirtualizer grid",
   "WebPageAdminCard",
   "DropdownMenu",
   "AlertDialog"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_WEBSITE_VIEW to view (NoAccessMessage otherwise); create/publish/clone/delete + Tema Ayarları gated on ORG_WEBSITE_MANAGE",
  "dataSources": [
   "WebPagesPageQuery: organization.webPages{id,normalizedPath,slug,title,root,isActive, ...WebPageAdminCard_webPage}, websiteSettings{rootData, customDomain{domain,verificationStatus}}"
  ],
  "notes": "Empty variants use distinct copy: no pages ('noPages'/'noPagesDescription') vs no search match ('noMatchingPages') vs no filter results ('noFilterResults'). Default sort: home-first then by path (backend order preserved).",
  "cluster": "web-cms"
 },
 {
  "surface": "Web Pages — first-run / add-page Onboarding wizard",
  "route": "/[organizationSlug]/admin/web-pages?tab=pages (inline when no non-profile pages, or 'Yeni Sayfa Oluştur')",
  "titleTR": "Web Sitenizi Oluşturun",
  "purpose": "Guided multi-step wizard to bootstrap the whole website or add a page — choose AI vs manual/template method, then site type, style, colors, content, details, summary.",
  "layout": "Stepper wizard replacing the list body. Stepper labels: Hoş Geldiniz · Site Türü · Stil · Tema · İçerik · Detaylar · Tamamla (plus Oluşturma Yöntemi / Şablon Seçimi). Welcome screen with 3 feature cards ('Kolay Tasarım','Hızlı Kurulum','AI Destekli') + 'Başlayalım'. Method selection: 'AI ile Oluştur' vs 'Manuel Oluştur' cards. Add-page mode ('Yeni Sayfa Ekle') shows 'AI ile Oluştur' vs 'Boş veya Şablon', with 'Zaten var' badges on existing paths. Navigation footer: Geri / Devam Et / Atla / Sayfalara Dön.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "tabs": [
   "Site Türü (Portfolyo/İş-Kurumsal/Blog/Link-in-Bio/Eğitim/Abonelik)",
   "Stil (Modern/Yaratıcı/Profesyonel/Zarif/Eğlenceli/Minimal)",
   "Tema (color presets)"
  ],
  "actions": [
   "Başlayalım",
   "Devam Et",
   "Geri",
   "Atla",
   "AI ile Başla",
   "Manuel olarak devam et"
  ],
  "dialogs": [
   "Template picker dialog ('Sayfa Oluştur': AI ile Site Oluştur card + 'veya şablon seç' grid, 'Bu Şablonu Kullan','Şablonsuz devam et')"
  ],
  "keyComponents": [
   "Stepper",
   "Card grid",
   "ColorPreset swatches",
   "Button",
   "OnboardingWizard"
  ],
  "states": [
   "loading",
   "empty"
  ],
  "gating": "ORG_WEBSITE_MANAGE",
  "dataSources": [
   "Local template kits + backend site/page templates (Templates.* messages)"
  ],
  "notes": "mode='firstRun' when org has zero non-profile pages; mode='addPage' otherwise. Template selection has tabs Sayfa / Site / Kit and kit-creation progress ('{current}/{total} sayfa oluşturuluyor').",
  "cluster": "web-cms"
 },
 {
  "surface": "AI Website Generator (AI ile Site Oluştur)",
  "route": "/[organizationSlug]/admin/web-pages (opened from wizard 'AI ile Başla' / 'AI ile Web Sitesi Oluştur')",
  "titleTR": "AI ile Site Oluştur",
  "purpose": "Long AI intake form that generates an entire website from user-provided identity, brand, reference site and free-text vision; then preview/regenerate/accept-and-edit.",
  "layout": "Scrolling form with numbered sections: 1. Temel Bilgiler (Ad, Meslek), 2. Kendinizi Tanıtın (Hakkınızda, Profil Fotoğrafı upload, CV/Özgeçmiş PDF upload), 3. Site Stratejisi (Site Tipi cards, Marka Renkleri), 4. Sosyal Medya (Instagram/LinkedIn/WhatsApp/E-posta), 5. Referans Site (URL + 'Analiz Et'), 6. Vizyonunuz (large textarea, min 50 chars). Footer: İptal / Siteyi Oluştur. Generation overlay with per-page status pills (Bekliyor/Oluşturuluyor/Kaydediliyor/Tamamlandı/Başarısız) + progress bar. Preview screen: 'Site Önizlemesi' with Yeniden Oluştur / Vazgeç / Kabul Et ve Düzenle, plus a feedback chat panel.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Siteyi Oluştur",
   "Analiz Et",
   "Yeniden Oluştur",
   "Kabul Et ve Düzenle",
   "İptal",
   "Başarısız sayfaları tekrar dene"
  ],
  "dialogs": [
   "Reference-site style analysis result card (Renk Paleti / Tasarım / Hero + 'Analizi Temizle')",
   "AI feedback chat ('Değişiklik yapmak için mesaj yazın')",
   "Partial-failure panel (Oluşturulan/Başarısız/Atlanan)"
  ],
  "keyComponents": [
   "Multi-section form",
   "FileUpload (image + PDF)",
   "WebsiteType cards",
   "BrandColor swatches",
   "Textarea with char counter",
   "Progress bar",
   "Status pills",
   "Chat panel"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_WEBSITE_MANAGE",
  "dataSources": [
   "AI generation service (posthog-tracked), storage of generated site content"
  ],
  "notes": "WebsiteTypes: marketing/link_in_bio/blog/portfolio/coaching/course_landing/event. BrandColors palette of ~14 named swatches with category subtitles. Missing-info + missing-vision validation toasts.",
  "cluster": "web-cms"
 },
 {
  "surface": "Web Page editor (drag-drop block builder)",
  "route": "/[organizationSlug]/admin/web-pages/[slug]",
  "titleTR": "(page title) — fallback 'Sayfayı Düzenle'",
  "purpose": "Full-screen visual page builder to edit a single web page: canvas with inline editing, block palette, per-block settings, theme, SEO, AI refine, save/publish.",
  "layout": "3-pane editor shell. Top toolbar: Geri, Undo (⌘Z)/Redo(⌘⇧Z), Sayfa Yapısını Göster, Bölüm Ekle, SEO Ayarları, Sayfa Ayarları, Önizleme, AI ile Geliştir, SaveStatusBadge (Kaydedildi/Kaydediliyor/Kaydedilmemiş değişiklikler/Kaydetme hatası), Kaydet, page switcher ('Sayfa değiştir'). Left sidebar tabs: Sayfa | Bloklar | Sayfa Özeti (outline, drag-reorder). Center: live canvas (click text to edit inline, click images to swap). Right SettingsPanel: tabs Genel | Tasarım | Gelişmiş. Section-hover toolbar per block: Yukarı Taşı/Aşağı Taşı/Kopyala/Şablon Olarak Kaydet/AI ile Geliştir/Sil.",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "tabs": [
   "Left: Sayfa / Bloklar / Sayfa Özeti",
   "Right SettingsPanel: Genel / Tasarım / Gelişmiş"
  ],
  "actions": [
   "Kaydet",
   "Bölüm Ekle",
   "SEO Ayarları",
   "Sayfa Ayarları",
   "Önizleme",
   "AI ile Geliştir",
   "Undo/Redo"
  ],
  "dialogs": [
   "Section Browser ('Bölüm Ekle': search, category filter Önerilen/Açılış & Navigasyon/Özellik Bölümleri/İçerik & Medya/Hakkında & Ekip/Sosyal Kanıt/Dönüşüm & Etkileşim/Satış & Kurslar/Yardımcı & Hukuki + Kayıtlı Şablonlar)",
   "WebPageSeoDialog (SEO Ayarları)",
   "WebPageSettingsDialog (Sayfa Ayarları: Başlık, Web Sayfası Adresi, 'Ana sayfa için boş bırakın')",
   "Save-as-template dialog",
   "AI block-refine popover ('AI ile Düzenle' with quick chips)",
   "AIChatPanel overlay",
   "Local-draft restore dialog ('Yerel taslak bulundu' / 'Kaydedilmemiş değişiklikler bulundu')",
   "Drop-rejected toast"
  ],
  "keyComponents": [
   "EditorHeader",
   "SettingsPanel",
   "SectionBrowser",
   "Canvas",
   "Outline (dnd)",
   "SaveStatusBadge",
   "Tabs",
   "Tooltip",
   "AIChat",
   "ErrorBoundary"
  ],
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "ORG_WEBSITE_VIEW (route reachable); editor is under website management",
  "dataSources": [
   "AdminWebPageQuery: organization.webPage{title,hiddenZoneBlockIds, ...UpdateWebPageEditor_webPage}, ...UpdateWebPageEditor_organization, websiteSettings{rootData,headerZone,footerZone}, uiSettings{primary/background/foreground/border colors +Dark, fontDisplay, fontSans}"
  ],
  "notes": "initialPreviewMode via ?preview=1. ErrorBoundary fallback: 'Editör yüklenirken bir hata oluştu.' + 'Sayfayı Yenile'. Legacy ?tab=content/seo stripped. Blocks come from the huge WebsiteEditorComponents library (ProductHero, LearningOutcomesGrid, CourseStatsStrip, etc.).",
  "cluster": "web-cms"
 },
 {
  "surface": "Web Page editor — Preview mode",
  "route": "/[organizationSlug]/admin/web-pages/[slug]?preview=1",
  "titleTR": "(page title)",
  "purpose": "Read-only rendering of the page inside the editor (blocks rendered as public would see, inline editing disabled).",
  "layout": "Same editor shell with canvas in preview mode: toolbar shows 'Önizleme Modu' / 'Önizlemeyi Kapat'; sidebars hidden/collapsed. Blocks render as isPreview.",
  "priority": "edge",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Önizlemeyi Kapat"
  ],
  "states": [
   "loading"
  ],
  "gating": "ORG_WEBSITE_VIEW",
  "dataSources": [
   "Same AdminWebPageQuery"
  ],
  "notes": "Standalone /preview route is a permanent redirect to ?preview=1.",
  "cluster": "web-cms"
 },
 {
  "surface": "Create Web Page flow (new)",
  "route": "/[organizationSlug]/admin/web-pages/new",
  "titleTR": "Sayfa Oluştur",
  "purpose": "Confirm title + address for a new (possibly AI-generated) page then land in the editor.",
  "layout": "Suspense (AdminContentSkeleton). Simple form: subtitle 'Yeni bir sayfa oluşturun ve düzenlemeye başlayın.', Başlık input (placeholder 'Örn: Ana Sayfa, Hakkımızda, İletişim'), Web Sayfası Adresi. Restored-from-AI variant: 'Oluşturulan sayfan hazır' + 'Sayfayı görüntüle ve özelleştir'.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Sayfayı görüntüle ve özelleştir"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_WEBSITE_MANAGE",
  "dataSources": [
   "CreateWebPageFlow (create web page mutation)"
  ],
  "notes": "Validation: path characters, no leading/trailing slash, reserved path, title required. Failure toasts (createFailedTitle/Validation/NoResponse).",
  "cluster": "web-cms"
 },
 {
  "surface": "Product Pages tab (Generated page rules list)",
  "route": "/[organizationSlug]/admin/web-pages?tab=generated",
  "titleTR": "Ürün Sayfaları",
  "purpose": "Manage auto-generated page templates that mint a public page per entity (course, bundle, tag, instructor, term, DP, LE, coaching).",
  "layout": "Lazy tab. Empty state 'Henüz özel sayfa şablonu yok' + description + 'Yeni sayfa şablonu'. Populated: sections grouped by entity type (Kurslar / Dijital Ürünler / Paketler / Koçluk Seansları / Canlı Etkinlikler / Etiket Sayfaları / Eğitmen Sayfaları / Dönem Sayfaları), each entity card with status (Yayında/Taslak/Sayfa yok/Arşivlenmiş) + actions (Bu sayfayı özelleştir / Sayfayı düzenle / URL kopyala). Product search ('Ürün ara...'), tag filter (Etikete göre filtrele / hariç tut), status filter. 'Başka bir sayfa türü mü gerekiyor?' section to add rules.",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "filters": [
   "Ürün ara",
   "Etiketler (include/exclude)",
   "Durum: Tümü / Yayında / Arşivlenmiş"
  ],
  "actions": [
   "Yeni sayfa şablonu",
   "Şablonu Özelleştir",
   "Bu sayfayı özelleştir",
   "Aktifleştir/Pasifleştir",
   "Varsayılan şablona sıfırla"
  ],
  "dialogs": [
   "Create rule dialog / Onboarding wizard (Ürün Sayfaları Oluştur — steps Varlık Türü/Detaylar/Tamamla; 'Tüm ürün sayfalarını oluştur')",
   "Deactivate confirm ('...Pasifleştir?')",
   "Reset-to-default confirm",
   "Delete rule confirm ('...şablonunu silmek istediğine emin misin?')",
   "Deactivated banner ('Bu sayfalar kapalı')"
  ],
  "keyComponents": [
   "Section list",
   "Entity cards",
   "StatusBadge",
   "Popover filters",
   "OnboardingWizard (stepper)",
   "DropdownMenu"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "gating": "ORG_WEBSITE_VIEW; manage actions ORG_WEBSITE_MANAGE",
  "dataSources": [
   "GeneratedPageRulesTab query (rules + per-entity generated pages)"
  ],
  "notes": "Onboarding wizard has welcome (Dinamik İçerik/Otomatik URL'ler/SEO Şablonları), entity-type picker, details (Şablon Adı, Sayfa Grup Adı with URL preview), summary.",
  "cluster": "web-cms"
 },
 {
  "surface": "Generated Page Rule detail/editor",
  "route": "/[organizationSlug]/admin/web-pages/generated/[ruleId]",
  "titleTR": "(rule name) — fallback 'Sayfa şablonu'",
  "purpose": "Edit one generated-page rule: its template content, SEO template vars, settings, and list of live URLs.",
  "layout": "Header: rule name + status Badge (Aktif/Pasif) + entity-type Badge. Tabs: İçerik | SEO | Ayarlar | URL'ler. İçerik = the block editor (UpdateGeneratedPageEditor) with entity-field bindings ('Sayfa Varlığına Bağla'). SEO = template fields (Sayfa Başlığı, Açıklama, OG Title/Description, Anahtar Kelimeler) with insertable variables ('{title}', '{slug}', custom-field vars). Ayarlar = name/entityType/urlPattern/priority/isActive. URL'ler = table.",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "tabs": [
   "İçerik",
   "SEO",
   "Ayarlar",
   "URL'ler"
  ],
  "tableColumns": [
   "URL",
   "Tür",
   "Özelleştirilmiş"
  ],
  "actions": [
   "Kaydet",
   "Değişken ekle",
   "Sayfa Varlığına Bağla / Bağlantıyı Kaldır",
   "Daha Fazla Yükle"
  ],
  "dialogs": [
   "GeneratedPageRuleSeoDialog",
   "Field-binding popover (bind to entity property, Varsayılan Değer, Boşsa Gizle)",
   "Insert-variable popover ('Değişken ekle', 'Değişken ara...')"
  ],
  "keyComponents": [
   "Tabs",
   "Badge",
   "Block editor",
   "SEO form",
   "Data table",
   "Popover"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "gating": "ORG_WEBSITE_VIEW/MANAGE",
  "dataSources": [
   "AdminGeneratedPageRuleQuery: node ... on GeneratedPageRule{name,entityType,urlPattern,isActive,priority,content,seoFields,tagGroup{id,name,slug}, ...UpdateGeneratedPageEditor_rule, ...GeneratedPageRuleSettings_rule, ...GeneratedPageRuleSEO_rule, ...GeneratedPageUrlsList_rule}; organization.websiteSettings.rootData, uiSettings{colors,fonts}"
  ],
  "notes": "URL's tab empty state 'Henüz oluşturulmuş URL yok'. Per-product customization: orphan warnings ('Bu değişiklik ürün özelleştirmelerini etkileyecek'), removed-sections notice, restore section.",
  "cluster": "web-cms"
 },
 {
  "surface": "Content Pages tree (Bloglar)",
  "route": "/[organizationSlug]/admin/content-pages",
  "titleTR": "Bloglar",
  "purpose": "Top-level content CMS: manage categories & pages grouped by render mode (Blog / Makaleler / Yardım Merkezi); create, reorder, search, drill into sections.",
  "layout": "PageHeader 'Bloglar'. Tabs with count badges: Blog | Makaleler | Yardım Merkezi. Right controls: ContentPageSearchCommand ('Sayfa ara…'), 'Site üst/alt bilgisi' link (PanelTop), 'Ana kategori ekle' (+). Per-tab description text. BLOG tab = CategoryCardGrid (post cards); ARTICLE = docs list; HELP_CENTER = directory (2-col sections). Empty per-tab uses RenderModeWireframe + 'Bu görünüm için henüz kategori yok.' + 'Ekle'. Global empty: BookOpen + 'Henüz kategori veya sayfa yok.' + 'İlk kategoriyi ekle'.",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "tabs": [
   "Blog",
   "Makaleler",
   "Yardım Merkezi"
  ],
  "filters": [
   "Search command (admin mode)"
  ],
  "actions": [
   "Ana kategori ekle",
   "Site üst/alt bilgisi",
   "İçerik Ekle"
  ],
  "dialogs": [
   "CreateItemDialog (2-step: 'Ne eklemek istiyorsunuz?' Sayfa vs Alt Kategori → details: Başlık, Slug, İkon, Bölüm türü)",
   "RenameDialog",
   "SlugDialog",
   "MoveToDialog",
   "RenderModeDialog (Bölüm Türünü Değiştir)",
   "ManageOrderDialog (drag reorder, auto-save)",
   "ContentPageNodeActions dropdown (Arşivle/Yayınla/İçeriği Düzenle/Taşı/Kalıcı sil…)"
  ],
  "keyComponents": [
   "Tabs",
   "Badge counts",
   "Command palette",
   "CategoryCardGrid",
   "CategoryNode/PageNode tree",
   "Breadcrumb",
   "Dialog",
   "AlertDialog"
  ],
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "gating": "ORG_CONTENT_MANAGE to view; 'Site üst/alt bilgisi' gated on ORG_WEBSITE_MANAGE",
  "dataSources": [
   "AdminContentPagesPageQuery: organization.adminContentTree{id,slug,label,icon,status,order,renderMode,bannerImage, children{...pages{id,slug,title,status,order}}}"
  ],
  "notes": "Skeleton = 6 pulse rows. Provenance line (Oluşturan/Yayınlandı/Güncellendi, Yapay zekâ/Sistem).",
  "cluster": "web-cms"
 },
 {
  "surface": "Content category drill-in",
  "route": "/[organizationSlug]/admin/content-pages?category=<id>",
  "titleTR": "(category label breadcrumb)",
  "purpose": "Inside a category: view/manage its subcategories + pages laid out per render mode, with a toolbar of primary section actions.",
  "layout": "Back arrow + Breadcrumb header (root 'Bloglar' → …). Action row: İçerik Ekle, Açılış İçeriğini Düzenle, Sıralama, Bölüm Türü, ContentPageNodeActions '⋯'. Contents laid out per mode: BLOG=post cards (+ PageCard grid), ARTICLE=divided docs list, HELP_CENTER=nested tree. Empty: FileText + 'Bu kategori boş. İlk sayfayı ekleyerek başlayın.' + 'İçerik Ekle'. Archived categories render at 60% opacity with disabled actions.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "İçerik Ekle",
   "Açılış İçeriğini Düzenle",
   "Sıralama",
   "Bölüm Türü"
  ],
  "dialogs": [
   "CreateItemDialog",
   "RenameDialog",
   "SlugDialog",
   "MoveToDialog",
   "ManageOrderDialog",
   "RenderModeDialog"
  ],
  "keyComponents": [
   "Breadcrumb",
   "Button toolbar",
   "CategoryNode/PageNode",
   "PageCard",
   "CategoryCardGrid",
   "DropdownMenu"
  ],
  "states": [
   "empty"
  ],
  "gating": "ORG_CONTENT_MANAGE",
  "dataSources": [
   "Same adminContentTree (client-side drill via findCategoryPath)"
  ],
  "notes": "Lives in URL (?category=) so browser-back exits drill-in.",
  "cluster": "web-cms"
 },
 {
  "surface": "Content Page editor (block editor)",
  "route": "/[organizationSlug]/admin/content-pages/page/[pageId]",
  "titleTR": "İçerik Sayfasını Düzenle",
  "purpose": "Edit a single content page (article/blog/doc): metadata + rich markdown/MDX block body with product/media blocks, draft/publish lifecycle, access gating, SEO/banner.",
  "layout": "Persistent tree sidebar (left, from (editor) layout) + right editor column. EditorHeader: back, title 'İçerik Sayfasını Düzenle', Görüntüle/Önizle, Taslak Kaydet, Yayınla, Banner ve SEO, Taslağı Sil, Arşivle/Geri Yükle, Yayından Kaldır, Kalıcı Sil, last-saved indicator. ContentProvenanceLine. Optional help-doc-key row (pi org). 3-col metadata grid (Başlık, Slug, Açıklama). PageAccessPanel (access mode/unlisted). ContentPageBlockEditor pane (toolbar of custom blocks + '/' commands). Editor tour available.",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Taslak Kaydet",
   "Yayınla",
   "Banner ve SEO",
   "Önizle",
   "Görüntüle",
   "Arşivle",
   "Geri Yükle",
   "Yayından Kaldır",
   "Kalıcı Sil",
   "Taslağı Sil"
  ],
  "dialogs": [
   "SeoBanner sheet (Banner ve SEO: banner image + search-engine title/description, OG, X/Twitter, keywords, CTA)",
   "Image picker (Görsel Seç)",
   "GIF picker (GIF Seç)",
   "Video picker (Video Seç)",
   "Product picker (Ürün Seç: tabs Dersler/Dijital Ürünler/Paketler/Etkinlikler/Koçluk, link target Tanıtım/Satın Alma/Özel URL)",
   "Discard-draft confirm",
   "Archive confirm",
   "Delete confirm (type-title-to-confirm)"
  ],
  "keyComponents": [
   "EditorHeader",
   "ContentPageBlockEditor",
   "PageAccessPanel",
   "ContentProvenanceLine",
   "Sheet",
   "Dialog",
   "AlertDialog",
   "Input/Label",
   "Toast",
   "Tour"
  ],
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "ORG_CONTENT_MANAGE (NoAccessMessage with title 'İçerik Düzenle')",
  "dataSources": [
   "ContentPageEditorPageQuery: node ... on ContentPage{id,title,slug,description,body,draft,status,publicPath,bannerImage,seoFields,unlisted,access{mode},createdVia,createdBy{givenName,lastName,image(48)},publishedAt,updatedAt}; organization.websiteSettings.customDomain",
   "Mutations: saveContentPageDraft, publishContentPage, archiveContentPage, restoreContentPage, unpublishContentPage, deleteContentPage, discardContentPageDraft (all with userErrors)"
  ],
  "notes": "Draft/publish state machine (Taslak/Yayında/Arşivlenmiş). Ctrl/Cmd+S saves. Block editor blocks: Bilgi/İpucu/Uyarı/Tehlike callouts, Görsel/GIF/Video, Ürün Kartı/Butonu/Bağlantısı/Izgarası, headings/list/quote/code/table.",
  "cluster": "web-cms"
 },
 {
  "surface": "Category Landing editor",
  "route": "/[organizationSlug]/admin/content-pages/category/[categoryId]",
  "titleTR": "Bölüm Açılış İçeriğini Düzenle",
  "purpose": "Edit the landing (açılış) content of a content category — same block editor + draft/publish lifecycle as a page, but for a category banner/landing.",
  "layout": "Same (editor) layout with tree sidebar + EditorHeader ('Açılış İçeriği'/'Bölüm Açılış İçeriğini Düzenle'), Açıklama field, Banner ve SEO, block editor. Draft/publish/archive/restore/unpublish/delete actions mirror the page editor.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Taslak Kaydet",
   "Yayınla",
   "Banner ve SEO",
   "Önizle",
   "Arşivle",
   "Geri Yükle",
   "Yayından Kaldır",
   "Kalıcı Olarak Sil",
   "Taslağı Sil"
  ],
  "dialogs": [
   "SeoBanner sheet",
   "Image/GIF/Video/Product pickers",
   "Discard/Archive/Delete confirms (type category name to confirm)"
  ],
  "keyComponents": [
   "EditorHeader",
   "ContentPageBlockEditor",
   "Sheet",
   "AlertDialog"
  ],
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "ORG_CONTENT_MANAGE",
  "dataSources": [
   "CategoryLandingEditorPageQuery + mutations (save/publish/archive/restore/unpublish/delete/discard draft) with userErrors"
  ],
  "notes": "Uses Admin.ContentPages.CategoryEditor.* copy. Archived landing can't be edited until restored.",
  "cluster": "web-cms"
 },
 {
  "surface": "Content Page preview",
  "route": "/[organizationSlug]/admin/content-pages/preview/[pageId]",
  "titleTR": "{title} · Önizleme (fallback 'Önizleme')",
  "purpose": "Admin-only rendered preview of a content page's draft or published body with an İçindekiler ToC.",
  "layout": "Full rendered ContentPagePreview of the MDX body. Banner at top: draft → 'Taslak önizleniyor — bu sayfa yalnızca organizasyon yöneticilerine görünür.'; published → 'Yayınlanmış sürüm (taslak yok)…'. MDX compile errors surfaced ('İçerik Hatası').",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "ORG_CONTENT_MANAGE (NoAccessMessage 'Önizleme')",
  "dataSources": [
   "ContentPagePreviewRouteQuery: node ... on ContentPage{title,description,body,draft,...}"
  ],
  "notes": "parseDraft mirrors editor; prefers draft over published fields.",
  "cluster": "web-cms"
 },
 {
  "surface": "Category Landing preview",
  "route": "/[organizationSlug]/admin/content-pages/preview/category/[categoryId]",
  "titleTR": "{title} · Önizleme",
  "purpose": "Admin-only rendered preview of a category landing's draft/published content.",
  "layout": "Same as content-page preview but for a category landing (banner + rendered body + draft/published banner).",
  "priority": "edge",
  "suggestedCanvas": "08-web-cms",
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "gating": "ORG_CONTENT_MANAGE",
  "dataSources": [
   "CategoryLandingPreviewRoute query (node ... on ContentPageCategory)"
  ],
  "notes": "Uses same Preview.* copy.",
  "cluster": "web-cms"
 },
 {
  "surface": "Site Chrome editor (Site üst/alt bilgisi)",
  "route": "/[organizationSlug]/admin/content-pages/site-chrome",
  "titleTR": "Site üst/alt bilgisi",
  "purpose": "Configure the marketing navbar + footer shown on content pages (blog/article sections): links, CTA, footer columns, socials, copyright, and where it appears.",
  "layout": "force-dynamic page (AdminContentSkeleton fallback). Sheet/panel form: 'Üst menü' section (menu links list with Etiket + Bağlantı, 'Bağlantı ekle', 'Eylem düğmesi'), 'Alt bilgi' section (Slogan, Bağlantı sütunları with 'Sütun ekle', Yasal bağlantılar, Sosyal medya URLs Instagram/YouTube/LinkedIn/X/Facebook, Telif hakkı metni), 'Nerede gösterilsin' (choose blog/article roots; Yardım Merkezi always excluded), 'Arama kutusunu göster' toggle, Önizleme. Footer buttons: İptal / Kaydet. Back link 'İçerik sayfalarına dön'.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Kaydet",
   "Bağlantı ekle",
   "Sütun ekle"
  ],
  "dialogs": [
   "Page picker ('Sayfa seç': tabs İçerik sayfaları / Web sayfaları / Ürünler, search, grouped products Kurslar/Dijital ürünler/Paketler/Canlı etkinlikler/Birebir görüşmeler)"
  ],
  "keyComponents": [
   "Sheet/Form",
   "Repeater lists",
   "Toggle/Switch",
   "Tabs picker",
   "Preview panel"
  ],
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "gating": "ORG_WEBSITE_MANAGE",
  "dataSources": [
   "ContentChromeEditor query (org navbar/footer chrome config + eligible roots)"
  ],
  "notes": "Empty roots: 'Henüz blog veya makale bölümü yok…'. Save success toast 'Site üst/alt bilgisi kaydedildi.'",
  "cluster": "web-cms"
 },
 {
  "surface": "Profile Page editor (Profil Kartım)",
  "route": "/[organizationSlug]/admin/profile-page",
  "titleTR": "Profil Kartım",
  "purpose": "WYSIWYG editor for the org's profile/landing card (link-in-bio style) that acts as the main website: banner, avatar, name/title/description, metrics, CTA, social links, and product sections; publish/unpublish/delete.",
  "layout": "ProfileEditorLayout: live editable profile card canvas + controls. Top controls: Kaydet, Yayınla/Yayından Kaldır, Önizleme/Düzenleme toggle, device toggles (Masaüstü/Tablet/Mobil), Tema, Yazı Tipi, Metrikleri Göster, Gelişmiş Düzenleyici. Editable regions (clickToEdit 'Düzenlemek için tıklayın'): Kapak Görseli (Gradyan/Görsel), Profil Fotoğrafı, İsim, Başlık, Açıklama, Metrikler (Öğrenci/Kurs/Görüşme), Aksiyon Butonu, Sosyal Medya Bağlantıları. Product sections toggles: Kurslar/Görüşmeler/Dijital Ürünler/Webinarlar/Paketler. Conflict banner when a custom root page overrides the profile.",
  "priority": "primary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Kaydet",
   "Yayınla",
   "Yayından Kaldır",
   "Sayfayı Görüntüle",
   "Bağlantı Ekle (social)",
   "Sayfayı Sil"
  ],
  "dialogs": [
   "Image picker (banner/avatar)",
   "Social platform picker ('Platform Seçin', search)",
   "Unpublish confirm ('Tanıtım Sayfasını Yayından Kaldır')",
   "Delete confirm ('Tanıtım Sayfasını Sil', geri alınamaz)",
   "Draft-recovery dialog ('Yerel taslak bulundu' → Geri Yükle / Sil)",
   "Card link popover ('Bu kartın bağlantısı': Ürün sayfası / Satın alma sayfası)"
  ],
  "keyComponents": [
   "ProfileEditorLayout",
   "Editable card",
   "Device toggle",
   "Theme preset picker",
   "Social picker",
   "AlertDialog",
   "Toast",
   "ErrorBoundary"
  ],
  "states": [
   "loading",
   "empty",
   "error",
   "permission-denied"
  ],
  "gating": "ORG_WEBSITE_VIEW (NoAccessMessage 'Profil Kartım')",
  "dataSources": [
   "ProfilePageEditorQuery: organization{id,name,slug,image(200), webPages(path:'__profile__'){id,slug,content,isActive, ...SEOWebPage_webPage}, websiteSettings{customDomain,faviconUrl}, activeWebPage(path:''){id,content}, ...ProfileEditorLayout_organization}"
  ],
  "notes": "Theme presets (modern-minimal, organic-calm, creative-pop, editorial-warm, sunset-horizon, urban-minimal + dark variants) and fonts (Modern/Klasik/Mono). Local-draft autosave to localStorage; beforeunload guard. hasConflict warns when a Puck root page hides the profile card. 'Gelişmiş Düzenleyici' escapes to the full web-page editor.",
  "cluster": "web-cms"
 },
 {
  "surface": "Profile Page onboarding wizard",
  "route": "/[organizationSlug]/admin/profile-page (shown when no profile page exists)",
  "titleTR": "Tanıtım Sayfanızı Oluşturun",
  "purpose": "First-run guided setup for the profile card before the full editor.",
  "layout": "Stepper: Temel Bilgiler · Tema · Sosyal Medya · Tamamla. Welcome (3 feature cards: Kişisel Marka/Sosyal Bağlantılar/Kolay Kurulum, 'Başlayalım', 'Editöre geç'). Basics (avatar, Adınız, Ünvanınız, Hakkınızda). Theme (color preset + font). Socials (add-platform grid). Summary (review + 'Profili Yayınla'). Navigation: Geri/Devam Et/Atla.",
  "priority": "secondary",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Başlayalım",
   "Editöre geç",
   "Devam Et",
   "Profili Yayınla"
  ],
  "keyComponents": [
   "Stepper",
   "Avatar upload",
   "Theme presets",
   "Social picker",
   "Card",
   "Button"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_WEBSITE_VIEW",
  "dataSources": [
   "Create + activate profile web page mutations"
  ],
  "notes": "publishSuccess 'Profiliniz yayınlandı!'; if activate fails: 'Profil oluşturuldu ancak yayınlanamadı. Editörden yayınlayabilirsiniz.'",
  "cluster": "web-cms"
 },
 {
  "surface": "Theme Settings (Tema Ayarları)",
  "route": "/[organizationSlug]/admin/settings?tab=organization#theme (linked from Web Pages list)",
  "titleTR": "Tema Ayarları",
  "purpose": "Site-wide theme controls referenced from web-pages: colors, fonts, type scales, site mode (light/dark/system), preset combinations, live preview.",
  "layout": "Tabs: Renkler | Yazı Tipleri | Yazı Ölçekleri. Color pickers (Tema Renkleri, light/dark). Site Modu radio (Açık/Koyu/Sistem). Fonts (Başlık Fontu, Yazı Fontu, 'Font seç…') + Yazı Kalınlıkları. Hazır Kombinasyonlar presets. Preview panel (Örnek Başlık/paragraf/buton, Açık Tema/Koyu Tema). Footer: Temizle/Geri Al/Kaydet + 'Değişiklik yok' state.",
  "priority": "edge",
  "suggestedCanvas": "08-web-cms",
  "tabs": [
   "Renkler",
   "Yazı Tipleri",
   "Yazı Ölçekleri"
  ],
  "actions": [
   "Kaydet",
   "Temizle",
   "Geri Al",
   "Varsayılana sıfırla"
  ],
  "dialogs": [
   "Clear-confirm ('Tema Ayarlarını Sıfırla')"
  ],
  "keyComponents": [
   "Tabs",
   "ColorPicker",
   "FontSelect",
   "Preview card",
   "Button"
  ],
  "states": [
   "loading",
   "error"
  ],
  "gating": "ORG_WEBSITE_MANAGE",
  "dataSources": [
   "Org uiSettings / websiteSettings theme"
  ],
  "notes": "Cross-cluster (lives under settings) but reached directly from the web-pages list header; included for completeness. themeSettingsError fallback: 'Tema ayarları yüklenirken bir hata oluştu.'",
  "cluster": "web-cms"
 },
 {
  "surface": "Product Page Preview embed (Yayındaki Sayfa)",
  "route": "embedded panel on a product admin page (WebPages.ProductPagePreview)",
  "titleTR": "Yayındaki Sayfa",
  "purpose": "Shows a product's live public generated page (or a CTA to enable a default layout) as an embedded iframe preview from the product's own admin screen.",
  "layout": "Card with title 'Yayındaki Sayfa' + subtitle. Iframe live preview ('Yayındaki sayfa önizlemesi') with Siteyi Görüntüle / Sayfayı Düzenle / Özelleştir / Önizlemeyi Göster-Gizle. Empty (no rule): 'Varsayılanları Yayına Al' / 'Doğrudan Kural Oluştur'. External-domain fallback: 'Önizleme burada gösterilemiyor'.",
  "priority": "edge",
  "suggestedCanvas": "08-web-cms",
  "actions": [
   "Siteyi Görüntüle",
   "Sayfayı Düzenle",
   "Özelleştir",
   "Varsayılanları Yayına Al"
  ],
  "states": [
   "empty",
   "error"
  ],
  "gating": "ORG_WEBSITE_MANAGE",
  "dataSources": [
   "Generated page rule for the product entity"
  ],
  "notes": "Bridges product admin surfaces to the generated-pages system; can't embed when page is on a custom domain.",
  "cluster": "web-cms"
 },
 {
  "surface": "My Courses (Derslerim)",
  "route": "/[organizationSlug]/derslerim",
  "titleTR": "Kurslarım",
  "purpose": "Student learn-app home: everything the viewer is enrolled in, plus cross-sell of other orderables. Redirects to /giris if not a student.",
  "layout": "Top OrganizationStudentNavigationSection (logo + nav links Kurslarım / Birebir Görüşmelerim + cart icon + Giriş Yap when logged out). Then stacked sections each mx-auto max-w-7xl: (1) enrolled course academic terms as 2-col grid of horizontal image cards; (2) 'Canlı Etkinliklerim' live-event cards 2-col; (3) 'Dijital Ürünlerim' digital-product cards 2-col; (4) 'Avantajlı Toplu Paketler' bundles; (5) 'Kaydolabileceğin Diğer Ürünler' cross-sell orderables grid. Infinite scroll (24/page) via intersection observer.",
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "NavigationSection",
   "Card (HorizontalImageCard)",
   "HorizontalImageCardSkeleton",
   "Alert (warning)",
   "Suspense"
  ],
  "actions": [
   "Kursa git (card click)",
   "Kaydol / Satın Al (cross-sell)"
  ],
  "gating": "Requires organization.viewerStudent; anonymous → RedirectToPiHref /giris?nextToStart",
  "dataSources": [
   "ViewerCourseAcademicTermsPageQuery",
   "ViewerCourseAcademicTerms_courseAcademicTerms (viewerCourseAcademicTerms connection)",
   "ViewerLiveEvents_liveEvents",
   "ViewerDigitalProducts_digitalProducts",
   "ViewerOrderableBundles_orderableBundles",
   "ViewerOrderables_orderables (union CourseAcademicTerm|LiveEvent|DigitalProduct)"
  ],
  "notes": "Empty enrolled state renders warning Alert 'Hiçbir Kursa Sahip Değilsin' / 'Kayıtlı olduğun hiçbir kurs bulunmamaktadır.' Live/DP sections hide entirely when totalCount===0. Sends GTM view_item_list events. Section titles from ViewerCourseAcademicTerms/ViewerDigitalProducts/ViewerLiveEvents/ViewerOrderables namespaces.",
  "cluster": "student-app"
 },
 {
  "surface": "Course Player shell (layout)",
  "route": "/[organizationSlug]/dersler/ogren/[courseSlug]/[academicTermSlug]",
  "titleTR": "(course academic term title)",
  "purpose": "Full-screen course-learning shell: top nav bar with hamburger, collapsible section/item navigator sidebar, scrollable content main. Applies term's effectiveUiSettings theme + custom page colors (light/dark).",
  "layout": "h-dvh flex-col. CourseLearnNavBar (hamburger side = courseContentsSide left/right). Below: flex row (reversed if contents on RIGHT) — Sheet-based sidebar (mobile) / persistent ScrollArea sidebar (sm w-56 md:w-80) containing CourseLearnItemNavigator (sections → items, optionally showing video sections); ScrollArea main with CourseLearnAccountSharingGuard wrapping item content. Dark mode + CSS color vars from term settings.",
  "states": [
   "loading",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "CourseLearnNavBar",
   "CourseLearnItemNavigator",
   "Sheet/SheetContent (mobile sidebar)",
   "ScrollArea",
   "CourseLearnAccountSharingGuard",
   "PageColorsProvider"
  ],
  "actions": [
   "Toggle sidebar (hamburger)",
   "Select section item"
  ],
  "dialogs": [
   "Mobile navigator Sheet"
  ],
  "gating": "notFound if no academicTerm; RedirectToPiHref /giris if no viewer. Account-sharing guard can block concurrent sessions.",
  "dataSources": [
   "CourseLearnLayoutQuery (course.academicTerm: viewerHasReadAccess, effectiveUiSettings themePreference/courseContentsSide/colors, CourseContext_courseAcademicTerm, CourseLearnItemNavigator_sections)"
  ],
  "notes": "courseContentsSide LEFT/RIGHT mirrors the whole layout. themePreference DARK/LIGHT/system.",
  "cluster": "student-app"
 },
 {
  "surface": "Course Item viewer",
  "route": ".../[courseSlug]/[academicTermSlug]/[itemSlug]",
  "titleTR": "(item title | term title | org name)",
  "purpose": "Renders a single course item (video, audio, PDF/document, question/quiz, exam, assignment, forum, live, embed, SCORM, cmi5) with progress tracking; gates locked/unpurchased/undripped content.",
  "layout": "HiddenItemAlert (warning) at top if item.hidden. Then CourseItem in 'learn' mode renders type-specific player/content + description + attachments + Next/Report buttons. If no read access AND not freeAccess: centered '<title> konusuna erişmek için kursa kaydolman gerekiyor!' + ViewerOrderableCourseAcademicTermCard (purchase CTA).",
  "states": [
   "loading",
   "empty",
   "permission-denied",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "CourseItem",
   "CourseItemVideoPlayer",
   "CourseItemAudioPlayer",
   "CourseItemPDFAttachmentViewer",
   "QuestionCourseItem",
   "ScormCourseItem",
   "Cmi5CourseItem",
   "EmbedCourseItem",
   "Alert",
   "ViewerOrderableCourseAcademicTermCard",
   "NextItemButton",
   "ReportItemButton",
   "ShowHintButton",
   "ShowAnswerButton"
  ],
  "actions": [
   "Sonraki içerik (NextItemButton)",
   "İçeriği bildir (ReportItemButton)",
   "Dinlendi olarak işaretle (audio)",
   "İpuçları / Çözümü Göster (question)",
   "İndir (attachments)"
  ],
  "dialogs": [
   "Report item dialog"
  ],
  "gating": "viewerHasReadAccess OR item.freeAccess; drip locks (releasesIn / dripLockedDaysAfterEnrollment / dripLockedAfterCompletion), prerequisite locks, member preview banners",
  "dataSources": [
   "CourseItemPageQuery (course.academicTerm.item: title/freeAccess/hidden, CourseItem_item, ViewerOrderableCourseAcademicTermCard)"
  ],
  "notes": "CourseItem namespace locked copy: 'İçerik Kilitli', 'Tamamlanmamış Önkoşullar', 'Gizli İçerik', 'Önizleme Modu' (member preview), per-type 'X henüz yayınlanmadı'. Safari PDF warning.",
  "cluster": "student-app"
 },
 {
  "surface": "Course term landing / next-item redirect",
  "route": ".../[courseSlug]/[academicTermSlug] (index)",
  "titleTR": "Bu kursta henüz bir içerik yok.",
  "purpose": "Server component that redirects to viewerNextItem or first item; if the term has no items, shows an empty placeholder.",
  "layout": "Centered HourglassIcon + h3 'Bu kursta henüz bir içerik yok.' + p 'İçerikler yakında eklenecek. Lütfen bekleyin.' Below: term title row + NextItemButton, then ReportItemButton row. Padding mirrors courseContentsSide.",
  "states": [
   "empty"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "HourglassIcon",
   "NextItemButton",
   "ReportItemButton"
  ],
  "actions": [
   "Sonraki içerik",
   "Bildir"
  ],
  "gating": "notFound if no academicTerm",
  "dataSources": [
   "RedirectToNextItemPageQuery (academicTerm.viewerNextItem, sections.items, effectiveUiSettings.courseContentsSide)"
  ],
  "notes": "CourseAcademicTermLanding.emptyTitle/emptyDescription.",
  "cluster": "student-app"
 },
 {
  "surface": "Digital Product learn page",
  "route": "/[organizationSlug]/dijital-urunler/ogren/[slug]",
  "titleTR": "Kütüphanen",
  "purpose": "Post-purchase digital-product library: header with cover, metadata badges, downloadable file list with search, and 'about' aside.",
  "layout": "Nav section. Header: cover image (aspect square) + eyebrow 'Kütüphanen' + title + shortDescription + badges (file count, total size, Ömür boyu erişim / Süreli erişim / '{date} tarihine kadar erişim') + 'Güncellendi: {date}' + 'Hazırlayan {org}'. Body grid: main Card 'Dosyalar' / 'İstediğin zaman istediğin dosyayı indir...' with search input (shown if >4 files) and divided file list rows (title, TYPE·size·date, download icon); optional aside Card 'Bu ürün hakkında' rendering orderPageDescription (Potion).",
  "states": [
   "empty",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Badge",
   "Input (search)",
   "AttachmentDownloadButton",
   "EmptyCourseImage",
   "PotionRenderer"
  ],
  "filters": [
   "Dosyalarda ara (search)"
  ],
  "actions": [
   "İndir (per-file download)"
  ],
  "gating": "no viewer → RedirectToPiHref /giris; no viewerHasReadAccess → redirect to /dijital-urunler/[slug] sales page",
  "dataSources": [
   "DigitalProductLearnPageQuery (digitalProduct: attachments{title,fileName,fileType,fileSize,createdAt}, accessType INFINITE/timed, accessExpiresAt, orderPageDescription, AttachmentDownloadButton_attachment)"
  ],
  "notes": "Empty: PackageIcon + 'Hazırlayan henüz dosya eklemedi.' Search-no-result: '\"{query}\" ile eşleşen dosya yok.' DigitalProductLearnPage namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Live Event learn page",
  "route": "/[organizationSlug]/etkinlikler/ogren/[slug]",
  "titleTR": "(event title)",
  "purpose": "Post-purchase live-event page: countdown/state machine (Upcoming → Live → Ended), join link, recording section, event details, about.",
  "layout": "Nav section. Header with cover image, title, hostedBy '{org}'. State-driven hero: Upcoming → EventCountdown ('Başlamasına' Gün/Saat/Dakika/Saniye) + 'Katılım bağlantısını gör'; Live → 'Etkinlik şu anda yayında' + join (or 'Düzenleyen henüz katılım bağlantısını paylaşmadı'); Ended → 'Bu etkinlik sona erdi' + recording ('Kayıt' / 'Kayıt işleniyor...' / 'Bu etkinlik için bir kayıt yayınlanmadı.'); TBA → 'Tarih duyurulacak'. Details card: Tarih ve saat / Süre / Platform / Kapasite / Erişim bitiş. About card (Potion). AddToCalendarButton.",
  "states": [
   "loading",
   "permission-denied",
   "empty"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "EventCountdown",
   "Card",
   "Badge",
   "Button",
   "AddToCalendarButton",
   "PotionRenderer"
  ],
  "actions": [
   "Şimdi Katıl / Katılım Bağlantısı",
   "Takvime ekle",
   "Katılım bağlantısını gör (preview)"
  ],
  "gating": "viewerHasReadAccess (redirect to sales page otherwise)",
  "dataSources": [
   "LiveEventPageQuery (liveEvent: startDate,endDate,platform,url,capacity,autoPublishRecording,accessType,accessExpiresAt,tags,viewerHasReadAccess)"
  ],
  "notes": "Namespaces LiveEventLearnPage (detail) + LiveEventPage (badges 'CANLI'/'Yaklaşan'/'Sona Erdi', countdown). setTimeout boundary ticking for state transitions.",
  "cluster": "student-app"
 },
 {
  "surface": "Coaching Sessions list (Birebir)",
  "route": "/[organizationSlug]/birebir",
  "titleTR": "Birebir Görüşmelerim",
  "purpose": "Student's 1:1 coaching hub: sessions the student has access to (with remaining counts) and upcoming reservations across the org.",
  "layout": "Nav section + centered main max-w-7xl. ViewerCoachingSessions ('Birebir Görüşmelerim' grid of ViewerCoachingSessionCard, each '{n} seans hakkı'). ViewerUpcomingOrganizationReservations ('Yaklaşan Birebir Görüşme Seansları' or empty 'Yaklaşan birebir görüşme seansınız bulunmamaktadır.').",
  "states": [
   "empty",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "ViewerCoachingSessions",
   "ViewerCoachingSessionCard",
   "ViewerUpcomingOrganizationReservations",
   "InstructorCard"
  ],
  "actions": [
   "Görüşme kartına git / Randevu al"
  ],
  "gating": "requires viewerStudent; else redirect /giris",
  "dataSources": [
   "ViewerCoachingSessionsPageQuery (ViewerCoachingSessions_coachingSessions, ViewerUpcomingOrganizationReservations_reservations)"
  ],
  "notes": "Nav only shows Birebir link when organization.coachingSessions.totalCount>0. ViewerCoachingSessions namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Coaching Session detail & booking",
  "route": "/[organizationSlug]/birebir/[coachingSessionSlug]",
  "titleTR": "(session title) / Birebir Detay",
  "purpose": "Book a 1:1 slot (in-house slot picker or Calendly), see remaining session rights, buy more session packs, and view/manage upcoming reservations.",
  "layout": "Nav section. Header (title, description via Potion). If has rights: '{count} adet birebir görüşme randevusu hakkın bulunuyor.' + booking UI — InHouseSlotPicker (instructor select → 'Tarih Seçin' calendar → slot list → 'Randevu Oluştur' → success 'Randevunuz Onaylandı!' + 'Toplantıya Katıl') OR Calendly InlineWidget OR external 'Randevu Oluştur'. ViewerUpcomingCoachingSessionReservations list. Buy-more 'Görüşme Hakkı Al' with CoachingSessionPlanSelector cards (seans count, price, %indirim, 'Hemen Al').",
  "states": [
   "loading",
   "empty",
   "permission-denied",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "InHouseSlotPicker",
   "CoachingSessionPlanSelector",
   "ViewerUpcomingCoachingSessionReservations",
   "InlineWidget (Calendly)",
   "Badge",
   "Button",
   "PotionRenderer"
  ],
  "actions": [
   "Randevu Oluştur",
   "Toplantıya Katıl",
   "Hemen Al (buy plan)",
   "İptal Et / Yeniden Planla (reservation)"
  ],
  "dialogs": [
   "Reschedule reservation dialog",
   "Cancel reservation confirm",
   "Booking success"
  ],
  "gating": "notFound / rename-redirect; buy flow creates order",
  "dataSources": [
   "CoachingSessionPageQuery (coachingSession + InHouseSlotPicker_tutorAvailableSlots + ViewerUpcomingCoachingSessionReservations_reservations)",
   "CreateCoachingSessionReservation(Link) mutations",
   "CoachingSessionPageCreateOrderMutation"
  ],
  "notes": "Namespaces CoachingSessionPurchase + InHouseSlotPicker + CoachingSessionReservation. In-house vs Calendly booking modes. 'Randevu Hakkınız Bulunmuyor' empty state.",
  "cluster": "student-app"
 },
 {
  "surface": "Reservation actions (reschedule / cancel / meeting link)",
  "route": ".../birebir[...] (dialogs on reservation cards)",
  "titleTR": "Randevuyu Yeniden Planla / Randevuyu İptal Et",
  "purpose": "Manage an existing coaching reservation.",
  "layout": "RescheduleReservationDialog (reuses slot picker, 'Bu görüşme artık yeniden planlanamıyor.' / load-error). Cancel confirm AlertDialog: 'Randevuyu İptal Et' / 'Bu randevuyu iptal etmek istediğinize emin misiniz? Randevu hakkınız hesabınıza iade edilecektir.' / 'Randevuyu İptal Et' / 'Vazgeç'. Row dropdown 'Menüyü Aç' → 'Görüşme Linkini Güncelle'.",
  "states": [
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "RescheduleReservationDialog",
   "AlertDialog",
   "DropdownMenu",
   "UpdateReservationDialog"
  ],
  "actions": [
   "İptal Et",
   "Yeniden Planla",
   "Görüşme Linkini Güncelle",
   "Görüşmeye Katıl"
  ],
  "dialogs": [
   "Reschedule dialog",
   "Cancel confirm",
   "Update meeting link dialog"
  ],
  "gating": "isCancelEnabled + cancel window",
  "dataSources": [
   "CoachingSessionReservation fragment",
   "reservation status enum RESERVED/COMPLETED/CANCELED_BY_USER/CANCELED_BY_ORGANIZATION"
  ],
  "notes": "Status badges via CoachingSessionReservationStatus. Timezone note 'Saatler {timezone} saat dilimine göredir.' ReservationRowActions namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Login page",
  "route": "/[organizationSlug]/giris",
  "titleTR": "Teachfluence Hesabına Giriş Yap",
  "purpose": "Student sign-in. Renders the org's Puck-authored 'giris' page if configured, else a hardcoded fallback (NavigationSection + Login block).",
  "layout": "Fallback: NavigationSection + Login block (email OTP + Google + password, googleFirst order, divider). Org-customizable via page builder.",
  "states": [
   "loading"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Login block (editor)",
   "NavigationSection"
  ],
  "actions": [
   "Giriş Yap (Google / email OTP / password)"
  ],
  "gating": "public",
  "dataSources": [
   "renderOrganizationPageOrNull('giris')"
  ],
  "notes": "Supports ?next= redirect (used by LoginToViewPage). Login block flags: emailOtpLogin, googleLogin, passwordLogin. Title PageTitles.signIn.",
  "cluster": "student-app"
 },
 {
  "surface": "Forgot password (request reset)",
  "route": "/[organizationSlug]/sifremi-unuttum",
  "titleTR": "Şifremi unuttum",
  "purpose": "Request a password-reset email (anti-enumeration: generic success regardless of account existence).",
  "layout": "Centered Card. Form state: 'Şifremi unuttum' / 'Hesabınızın e-posta adresini girin...' + E-posta input + 'Sıfırlama bağlantısı gönder' + 'Girişe dön'. Sent state: 'E-postanızı kontrol edin' / 'Bu e-posta adresine kayıtlı bir hesap varsa, şifre sıfırlama bağlantısı gönderdik.' + 'Girişe dön'.",
  "states": [
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Form",
   "Input",
   "FormSubmitButton",
   "PiLink"
  ],
  "actions": [
   "Sıfırlama bağlantısı gönder",
   "Girişe dön"
  ],
  "gating": "public (uses org context)",
  "dataSources": [
   "RequestPasswordResetPageMutation (requestStudentPasswordReset)"
  ],
  "notes": "networkError root 'Bağlantı hatası. Lütfen tekrar deneyin.' PasswordReset namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Reset password",
  "route": "/[organizationSlug]/sifre-sifirla?token=",
  "titleTR": "Yeni şifre belirle",
  "purpose": "Set a new password via emailed token; auto-signs in on success.",
  "layout": "Centered Card. Valid: 'Yeni şifre belirle' + 'Yeni şifre' + 'Yeni şifre (tekrar)' (8-128 policy) + 'Şifreyi güncelle'. Invalid/expired/missing token: InvalidTokenCard 'Bağlantı geçersiz' / 'Yeni bağlantı iste' + 'Girişe dön'.",
  "states": [
   "error",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Form",
   "Input",
   "FormSubmitButton",
   "PiLink"
  ],
  "actions": [
   "Şifreyi güncelle",
   "Yeni bağlantı iste",
   "Girişe dön"
  ],
  "gating": "token required; server rejects bad/expired/used → InvalidTokenCard",
  "dataSources": [
   "ResetPasswordPageMutation (resetStudentPassword → credentials.accessToken)"
  ],
  "notes": "Clears anonymous cart on success. passwordMismatch 'Şifreler eşleşmiyor.' PasswordReset namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Terms / legal acceptance",
  "route": "/[organizationSlug]/terms-acceptance?next=",
  "titleTR": "Yasal Belgeleri Kabul Et",
  "purpose": "Gate requiring the student to read & accept pending legal documents before continuing to ?next.",
  "layout": "Multi-document stepper: 'Belge {current}/{total}', scrollable document body (Potion/HTML), 'Kabul etmek için belgeyi sonuna kadar okuyun', checkbox '\"{title}\" belgesini okudum ve kabul ediyorum', 'Kabul Et ve Devam Et' / 'Sonraki Belge'.",
  "states": [
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Checkbox",
   "Button",
   "ScrollArea",
   "PotionRenderer"
  ],
  "actions": [
   "Kabul Et ve Devam Et",
   "Sonraki Belge"
  ],
  "gating": "notFound if org missing; open-redirect-safe next validation",
  "dataSources": [
   "TermsAcceptancePageQuery (organization legal documents)"
  ],
  "notes": "acceptError 'Belgeler kabul edilemedi'. Legal + PageTitles.acceptTerms namespaces.",
  "cluster": "student-app"
 },
 {
  "surface": "Subscription plans / overview",
  "route": "/[organizationSlug]/abonelik",
  "titleTR": "Abonelik Planları",
  "purpose": "Show subscription tiers to subscribe to, or manage the viewer's current subscription (status, billing, tier change, cancel, card update).",
  "layout": "Not subscribed: 'Abonelik Planları' / 'Size uygun abonelik planını seçin' with tier cards (features list, price with cadence ay/hafta/3 ay/6 ay/yıl, 'Abone Ol', trial '{days} gün ücretsiz deneme'). Subscribed: StudentSubscriptionOverview card — status badge, 'Mevcut Planınız', included features, next billing / current period / trial end, alerts (Ödeme Gecikti / İptal Planlandı / Plan Değişikliği Planlandı), CTAs 'Plan Değiştir' / 'Aboneliği İptal Et' / 'Kartı Güncelle' / 'Özel İçeriklere Eriş'.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Badge",
   "Alert",
   "Collapsible",
   "OrgSubscriptionTierSelector",
   "Button"
  ],
  "actions": [
   "Abone Ol",
   "Plan Değiştir",
   "Aboneliği İptal Et",
   "Kartı Güncelle",
   "Ücretli Plana Geç (trial conversion)"
  ],
  "dialogs": [
   "ChangeTierDialog",
   "StudentCancelSubscriptionDialog",
   "StudentChangeCardDialog"
  ],
  "gating": "membership; noPaymentMethodAvailable guard",
  "dataSources": [
   "StudentSubscriptionPageQuery (org subscription products/tiers/pricing + viewer subscription status/period/tier)"
  ],
  "notes": "Empty: 'Abonelik Bulunamadı' / 'Şu anda aktif bir abonelik ürünü bulunmuyor.' Status enum PENDING/TRIALING/ACTIVE/PAST_DUE/CANCELED/EXPIRED. StudentSubscription namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Change tier dialog",
  "route": "/[organizationSlug]/abonelik (modal)",
  "titleTR": "Plan Değiştir",
  "purpose": "Preview & confirm upgrade/downgrade with proration.",
  "layout": "Dialog: Mevcut Plan / Yeni Plan selector, Yükseltme/Düşürme badge, Mevcut fiyat / Yeni fiyat / Kalan süre için kredi / Ödenecek tutar / Geçerlilik tarihi, note 'Plan düşürme mevcut dönem sonunda geçerli olacaktır.', 'Şimdi Yükselt' / 'Dönem Sonunda Değiştir' / 'Değişikliği Onayla' / 'Vazgeç'.",
  "states": [
   "loading",
   "error",
   "empty"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Dialog",
   "ChangeTierDialog",
   "OrgSubscriptionTierSelector"
  ],
  "actions": [
   "Şimdi Yükselt",
   "Dönem Sonunda Değiştir",
   "Değişikliği Onayla",
   "Vazgeç"
  ],
  "gating": "requires other tiers ('Değiştirilebilecek başka plan bulunmuyor.')",
  "dataSources": [
   "tier change preview + change mutations"
  ],
  "notes": "StudentSubscription.changeTier namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Cancel subscription dialog",
  "route": "/[organizationSlug]/abonelik (modal)",
  "titleTR": "Aboneliği İptal Et",
  "purpose": "Cancel immediately or at period end with optional reason.",
  "layout": "Dialog: choose 'Hemen İptal Et' (warning: erişiminiz sona erer) or 'Dönem Sonunda İptal Et' ('{date} tarihine kadar aktif kalacaktır'), 'İptal Sebebi (isteğe bağlı)' textarea, 'Aboneliği İptal Et' / 'Aboneliğimi Koru'.",
  "states": [
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Dialog/AlertDialog",
   "Textarea",
   "Button"
  ],
  "actions": [
   "Hemen İptal Et",
   "Dönem Sonunda İptal Et",
   "Aboneliği İptal Et",
   "Aboneliğimi Koru"
  ],
  "gating": "",
  "dataSources": [
   "cancel subscription mutation"
  ],
  "notes": "StudentSubscription.cancel namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Change card dialog",
  "route": "/[organizationSlug]/abonelik (modal)",
  "titleTR": "Ödeme Yöntemini Güncelle",
  "purpose": "Add a new card for the subscription (1 TL verification hold refunded).",
  "layout": "Dialog: 'Aboneliğiniz için yeni bir kart ekleyin.', notice 'Kart doğrulaması için 1 TL tutarında bir işlem yapılacak ve otomatik olarak iade edilecektir.', card form fields, 'Kartı Güncelle'.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Dialog",
   "StudentChangeCardDialog",
   "payment form"
  ],
  "actions": [
   "Kartı Güncelle"
  ],
  "gating": "",
  "dataSources": [
   "change card mutation / provider iframe"
  ],
  "notes": "Success/fail toasts (Kart Güncellendi / Kart Güncellenemedi). StudentSubscription.changeCard/cardUpdate.",
  "cluster": "student-app"
 },
 {
  "surface": "Subscription checkout",
  "route": "/[organizationSlug]/abonelik/odeme?subscriptionId=",
  "titleTR": "Ödeme",
  "purpose": "Pay for a pending subscription (order summary + card form / provider iframe).",
  "layout": "Two-column: 'Sipariş Özeti' (tier, price/cadence, trial) + 'Ödeme' panel with card fields (Kart Numarası, Kart Sahibinin Adı, Son Kullanma Tarihi AA/YY, CVC) or provider iframe, 'Ödemeyi Tamamla' / 'Güvenli ödeme'. Guards: redirect to /abonelik if no subscriptionId; 'Fiyat Bulunamadı' / 'Ödeme Gerekli Değil' states.",
  "states": [
   "loading",
   "error",
   "empty"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "payment form / provider iframe",
   "Button"
  ],
  "actions": [
   "Ödemeyi Tamamla / Ödemeye Devam Et",
   "Planlara Dön",
   "Tekrar Dene"
  ],
  "gating": "subscriptionId required; must be payable (subscriptionAlreadyActive / subscriptionCancelled / subscriptionNotPayable)",
  "dataSources": [
   "SubscriptionCheckoutPageQuery (subscription by id)"
  ],
  "notes": "iframe postMessage flow to basarili/basarisiz sub-pages. StudentSubscription.checkout + PageTitles.payment.",
  "cluster": "student-app"
 },
 {
  "surface": "Subscription payment success",
  "route": "/[organizationSlug]/abonelik/odeme/basarili",
  "titleTR": "Ödeme Başarılı",
  "purpose": "Confirmation after subscription payment; fires GTM/Meta purchase; iframe-aware.",
  "layout": "Centered Card: green CheckCircle2Icon, 'Ödeme Başarılı', 'Aboneliğiniz aktifleştirildi.', 'Aboneliğimi Görüntüle'. Iframe mode: minimal check icon + 'Ödeme Başarılı'.",
  "states": [],
  "priority": "secondary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "CheckCircle2Icon",
   "Button/Link"
  ],
  "actions": [
   "Aboneliğimi Görüntüle"
  ],
  "gating": "",
  "dataSources": [
   "GTM purchase event, Meta Pixel trackPurchase"
  ],
  "notes": "StudentSubscription.checkout.paymentSuccessful/subscriptionActivated.",
  "cluster": "student-app"
 },
 {
  "surface": "Subscription payment failure",
  "route": "/[organizationSlug]/abonelik/odeme/basarisiz",
  "titleTR": "Ödeme Başarısız",
  "purpose": "Failure screen after subscription payment.",
  "layout": "Centered Card: red XCircleIcon, 'Ödeme Başarısız', 'Ödemeniz işlenemedi. Lütfen tekrar deneyin.', 'Tekrar Dene' (if subscriptionId) + 'Planlara Dön'. Iframe mode: minimal.",
  "states": [],
  "priority": "secondary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "XCircleIcon",
   "Button/Link"
  ],
  "actions": [
   "Tekrar Dene",
   "Planlara Dön"
  ],
  "gating": "",
  "dataSources": [],
  "notes": "postMessage to parent when iframe. StudentSubscription.checkout.paymentFailed.",
  "cluster": "student-app"
 },
 {
  "surface": "My Orders (Siparişlerim)",
  "route": "/[organizationSlug]/siparisler",
  "titleTR": "Siparişlerim",
  "purpose": "Student's purchase history + sent/received gifts, with status filtering.",
  "layout": "Nav section + container. Header ShoppingCartIcon + 'Siparişlerim' + 'Siparişlerini ve hediyelerini buradan takip edebilirsin.' Tabs: 'Siparişlerim' / 'Gönderdiğim Hediyeler' / 'Aldığım Hediyeler'. Orders tab: right-aligned status filter dropdown (multi-select checkboxes, 'Tüm Durumlar' / '{count} durum seçili'), infinite list of StudentOrderCard + StudentSubscriptionPaymentCard (mixed union feed). Gifts tabs: SentGiftsList / ReceivedGiftsList.",
  "states": [
   "loading",
   "empty"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Tabs",
   "DropdownMenu (checkbox filter)",
   "StudentOrderCard",
   "StudentSubscriptionPaymentCard",
   "SentGiftsList",
   "ReceivedGiftsList",
   "Skeleton"
  ],
  "tabs": [
   "Siparişlerim",
   "Gönderdiğim Hediyeler",
   "Aldığım Hediyeler"
  ],
  "filters": [
   "Duruma Göre Filtrele (OrderStatus multi-select: BILLING_PENDING/COMPLETED/FAILED/PARTIALLY_REFUNDED/PAYMENT_PENDING/PROVISIONAL_SUCCESS/REFUND_REQUESTED/REFUNDED/REGISTER_PENDING/TIMED_OUT)"
  ],
  "actions": [
   "Detayları Gör (order card)",
   "Daha Fazla Yükle",
   "Aboneliği Gör (subscription payment card)"
  ],
  "dialogs": [],
  "gating": "requires viewerStudent else redirect /",
  "dataSources": [
   "StudentOrdersPageQuery",
   "StudentOrdersList_organization (viewerPurchases connection, union Order|StudentOrgSubscriptionPayment)",
   "StudentOrderCard_order",
   "StudentSubscriptionPaymentCard_payment"
  ],
  "notes": "Empty 'Henüz siparişin yok'. Filter note: status filter excludes subscription payments. Order card shows '{count} ürün', 'Boş Sipariş', 'Detayları Gör'. Payment card status labels (Bekliyor/Yanıt Bekleniyor/Başarılı/Başarısız/İade Edildi) + type labels (İlk Ödeme/Yinelenen/Yükseltme/Yeniden Deneme).",
  "cluster": "student-app"
 },
 {
  "surface": "Cart (Sepet)",
  "route": "/[organizationSlug]/sepet",
  "titleTR": "Sepetim",
  "purpose": "Shopping cart with line items, coupon, gift options, and checkout.",
  "layout": "Cart items list (type labels Eğitim/Paket/Birebir Görüşme, session count) + Sipariş Özeti panel (İndirim Kodu input + Uygula, Ara Toplam, İndirim, Toplam, 'Siparişi Tamamla'). Gift toggle 'Hediye olarak gönder' → gift details (Teslimat Yöntemi E-posta/Link, Alıcı E-posta, Alıcı Adı). Empty: 'Sepetiniz boş' / 'Sepetinizde henüz ürün bulunmuyor...' + 'Kurslarıma Git'.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Input (coupon)",
   "Button",
   "GiftDetailsForm"
  ],
  "actions": [
   "Uygula (coupon)",
   "Siparişi Tamamla",
   "Kaldır (remove item)",
   "Hediye olarak gönder",
   "Kurslarıma Git"
  ],
  "gating": "public/anonymous cart supported",
  "dataSources": [
   "CartPageQuery"
  ],
  "notes": "Commerce/checkout surface in student route group — may also belong to a checkout canvas. CartPage namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Create Order (checkout entry)",
  "route": "/[organizationSlug]/siparis?course=|coaching=|bundle=|digitalProduct=|liveEvent=|plan=",
  "titleTR": "Siparişin oluşturuluyor...",
  "purpose": "Direct-buy entry: builds an order for a single orderable then redirects to the order page.",
  "layout": "Transitional 'Siparişin oluşturuluyor...' state, then redirect to /siparis/[slug]. notFound if no orderable query param.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "CreateOrderPage"
  ],
  "actions": [],
  "gating": "requires a valid orderable query param",
  "dataSources": [
   "CreateOrderPageQuery (course/coaching/bundle/digitalProduct/liveEvent by slug + plan)",
   "create order mutation"
  ],
  "notes": "Commerce entry point. CreateOrder namespace ('Sipariş oluşturulamadı').",
  "cluster": "student-app"
 },
 {
  "surface": "Order detail / payment",
  "route": "/[organizationSlug]/siparis/[slug]",
  "titleTR": "Sipariş",
  "purpose": "Full checkout for an order: account info, billing info, gift additions, order summary, and payment.",
  "layout": "Sections: Hesap Bilgileri, Fatura Bilgileri (or Makbuz Bilgileri), gift add-on ('Bunu da hediye et!'), Sipariş Özeti (Toplam, Toplam İndirim, Ödenen (Taksitli)), Ödeme Seçenekleri + 'Öde'. Free-order: 'Ücretsiz Siparişinizi Tamamlayın' + 'Siparişi Tamamla'. Payment failure alerts. Success view: 'Ödeme Başarılı!' / 'Hemen öğrenmeye başla.'",
  "states": [
   "loading",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "BillingForm",
   "PaymentForm",
   "PaymentProvider iframe",
   "OrderPromotions",
   "GiftDetailsForm",
   "Card"
  ],
  "actions": [
   "Öde",
   "Siparişi Tamamla (free)",
   "Bunu da hediye et!",
   "Kaldır (item)"
  ],
  "dialogs": [
   "Gift recipient chooser (Bu hediyeyi kim alsın?)"
  ],
  "gating": "order ownership",
  "dataSources": [
   "OrderPageQuery (order + organization)",
   "OrderSuccessDataRefetch",
   "createOrder/pay mutations"
  ],
  "notes": "Commerce/checkout surface in student route group. Order + OrderPage + OrderSuccessPage namespaces. Providers Stripe/Iyzico/PayTR.",
  "cluster": "student-app"
 },
 {
  "surface": "Gift redemption",
  "route": "/[organizationSlug]/hediye?token=",
  "titleTR": "Hediye",
  "purpose": "Redeem a gifted product into the viewer's account.",
  "layout": "Card: '{name} sana bir hediye gönderdi!' / 'Sana bir hediye gönderildi!', 'Hediye İçeriği' item list, 'Hediyeni Almaya Hazırsın!' + 'Hediyeyi Al'. State variants: login-required ('Giriş Gerekli'), pending-payment ('Hediye Henüz Hazır Değil'), not-found, already-redeemed (by others / by you).",
  "states": [
   "empty",
   "permission-denied",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Button"
  ],
  "actions": [
   "Hediyeyi Al",
   "Giriş Yap"
  ],
  "gating": "token required; login required to redeem",
  "dataSources": [
   "OrganizationGiftRedemptionPageQuery (gift by token)"
  ],
  "notes": "GiftRedemptionPage namespace. Invalid token → 'Hediye Bulunamadı'.",
  "cluster": "student-app"
 },
 {
  "surface": "Invitation acceptance",
  "route": "/[organizationSlug]/davet?token=",
  "titleTR": "Davet kodunuzu girin",
  "purpose": "Accept an organization invitation (also a manual code-entry page under the 'davet' namespace).",
  "layout": "InvitationPage from token; notFound on unknown/expired. Manual code-entry variant: 'Davet kodunuzu girin' / 'Size paylaşılan davet kodunu aşağıya yazın.' + code input + 'Daveti aç'.",
  "states": [
   "permission-denied",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "OrganizationInvitationPage",
   "Input",
   "Button"
  ],
  "actions": [
   "Daveti aç / Kabul Et"
  ],
  "gating": "valid token required (notFound otherwise)",
  "dataSources": [
   "OrganizationInvitationPageQuery (invitation by token)"
  ],
  "notes": "InvitationStatus enum PENDING/ACCEPTED/CANCELED/EXPIRED. noindex/nofollow. davet namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Student settings (Ayarlar)",
  "route": "/[organizationSlug]/ayarlar",
  "titleTR": "Ayarlar",
  "purpose": "Manage profile (name, image, email), preferred locale/timezone, custom fields, email preferences, password/security, and accepted legal documents.",
  "layout": "Nav section + profile form: İsim, Soyisim, Profil Resmi, Email (admin-only note), custom fields, Tercih Edilen Dil (İngilizce/Almanca/Türkçe), Tercih Edilen Saat Dilimi, 'Profilini Güncelle'. Cards: 'Kabul Edilen Sözleşmeler' (StudentAcceptedLegalDocuments — 'Kabul tarihi: {date}', 'Görüntüle', empty 'Henüz kabul edilmiş belge yok'), PasswordSecurityCard, EmailPreferencesForm ('E-posta Tercihleri' — Pazarlama/Kayıt/Rezervasyon/Üyelik bildirimleri toggles + suppression banner).",
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "OrganizationStudentSettings",
   "CustomFieldFormInput",
   "PasswordSecurityCard",
   "EmailPreferencesForm",
   "StudentAcceptedLegalDocuments",
   "Card",
   "Select",
   "Switch"
  ],
  "actions": [
   "Profilini Güncelle",
   "Tercihleri kaydet (email)",
   "Görüntüle (documents)",
   "change password"
  ],
  "dialogs": [
   "Document viewer"
  ],
  "gating": "member; some fields admin-only ('Bu bilgiyi yalnızca organizasyon yöneticileri değiştirebilir.')",
  "dataSources": [
   "OrganizationStudentSettingsPageQuery"
  ],
  "notes": "OrganizationStudentSettings + Student.EmailPreferences namespaces.",
  "cluster": "student-app"
 },
 {
  "surface": "Digital product delivery (post-purchase download)",
  "route": "/[organizationSlug]/dijital-urun-teslimat?token=",
  "titleTR": "Dijital Ürün Teslimatı",
  "purpose": "Token-gated per-visitor download page for a purchased digital product (watermarked personal copy).",
  "layout": "Card 'Dijital ürün teslimatı' / 'Satın aldığınız ürünün belgelerini aşağıdan indirebilirsiniz.' States: preparing ('Kişisel kopyanız hazırlanıyor…' / 'Sırada bekliyor…'), ready ('Dosyanız hazır' + 'İndir'), no-documents ('Bu ürün için indirilebilir belge bulunmuyor.'). Invalid/missing token: InvalidLinkCard 'Bağlantı geçersiz veya süresi dolmuş'.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "Card",
   "Button",
   "InvalidLinkCard"
  ],
  "actions": [
   "İndir"
  ],
  "gating": "token required; noindex/nofollow, force-dynamic",
  "dataSources": [
   "DigitalProductDeliveryPageQuery (by token)"
  ],
  "notes": "DigitalProductDelivery namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Certificate (public) page",
  "route": "/[organizationSlug]/certificates/[certificateId]",
  "titleTR": "{studentName} - {courseTitle} Sertifikası",
  "purpose": "Publicly-shareable rendered course-completion certificate with share/download actions.",
  "layout": "CertificateRenderer (visual certificate: '{name} adına verilmiştir', '{date} tarihinde verildi', verifiedBy org). CertificateActions bar: 'Bağlantıyı Kopyala', 'LinkedIn'e Ekle', 'PNG İndir', 'PDF İndir'. Revoked variant: 'Bu Sertifika İptal Edildi' / 'Bu sertifika artık geçerli değildir.' + revoke date/reason. Not-found: 'Sertifika Bulunamadı'.",
  "states": [
   "empty",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "CertificateRenderer",
   "CertificateActions",
   "Button"
  ],
  "actions": [
   "Bağlantıyı Kopyala",
   "LinkedIn'e Ekle",
   "PNG İndir",
   "PDF İndir"
  ],
  "gating": "public (OG/Twitter meta for sharing)",
  "dataSources": [
   "PublicCertificatePageQuery (studentCertificate: organizationStudent, courseAcademicTerm.course.organization)"
  ],
  "notes": "Public.Certificates namespace. html2canvas + pdf-lib client export.",
  "cluster": "student-app"
 },
 {
  "surface": "Certificate claim card (in-course)",
  "route": ".../dersler/ogren/[courseSlug]/[academicTermSlug] (embedded)",
  "titleTR": "Sertifika",
  "purpose": "Shows certificate eligibility/progress inside the course and lets the student claim it.",
  "layout": "Card 'Sertifika' with criteria text (completeAll / '%{percentage}'sini tamamlayarak' / specificItems / noCriteria), Progress bar + '%{current} tamamlandı (gerekli: %{required})' or '{completed}/{total} içerik tamamlandı', reason when locked (notEnrolled/incomplete), 'Sertifika Al' → 'Alınıyor...' or 'Sertifikayı Görüntüle' when already claimed. Admin preview note.",
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "priority": "secondary",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "CertificateClaimCard",
   "CertificateClaimCardSkeleton",
   "Progress",
   "Button",
   "ErrorBoundary"
  ],
  "actions": [
   "Sertifika Al",
   "Sertifikayı Görüntüle"
  ],
  "gating": "enrollment + completion criteria; admin sees preview note",
  "dataSources": [
   "certificate template criteriaType/criteriaConfig + student progress + claim mutation"
  ],
  "notes": "Student.Certificates namespace. loadError fallback.",
  "cluster": "student-app"
 },
 {
  "surface": "Login-to-view wall",
  "route": "any student page (client guard)",
  "titleTR": "Giriş gerekli",
  "purpose": "Shown when an anonymous viewer hits gated student content.",
  "layout": "ErrorLayout: 'Giriş gerekli', 'Bu içeriği görüntülemek için giriş yapmanız gerekiyor.', 'Giriş Yap' (→ /giris?next=current), hint 'Giriş yaptıktan sonra otomatik olarak bu sayfaya yönlendirileceksiniz.'",
  "states": [
   "permission-denied"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "LoginToViewPage",
   "ErrorLayout",
   "Button"
  ],
  "actions": [
   "Giriş Yap"
  ],
  "gating": "anonymous viewer",
  "dataSources": [],
  "notes": "AccessGate.student namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Access-denied wall (Request access)",
  "route": "any student page (client guard)",
  "titleTR": "Erişim reddedildi",
  "purpose": "Authenticated-but-unauthorized viewer for this org.",
  "layout": "ErrorLayout: 'Erişim reddedildi', 'Bu hesabın bu organizasyona erişim yetkisi bulunmuyor.', accountLabel 'Giriş yapılan hesap', actions 'Farklı bir hesapla giriş yap' (logout) + 'Ana sayfaya dön', hint 'Erişim almak için doğru hesapla giriş yapın ya da organizasyon yöneticinizle iletişime geçin.'",
  "states": [
   "permission-denied"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "RequestAccessPage",
   "ErrorLayout",
   "Button"
  ],
  "actions": [
   "Farklı bir hesapla giriş yap",
   "Ana sayfaya dön"
  ],
  "gating": "wrong-account/no-access",
  "dataSources": [
   "useLogout"
  ],
  "notes": "AccessGate.student + signedInAs/switchAccount/returnHome.",
  "cluster": "student-app"
 },
 {
  "surface": "Student route error boundary",
  "route": "/[organizationSlug]/(student) error.tsx",
  "titleTR": "Bir şeyler ters gitti",
  "purpose": "Catches unexpected server/render errors in student routes.",
  "layout": "ErrorLayout (warning tone): AlertTriangle, 'Bir şeyler ters gitti', 'Bu sayfa yüklenirken beklenmeyen bir sorun oluştu...', 'Tekrar dene' (RefreshCw reset), reference 'Hata kodu: {id}'.",
  "states": [
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "ErrorLayout",
   "Button",
   "AlertTriangle"
  ],
  "actions": [
   "Tekrar dene"
  ],
  "gating": "",
  "dataSources": [
   "Sentry.captureException"
  ],
  "notes": "AccessGate.serverError namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Not-found (org 404)",
  "route": "/[organizationSlug]/(student) not-found.tsx + /404",
  "titleTR": "Sayfa bulunamadı",
  "purpose": "Org-scoped 404 — tries custom NotFoundPage registry, then Puck-authored /404 page, then global fallback.",
  "layout": "AccessGate.notFound: 'Sayfa bulunamadı' / 'Aradığınız sayfa taşınmış, silinmiş ya da hiç var olmamış olabilir.' OR the org's custom-built 404 page.",
  "states": [
   "empty"
  ],
  "priority": "edge",
  "suggestedCanvas": "09-student-app",
  "keyComponents": [
   "ErrorLayout / custom NotFoundPage / Puck page"
  ],
  "actions": [
   "Ana sayfaya dön"
  ],
  "gating": "noindex",
  "dataSources": [
   "renderOrganizationPageOrNull('404')"
  ],
  "notes": "AccessGate.notFound namespace.",
  "cluster": "student-app"
 },
 {
  "surface": "Public storefront landing / marketing page (dynamic)",
  "route": "/[organizationSlug]/[[...slug]] — segment app/(student)/(integrations)/(website)/[[...slug]]/page.tsx",
  "titleTR": "(dynamic: web page SEO title | organization name)",
  "purpose": "Renders the organization's public website for any slug path: page-builder (Puck/EditorServerRender) web pages, custom code pages (coursuite/flu registries), or profile-page fallback. This is the org site students browse and buy from. Wrapped in OrganizationWebsiteThemeLayout (org theme/rootData).",
  "layout": "Full-bleed themed site page rendered from the org's page-builder tree (blocks/zones composed via composePageContentWithZones); org navbar + footer come from the theme layout. Resolution cascade: exact custom page -> web page -> wildcard custom page -> notFound.",
  "states": [
   "loaded",
   "not-found",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "OrganizationWebsiteThemeLayout",
   "EditorServerRender",
   "ProfilePageRenderer",
   "custom-pages registry"
  ],
  "dataSources": [
   "OrganizationResolvedPageQuery",
   "loadOrganizationMetadataSource",
   "renderOrganizationPageOrNull",
   "websiteSettings.faviconUrl/rootData/themePreference"
  ],
  "notes": "revalidate=0 (per-request, authenticated favicon lookup). Has a cached public twin at /[organizationSlug]/cached/[[...slug]].",
  "cluster": "storefront"
 },
 {
  "surface": "Public storefront landing (cached public twin)",
  "route": "/[organizationSlug]/cached/[[...slug]] — app/[organizationSlug]/cached/[[...slug]]/page.tsx",
  "titleTR": "(dynamic web page title; canonical URL honors verified custom domain)",
  "purpose": "5-minute-cached (revalidate=300) public render of the org website for anonymous/SEO traffic. Branches: content page (blog CMS), content category page, gated Puck web page, profile-page renderer, custom page, site-setup placeholder, notFound.",
  "layout": "Same themed page-builder render as the dynamic twin, plus defense-in-depth access gate computed before profile branch; permanentRedirect on legacy slug; renders SiteSetupPlaceholder when the site is not yet published/connected.",
  "states": [
   "loaded",
   "empty",
   "permission-denied",
   "not-found",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "EditorServerRender",
   "FullPageGate",
   "SiteSetupPlaceholder",
   "ProfilePageRenderer"
  ],
  "dataSources": [
   "OrganizationActivePageQuery",
   "ProfilePageRendererQuery",
   "loadPublicSerializableQuery(WithTags)",
   "orgProductPagesTag"
  ],
  "notes": "error.tsx + not-found.tsx present in cached/ segment.",
  "cluster": "storefront"
 },
 {
  "surface": "Site setup placeholder (site not published)",
  "route": "rendered inside /[organizationSlug]/cached/[[...slug]] via SiteSetupPlaceholder",
  "titleTR": "Site çok yakında / Site hazırlanıyor",
  "purpose": "Shown when a custom domain is connecting or the org site is unpublished, instead of a raw 404.",
  "layout": "Centered card: title + description. Two variants: 'connecting' (Site hazırlanıyor / 'Bu alan adı bağlanıyor...') and 'unpublished' (Site çok yakında / '{orgName} sitesi henüz yayında değil...').",
  "states": [
   "empty"
  ],
  "priority": "edge",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "SiteSetupPlaceholder",
   "ErrorLayout"
  ],
  "dataSources": [
   "AccessGate.siteSetup messages",
   "shouldShowSiteSetupPlaceholder"
  ],
  "notes": "TR from AccessGate.siteSetup.*",
  "cluster": "storefront"
 },
 {
  "surface": "Full-page access gate (password / restricted / login-required)",
  "route": "rendered inside cached/[[...slug]] via FullPageGate",
  "titleTR": "Bu sayfa parola korumalı / Erişiminiz yok / Giriş gerekli",
  "purpose": "Blocks a gated web page. Password-protected pages show an unlock form; restricted pages show a denial; login-required pages prompt sign-in.",
  "layout": "Centered gate card. Password variant: 'Parola' label + 'Sayfa parolası' placeholder + 'Kilidi aç' button (states: 'Açılıyor…', errors: hatalı/rate-limited/expired). Restricted: 'Erişiminiz yok' + description + 'Giriş yapılan hesap' / 'Farklı bir hesapla giriş yap' / 'Ana sayfaya dön'. Student login: 'Giriş Yap'.",
  "states": [
   "permission-denied",
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "FullPageGate",
   "ErrorLayout",
   "Button",
   "Input"
  ],
  "dataSources": [
   "getGateKind",
   "AccessGate.password/restricted/student/section messages"
  ],
  "actions": [
   "Kilidi aç",
   "Farklı bir hesapla giriş yap",
   "Ana sayfaya dön",
   "Giriş Yap"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Cart (Sepetim)",
  "route": "/[organizationSlug]/sepet",
  "titleTR": "Sepetim",
  "purpose": "Shopping cart: review orderables, apply/remove coupon, optionally mark items as gift, and start checkout (createOrder). Works for logged-in and anonymous (localStorage cartId) viewers.",
  "layout": "Storefront navbar + 2-col grid (max-w-4xl). Left: item cards (image, title, product-type label 'Eğitim/Paket/Birebir Görüşme', selected reservation slot 'Seçilen Randevu', trash remove, per-item gift toggle 'Hediye olarak gönder' expanding to a gift form). Right: sticky 'Sipariş Özeti' card — applied coupon chips (X to remove), coupon input 'İndirim Kodu' + 'Uygula', 'Ara Toplam' / 'İndirim' / 'Toplam', 'Siparişi Tamamla' button. Below: CartRecommendations.",
  "states": [
   "loading",
   "empty",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "filters": [],
  "actions": [
   "Uygula",
   "Siparişi Tamamla",
   "Hediye olarak gönder",
   "(remove item)",
   "(remove coupon)"
  ],
  "dialogs": [
   "Per-item gift form (Teslimat Yöntemi E-posta/Link, Alıcı E-posta, Alıcı Adı, Kişisel Mesaj)"
  ],
  "keyComponents": [
   "Card",
   "Checkbox",
   "RadioGroup",
   "Input",
   "Textarea",
   "Separator",
   "CartRecommendations"
  ],
  "dataSources": [
   "CartPageQuery",
   "CartPageAnonymousCartQuery",
   "CartPageAddCouponMutation",
   "CartPageRemoveCouponMutation",
   "CartPageRemoveItemMutation",
   "CartPageCreateOrderMutation",
   "viewerCart{originalPrice,sellingPrice,discountedPrice,orderables,promotions}"
  ],
  "notes": "On checkout redirects to /siparis/{slug}. TR in CartPage.*",
  "cluster": "storefront"
 },
 {
  "surface": "Cart empty state",
  "route": "/[organizationSlug]/sepet (empty)",
  "titleTR": "Sepetiniz boş",
  "purpose": "Shown when cart has no orderables.",
  "layout": "Centered card: ShoppingCart icon, 'Sepetiniz boş', 'Sepetinizde henüz ürün bulunmuyor. Eğitimlerimize göz atın!', 'Kurslarıma Git' button.",
  "states": [
   "empty"
  ],
  "priority": "edge",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "Kurslarıma Git"
  ],
  "keyComponents": [
   "Card",
   "Button"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Create order redirect (Siparişin oluşturuluyor)",
  "route": "/[organizationSlug]/siparis?course|coaching|bundle|digitalProduct|liveEvent|plan=...",
  "titleTR": "(none — transient)",
  "purpose": "Direct 'buy now' entry: reads product query params, calls createOrder, then redirects to /siparis/{slug}. No visible UI beyond a status line.",
  "layout": "Minimal page with a single status line: 'Siparişin oluşturuluyor...' or 'Sipariş oluşturulamadı.' on error. notFound() when no product param or unorderable.",
  "states": [
   "loading",
   "error",
   "not-found"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "dataSources": [
   "CreateOrderPageQuery(course/coachingSession/plan/bundle/digitalProduct/liveEvent)",
   "CreateOrderPageCreateOrderMutation"
  ],
  "notes": "TR in CreateOrder.*",
  "cluster": "storefront"
 },
 {
  "surface": "Checkout / Order page (Sipariş)",
  "route": "/[organizationSlug]/siparis/[slug]",
  "titleTR": "Sipariş | {organization name}",
  "purpose": "Main checkout for a PAYMENT_PENDING order: order summary + gift info + 3-step accordion (account info, billing info, payment). Also renders success/failed/expired states for the same order.",
  "layout": "Two-column: left order summary ('Sipariş Özeti', line items via OrderLineItem, gift-order note 'Bu sipariş hediye içeriyor', 'Bunu da hediye et!' upsell card, OrderPromotions, 'Toplam'/'Toplam İndirim'/'Ödenen (Taksitli)'). Right accordion: 'Hesap Bilgileri' (StudentInformationStep), 'Fatura Bilgileri'/'Makbuz Bilgileri' (BillingInformationStep), 'Ödeme' (payment step: FreeOrderCompletionStep OR PiPaytrPaymentStep OR PaytrPaymentStep OR provider card 'ile öde'/'Öde'). Payment-failed alert + 'Tekrar Dene'. Expired: 'Sipariş zaman aşımına uğradı...' + 'Ana sayfaya dön'.",
  "states": [
   "loading",
   "error",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "Öde",
   "Tekrar Dene",
   "Siparişi Tamamla (free)",
   "Devam Et",
   "Ana sayfaya dön",
   "Bunu da hediye et!"
  ],
  "dialogs": [
   "GiftThisDialog (Hediye Olarak Gönder)"
  ],
  "keyComponents": [
   "Accordion",
   "Card",
   "Alert",
   "OrderLineItem",
   "OrderPromotions",
   "OrderRecommendations",
   "StudentInformationStep",
   "BillingInformationStep",
   "PaytrPaymentStep",
   "PiPaytrPaymentStep",
   "FreeOrderCompletionStep"
  ],
  "dataSources": [
   "OrderPageQuery",
   "OrderPage_order fragment",
   "OrderPageCreateOrderTransactionMutation",
   "OrderPageOrderProvisionalApproveMutation",
   "order.status/activeTransaction/activePaymentMethods"
  ],
  "notes": "Status branching: PAYMENT_PENDING=checkout; COMPLETED/BILLING/PROVISIONAL/REGISTER/REFUND*=OrderSuccessPage; TIMED_OUT=expired. TR in OrderPage.*",
  "cluster": "storefront"
 },
 {
  "surface": "Order success (Ödeme Başarılı)",
  "route": "/[organizationSlug]/siparis/[slug] (completed/paid states)",
  "titleTR": "Ödeme Başarılı!",
  "purpose": "Post-purchase confirmation for a completed/paid/refund-state order; shows purchased items grouped by gift vs 'for you', totals, and start-learning CTAs.",
  "layout": "'Teşekkürler!' + 'Ödeme Başarılı!' + 'Hemen öğrenmeye başla.' / 'Hedifeleriniz gönderilmeye hazır.'; 'Siparişin' item list (OrderLineItem, 'Senin için' / '{name} için hediye' / 'Bağlantı ile paylaş' groups); 'Toplam' / 'Toplam İndirim' (Otomatik İndirim) / 'Ödenen (Taksitli)'. Processing state: 'Ödemeniz işleniyor...' with OrderSuccessDataRefetchLoop polling.",
  "states": [
   "loading",
   "loaded"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "OrderSuccessPage",
   "OrderLineItem",
   "OrderSuccessDataRefetchLoop"
  ],
  "dataSources": [
   "OrderSuccessPage_order fragment"
  ],
  "notes": "TR in OrderSuccessPage.*; item CTAs 'Öğrenmeye Başla'/'Randevu Oluştur'/'Etkinliğe Git'/'Ürüne Git'.",
  "cluster": "storefront"
 },
 {
  "surface": "Gift-this upsell dialog",
  "route": "modal from /siparis/[slug] ('Bunu da hediye et!')",
  "titleTR": "Hediye Olarak Gönder",
  "purpose": "Add a recommended orderable to the current order as a gift; choose an existing gift recipient or a new person/link recipient.",
  "layout": "Dialog: 'Sevdiklerinize hediye olarak gönderin', recipient chooser ('Bu hediyeyi kim alsın?' — '{name} için hediyeye ekle' / 'Farklı birine gönder' / 'Bağlantı ile paylaş'), 'Devam'/'İptal', adding state 'Ekleniyor...'.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "GiftThisDialog",
   "Dialog",
   "RadioGroup"
  ],
  "dataSources": [
   "OrderPage_giftableRecommendations",
   "addGiftToOrder mutation"
  ],
  "actions": [
   "Devam",
   "İptal"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Student information step",
  "route": "accordion step inside /siparis/[slug]",
  "titleTR": "Hesap Bilgileri",
  "purpose": "Collect/confirm the buyer email and any org-defined checkout custom fields before payment.",
  "layout": "Form: email field + custom fields (Seçiniz placeholders, required '*'), validation ('Lütfen geçerli bir e-posta adresi girin.', 'Bu alan zorunludur.', 'Lütfen geçerli bir URL girin.').",
  "states": [
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "StudentInformationStep",
   "CustomFieldInput",
   "Form"
  ],
  "dataSources": [
   "checkoutCustomFields util",
   "StudentInformationStep.CustomFields/Validation messages"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Billing information step",
  "route": "accordion step inside /siparis/[slug]",
  "titleTR": "Fatura Bilgileri / Makbuz Bilgileri",
  "purpose": "Collect billing/invoice details (individual or corporate) required for the receipt/invoice; fields are configurable per org.",
  "layout": "Form: Ülke (combobox), Ad, Soyad, Adres, İl, İlçe, Telefon Numarası, 'Kurumsal Fatura' toggle -> T.C. Kimlik Numarası / Şirket Adı / Vergi Numarası (or Vergi/KDV Numarası intl) / Vergi Dairesi; 'Devam Et'. Extensive Zod validation strings (BillingForm.Validation).",
  "states": [
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "BillingInformationStep",
   "Combobox",
   "Input",
   "Checkbox"
  ],
  "dataSources": [
   "BillingInformationStep_order fragment",
   "billingFieldConfig util",
   "BillingForm messages"
  ],
  "actions": [
   "Devam Et"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Free order completion step",
  "route": "payment step inside /siparis/[slug] (0-price order)",
  "titleTR": "Ücretsiz Siparişinizi Tamamlayın",
  "purpose": "Complete a $0 order without card entry.",
  "layout": "'Bu sipariş ücretsizdir. Kaydınızı tamamlamak için aşağıya tıklayın.' + 'Siparişi Tamamla' button (busy: 'Sipariş tamamlanıyor...').",
  "states": [
   "loading",
   "error"
  ],
  "priority": "edge",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "FreeOrderCompletionStep"
  ],
  "dataSources": [
   "Order.freeOrder* messages"
  ],
  "actions": [
   "Siparişi Tamamla"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "PayTR / PiPaytr card payment step",
  "route": "payment step inside /siparis/[slug]",
  "titleTR": "Ödeme",
  "purpose": "Direct PayTR card form (PI_PAYTR) or embedded PayTR iframe checkout with installment options.",
  "layout": "Card form: 'Kart Numarası', 'Kart Üzerindeki İsim', 'Ay / Yıl', 'CVC' (+tooltip), installment select ('Tek Çekim' / '{count} Taksit' rows from PiPaytr installment rates), 'Devam Et', 'Ödemeler güvenli ve şifrelidir'. Ongoing state shows embedded iframe; error -> 'Ödeme Başarısız Oldu' alert.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "PaytrPaymentStep",
   "PiPaytrPaymentStep",
   "PaymentForm"
  ],
  "dataSources": [
   "PaytrPaymentStep_order",
   "PiPaytrPaymentStep_order",
   "PiPaytrPaymentStep_piPaytrInstallmentRates",
   "PaymentForm messages"
  ],
  "actions": [
   "Devam Et",
   "Öde"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "My Orders (Siparişlerim)",
  "route": "/[organizationSlug]/siparisler",
  "titleTR": "Siparişlerim",
  "purpose": "Student's purchase history plus sent/received gifts, across 3 tabs.",
  "layout": "Storefront navbar + page header (cart icon + 'Siparişlerim' + 'Siparişlerini ve hediyelerini buradan takip edebilirsin.'). Tabs: 'Siparişlerim' / 'Gönderdiğim Hediyeler' / 'Aldığım Hediyeler'. Orders tab: status filter dropdown ('Duruma Göre Filtrele', checkbox list of statuses, note 'Durum filtresi yalnızca siparişlere uygulanır...'), order cards (StudentOrderCard: '{count} ürün', 'Detayları Gör'), 'Daha Fazla Yükle' pagination.",
  "states": [
   "loading",
   "empty",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "tabs": [
   "Siparişlerim",
   "Gönderdiğim Hediyeler",
   "Aldığım Hediyeler"
  ],
  "filters": [
   "Durum (OrderStatus multi-select)"
  ],
  "actions": [
   "Daha Fazla Yükle",
   "Detayları Gör"
  ],
  "keyComponents": [
   "Tabs",
   "Skeleton",
   "StudentOrdersList",
   "SentGiftsList",
   "ReceivedGiftsList",
   "StudentOrderCard",
   "Select/Checkbox filter"
  ],
  "dataSources": [
   "StudentOrdersPageQuery",
   "StudentOrdersList_organization",
   "viewerPurchases(orderStatus)"
  ],
  "gating": "Requires viewerStudent (redirects to / if not a student)",
  "notes": "Empty: 'Henüz siparişin yok'; filtered no-match: 'Eşleşen sipariş yok'. force-dynamic. TR StudentOrdersPage.*/OrderStatus.*",
  "cluster": "storefront"
 },
 {
  "surface": "Sent / Received gifts lists",
  "route": "/[organizationSlug]/siparisler (sent/received tabs)",
  "titleTR": "Gönderdiğim Hediyeler / Aldığım Hediyeler",
  "purpose": "Lists gifts the student has sent or received, with status and details.",
  "layout": "Gift cards (GiftCard): status badge (Ödeme Bekleniyor/Kullanılabilir/Kullanıldı), Alıcı/Gönderen, Mesaj, Hediye İçeriği, dates, 'Bağlantıyı Kopyala'.",
  "states": [
   "loading",
   "empty"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "SentGiftsList",
   "ReceivedGiftsList",
   "GiftCard"
  ],
  "dataSources": [
   "GiftCard/GiftStatus messages"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Gift redemption (Hediye)",
  "route": "/[organizationSlug]/hediye?token=",
  "titleTR": "Hediye",
  "purpose": "Recipient lands from a gift link/email to preview and redeem a gift into their account.",
  "layout": "Storefront navbar + centered content. GiftPreview ('Sana Bir Hediye!', '{name} tarafından', 'Hediye İçeriği'). If logged in: 'Hediyeni Almaya Hazırsın!' card + 'Hediyeyi Al' button. If not: 'Hediyeyi almak için giriş yapman gerekiyor' + RegisterForm with info alert. States: REDEEMED success ('Hediye Başarıyla Alındı!' + item list), PENDING_PAYMENT ('Hediye Henüz Hazır Değil'), not-found/invalid token, already-redeemed.",
  "states": [
   "loaded",
   "empty",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "Hediyeyi Al",
   "Giriş Yap (register)"
  ],
  "keyComponents": [
   "GiftPreview",
   "GiftNotFoundOrRedeemed",
   "RegisterForm",
   "OrderLineItem",
   "Alert",
   "Card"
  ],
  "dataSources": [
   "OrganizationGiftRedemptionPageQuery(giftByToken)",
   "OrganizationGiftRedemptionPageRedeemGiftMutation",
   "GiftPreview_gift"
  ],
  "notes": "No/invalid token -> 'Geçersiz hediye bağlantısı' / GiftNotFoundOrRedeemed. force-dynamic. TR GiftRedemptionPage.*",
  "cluster": "storefront"
 },
 {
  "surface": "Digital product delivery (Dijital ürün teslimatı)",
  "route": "/[organizationSlug]/dijital-urun-teslimat?token=",
  "titleTR": "Dijital Ürün Teslimatı",
  "purpose": "Token-gated post-purchase download page for a digital product's documents.",
  "layout": "Storefront navbar + centered card. Heading 'Dijital ürün teslimatı' + product title + 'Satın aldığınız ürünün belgelerini aşağıdan indirebilirsiniz.'; document list (file icon, title, fileName · size, per-file download button 'İndir' with prepare/poll states 'Sırada bekliyor…' / 'Kişisel kopyanız hazırlanıyor…' / 'Dosyanız hazır'). Empty: 'Bu ürün için indirilebilir belge bulunmuyor.' Invalid/missing token: InvalidLinkCard ('Bağlantı geçersiz veya süresi dolmuş').",
  "states": [
   "loaded",
   "empty",
   "error"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "İndir"
  ],
  "keyComponents": [
   "DigitalProductDeliveryPage",
   "DigitalProductDeliveryDownloadButton",
   "DeliveryDownloadPollCoordinator",
   "Card"
  ],
  "dataSources": [
   "DigitalProductDeliveryPageQuery(digitalProductDelivery.product.documents)"
  ],
  "gating": "noindex, reads cookies, force-dynamic",
  "notes": "TR DigitalProductDelivery.*",
  "cluster": "storefront"
 },
 {
  "surface": "Student settings / profile (Ayarlar)",
  "route": "/[organizationSlug]/ayarlar",
  "titleTR": "Ayarlar | {organization name}",
  "purpose": "Student self-service profile settings for the org: name, avatar, preferred language/timezone, custom fields, accepted legal documents, and password/security.",
  "layout": "Storefront navbar + centered card 'Profilini Güncelle': Profil Resmi (ImageUploader/avatar), İsim, Soyisim, Email (admin-only note 'Bu bilgiyi yalnızca organizasyon yöneticileri değiştirebilir.'), Tercih Edilen Dil (select), Tercih Edilen Saat Dilimi (select), org custom fields (some 'Profilde gözükmez'), 'Güncelle' submit. Also 'Kabul Edilen Sözleşmeler' list ('Görüntüle') and 'Güvenlik' password set/change section.",
  "states": [
   "loaded",
   "permission-denied"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "Profilini Güncelle",
   "Görüntüle"
  ],
  "keyComponents": [
   "OrganizationStudentSettings",
   "Form",
   "Select",
   "ImageUploader",
   "CustomFieldInput",
   "Card"
  ],
  "dataSources": [
   "OrganizationStudentSettingsPageQuery",
   "OrganizationStudentSettings_organization",
   "OrganizationStudentSettingsUpdateOrganizationStudentMutation"
  ],
  "gating": "Requires viewerStudent (redirects to /{slug}/giris otherwise)",
  "notes": "TR OrganizationStudentSettings.*",
  "cluster": "storefront"
 },
 {
  "surface": "Organization invitation (Davet)",
  "route": "/[organizationSlug]/davet?token=",
  "titleTR": "(noindex; StudentInvitation card)",
  "purpose": "Accept a student invitation to the organization via a token link; sign in / switch account then accept.",
  "layout": "Storefront navbar + centered StudentInvitation card: invitation details, sign-in options (Google / email), 'Daveti aç'/accept button, wrong-account -> logout/switch. Standalone /davet code-entry form also exists: 'Davet kodunuzu girin' + 'Davet kodu' input + 'Daveti aç'.",
  "states": [
   "loaded",
   "not-found",
   "error"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "Daveti aç",
   "(accept invitation)",
   "(sign in / switch account)"
  ],
  "keyComponents": [
   "StudentInvitation",
   "Card",
   "Button",
   "RegisterForm"
  ],
  "dataSources": [
   "OrganizationInvitationPageQuery(invitation)",
   "StudentInvitation fragment",
   "acceptInvitation mutation"
  ],
  "gating": "noindex, force-dynamic; notFound on unknown/expired token",
  "notes": "TR davet.* + InvitationStatus.*",
  "cluster": "storefront"
 },
 {
  "surface": "Public form (Form)",
  "route": "/[organizationSlug]/form/[formSlug]",
  "titleTR": "{form title} | {organization name}",
  "purpose": "Renders an org's public/dynamic form (lead capture, application, paid form, etc.) using the shared Form renderer with optional payment.",
  "layout": "Optional storefront navbar (per form navigation settings showNavbar) + Form renderer (mode='form') supporting multi-question navigation, calculations, grading, and inline payment (uses org's active payment method, PI_PAYTR preferred). Redirects to /form/{slug}/sonuc on completion.",
  "states": [
   "loaded",
   "permission-denied",
   "not-found"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "Form",
   "OrganizationStudentNavigationSection",
   "form/components/payment"
  ],
  "dataSources": [
   "FormPageQuery(organization.form + activePaymentMethods)",
   "Form fragment",
   "effectiveNavigationSettings.showNavbar"
  ],
  "gating": "form.viewerHasAccess false -> redirect to /{slug}/giris",
  "notes": "TR under Form/FormQuestion/FormResults namespaces.",
  "cluster": "storefront"
 },
 {
  "surface": "Form result / thank-you (Sonuç)",
  "route": "/[organizationSlug]/form/[formSlug]/sonuc",
  "titleTR": "{form title} | {organization name}",
  "purpose": "Post-submission result/thank-you page for a completed form.",
  "layout": "FormResultPage rendering the form's configured completion/result content.",
  "states": [
   "loaded",
   "not-found"
  ],
  "priority": "edge",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "FormResultPage"
  ],
  "dataSources": [
   "FormResultPageQuery"
  ],
  "gating": "noindex",
  "cluster": "storefront"
 },
 {
  "surface": "Standalone payment (Ödeme)",
  "route": "/odeme/[slug]",
  "titleTR": "Ödeme",
  "purpose": "Iframe-embeddable standalone payment surface for an order slug; posts success/fail via postMessage to the parent window (used for embedded checkout).",
  "layout": "Minimal centered result surface: success -> 'Ödeme başarılı!' + 'Bu pencereyi kapatabilirsiniz.'; fail -> 'Ödeme başarısız oldu' + 'Lütfen kart bilgilerinizi ve limitinizi kontrol edin.'; also 'Sipariş durumu ödeme yapmaya uygun değil' / 'Ödeme yöntemi bulunamadı'.",
  "states": [
   "loaded",
   "error",
   "not-found"
  ],
  "priority": "secondary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "PaymentPage"
  ],
  "dataSources": [
   "PaymentPageQuery",
   "PaymentPage order fragment"
  ],
  "notes": "error.tsx + not-found.tsx present (AccessGate serverError/notFound layout). TR PaymentPage.*",
  "cluster": "storefront"
 },
 {
  "surface": "Subscription payment (Abonelik Ödemesi)",
  "route": "/abonelik-odeme/[subscriptionId]?orgSlug=&iframe=",
  "titleTR": "Abonelik Ödemesi",
  "purpose": "Checkout for an org membership subscription (StudentOrgSubscription): auto-initiates payment for PENDING subs and renders the PayTR card form or redirects to Stripe; supports embedded iframe mode.",
  "layout": "Themed layout. Full mode: header 'title/description' + 2-col grid — left 'Sipariş Özeti' card (tier name/description, interval badge, feature checklist, price with discount + cadence suffix, trial days), right 'Ödeme' card (PayTR form via StudentSubscriptionPaytrForm, loading 'preparingPayment', errors). Iframe mode: compact form only. Non-PENDING -> 'Ödeme Gerekli Değil' card (already active / cancelled / not payable). priceUnavailable -> unavailable alert.",
  "states": [
   "loading",
   "error",
   "not-found",
   "empty"
  ],
  "priority": "primary",
  "suggestedCanvas": "10-storefront",
  "keyComponents": [
   "SubscriptionPaymentPage",
   "StudentSubscriptionPaytrForm",
   "Card",
   "Badge",
   "Alert"
  ],
  "dataSources": [
   "SubscriptionPaymentPageQuery(node StudentOrgSubscription.tier.pricing/lifetimePricing)",
   "SubscriptionPaymentPageInitiatePaymentMutation",
   "resolveTierPricing",
   "cadenceFromSubscription"
  ],
  "gating": "redirect('/') when orgSlug missing",
  "notes": "loading.tsx + error.tsx + not-found.tsx present. TR StudentSubscription.checkout.* + Admin.OrgSubscriptions.allowedIntervals.*",
  "cluster": "storefront"
 },
 {
  "surface": "Payment/subscription error & not-found boundaries",
  "route": "/odeme/[slug]/error|not-found, /abonelik-odeme/[subscriptionId]/error|not-found, /cached error|not-found",
  "titleTR": "Bir şeyler ters gitti / Sayfa bulunamadı",
  "purpose": "Route-level error and 404 boundaries for the standalone payment and cached storefront segments.",
  "layout": "ErrorLayout centered card: error -> 'Bir şeyler ters gitti' + description + 'Tekrar dene' (RefreshCw) + optional 'Hata kodu: {id}'; not-found -> 'Sayfa bulunamadı' + description + 'Ana sayfaya dön' (Home).",
  "states": [
   "error",
   "not-found"
  ],
  "priority": "edge",
  "suggestedCanvas": "10-storefront",
  "actions": [
   "Tekrar dene",
   "Ana sayfaya dön"
  ],
  "keyComponents": [
   "ErrorLayout",
   "Button"
  ],
  "dataSources": [
   "AccessGate.serverError/notFound messages",
   "Sentry.captureException"
  ],
  "cluster": "storefront"
 },
 {
  "surface": "Marketing homepage",
  "route": "/(pi)/ (teachfluence.com root, org slug \"pi\")",
  "titleTR": "(SEO title from organization.activeWebPage.seoFields; org homepage)",
  "purpose": "Public marketing landing page for Teachfluence, fully composed in the Puck/editor page-builder CMS (organization pi's activeWebPage). Wrapped in NavBar + org/auth context.",
  "layout": "Sticky NavBar at top; body is CMS-rendered blocks via EditorServerRender (hero, feature sections, FAQ etc. defined by activeWebPage.content JSON). JSON-LD structured data injected (Organization, WebSite, SoftwareApplication, FAQ schemas). HomePageTracker fires GTM/Meta pixel.",
  "states": [
   "loading",
   "error",
   "empty"
  ],
  "priority": "primary",
  "dataSources": [
   "LandingPageQuery",
   "organization(slug:\"pi\"){ id slug activeWebPage(path){ content seoFields } }",
   "AdminAuthContext_authState",
   "OrganizationContext_organization"
  ],
  "keyComponents": [
   "NavBar",
   "EditorServerRender (Puck)",
   "JsonLd",
   "HomePageTracker"
  ],
  "notes": "activeWebPage missing -> notFound() (renders 404). revalidate=0 (SSR-fresh, dynamic). Content is admin-editable via the page builder, not hardcoded.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Public top NavBar (logged-out)",
  "route": "shared across all (pi) marketing pages",
  "titleTR": "Teachfluence (logo)",
  "purpose": "Primary marketing site navigation and auth entry points for anonymous visitors.",
  "layout": "Sticky translucent header (backdrop-blur, border-b). Left: logo (full logo-full.png on sm+, PiLogo mark on mobile) linking to /. Right (desktop lg+): link buttons Blog, Özellikler, İletişim, Fiyatlar + LanguageSelect; then outline 'Giriş Yap' button (all breakpoints) + primary 'Hemen Başla' button; mobile shows hamburger.",
  "states": [],
  "priority": "primary",
  "actions": [
   "Giriş Yap",
   "Hemen Başla"
  ],
  "keyComponents": [
   "NavBar",
   "Button",
   "LanguageSelect",
   "Sheet (mobile)"
  ],
  "filters": [],
  "tabs": [
   "Bilgi Girişimciliği Merkezi (blog)",
   "Özellikler",
   "İletişim",
   "Fiyatlar"
  ],
  "notes": "Nav labels (NavBar ns): blog='Bilgi Girişimciliği Merkezi', features='Özellikler', contact='İletişim', pricing='Fiyatlar', login='Giriş Yap', start='Hemen Başla', menu='Menü'. Login link goes to /giris, Hemen Başla to /kaydol.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Mobile nav menu (hamburger Sheet)",
  "route": "shared (pi) pages, mobile/tablet",
  "titleTR": "Menü",
  "purpose": "Slide-out right-side sheet with nav links on small screens.",
  "layout": "Sheet from right (w-72). Header 'Menü'. Vertical ghost buttons: 'Hemen Başla', separator, 'Bilgi Girişimciliği Merkezi', 'Özellikler', 'İletişim', 'Fiyatlar'; LanguageSelect shown only when org exposes >1 language.",
  "states": [],
  "priority": "edge",
  "dialogs": [
   "Menü (Sheet)"
  ],
  "keyComponents": [
   "Sheet",
   "BurgerIcon",
   "Button",
   "Separator",
   "LanguageSelect"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "NavBar viewer dropdown (logged-in)",
  "route": "shared (pi) pages when viewer is a User",
  "titleTR": "(user avatar menu)",
  "purpose": "Authenticated user's account/org switcher shown in place of login buttons.",
  "layout": "Avatar button opens DropdownMenu (w-56): label with full name + email; scrollable list of member organizations each showing avatar, org name, org status, 'Yönetici Paneli' link to /{slug}/admin and 'Öğrenci Anasayfası' external link; 'Organizasyon Oluştur' (if canCreateOrganization); 'Davet Programı' (->/hesabim); language submenu; 'Oturumu Kapat'.",
  "states": [],
  "priority": "secondary",
  "actions": [
   "Yönetici Paneli",
   "Öğrenci Anasayfası",
   "Organizasyon Oluştur",
   "Davet Programı",
   "Oturumu Kapat"
  ],
  "dialogs": [
   "Profile DropdownMenu",
   "LanguageSelectSubMenu"
  ],
  "keyComponents": [
   "DropdownMenu",
   "Avatar",
   "NotificationBell (adminMode only)"
  ],
  "dataSources": [
   "viewer.organizationsAsMember",
   "viewer.givenName/lastName/email/image",
   "canCreateOrganization"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Features page (Özellikler)",
  "route": "/(pi)/ozellikler",
  "titleTR": "(seoFields title for 'ozellikler' page)",
  "purpose": "Marketing features page, CMS/page-builder rendered (activeWebPage path='ozellikler').",
  "layout": "NavBar + PiPageWrapper + EditorServerRender of the 'ozellikler' CMS page content; JSON-LD features schema; FeaturesPageTracker fires analytics.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "primary",
  "dataSources": [
   "PiPageQuery via loadPiPageData('ozellikler')",
   "organization.activeWebPage.content/seoFields"
  ],
  "keyComponents": [
   "PiPageWrapper",
   "EditorServerRender",
   "JsonLd",
   "FeaturesPageTracker"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Pricing page (Fiyatlar)",
  "route": "/(pi)/pricing",
  "titleTR": "(seoFields title for 'pricing' page)",
  "purpose": "Marketing pricing page. CMS-rendered activeWebPage(path='pricing') with GTM view_pricing + Meta trackPricingView events on mount.",
  "layout": "NavBar + EditorServerRender of pricing CMS content. Fires sendGTMEvent view_pricing and trackPricingView analytics on load.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "primary",
  "dataSources": [
   "PricingPageQuery",
   "organization(slug:\"pi\").activeWebPage(path:'pricing'){content seoFields}"
  ],
  "keyComponents": [
   "NavBar",
   "EditorServerRender",
   "AdminAuthContextProvider",
   "OrganizationContextProvider"
  ],
  "notes": "activeWebPage missing -> notFound(). Pricing content itself is authored in the page builder, not hardcoded plan cards.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Contact page (İletişim)",
  "route": "/(pi)/iletisim",
  "titleTR": "(seoFields title for 'iletisim'; noindex)",
  "purpose": "Contact page, CMS-rendered (path='iletisim'), noindexed.",
  "layout": "PiPageWrapper + EditorServerRender of 'iletisim' CMS content (contact form/info authored in page builder).",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "dataSources": [
   "loadPiPageData('iletisim')"
  ],
  "keyComponents": [
   "PiPageWrapper",
   "EditorServerRender"
  ],
  "notes": "generatePiPageMetadata with noindex:true.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Link-in-bio page",
  "route": "/(pi)/linkinbio",
  "titleTR": "(seoFields title for 'linkinbio')",
  "purpose": "Social link-in-bio landing, CMS-rendered (path='linkinbio').",
  "layout": "PiPageWrapper + EditorServerRender of 'linkinbio' CMS content.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "dataSources": [
   "loadPiPageData('linkinbio')"
  ],
  "keyComponents": [
   "PiPageWrapper",
   "EditorServerRender"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Campaign landing pages (CMS-driven)",
  "route": "/(pi)/gizemkampanya, /merdor, /ilaydabilek-kampanya (path 'ilaydabilek'), /pozitif, /yilbasikampanya, /chatgpt-prompt-paketi, /usage",
  "titleTR": "(per-page seoFields; some noindex e.g. usage)",
  "purpose": "Marketing / promo campaign landing pages. Each is a thin route that loads a distinct page-builder page by slug and renders it identically.",
  "layout": "Every one is the same shell: generatePiPageMetadata + loadPiPageData(SLUG) -> PiPageWrapper + EditorServerRender(resolvedData). No bespoke UI; all visual content is authored per-slug in the CMS page builder. usage uses noindex.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "dataSources": [
   "loadPiPageData(<slug>)",
   "organization.activeWebPage(path:<slug>).content"
  ],
  "keyComponents": [
   "PiPageWrapper",
   "EditorServerRender (Puck)"
  ],
  "notes": "chatgpt-prompt-paketi, gizemkampanya, merdor, pozitif, yilbasikampanya, ilaydabilek, usage are structurally identical — designer should treat each as a page-builder canvas, not a coded layout. revalidate=0.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Sign-up page (Kaydol) — pre-auth Register",
  "route": "/(pi)/kaydol",
  "titleTR": "Ücretsiz Teachfluence Hesabı Oluştur (PageTitles.createAccount)",
  "purpose": "Primary sign-up funnel. GetStartedFlow renders the two-pane Register screen for anonymous visitors (mode=register). ?flow=subscription routes to PromoOnboardingFlow instead.",
  "layout": "Full-height split: left = primary-colored panel with Unicourse logo + Dorukhan Özcan testimonial quote (register.dorukQuote) + author card; right = RegisterForm. Heading 'Bir hesap oluştur' (register.createAccount), sub '<strong>14 gün ücretsiz deneme</strong> ile bir hesap oluştur...', PiLogo. Google button 'Google ile oturum aç', 'veya' divider, EmailOtpLogin (email -> OTP). Terms line, footer 'Zaten hesabın var mı? Giriş yap' (-> /giris).",
  "states": [
   "loading"
  ],
  "priority": "primary",
  "actions": [
   "Google ile oturum aç",
   "Giriş Kodu Gönder",
   "Giriş yap (footer)"
  ],
  "dataSources": [
   "RegisterPageQuery",
   "organization(slug:\"pi\")",
   "AdminAuthContext_authState"
  ],
  "keyComponents": [
   "GetStartedFlow",
   "Register",
   "RegisterForm",
   "EmailOtpLogin",
   "Alert",
   "Suspense loader (Loader2Icon)"
  ],
  "notes": "In-app-browser detection shows a warning Alert (register.inAppWarningTitle/Description) instead of the Google button. ?next= shows an info Alert 'Giriş yaptıktan sonra otomatik olarak yönlendirileceksiniz.' Captures ?ref=/UTM referral.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Login page (Giriş) — Register mode=login",
  "route": "/(pi)/giris",
  "titleTR": "Teachfluence Hesabına Giriş Yap (PageTitles.signIn) — noindex",
  "purpose": "Login route. Reuses the exact kaydol Register/OTP/Google flow with login-framed copy (mode=login). Same GraphQL op (RegisterPageQuery).",
  "layout": "Identical two-pane Register layout, but heading 'Hesabına giriş yap' (register.signInTitle), sub 'Kurslarını yönetmek için hesabına giriş yap.' Footer cross-link 'Hesabın yok mu? Hemen başla' (-> /kaydol). Promo onboarding never entered from login.",
  "states": [
   "loading"
  ],
  "priority": "primary",
  "actions": [
   "Google ile oturum aç",
   "Giriş Kodu Gönder",
   "Hemen başla (footer)"
  ],
  "dataSources": [
   "RegisterPageQuery"
  ],
  "keyComponents": [
   "RegisterPage(mode=login)",
   "GetStartedFlow(mode=login)",
   "RegisterForm",
   "EmailOtpLogin"
  ],
  "notes": "robots index:false (de-indexed as duplicate of /kaydol). ?next=/hesabim etc. supported. PI-1280.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Email OTP login form (inside Register)",
  "route": "embedded in /kaydol, /giris, /davet accept",
  "titleTR": "Email / Giriş Kodu",
  "purpose": "Email one-time-code auth widget: enter email, receive & verify OTP.",
  "layout": "Email input labeled 'Email' (register.identifier), 'Giriş Kodu Gönder' button; after send, OTP input 'Giriş Kodu' + resend ('Kodu tekrar gönder{message}'). Validation 'Geçerli bir email adresi girin'.",
  "states": [
   "error"
  ],
  "priority": "secondary",
  "actions": [
   "Giriş Kodu Gönder",
   "Kodu tekrar gönder"
  ],
  "keyComponents": [
   "EmailOtpLogin"
  ],
  "notes": "Errors: loginOtpSendError 'Giriş kodunuz gönderilemedi...', loginOtpVerifyError 'Giriş yapılamadı. Lütfen kodu kontrol edip tekrar deneyin.' Success toasts loginSuccess/loginSuccessDescription.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Post-auth organization selection step",
  "route": "/kaydol (and /giris) after auth, no ?next",
  "titleTR": "Yönetici Paneli / Organizasyon Oluştur",
  "purpose": "After OTP/Google auth, an authenticated user with existing orgs picks one, or creates a new org.",
  "layout": "NavBar + centered list of org cards (avatar, org name, org status, 'Yönetici Paneli' text, arrow) linking to /{slug}/admin; below, 'Organizasyon Oluştur' button (if canCreateOrganization). If no orgs -> renders CreateOrganization form directly. Fires GTM login/sign_up + Meta trackRegistrationComplete.",
  "states": [],
  "priority": "secondary",
  "actions": [
   "(select organization)",
   "Organizasyon Oluştur"
  ],
  "keyComponents": [
   "GetStartedFlow OrganizationStep",
   "CreateOrganization",
   "Avatar",
   "PiLink"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Create organization form",
  "route": "/kaydol (org step / new user)",
  "titleTR": "Bir organizasyon oluştur (register.createOrganizationTitle)",
  "purpose": "New-org creation form for a first-time educator/creator.",
  "layout": "Card with title 'Bir organizasyon oluştur', description; fields: Organizasyon Adı (with description + student notice 'Öğrenci misin?...'), Organizasyon Kullanıcı Adı (slug, {slug}.teachfluence.com helper), Telefon Numarası (PhoneInput), consent checkboxes (allowEmailDescription, allowPhoneDescription). Submit creates org and redirects to admin. Live slug availability check (checkOrganizationSlug).",
  "states": [
   "error"
  ],
  "priority": "secondary",
  "actions": [
   "(create organization submit)"
  ],
  "dataSources": [
   "CreateOrganizationMutation",
   "CreateOrganizationCheckSlugMutation"
  ],
  "keyComponents": [
   "Form (react-hook-form + zod)",
   "Input",
   "PhoneInput",
   "Checkbox",
   "Card"
  ],
  "notes": "Slug validation errors: required/maxLength(40)/invalidChars/forbidden/unavailable. Name maxLength 200. BANNED_ORGANIZATION_SLUGS enforced client-side. Applies stored referral on success.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "MCP connect bridge — redirecting & error states",
  "route": "/kaydol?next=<mcp authorize url>",
  "titleTR": "Bağlantı tamamlanamadı (register.mcpConnectErrorTitle)",
  "purpose": "Handles OAuth/MCP connect bridge after login when ?next is an allowlisted first-party URL.",
  "layout": "Redirecting: NavBar + 'Yönlendiriliyorsunuz...' (register.redirecting). Loop-guard tripped: NavBar + centered card, h1 'Bağlantı tamamlanamadı', p 'Yapay zeka uygulamanı bağlarken bir sorun oluştu. Lütfen tekrar dene.', 'Tekrar dene' button.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "edge",
  "actions": [
   "Tekrar dene"
  ],
  "keyComponents": [
   "GetStartedFlow",
   "NavBar",
   "Button"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Account / Referral dashboard (Hesabım)",
  "route": "/(pi)/hesabim",
  "titleTR": "Davet Programı (Referral.title)",
  "purpose": "Logged-in user's referral (davet) program dashboard: share link, funnel stats, earnings, referral & reward lists.",
  "layout": "NavBar + max-w-4xl column. Header 'Davet Programı' / sub 'Bağlantını paylaş, abonelik gelirinden pay kazan.' Referral link Card (code + CopyButton, or 'Davet bağlantın henüz hazır değil'). Stat grid (2/4 cols): Toplam davet, Kayıt oldu, Organizasyon oluşturdu, Dönüşüm. Earnings grid (3): Beklemede/Onaylandı/Ödendi money cards ('Yok' when empty). ReferralsList + ReferralRewardsList (each with 'Daha fazla yükle', empty states 'Henüz davet yok.'/'Henüz ödül yok.').",
  "states": [
   "empty",
   "permission-denied"
  ],
  "priority": "primary",
  "dataSources": [
   "HesabimPageQuery",
   "ReferralDashboard_user fragment",
   "referralCode{code status}",
   "referralStats{totalReferrals signedUpCount orgCreatedCount convertedCount pendingRewards approvedRewards paidRewards}",
   "ReferralsList_user",
   "ReferralRewardsList_user"
  ],
  "keyComponents": [
   "ReferralDashboard",
   "Card",
   "CopyButton",
   "StatCard",
   "EarningsCard"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Hesabım — not authenticated state",
  "route": "/(pi)/hesabim (viewer not a User)",
  "titleTR": "Bu sayfaya erişmek için giriş yapmalısın (register.loginRequired)",
  "purpose": "Prompt anonymous visitors to log in before viewing referral dashboard.",
  "layout": "NavBar + centered: muted text 'Davetlerini görmek için giriş yap.' (Referral.loginRequired) + primary 'Giriş yap' button -> /giris?next=/hesabim.",
  "states": [
   "permission-denied"
  ],
  "priority": "edge",
  "actions": [
   "Giriş yap"
  ],
  "keyComponents": [
   "Button",
   "Link"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Subscription promo landing (Abonelik)",
  "route": "/(pi)/abonelik",
  "titleTR": "Promosyon kodu ile Teachfluence'a başla (PromoOnboarding.landingMetaTitle)",
  "purpose": "Entry point for promo-code driven subscription onboarding. Visitor enters a promo code, which is validated then routed to /kaydol?flow=subscription&promo=CODE.",
  "layout": "NavBar + 2-col hero. Left: PiLogo, headline 'Promosyon kodunla Teachfluence'a başla', subtitle, 3 bullets (anında erişim / kartını kaydet / kampanyalı fiyatlar). Right: bordered card form 'Promosyon kodun' (TagIcon), label 'Promosyon kodu', Input placeholder 'Örn. TEACH2026', destructive Alert on error ('Promosyon kodu geçersiz.'/'Bağlantı hatası...'), submit 'Devam et' (or 'Kontrol ediliyor…') + ArrowRight, help text.",
  "states": [
   "error",
   "loading"
  ],
  "priority": "primary",
  "actions": [
   "Devam et"
  ],
  "dataSources": [
   "AbonelikLandingPageQuery",
   "AbonelikLandingPagePromotionQuery (validateSubscriptionPromotionCode)"
  ],
  "keyComponents": [
   "AbonelikLandingPage",
   "NavBar",
   "PiLogo",
   "Input",
   "Alert",
   "Button"
  ],
  "notes": "pi org missing -> Sentry error + notFound(). revalidate=0.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Promo onboarding — OTP signup step",
  "route": "/kaydol?flow=subscription&promo=CODE (anonymous)",
  "titleTR": "İndirimin seni bekliyor (PromoOnboarding.signupWithPromoHeadline)",
  "purpose": "First step of promo subscription funnel for unauthenticated users: create account via OTP/Google with promo highlighted.",
  "layout": "Minimal NavBar (logo only) + OtpSignupStep: promo highlight badge/card ('Promosyon Hazır', % or ₺ discount / trial-extension), signup form ('Hesabını oluştur', Google + email OTP), trust badges (Bugün ödeme yok / İstediğin zaman iptal / Güvenli ödeme).",
  "states": [
   "error"
  ],
  "priority": "secondary",
  "keyComponents": [
   "PromoOnboardingFlow",
   "OtpSignupStep",
   "PromoDetailsCard",
   "NavBar(minimal)",
   "ErrorBoundary"
  ],
  "notes": "No promo code -> router.replace('/abonelik'). Wrapped in ErrorBoundary with destructive Alert fallback (unexpectedErrorTitle/Message).",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Promo onboarding — checkout step",
  "route": "/kaydol?flow=subscription&promo=CODE (authenticated)",
  "titleTR": "Aboneliğini tamamla (PromoOnboarding.checkoutTitle)",
  "purpose": "Subscription checkout with promo auto-applied: trial price summary + PayTR billing info + card payment.",
  "layout": "Minimal NavBar + 2-col grid: left TrialPriceSummary (plan, discount, trial), right column = payment section. paymentFailed Alert (Admin.Settings.PaytrSubscription.paymentFailed). Promo states: validating spinner ('Kontrol ediliyor…'), promo-not-eligible Alert with 'Başka bir kod dene', watchdog timeout retry, free-today hint ('Bugün ödeme alınmaz...'). PaytrBillingInfoForm then PaytrPaymentForm. Free path uses 'Aboneliği Başlat' CTA.",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "actions": [
   "Aboneliği Başlat / (Ödemeyi Tamamla)",
   "Başka bir kod dene",
   "Tekrar dene"
  ],
  "dataSources": [
   "CheckoutStepPlansQuery (piEducationPaymentPlans)",
   "usePromotionCode",
   "validateSubscriptionPromotionCode"
  ],
  "keyComponents": [
   "CheckoutStep",
   "TrialPriceSummary",
   "PaytrBillingInfoForm",
   "PaytrPaymentForm",
   "Alert"
  ],
  "notes": "Default plan STARTER/MONTHLY (fallback plans[0]). plansUnavailable Alert when no plan / NaN price. Redirects to PayTR then back with ?payment=success|fail.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Promo onboarding — get started / org naming step",
  "route": "/kaydol?flow=subscription...&payment=success",
  "titleTR": "Başlayalım (PromoOnboarding.getStartedTitle)",
  "purpose": "Post-payment step: name the placeholder organization and pick its slug before entering admin.",
  "layout": "Minimal NavBar + centered card: h1 'Başlayalım', sub 'Hesabını kişiselleştirmek için organizasyonuna bir isim ver.' Fields: 'Organizasyon adı' (placeholder 'Örn. Atölyem...'), 'Organizasyon bağlantısı' (slug, helper 'teachfluence.com/{slug}...', live availability spinner + slugTaken/slugInvalid errors). Submit 'Devam et' + ArrowRight -> /{slug}/admin.",
  "states": [
   "error",
   "loading"
  ],
  "priority": "secondary",
  "actions": [
   "Devam et"
  ],
  "dataSources": [
   "StartStepUpdateOrganizationMutation (updateOrganization)",
   "StartStepCheckSlugMutation (checkOrganizationSlug)"
  ],
  "keyComponents": [
   "StartStep",
   "Input",
   "Alert",
   "Button"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Promo onboarding — loading / error / provisioning states",
  "route": "/kaydol?flow=subscription (transient)",
  "titleTR": "Ödeme ekranı hazırlanıyor… / Bir şeyler ters gitti",
  "purpose": "Transient states across the promo funnel.",
  "layout": "Minimal NavBar + spinner: 'Ödeme ekranı hazırlanıyor…' (preparingCheckout) while placeholder org provisions. Placeholder org error: destructive Alert 'Hesabın hazırlanırken bir sorun oluştu...' + optional 'Hata kodu: {code}' + 'Tekrar dene'. Generic ErrorBoundary fallback: 'Bir şeyler ters gitti' / 'Lütfen sayfayı yenileyip tekrar deneyin.'",
  "states": [
   "loading",
   "error"
  ],
  "priority": "edge",
  "actions": [
   "Tekrar dene"
  ],
  "keyComponents": [
   "AuthenticatedFlow",
   "Loader2Icon",
   "Alert",
   "usePlaceholderOrg"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Invitation code entry (Davet)",
  "route": "/(pi)/davet (no ?token)",
  "titleTR": "Davet kodunuzu girin (davet.title)",
  "purpose": "Prompt to enter an invitation code/token when arriving at /davet without one.",
  "layout": "Centered Card (max-w-md): title 'Davet kodunuzu girin', desc 'Size paylaşılan davet kodunu aşağıya yazın.', Input placeholder 'Davet kodu', submit 'Daveti aç' (loading). Empty error 'Lütfen davet kodunuzu girin'. Redirects to /davet?token=CODE.",
  "states": [
   "error"
  ],
  "priority": "secondary",
  "actions": [
   "Daveti aç"
  ],
  "keyComponents": [
   "InvitationCodeEntry",
   "Card",
   "Input",
   "Button"
  ],
  "notes": "Page is noindex/nofollow. /davet/<anything> path-segment 404s (fast catch-all).",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Invitation accept page (Davet with token)",
  "route": "/(pi)/davet?token=CODE",
  "titleTR": "{Organizasyon} üye daveti / {Kurs} Eğitmen ekibi daveti",
  "purpose": "Show an org-member or course-instructor invitation and let the user accept it.",
  "layout": "NavBar + centered Card: title reflects org member vs instructor invite; body '{davet eden} ({email}) seni <org> organizasyonuna davet etti' (or eğitmen ekibine). If logged in: 'Daveti kabul et' button (mutation acceptInvitation) -> redirect to org/course admin. If logged out: embedded RegisterForm with info Alert 'Giriş yapman gerekiyor' + must log in with the invited email.",
  "states": [
   "error",
   "empty"
  ],
  "priority": "secondary",
  "actions": [
   "Daveti kabul et",
   "(login via RegisterForm)"
  ],
  "dataSources": [
   "InvitationPageQuery",
   "invitation(token){UserInvitation}",
   "UserInvitationAcceptInvitationMutation (acceptInvitation)"
  ],
  "keyComponents": [
   "InvitationPage",
   "UserInvitation",
   "RegisterForm",
   "Card",
   "Alert"
  ],
  "notes": "Accept success/failure toasts ('Davet kabul edildi.' / 'Davet kabul edilemedi.').",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Invitation — wrong-user / not-found / expired",
  "route": "/(pi)/davet?token=CODE (edge)",
  "titleTR": "Bu davet başka bir kullanıcıya ait / (not found)",
  "purpose": "Edge states for invitations.",
  "layout": "Wrong user: Card 'Bu davet başka bir kullanıcıya ait' + 'Bu davet {email} adresi için gönderilmiştir.' Unknown/expired token -> notFound() (renders /davet InvitationNotFoundOrExpired or 404). Status not PENDING/ACCEPTED -> InvitationNotFoundOrExpired.",
  "states": [
   "error",
   "empty"
  ],
  "priority": "edge",
  "keyComponents": [
   "UserInvitation",
   "InvitationNotFoundOrExpired",
   "Card"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Legal pages (Privacy / Terms)",
  "route": "/(pi)/privacy, /(pi)/terms",
  "titleTR": "(seoFields; both noindex)",
  "purpose": "Gizlilik/KVKK and Kullanım Sözleşmesi legal content, CMS-rendered.",
  "layout": "PiPageWrapper + EditorServerRender of 'privacy' / 'terms' page-builder content. Linked from RegisterForm terms line ('Kaydolarak Kullanım Sözleşmesi ve Gizlilik ve KVKK Politikası'nı kabul ediyorsun.').",
  "states": [
   "loading",
   "error"
  ],
  "priority": "secondary",
  "dataSources": [
   "loadPiPageData('privacy'|'terms')"
  ],
  "keyComponents": [
   "PiPageWrapper",
   "EditorServerRender"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "404 Not Found (pi)",
  "route": "/(pi)/not-found (any unmatched (pi) route)",
  "titleTR": "Sayfa bulunamadı (AccessGate.notFound.title)",
  "purpose": "Marketing-segment 404 page.",
  "layout": "ErrorLayout (tone muted, Compass icon): title 'Sayfa bulunamadı', desc 'Aradığınız sayfa taşınmış, silinmiş ya da hiç var olmamış olabilir.', primary 'Ana sayfaya dön' button (Home icon) -> /.",
  "states": [
   "error"
  ],
  "priority": "edge",
  "actions": [
   "Ana sayfaya dön"
  ],
  "keyComponents": [
   "ErrorLayout",
   "Button"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Route error boundary (pi 500)",
  "route": "/(pi)/error (thrown render error)",
  "titleTR": "Bir şeyler ters gitti (AccessGate.serverError.title)",
  "purpose": "Client error boundary for (pi) routes; captures to Sentry.",
  "layout": "ErrorLayout (tone warning, AlertTriangle icon): title 'Bir şeyler ters gitti', desc 'Bu sayfa yüklenirken beklenmeyen bir sorun oluştu...', 'Tekrar dene' button (RefreshCw, calls reset), optional 'Hata kodu: {digest}' reference.",
  "states": [
   "error"
  ],
  "priority": "edge",
  "actions": [
   "Tekrar dene"
  ],
  "keyComponents": [
   "ErrorLayout",
   "Button",
   "Sentry.captureException"
  ],
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Internal Referral Console (staff)",
  "route": "/(pi)/internal/referral-console",
  "titleTR": "Davet Konsolu (Referral.console.title)",
  "purpose": "Internal Teachfluence-staff console to manage referral codes, partners, ledger and analytics for the pi program. Not a public marketing surface.",
  "layout": "NavBar + PageTabs synced to URL: 'Analitik' (overview: Toplam kod/Aktif kod/Ortaklar, funnel, liability), 'Kodlar ve Ortaklar' (codes table: Kod/Sahip/Pay/Süre/Durum + partners table Ad/E-posta/Durum, create/edit dialogs), 'Ödül Defteri' (ledger: Tutar/Kaynak/Yararlanıcı/Durum/Oluşturuldu, approve/markPaid/reverse/exportCsv, bulk select).",
  "states": [
   "error",
   "empty",
   "permission-denied"
  ],
  "priority": "edge",
  "tabs": [
   "Analitik",
   "Kodlar ve Ortaklar",
   "Ödül Defteri"
  ],
  "tableColumns": [
   "Kod",
   "Sahip",
   "Pay",
   "Süre",
   "Durum",
   "Tutar",
   "Kaynak",
   "Yararlanıcı",
   "Oluşturuldu"
  ],
  "actions": [
   "Yeni kod",
   "Yeni ortak",
   "Onayla",
   "Ödendi işaretle",
   "Geri al",
   "CSV dışa aktar",
   "Kaydet"
  ],
  "dialogs": [
   "Yeni/Düzenle ortak (partnerForm)",
   "Yeni kod (codeForm)",
   "Ödülleri ödendi işaretle",
   "Ödülü geri al"
  ],
  "dataSources": [
   "ReferralConsolePageQuery",
   "referralProgramOverview{totalCodes activeCodes totalPartners funnel liability}"
  ],
  "keyComponents": [
   "PageTabs",
   "ReferralAnalytics",
   "ReferralCodesPanel",
   "ReferralLedgerPanel"
  ],
  "notes": "Internal tool colocated under (pi) — likely belongs to an internal/admin canvas, not the public marketing site; included for completeness.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 },
 {
  "surface": "Internal data-validator tools (staff)",
  "route": "/(pi)/internal/question-data-validator, /(pi)/internal/website-data-validator",
  "titleTR": "(internal QA tools)",
  "purpose": "Internal Teachfluence QA/validation utilities under a shared internal layout. Not public marketing pages.",
  "layout": "Wrapped by app/(pi)/internal/layout.tsx; data-validation dashboards for question/website data. Out of the public marketing scope.",
  "states": [
   "loading"
  ],
  "priority": "edge",
  "keyComponents": [
   "internal/layout"
  ],
  "notes": "Flagged as internal — a designer recreating the marketing site can skip; noted so nothing under (pi) is unaccounted for.",
  "suggestedCanvas": "11-marketing-site",
  "cluster": "marketing-site"
 }
]