{"version":"1.0","encoding":"UTF-8","feed":{"xmlns":"http://www.w3.org/2005/Atom","xmlns$openSearch":"http://a9.com/-/spec/opensearchrss/1.0/","xmlns$blogger":"http://schemas.google.com/blogger/2008","xmlns$georss":"http://www.georss.org/georss","xmlns$gd":"http://schemas.google.com/g/2005","xmlns$thr":"http://purl.org/syndication/thread/1.0","id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725"},"updated":{"$t":"2026-09-12T23:11:40.031+03:00"},"category":[{"term":"tutorial"},{"term":"Vibe Coding"},{"term":"Bildirim Entegrasyonu"}],"title":{"type":"text","$t":"Muhammed Akif Kayacan"},"subtitle":{"type":"html","$t":"Muhammed Akif Kayacan'ın kişisel portföyü. Tasarım, otomasyon ve yapay zekâyı bir araya getiren projeler, deneyimler ve dijital üretim yaklaşımı."},"link":[{"rel":"http://schemas.google.com/g/2005#feed","type":"application/atom+xml","href":"https:\/\/www.aakif.net\/feeds\/posts\/default"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default?alt=json"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/"},{"rel":"hub","href":"http://pubsubhubbub.appspot.com/"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}],"generator":{"version":"7.00","uri":"http://www.blogger.com","$t":"Blogger"},"openSearch$totalResults":{"$t":"7"},"openSearch$startIndex":{"$t":"1"},"openSearch$itemsPerPage":{"$t":"25"},"entry":[{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-122220330648239606"},"published":{"$t":"2026-09-12T00:27:06.647+03:00"},"updated":{"$t":"2026-09-12T23:11:40.031+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"tutorial"}],"title":{"type":"text","$t":"Semantik HTML Temizleyici \u0026 Tema Uyumluluk Rehberi"},"content":{"type":"html","$t":"\u003C!DOCTYPE html\u003E\n\u003Chtml lang=\"tr\"\u003E\n\u003Chead\u003E\n  \u003Cmeta charset=\"UTF-8\"\u003E\n  \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003E\n  \u003Ctitle\u003ESemantik HTML Temizleyici \u0026 Tema Uyumluluk Rehberi\u003C\/title\u003E\n  \u003Cstyle\u003E\n    :root {\n      --bg: #f8fafc;\n      --surface: #ffffff;\n      --surface-subtle: #f1f5f9;\n      --card-border: #e2e8f0;\n      --card-border-focus: #cbd5e1;\n      --text: #0f172a;\n      --text-body: #334155;\n      --text-muted: #64748b;\n      --primary: #2563eb;\n      --primary-hover: #1d4ed8;\n      --primary-subtle: #eff6ff;\n      --primary-border: #bfdbfe;\n      --accent: #d97706;\n      --accent-subtle: #fffbeb;\n      --accent-border: #fde68a;\n      --success: #16a34a;\n      --success-subtle: #f0fdf4;\n      --success-border: #bbf7d0;\n      --code-bg: #0f172a;\n      --code-text: #f8fafc;\n    }\n\n    * {\n      box-sizing: border-box;\n      margin: 0;\n      padding: 0;\n      font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n    }\n\n    body {\n      background-color: var(--bg);\n      color: var(--text-body);\n      line-height: 1.75;\n      padding: 40px 20px;\n    }\n\n    .max-wrapper {\n      max-width: 920px;\n      margin: 0 auto;\n    }\n\n    header {\n      margin-bottom: 36px;\n      border-bottom: 1px solid var(--card-border);\n      padding-bottom: 28px;\n    }\n\n    .badge-bar {\n      display: flex;\n      gap: 10px;\n      margin-bottom: 14px;\n      flex-wrap: wrap;\n    }\n\n    .tag {\n      font-size: 0.78rem;\n      font-weight: 700;\n      text-transform: uppercase;\n      letter-spacing: 0.05em;\n      padding: 4px 10px;\n      border-radius: 9999px;\n    }\n\n    .tag-blue {\n      background: var(--primary-subtle);\n      color: var(--primary);\n      border: 1px solid var(--primary-border);\n    }\n\n    .tag-amber {\n      background: var(--accent-subtle);\n      color: var(--accent);\n      border: 1px solid var(--accent-border);\n    }\n\n    h1 {\n      font-size: 2.1rem;\n      line-height: 1.35;\n      color: var(--text);\n      margin-bottom: 12px;\n      font-weight: 800;\n    }\n\n    .subtitle {\n      font-size: 1.1rem;\n      color: var(--text-muted);\n      line-height: 1.6;\n    }\n\n    .card {\n      background: var(--surface);\n      border: 1px solid var(--card-border);\n      border-radius: 12px;\n      padding: 32px;\n      margin-bottom: 30px;\n      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 6px -2px rgba(0, 0, 0, 0.02);\n    }\n\n    h2 {\n      font-size: 1.38rem;\n      color: var(--text);\n      margin-bottom: 16px;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    p {\n      margin-bottom: 16px;\n      color: var(--text-body);\n      font-size: 1rem;\n    }\n\n    ul, ol {\n      margin: 14px 0 20px 24px;\n      color: var(--text-body);\n      font-size: 0.98rem;\n    }\n\n    li {\n      margin-bottom: 8px;\n    }\n\n    code {\n      background: #f1f5f9;\n      color: #0f172a;\n      padding: 2px 6px;\n      border-radius: 4px;\n      font-size: 0.88em;\n      font-family: Consolas, Monaco, \"Courier New\", monospace;\n      border: 1px solid #e2e8f0;\n    }\n\n    .tool-box {\n      background: #ffffff;\n      border: 2px solid var(--primary-border);\n      border-radius: 12px;\n      padding: 28px;\n      margin: 35px 0;\n      box-shadow: 0 4px 14px rgba(37, 99, 235, 0.07);\n    }\n\n    .tab-bar {\n      display: flex;\n      gap: 8px;\n      border-bottom: 1px solid var(--card-border);\n      padding-bottom: 12px;\n      margin-bottom: 20px;\n      flex-wrap: wrap;\n    }\n\n    .tab-btn {\n      background: var(--surface-subtle);\n      border: 1px solid var(--card-border);\n      color: var(--text-body);\n      padding: 8px 16px;\n      border-radius: 6px;\n      font-weight: 600;\n      font-size: 0.88rem;\n      cursor: pointer;\n      transition: all 0.15s ease;\n    }\n\n    .tab-btn.active {\n      background: var(--primary);\n      color: #ffffff;\n      border-color: var(--primary);\n    }\n\n    .paste-area {\n      width: 100%;\n      min-height: 180px;\n      max-height: 360px;\n      overflow-y: auto;\n      border: 2px dashed #cbd5e1;\n      border-radius: 8px;\n      padding: 16px;\n      background: #f8fafc;\n      outline: none;\n      font-size: 0.95rem;\n      color: var(--text);\n      line-height: 1.6;\n      transition: border-color 0.2s, background 0.2s;\n    }\n\n    .paste-area:focus {\n      border-color: var(--primary);\n      background: #ffffff;\n    }\n\n    .paste-area:empty:before {\n      content: attr(data-placeholder);\n      color: #94a3b8;\n    }\n\n    .html-textarea {\n      width: 100%;\n      min-height: 180px;\n      padding: 14px;\n      border: 1px solid var(--card-border-focus);\n      border-radius: 8px;\n      background: #f8fafc;\n      font-family: Consolas, Monaco, monospace;\n      font-size: 0.88rem;\n      color: var(--text);\n      line-height: 1.5;\n      resize: vertical;\n      display: none;\n    }\n\n    .options-grid {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n      gap: 12px;\n      margin: 18px 0;\n      background: var(--surface-subtle);\n      padding: 16px;\n      border-radius: 8px;\n      border: 1px solid var(--card-border);\n    }\n\n    .option-item {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      font-size: 0.88rem;\n      color: var(--text-body);\n      user-select: none;\n      cursor: pointer;\n    }\n\n    .option-item input {\n      accent-color: var(--primary);\n      width: 16px;\n      height: 16px;\n      cursor: pointer;\n    }\n\n    .btn-row {\n      display: flex;\n      gap: 10px;\n      margin-top: 16px;\n      flex-wrap: wrap;\n    }\n\n    .btn {\n      background: var(--primary);\n      color: #ffffff;\n      font-weight: 600;\n      border: none;\n      padding: 10px 20px;\n      border-radius: 6px;\n      cursor: pointer;\n      font-size: 0.92rem;\n      transition: all 0.15s ease;\n      display: inline-flex;\n      align-items: center;\n      gap: 6px;\n      text-decoration: none;\n    }\n\n    .btn:hover {\n      background: var(--primary-hover);\n    }\n\n    .btn-outline {\n      background: #ffffff;\n      border: 1px solid var(--card-border-focus);\n      color: var(--text);\n    }\n\n    .btn-outline:hover {\n      background: var(--surface-subtle);\n      border-color: #94a3b8;\n    }\n\n    .stat-strip {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n      gap: 12px;\n      margin: 20px 0;\n    }\n\n    .stat-badge {\n      background: var(--surface-subtle);\n      border: 1px solid var(--card-border);\n      border-radius: 8px;\n      padding: 12px;\n      text-align: center;\n    }\n\n    .stat-num {\n      font-size: 1.5rem;\n      font-weight: 800;\n      color: var(--primary);\n    }\n\n    .stat-lbl {\n      font-size: 0.78rem;\n      color: var(--text-muted);\n      text-transform: uppercase;\n      font-weight: 700;\n    }\n\n    .output-section {\n      margin-top: 24px;\n      border-top: 1px solid var(--card-border);\n      padding-top: 20px;\n    }\n\n    .box-block {\n      background: #ffffff;\n      border: 1px solid var(--card-border);\n      border-radius: 8px;\n      margin-bottom: 18px;\n      overflow: hidden;\n    }\n\n    .box-block-head {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      background: #f8fafc;\n      padding: 10px 16px;\n      border-bottom: 1px solid var(--card-border);\n    }\n\n    .box-block-title {\n      font-size: 0.84rem;\n      font-weight: 700;\n      text-transform: uppercase;\n      letter-spacing: 0.04em;\n      color: var(--text-muted);\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    pre {\n      background: var(--code-bg);\n      border: none;\n      padding: 14px 16px;\n      font-size: 0.86rem;\n      color: #e2e8f0;\n      white-space: pre-wrap;\n      word-break: break-word;\n      max-height: 220px;\n      overflow-y: auto;\n      line-height: 1.55;\n    }\n\n    pre code {\n      background: transparent;\n      color: inherit;\n      border: none;\n      padding: 0;\n    }\n\n    .preview-sandbox {\n      padding: 20px;\n      background: #ffffff;\n      border: 1px solid var(--card-border);\n      border-radius: 8px;\n      margin-top: 10px;\n      max-height: 320px;\n      overflow-y: auto;\n    }\n\n    \/* Temanın varsayılan tipografisini simüle eden kural *\/\n    .preview-sandbox h1 { font-size: 1.7rem; color: #1e3a8a; margin-bottom: 12px; border-bottom: 2px solid #bfdbfe; padding-bottom: 6px; }\n    .preview-sandbox h2 { font-size: 1.35rem; color: #0f172a; margin: 18px 0 10px; }\n    .preview-sandbox h3 { font-size: 1.15rem; color: #1e293b; margin: 14px 0 8px; }\n    .preview-sandbox p { margin-bottom: 12px; color: #334155; line-height: 1.7; }\n    .preview-sandbox blockquote { border-left: 4px solid var(--primary); padding: 10px 16px; background: #eff6ff; color: #1e40af; font-style: italic; margin: 16px 0; }\n    .preview-sandbox ul, .preview-sandbox ol { margin: 12px 0 16px 24px; color: #334155; }\n    .preview-sandbox table { width: 100%; border-collapse: collapse; margin: 16px 0; }\n    .preview-sandbox th, .preview-sandbox td { border: 1px solid #cbd5e1; padding: 8px 12px; }\n    .preview-sandbox th { background: #f1f5f9; font-weight: bold; }\n    .preview-sandbox a { color: var(--primary); text-decoration: underline; }\n\n    .info-callout {\n      background: #f0f9ff;\n      border-left: 4px solid #0284c7;\n      padding: 16px 18px;\n      border-radius: 0 8px 8px 0;\n      margin: 18px 0;\n    }\n\n    .info-callout strong {\n      color: #0369a1;\n      display: block;\n      margin-bottom: 4px;\n    }\n\n    .info-callout p {\n      color: #0c4a6e;\n      margin-bottom: 0;\n      font-size: 0.94rem;\n    }\n\n    .hidden {\n      display: none !important;\n    }\n  \u003C\/style\u003E\n\u003C\/head\u003E\n\u003Cbody\u003E\n\n\u003Cdiv class=\"max-wrapper\"\u003E\n\n  \u003Cheader\u003E\n    \u003Cdiv class=\"badge-bar\"\u003E\n      \u003Cspan class=\"tag tag-blue\"\u003EWeb Tipografisi \u0026 CMS Uyumu\u003C\/span\u003E\n      \u003Cspan class=\"tag tag-amber\"\u003ESıfır Stil Çöpü\u003C\/span\u003E\n    \u003C\/div\u003E\n    \u003Ch1\u003ETemaya Uyumlu Semantik HTML: Word ve Web Kopyalarını Temizleme Rehberi\u003C\/h1\u003E\n    \u003Cp class=\"subtitle\"\u003EWord, Google Docs veya başka web sitelerinden kopyalanan metinlerin arkasında gelen binlerce gereksiz inline stil, yazı tipi (font-family) ve yabancı sınıfı temizleyip sitenizin kendi temasıyla ışıldamasını sağlayan yöntem ve canlı araç.\u003C\/p\u003E\n  \u003C\/header\u003E\n\n  \u003C!-- MAKALE BÖLÜMÜ --\u003E\n  \u003Cdiv class=\"card\"\u003E\n    \u003Ch2\u003E1. \"Inline Style Çöpü\" Nedir ve Neden Blog Temanızı Bozar?\u003C\/h2\u003E\n    \u003Cp\u003E\n      Microsoft Word, Google Docs veya bir web sayfasından zengin metin kopyalayıp doğrudan WordPress, Blogger veya özel CMS panelinize yapıştırdığınızda görsel editörler metnin arkasındaki gizli HTML etiketlerini de taşır.\n    \u003C\/p\u003E\n\n    \u003Cdiv class=\"info-callout\"\u003E\n      \u003Cstrong\u003EKopya İle Gelen Tipik Bir Word Çöpü Örneği:\u003C\/strong\u003E\n      \u003Cp\u003E\u003Ccode\u003E\u0026lt;p class=\"MsoNormal\" style=\"margin-bottom:0cm; line-height:115%; font-family:'Calibri',sans-serif; font-size:11.0pt; color:#1F497D;\"\u0026gt;\u003C\/code\u003E\u003C\/p\u003E\n    \u003C\/div\u003E\n\n    \u003Cp\u003EBu görünmez kodlar blogunuzda şu ciddi sorunlara yol açar:\u003C\/p\u003E\n    \u003Cul\u003E\n      \u003Cli\u003E\u003Cstrong\u003ECSS Önceliğini Ezme (Specificity):\u003C\/strong\u003E Sitenizin temasında \u003Ccode\u003Eh1\u003C\/code\u003E, \u003Ccode\u003Eh2\u003C\/code\u003E veya \u003Ccode\u003Eblockquote\u003C\/code\u003E için özel renkler, zarif yazı tipleri ve kenar boşlukları tanımlanmış olsa bile; etiketin üzerindeki inline \u003Ccode\u003Estyle=\"...\"\u003C\/code\u003E özellikleri temanızın tüm CSS kurallarını ezer.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EKaranlık Mod (Dark Mode) Çöküşü:\u003C\/strong\u003E Word'den gelen \u003Ccode\u003Ecolor:#000000; background:#FFFFFF\u003C\/code\u003E kodları, sitenizi karanlık modda gezen okuyucuların siyah arka plan üzerine siyah yazı veya göz yoran beyaz yamalar görmesine neden olur.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EMobil Uyumsuzluk:\u003C\/strong\u003E Word'ün tablo veya paragraflara iliştirdiği sabit piksel genişlikleri (\u003Ccode\u003Ewidth: 680px;\u003C\/code\u003E) cep telefonlarında sayfanın sağa doğru taşmasına ve taşma kaydırma çubuklarına yol açar.\u003C\/li\u003E\n    \u003C\/ul\u003E\n\n    \u003Ch2\u003E2. Çözüm: \"Stil Yok, Anlam Var\" (Semantik Temizlik)\u003C\/h2\u003E\n    \u003Cp\u003E\n      İçeriği temizlerken metni düz yazıya (Notepad) çevirip tüm kalınlıkları ve başlıkları kaybetmek zorunda değilsiniz. Doğru yaklaşım şudur:\n    \u003C\/p\u003E\n    \u003Col\u003E\n      \u003Cli\u003E\u003Cstrong\u003EEtiketi Koru:\u003C\/strong\u003E \u003Ccode\u003E\u0026lt;h1\u0026gt;\u003C\/code\u003E, \u003Ccode\u003E\u0026lt;h2\u0026gt;\u003C\/code\u003E, \u003Ccode\u003E\u0026lt;blockquote\u0026gt;\u003C\/code\u003E, \u003Ccode\u003E\u0026lt;ul\u0026gt;\u003C\/code\u003E, \u003Ccode\u003E\u0026lt;strong\u0026gt;\u003C\/code\u003E ve \u003Ccode\u003E\u0026lt;table\u0026gt;\u003C\/code\u003E etiketleri korunur. Böylece yazının hiyerarşisi bozulmaz.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003ENitelikleri Sıyır:\u003C\/strong\u003E Etiketin üzerindeki tüm \u003Ccode\u003Estyle\u003C\/code\u003E, \u003Ccode\u003Eclass=\"Mso...\"\u003C\/code\u003E, \u003Ccode\u003Eid\u003C\/code\u003E, \u003Ccode\u003Efont\u003C\/code\u003E, \u003Ccode\u003Eface\u003C\/code\u003E ve \u003Ccode\u003Esize\u003C\/code\u003E nitelikleri silinir.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003ETemaya Teslim Et:\u003C\/strong\u003E Çıplak ve tertemiz kalan \u003Ccode\u003E\u0026lt;blockquote\u0026gt;Alıntı metni\u0026lt;\/blockquote\u0026gt;\u003C\/code\u003E, temanızın kendi CSS dosyasında tanımlanan harika renk ve tırnak işareti stiliyle otomatik olarak mükemmel görünür.\u003C\/li\u003E\n    \u003C\/ol\u003E\n  \u003C\/div\u003E\n\n  \u003Cdiv class=\"tool-box\"\u003E\n    \u003Ch2\u003E🧹 Canlı Semantik HTML ve Word Temizleyici\u003C\/h2\u003E\n    \u003Cp\u003EWord'den, Docs'tan veya bir web sayfasından kopyaladığınız metni buraya yapıştırın; temanıza sıfır müdahale eden tertemiz semantik HTML'i anında alın:\u003C\/p\u003E\n\n    \u003Cdiv class=\"tab-bar\"\u003E\n      \u003Cbutton class=\"tab-btn active\" id=\"tabRich\" type=\"button\" onclick=\"switchInputMode('rich')\"\u003E📋 Zengin Metin Yapıştır (Word \/ Web)\u003C\/button\u003E\n      \u003Cbutton class=\"tab-btn\" id=\"tabHtml\" type=\"button\" onclick=\"switchInputMode('html')\"\u003E💻 Ham HTML Kodu Yapıştır\u003C\/button\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- Zengin Metin Yapıştırma Alanı --\u003E\n    \u003Cdiv class=\"paste-area\" id=\"pasteArea\" contenteditable=\"true\" data-placeholder=\"Word, Docs veya web sayfasından kopyaladığınız metni buraya yapıştırın (Ctrl + V)...\"\u003E\u003C\/div\u003E\n\n    \u003C!-- Ham HTML Metin Alanı --\u003E\n    \u003Ctextarea class=\"html-textarea\" id=\"htmlInput\" placeholder=\"Temizlemek istediğiniz ham HTML kodlarını buraya yapıştırın...\"\u003E\u003C\/textarea\u003E\n\n    \u003C!-- Temizleme Kuralları --\u003E\n    \u003Cdiv class=\"options-grid\"\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optStripStyles\" checked\u003E Tüm inline \u003Ccode\u003Estyle=\"...\"\u003C\/code\u003E niteliklerini temizle\n      \u003C\/label\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optStripClasses\" checked\u003E Yabancı class ve id'leri kaldır (MsoNormal vb.)\n      \u003C\/label\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optUnwrapSpans\" checked\u003E Boş\/Anlamsız \u003Ccode\u003E\u0026lt;span\u0026gt;\u003C\/code\u003E ve \u003Ccode\u003E\u0026lt;font\u0026gt;\u003C\/code\u003E etiketlerini aç\n      \u003C\/label\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optRemoveEmptyP\" checked\u003E Art arda gelen boş \u003Ccode\u003E\u0026lt;p\u0026gt;\u0026amp;nbsp;\u0026lt;\/p\u0026gt;\u003C\/code\u003E satırlarını sil\n      \u003C\/label\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optCleanLinks\" checked\u003E Linklerdeki (\u003Ccode\u003E\u0026lt;a\u0026gt;\u003C\/code\u003E) renk ve stilleri temizle\n      \u003C\/label\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optCleanTables\" checked\u003E Tablo sabit genişlik ve kenarlık stillerini sil\n      \u003C\/label\u003E\n      \u003Clabel class=\"option-item\"\u003E\n        \u003Cinput type=\"checkbox\" id=\"optDedupeFootnotes\" checked\u003E Dipnot listesindeki mükerrer kopyaları temizle (1'e 1 eşleştir)\n      \u003C\/label\u003E\n    \u003C\/div\u003E\n\n    \u003Cdiv class=\"btn-row\"\u003E\n      \u003Cbutton class=\"btn\" type=\"button\" id=\"cleanBtn\"\u003E✨ Metni Temizle ve Ayrıştır\u003C\/button\u003E\n      \u003Cbutton class=\"btn btn-outline\" type=\"button\" id=\"loadSampleBtn\"\u003E🧪 Örnek Kirli Word Metni Yükle\u003C\/button\u003E\n      \u003Cbutton class=\"btn btn-outline\" type=\"button\" id=\"clearBtn\"\u003E🗑️ Temizle\u003C\/button\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- Sonuç ve İstatistik Alanı --\u003E\n    \u003Cdiv class=\"output-section hidden\" id=\"resultsSection\"\u003E\n      \u003Cdiv class=\"stat-strip\"\u003E\n        \u003Cdiv class=\"stat-badge\"\u003E\n          \u003Cdiv class=\"stat-num\" id=\"statStylesRemoved\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-lbl\"\u003ESilinen Inline Stil\u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"stat-badge\"\u003E\n          \u003Cdiv class=\"stat-num\" id=\"statTagsCleaned\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-lbl\"\u003EArındırılan Etiket\u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"stat-badge\"\u003E\n          \u003Cdiv class=\"stat-num\" id=\"statSpansRemoved\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-lbl\"\u003EAçılan Gereksiz Span\u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"stat-badge\"\u003E\n          \u003Cdiv class=\"stat-num\" id=\"statFootnotesDeduped\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-lbl\"\u003EBirleştirilen Dipnot\u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Başlık (H1) Ayrı Kutu --\u003E\n      \u003Cdiv class=\"box-block\" id=\"titleBlockWrapper\"\u003E\n        \u003Cdiv class=\"box-block-head\"\u003E\n          \u003Cspan class=\"box-block-title\"\u003E📌 Yazı Başlığı (H1 \/ Title)\u003C\/span\u003E\n          \u003Cbutton class=\"btn btn-outline\" style=\"font-size:0.78rem; padding:4px 10px;\" onclick=\"copyBoxContent('titleOutputCode', this)\"\u003EBaşlığı Kopyala\u003C\/button\u003E\n        \u003C\/div\u003E\n        \u003Cpre\u003E\u003Ccode id=\"titleOutputCode\"\u003E\u003C\/code\u003E\u003C\/pre\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Gövde İçeriği Ayrı Kutu --\u003E\n      \u003Cdiv class=\"box-block\"\u003E\n        \u003Cdiv class=\"box-block-head\"\u003E\n          \u003Cspan class=\"box-block-title\"\u003E📝 Temizlenmiş Gövde HTML'i (H2, p, blockquote, ul, ol)\u003C\/span\u003E\n          \u003Cbutton class=\"btn btn-outline\" style=\"font-size:0.78rem; padding:4px 10px;\" onclick=\"copyBoxContent('bodyOutputCode', this)\"\u003EGövdeyi Kopyala\u003C\/button\u003E\n        \u003C\/div\u003E\n        \u003Cpre\u003E\u003Ccode id=\"bodyOutputCode\"\u003E\u003C\/code\u003E\u003C\/pre\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Canlı Tema Önizlemesi --\u003E\n      \u003Cdiv class=\"box-block\"\u003E\n        \u003Cdiv class=\"box-block-head\"\u003E\n          \u003Cspan class=\"box-block-title\"\u003E👁️ Canlı Tema Simülasyonu (Temanızın CSS'i devredeyken nasıl durur?)\u003C\/span\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"preview-sandbox\" id=\"previewSandbox\"\u003E\u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003Cdiv class=\"card\"\u003E\n    \u003Ch2\u003E3. Hangi Etiketler Neden Korunmalıdır?\u003C\/h2\u003E\n    \u003Cp\u003E\n      Bu araç metninizi sıradan bir düz yazıya (txt) indirgemez; aşağıdaki anlamsal etiketleri temizleyip koruyarak temanızın CSS tasarım motoruna teslim eder:\n    \u003C\/p\u003E\n    \u003Cul\u003E\n      \u003Cli\u003E\u003Cstrong\u003E\u0026lt;h1\u0026gt;, \u0026lt;h2\u0026gt;, \u0026lt;h3\u0026gt;:\u003C\/strong\u003E Başlıkların tüm \u003Ccode\u003Efont-size\u003C\/code\u003E, \u003Ccode\u003Efont-family\u003C\/code\u003E ve \u003Ccode\u003Ecolor\u003C\/code\u003E tanımları silinir. Temanızdaki H1 alt çizgisi veya H2 sol kenar çubuğu neyse birebir o uygulanır.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003E\u0026lt;blockquote\u0026gt;:\u003C\/strong\u003E Word'den gelen italik ve kenarlık stilleri temizlenir; temanızın alıntı tasarımı ne kadar şıksa doğrudan o stile bürünür.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003E\u0026lt;ul\u0026gt;, \u0026lt;ol\u0026gt;, \u0026lt;li\u0026gt;:\u003C\/strong\u003E Word'ün \u003Ccode\u003EMsoListParagraph\u003C\/code\u003E gibi garip liste sınıfları yok edilir; temiz, standart HTML listesi kalır.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003E\u0026lt;table\u0026gt;:\u003C\/strong\u003E \u003Ccode\u003Ewidth=\"640\"\u003C\/code\u003E veya \u003Ccode\u003Ecellpadding=\"0\"\u003C\/code\u003E gibi 20 yıl öncesinin HTML nitelikleri silinir, temanızın responsive (mobilde kaydırılabilir) tablo kurallarına teslim edilir.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003E\u0026lt;a href=\"...\"\u0026gt;:\u003C\/strong\u003E Yalnızca bağlantı hedefi (URL) korunur; Word'ün veya kaynağın atadığı mor\/mavi\/altı çizili inline renkler temizlenerek temanızın bağlantı rengi aktif edilir.\u003C\/li\u003E\n    \u003C\/ul\u003E\n  \u003C\/div\u003E\n\n\u003C\/div\u003E\n\n\u003Cscript\u003E\n  let currentMode = 'rich';\n\n  const tabRich = document.getElementById('tabRich');\n  const tabHtml = document.getElementById('tabHtml');\n  const pasteArea = document.getElementById('pasteArea');\n  const htmlInput = document.getElementById('htmlInput');\n\n  const cleanBtn = document.getElementById('cleanBtn');\n  const loadSampleBtn = document.getElementById('loadSampleBtn');\n  const clearBtn = document.getElementById('clearBtn');\n\n  const resultsSection = document.getElementById('resultsSection');\n  const statStylesRemoved = document.getElementById('statStylesRemoved');\n  const statTagsCleaned = document.getElementById('statTagsCleaned');\n  const statSpansRemoved = document.getElementById('statSpansRemoved');\n  const statFootnotesDeduped = document.getElementById('statFootnotesDeduped');\n\n  const titleOutputCode = document.getElementById('titleOutputCode');\n  const bodyOutputCode = document.getElementById('bodyOutputCode');\n  const previewSandbox = document.getElementById('previewSandbox');\n  const titleBlockWrapper = document.getElementById('titleBlockWrapper');\n\n  \/\/ Giriş Modu Değişimi\n  function switchInputMode(mode) {\n    currentMode = mode;\n    if (mode === 'rich') {\n      tabRich.classList.add('active');\n      tabHtml.classList.remove('active');\n      pasteArea.style.display = 'block';\n      htmlInput.style.display = 'none';\n      if (htmlInput.value.trim()) {\n        pasteArea.innerHTML = htmlInput.value;\n      }\n    } else {\n      tabHtml.classList.add('active');\n      tabRich.classList.remove('active');\n      htmlInput.style.display = 'block';\n      pasteArea.style.display = 'none';\n      htmlInput.value = pasteArea.innerHTML;\n    }\n  }\n\n  \/\/ Global erişim ve buton dinleyicileri\n  window.switchInputMode = switchInputMode;\n  tabRich.addEventListener('click', () =\u003E switchInputMode('rich'));\n  tabHtml.addEventListener('click', () =\u003E switchInputMode('html'));\n\n  \/\/ Temizleme İşlemi\n  cleanBtn.addEventListener('click', performCleaning);\n\n  function performCleaning() {\n    let rawHtml = '';\n    if (currentMode === 'rich') {\n      rawHtml = pasteArea.innerHTML.trim();\n    } else {\n      rawHtml = htmlInput.value.trim();\n    }\n\n    if (!rawHtml) {\n      resultsSection.classList.add('hidden');\n      return;\n    }\n\n    const optStripStyles = document.getElementById('optStripStyles')?.checked ?? true;\n    const optStripClasses = document.getElementById('optStripClasses')?.checked ?? true;\n    const optSanitizeFilePaths = document.getElementById('optSanitizeFilePaths')?.checked ?? true;\n    const optUnwrapSpans = document.getElementById('optUnwrapSpans')?.checked ?? true;\n    const optRemoveEmptyP = document.getElementById('optRemoveEmptyP')?.checked ?? true;\n    const optCleanLinks = document.getElementById('optCleanLinks')?.checked ?? true;\n    const optCleanTables = document.getElementById('optCleanTables')?.checked ?? true;\n    const optDedupeFootnotes = document.getElementById('optDedupeFootnotes')?.checked ?? true;\n\n    let stylesCount = 0;\n    let tagsCount = 0;\n    let spansCount = 0;\n    let dedupedFootnotesCount = 0;\n\n    \/\/ Sanal DOM üzerinde güvenli temizlik\n    const container = document.createElement('div');\n    container.innerHTML = rawHtml;\n\n    \/\/ 1. XML \/ Word Yorumlarını Temizle (\u003C!--[if gte mso...]\u003E)\n    cleanXmlComments(container);\n\n    \/\/ 1.1 Word'ün özel o:p etiketlerini tamamen kaldır\n    const msoTags = Array.from(container.querySelectorAll('o\\\\:p'));\n    msoTags.forEach(el =\u003E {\n      if (el.parentNode) el.parentNode.removeChild(el);\n    });\n\n    \/\/ 1.2 file:\/\/\/C:\/... yerel bilgisayar yollarını ve kırık Word atıf kalıntılarını dönüştür\/temizle\n    if (optSanitizeFilePaths) {\n      sanitizeLocalFilePathsAndBookmarks(container);\n    }\n\n    \/\/ 1.3 Paragraf içi dipnot atıflarını bozmadan ölü ve içi boş link artıklarını ayıkla\n    cleanCorruptWordAnchors(container);\n\n    \/\/ 2. Anlamsız Font ve Span Etiketlerini Aç (Unwrap)\n    if (optUnwrapSpans) {\n      const fontAndSpans = Array.from(container.querySelectorAll('font, span'));\n      fontAndSpans.forEach(el =\u003E {\n        const isFootnoteRef = el.className \u0026\u0026 el.className.includes('fn-ref');\n        if (!isFootnoteRef) {\n          spansCount++;\n          unwrapElement(el);\n        }\n      });\n    }\n\n    \/\/ 3. Tüm Etiketlerde Stil ve Yabancı Nitelikleri Temizle\n    const allElements = Array.from(container.querySelectorAll('*'));\n    allElements.forEach(el =\u003E {\n      tagsCount++;\n      const tag = el.tagName.toLowerCase();\n\n      \/\/ Inline style temizliği\n      if (optStripStyles \u0026\u0026 el.hasAttribute('style')) {\n        stylesCount++;\n        el.removeAttribute('style');\n      }\n\n      \/\/ Class ve ID temizliği\n      if (optStripClasses) {\n        if (el.hasAttribute('class') \u0026\u0026 !el.className.includes('fn-ref')) el.removeAttribute('class');\n        if (el.hasAttribute('id') \u0026\u0026 !el.id.startsWith('fn')) el.removeAttribute('id');\n      }\n\n      \/\/ Eski HTML özellikleri\n      const legacyAttrs = ['align', 'valign', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'face', 'size', 'color', 'clear', 'nowrap'];\n      legacyAttrs.forEach(attr =\u003E {\n        if (el.hasAttribute(attr)) el.removeAttribute(attr);\n      });\n\n      \/\/ Tablo temizliği\n      if (optCleanTables \u0026\u0026 (tag === 'table' || tag === 'td' || tag === 'th' || tag === 'tr')) {\n        el.removeAttribute('width');\n        el.removeAttribute('height');\n      }\n\n      \/\/ Link temizliği\n      if (optCleanLinks \u0026\u0026 tag === 'a') {\n        el.removeAttribute('target');\n        const href = el.getAttribute('href') || '';\n        if (href.startsWith('http:\/\/') || href.startsWith('https:\/\/')) {\n          el.setAttribute('target', '_blank');\n          el.setAttribute('rel', 'noopener noreferrer');\n        }\n      }\n    });\n\n    \/\/ 4. Boş Paragrafları ve Gereksiz \u0026nbsp; Bloklarını Temizle\n    if (optRemoveEmptyP) {\n      const paragraphs = Array.from(container.querySelectorAll('p'));\n      paragraphs.forEach(p =\u003E {\n        const text = p.textContent.replace(\/\\u00a0\/g, ' ').trim();\n        const hasMedia = p.querySelector('img, iframe, video, object, embed');\n        if (!text \u0026\u0026 !hasMedia) {\n          p.parentNode.removeChild(p);\n        }\n      });\n    }\n\n    \/\/ 5. Dipnotları Kaydırmadan Tekilleştir ve Paragraf İçi İşaretçileri Koru\n    if (optDedupeFootnotes) {\n      dedupedFootnotesCount = processAndSyncFootnotesWithoutDrift(container);\n    }\n\n    \/\/ 6. Başlığı (H1) ve Gövdeyi Ayır\n    let titleHtml = '';\n    let titleText = '';\n    const firstH1 = container.querySelector('h1');\n\n    if (firstH1) {\n      titleText = firstH1.textContent.trim();\n      titleHtml = `\u003Ch1\u003E${escapeHtml(titleText)}\u003C\/h1\u003E`;\n      firstH1.parentNode.removeChild(firstH1);\n      titleBlockWrapper.classList.remove('hidden');\n    } else {\n      const firstP = container.querySelector('p');\n      if (firstP \u0026\u0026 firstP.textContent.length \u003C 90 \u0026\u0026 !firstP.textContent.includes('.')) {\n        titleText = firstP.textContent.trim();\n        titleHtml = `\u003Ch1\u003E${escapeHtml(titleText)}\u003C\/h1\u003E`;\n        firstP.parentNode.removeChild(firstP);\n        titleBlockWrapper.classList.remove('hidden');\n      } else {\n        titleBlockWrapper.classList.add('hidden');\n      }\n    }\n\n    const cleanedBodyHtml = formatHtmlString(container.innerHTML.trim());\n\n    \/\/ İstatistikleri güncelle\n    statStylesRemoved.textContent = stylesCount;\n    statTagsCleaned.textContent = tagsCount;\n    statSpansRemoved.textContent = spansCount;\n    statFootnotesDeduped.textContent = dedupedFootnotesCount;\n\n    \/\/ Kod kutularını doldur\n    titleOutputCode.textContent = titleHtml || '(Yazıda ayrı bir H1 başlığı bulunamadı)';\n    bodyOutputCode.textContent = cleanedBodyHtml;\n\n    \/\/ Canlı önizlemeyi hazırla\n    previewSandbox.innerHTML = (titleHtml ? titleHtml : '') + cleanedBodyHtml;\n\n    resultsSection.classList.remove('hidden');\n  }\n\n  \/\/ Yardımcı DOM Fonksiyonları\n  function unwrapElement(element) {\n    const parent = element.parentNode;\n    if (!parent) return;\n    while (element.firstChild) {\n      parent.insertBefore(element.firstChild, element);\n    }\n    parent.removeChild(element);\n  }\n\n  function cleanXmlComments(rootNode) {\n    const iterator = document.createNodeIterator(rootNode, NodeFilter.SHOW_COMMENT, null, false);\n    let curNode;\n    const commentsToRemove = [];\n    while ((curNode = iterator.nextNode())) {\n      commentsToRemove.push(curNode);\n    }\n    commentsToRemove.forEach(c =\u003E {\n      if (c.parentNode) c.parentNode.removeChild(c);\n    });\n  }\n\n  \/\/ WORD'ÜN _ftn (DİPNOT) VE _ftnref (METNE DÖNÜŞ) KÖPRÜSÜNÜ ÇİFT YÖNLÜ BAĞLAYAN MOTOR\n  function sanitizeLocalFilePathsAndBookmarks(container) {\n    \/\/ 1. İçi tamamen boş olan (görünür metni olmayan \u003Ca\u003E\u003Csup\u003E\u003C\/sup\u003E\u003C\/a\u003E) ve hedef taşımayan hayalet Word linklerini ayıkla\n    const allAnchors = Array.from(container.querySelectorAll('a'));\n    allAnchors.forEach(a =\u003E {\n      const href = a.getAttribute('href') || '';\n      const name = a.getAttribute('name') || '';\n      const id = a.getAttribute('id') || '';\n      const text = a.textContent.trim();\n\n      \/\/ İçinde metin yoksa ve ne ftn ne de ftnref bilgisi taşımıyorsa kaldır\n      if (!text \u0026\u0026 !href.includes('_ftn') \u0026\u0026 !name.includes('_ftn') \u0026\u0026 !id.includes('fn')) {\n        if (a.parentNode) a.parentNode.removeChild(a);\n      }\n    });\n\n    \/\/ 2. file:\/\/\/ ve Word atıf bağlantılarını çift yönlü (ftn ⇄ ftnref) dönüştür\n    const targetAnchors = Array.from(container.querySelectorAll('a'));\n\n    targetAnchors.forEach(a =\u003E {\n      const href = a.getAttribute('href') || '';\n      const name = a.getAttribute('name') || '';\n      const id = a.getAttribute('id') || '';\n      const text = a.textContent.trim();\n\n      const isFileLink = href.includes('file:');\n      const isWordFtnLink = href.includes('#_ftn') || name.includes('_ftn') || id.includes('_ftn');\n\n      if (!isFileLink \u0026\u0026 !isWordFtnLink) return;\n\n      \/\/ DURUM A: DİPNOTTAN METNE GERİ DÖNÜŞ (Geri dönüş bağlantısı: href -\u003E #_ftnref1 VEYA name\/id -\u003E _ftn1)\n      const backMatch = href.match(\/#_ftnref(\\d+)\/i) || name.match(\/^_ftn(\\d+)$\/i) || id.match(\/^_ftn(\\d+)$\/i);\n      if (backMatch) {\n        const n = backMatch[1];\n        a.setAttribute('href', `#fnref-${n}`);\n        a.setAttribute('id', `fn-${n}`);\n        a.removeAttribute('name');\n        a.removeAttribute('title');\n        if (!text || text === `[${n}]` || text === `${n}`) {\n          a.textContent = `[${n}]`;\n        }\n        return;\n      }\n\n      \/\/ DURUM B: METİNDEN DİPNOTA İLERİ GİDİŞ (Metin içi işaretçi: href -\u003E #_ftn1 VEYA name\/id -\u003E _ftnref1)\n      const forwardMatch = href.match(\/#_ftn(\\d+)\/i) || name.match(\/^_ftnref(\\d+)$\/i) || id.match(\/^_ftnref(\\d+)$\/i);\n      if (forwardMatch) {\n        const n = forwardMatch[1];\n        a.setAttribute('href', `#fn-${n}`);\n        a.setAttribute('id', `fnref-${n}`);\n        a.removeAttribute('name');\n        a.removeAttribute('title');\n        if (!text || text === `[${n}]` || text === `${n}`) {\n          a.textContent = `[${n}]`;\n        }\n        return;\n      }\n\n      \/\/ DURUM C: Normal bir kelimeye bağlanmış alelade yerel dosya yolu (gizlilik ve güvenlik için linki sök, metni koru)\n      if (isFileLink) {\n        unwrapElement(a);\n      }\n    });\n  }\n\n  \/\/ Dipnotların yerini kaydıran içi boş ve çöp Word linklerini temizler\n  function cleanCorruptWordAnchors(container) {\n    \/\/ İçi tamamen boş \u003Ca\u003E ve \u003Csup\u003E etiketlerini temizle (Metin veya geçerli id\/href taşımıyorsa)\n    let changed = true;\n    let guard = 0;\n    while (changed \u0026\u0026 guard \u003C 10) {\n      guard++;\n      changed = false;\n      const empties = Array.from(container.querySelectorAll('a, sup'));\n      empties.forEach(el =\u003E {\n        if (!el.textContent.trim() \u0026\u0026 el.children.length === 0) {\n          const id = el.getAttribute('id') || '';\n          const name = el.getAttribute('name') || '';\n          if (!id.startsWith('fn') \u0026\u0026 !name.startsWith('fn')) {\n            if (el.parentNode) {\n              el.parentNode.removeChild(el);\n              changed = true;\n            }\n          }\n        }\n      });\n    }\n  }\n\n  \/\/ 1'E 1 TAM EŞLEŞTİRME MOTORU: NUMARALARI KAYDIRMAZ, SON DİPNOTU ASLA SİLMEZ\n  function processAndSyncFootnotesWithoutDrift(container) {\n    let deduped = 0;\n\n    \/\/ 1. Sayfa sonundaki dipnot bloklarını tespit et (ul\/ol, MsoFootnoteText, word-footnotes, blogger-footnotes)\n    let footnoteSources = Array.from(container.querySelectorAll('ul, ol')).filter(list =\u003E {\n      const items = Array.from(list.querySelectorAll('li'));\n      if (items.length === 0) return false;\n      return items.some(li =\u003E {\n        const t = li.textContent.trim();\n        const id = li.id || '';\n        return \/^(\\[(\\d+)\\]|\\((\\d+)\\)|(\\d+)[\\.\\-\\)])\\s+\/.test(t) || id.includes('fn-') || id.includes('footnote');\n      });\n    });\n\n    \/\/ Word'ün \u003Cp class=\"MsoFootnoteText\"\u003E veya \u003Cdiv id=\"ftn1\"\u003E biçimindeki dipnotlarını da yakala\n    let individualFootnoteParas = [];\n    if (footnoteSources.length === 0) {\n      const candidateParas = Array.from(container.querySelectorAll('p, div'));\n      individualFootnoteParas = candidateParas.filter(p =\u003E {\n        const cls = p.className || '';\n        const id = p.id || '';\n        const t = p.textContent.trim();\n        const hasFtnCls = typeof cls === 'string' \u0026\u0026 (cls.includes('Footnote') || cls.includes('footnote'));\n        const hasFtnId = typeof id === 'string' \u0026\u0026 (id.startsWith('ftn') || id.startsWith('fn-'));\n        const hasNotePattern = \/^(\\[(\\d+)\\]|\\((\\d+)\\)|(\\d+)[\\.\\-\\)])\\s+\/.test(t) \u0026\u0026 t.length \u003E 15;\n        return hasFtnCls || hasFtnId || (hasNotePattern \u0026\u0026 (p.querySelector('a[href*=\"_ftnref\"]') || p.querySelector('a[href*=\"fnref\"]')));\n      });\n    }\n\n    if (footnoteSources.length === 0 \u0026\u0026 individualFootnoteParas.length === 0) {\n      footnoteSources = Array.from(container.querySelectorAll('.blogger-footnotes, .word-footnotes'));\n    }\n\n    if (footnoteSources.length === 0 \u0026\u0026 individualFootnoteParas.length === 0) return 0;\n\n    \/\/ 2. Sayfa sonundaki dipnot metinlerini numaralarına göre 1'e 1 haritala\n    const detectedNotesMap = new Map();\n\n    const allSourceElements = footnoteSources.length \u003E 0 \n      ? footnoteSources.flatMap(w =\u003E {\n          const lis = Array.from(w.querySelectorAll('li'));\n          return lis.length \u003E 0 ? lis : Array.from(w.querySelectorAll('p'));\n        })\n      : individualFootnoteParas;\n\n    allSourceElements.forEach(source =\u003E {\n      const fullText = (source.textContent || '').trim();\n      if (!fullText) return;\n\n      \/\/ [1]... [2]... şeklinde tek satıra sıkışmış maddeleri ve münferit satırları ayrıştır\n      const regex = \/(?:\\[(\\d+)\\]|\\((\\d+)\\)|(\\d+)[\\.\\-\\)])\\s+([\\s\\S]*?)(?=(?:\\s*\\[\\d+\\]|\\s*\\(\\d+\\)|\\s*\\d+[\\.\\-\\)]\\s+[A-ZÇĞİÖŞÜa-zçğıöşü]|$))\/g;\n      let match;\n      let foundInSource = false;\n\n      while ((match = regex.exec(fullText)) !== null) {\n        foundInSource = true;\n        const num = parseInt(match[1] || match[2] || match[3], 10);\n        let body = match[4].replace(\/[↩\\^]\/g, '').trim();\n\n        if (!detectedNotesMap.has(num)) {\n          detectedNotesMap.set(num, { num: num, body: body });\n        } else {\n          deduped++; \/\/ Aynı numara daha önce kaydedilmişse mükerrer say\n        }\n      }\n\n      if (!foundInSource) {\n        const singleMatch = fullText.match(\/^(\\[(\\d+)\\]|\\((\\d+)\\)|(\\d+)[\\.\\-\\)])\\s+([\\s\\S]+)$\/);\n        if (singleMatch) {\n          const num = parseInt(singleMatch[2] || singleMatch[3] || singleMatch[4], 10);\n          let body = singleMatch[5].replace(\/[↩\\^]\/g, '').trim();\n          if (!detectedNotesMap.has(num)) {\n            detectedNotesMap.set(num, { num: num, body: body });\n          } else {\n            deduped++;\n          }\n        }\n      }\n    });\n\n    const finalNotes = Array.from(detectedNotesMap.values()).sort((a, b) =\u003E a.num - b.num);\n    if (finalNotes.length === 0) return 0;\n\n    \/\/ 3. Sayfa altındaki eski kirli ve mükerrer dipnot bloklarını kaldır\n    footnoteSources.forEach(el =\u003E {\n      if (el.previousElementSibling \u0026\u0026 \/h[1-6]|strong|div\/i.test(el.previousElementSibling.tagName)) {\n        const prevText = el.previousElementSibling.textContent.trim();\n        if (prevText.includes('Dipnot') || prevText.includes('Kaynak')) {\n          el.previousElementSibling.parentNode.removeChild(el.previousElementSibling);\n        }\n      }\n      if (el.parentNode) el.parentNode.removeChild(el);\n    });\n\n    individualFootnoteParas.forEach(p =\u003E {\n      if (p.parentNode) p.parentNode.removeChild(p);\n    });\n\n    \/\/ 4. METİN İÇİ İŞARETÇİLERİ 1'E 1 BAĞLA (ASLA KAYDIRMA, HİÇBİRİNİ SİLME)\n    finalNotes.forEach(item =\u003E {\n      const n = item.num;\n      const targetFootnoteId = `fn-${n}`;\n      const targetRefId = `fnref-${n}`;\n\n      \/\/ Metin içinde n numarasına ait bağlantıyı bul\n      const matchingAnchors = Array.from(container.querySelectorAll('a')).filter(a =\u003E {\n        const txt = a.textContent.trim();\n        const href = a.getAttribute('href') || '';\n        const id = a.getAttribute('id') || '';\n\n        const exactNumMatch = txt === `[${n}]` || txt === `${n}` || txt === `(${n})`;\n        const idMatch = new RegExp(`(?:fnref|ftnref|fn)-[a-zA-Z0-9_-]*${n}$`).test(id) || id === `fnref-${n}` || id === `_ftnref${n}`;\n        const hrefMatch = new RegExp(`(?:#fn|#_ftn|#footnote)-[a-zA-Z0-9_-]*${n}$`).test(href) || href === `#fn-${n}` || href === `#_ftn${n}`;\n\n        return exactNumMatch || idMatch || hrefMatch;\n      });\n\n      if (matchingAnchors.length \u003E 0) {\n        \/\/ Görünür [n] metnine sahip olanı seç\n        let primaryAnchor = matchingAnchors.find(a =\u003E a.textContent.trim() === `[${n}]` || a.textContent.trim() === `${n}`) || matchingAnchors[0];\n\n        \/\/ Yanında biriken içi boş kopyaları ayıkla\n        matchingAnchors.forEach(a =\u003E {\n          if (a !== primaryAnchor \u0026\u0026 (!a.textContent.trim() || a.textContent.trim() === `[${n}]`)) {\n            if (a.parentNode) a.parentNode.removeChild(a);\n          }\n        });\n\n        primaryAnchor.setAttribute('href', `#${targetFootnoteId}`);\n        primaryAnchor.setAttribute('id', targetRefId);\n        primaryAnchor.textContent = `[${n}]`;\n        primaryAnchor.style.cssText = 'text-decoration:none; font-weight:700; color:#2563eb; padding:0 3px;';\n\n        if (!primaryAnchor.parentElement || primaryAnchor.parentElement.tagName.toLowerCase() !== 'sup') {\n          const sup = document.createElement('sup');\n          sup.className = 'fn-ref';\n          primaryAnchor.parentNode.insertBefore(sup, primaryAnchor);\n          sup.appendChild(primaryAnchor);\n        } else {\n          primaryAnchor.parentElement.className = 'fn-ref';\n        }\n      } else {\n        \/\/ Bağlantı yoksa paragraftaki düz [n] metnini yerinde yakala\n        bindInlineTextToFootnote(container, n, targetFootnoteId, targetRefId);\n      }\n    });\n\n    \/\/ 5. Sayfa sonuna tekil, 1'e 1 eşleşen ve metne geri dönüşlü (↩) tertemiz listeyi ekle\n    const fnWrapper = document.createElement('div');\n    fnWrapper.className = 'blogger-footnotes';\n    fnWrapper.style.cssText = 'border-top: 1px solid #cbd5e1; margin-top: 36px; padding-top: 18px; font-size: 0.9em;';\n\n    let html = '\u003Cstrong style=\"display:block; margin-bottom:12px; color:#0f172a; font-size:1.05em;\"\u003EDipnotlar ve Kaynakça\u003C\/strong\u003E\\n\u003Cul style=\"list-style:none; padding:0; margin:0;\"\u003E\\n';\n\n    finalNotes.forEach(item =\u003E {\n      const n = item.num;\n      const targetFootnoteId = `fn-${n}`;\n      const targetRefId = `fnref-${n}`;\n      html += `  \u003Cli id=\"${targetFootnoteId}\" style=\"margin-bottom:8px; line-height:1.6;\"\u003E\\n    \u003Ca href=\"#${targetRefId}\" style=\"text-decoration:none; font-weight:700; color:#2563eb;\" title=\"Metindeki yerine dön\"\u003E[${n}]\u003C\/a\u003E ${escapeHtml(item.body)} \u003Ca href=\"#${targetRefId}\" title=\"Metne geri dön\" style=\"text-decoration:none; font-weight:bold; color:#2563eb; margin-left:4px;\"\u003E ↩\u003C\/a\u003E\\n  \u003C\/li\u003E\\n`;\n    });\n\n    html += '\u003C\/ul\u003E';\n    fnWrapper.innerHTML = html;\n    container.appendChild(fnWrapper);\n\n    return deduped;\n  }\n\n  \/\/ Düz metin halindeki [n] atıflarını paragraf içindeki tam yerinde yakalar\n  function bindInlineTextToFootnote(container, n, footnoteId, refId) {\n    const sups = Array.from(container.querySelectorAll('sup'));\n    for (let sup of sups) {\n      const txt = sup.textContent.trim();\n      if (txt === `${n}` || txt === `[${n}]` || txt === `(${n})`) {\n        sup.className = 'fn-ref';\n        sup.innerHTML = `\u003Ca href=\"#${footnoteId}\" id=\"${refId}\" style=\"text-decoration:none; font-weight:700; color:#2563eb; padding:0 3px;\"\u003E[${n}]\u003C\/a\u003E`;\n        return;\n      }\n    }\n\n    const regex = new RegExp(`\\\\[${n}\\\\]|\\\\(${n}\\\\)`);\n    const treeWalker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, null, false);\n    let textNode;\n    while ((textNode = treeWalker.nextNode())) {\n      if (regex.test(textNode.nodeValue)) {\n        const span = document.createElement('span');\n        span.innerHTML = textNode.nodeValue.replace(regex, `\u003Csup class=\"fn-ref\"\u003E\u003Ca href=\"#${footnoteId}\" id=\"${refId}\" style=\"text-decoration:none; font-weight:700; color:#2563eb; padding:0 3px;\"\u003E[${n}]\u003C\/a\u003E\u003C\/sup\u003E`);\n        textNode.parentNode.replaceChild(span, textNode);\n        unwrapElement(span);\n        return;\n      }\n    }\n  }\n\n  \/\/ HTML formatlayıcı (Girintileri temiz ve okunaklı yapar)\n  function formatHtmlString(html) {\n    return html\n      .replace(\/\u003E\\s*\u003C\/g, '\u003E\\n\u003C')\n      .replace(\/(\u003Cp[^\u003E]*\u003E)\/gi, '\\n$1')\n      .replace(\/(\u003C\\\/p\u003E)\/gi, '$1\\n')\n      .replace(\/(\u003Ch[1-6][^\u003E]*\u003E)\/gi, '\\n\\n$1')\n      .replace(\/(\u003C\\\/h[1-6]\u003E)\/gi, '$1\\n')\n      .replace(\/(\u003Cblockquote[^\u003E]*\u003E)\/gi, '\\n\\n$1\\n')\n      .replace(\/(\u003C\\\/blockquote\u003E)\/gi, '\\n$1\\n\\n')\n      .replace(\/\\n\\s*\\n\\s*\\n\/g, '\\n\\n')\n      .trim();\n  }\n\n  \/\/ Kopyalama Butonu İşlevi\n  function copyBoxContent(elementId, btn) {\n    const el = document.getElementById(elementId);\n    if (!el) return;\n\n    const tempTextArea = document.createElement('textarea');\n    tempTextArea.value = el.textContent;\n    document.body.appendChild(tempTextArea);\n    tempTextArea.select();\n    document.execCommand('copy');\n    document.body.removeChild(tempTextArea);\n\n    const originalText = btn.textContent;\n    btn.textContent = 'Kopyalandı!';\n    btn.style.borderColor = 'var(--success)';\n    btn.style.color = 'var(--success)';\n\n    setTimeout(() =\u003E {\n      btn.textContent = originalText;\n      btn.style.borderColor = '';\n      btn.style.color = '';\n    }, 1400);\n  }\n\n  \/\/ Örnek Kirli Word Metni Yükleyici\n  loadSampleBtn.addEventListener('click', () =\u003E {\n    const dirtyWordSample = `\n\u003Ch1 style=\"margin-top:0cm;margin-right:0cm;margin-bottom:12.0pt;margin-left:0cm;line-height:115%;font-size:24.0pt;font-family:'Calibri Light',sans-serif;color:#1F497D;font-weight:bold;\"\u003EModern Web Tasarımında Tipografi ve Standartlar\u003C\/h1\u003E\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom:10.0pt;line-height:115%;font-family:'Calibri',sans-serif;font-size:11.0pt;color:#333333;background:white;\"\u003E\n  Word'den kopyalanan ilk atıf burada yer alır[1]. Ardından ikinci bir kaynak belirtilir[2]. İlerleyen bir paragrafta ise yazar aynı ilk kaynağa tekrar atıfta bulunur[3].\n\u003C\/p\u003E\n\u003Cblockquote style=\"margin-top:5.0pt;margin-bottom:5.0pt;margin-left:36.0pt;border-left:3.0pt solid #4F81BD;padding-left:10.0pt;font-family:'Georgia',serif;color:#555555;font-style:italic;\"\u003E\n  \"İyi bir web sayfası, etiketlerin stiliyle değil anlamıyla (semantik) var olmalıdır.\"\n\u003C\/blockquote\u003E\n\u003Cp class=\"MsoNormal\" style=\"margin-bottom:10.0pt;line-height:115%;\"\u003E\n  Aşağıda yer alan dipnot listesinde 1. ve 3. maddeler birebir aynı kaynağa aittir:\n\u003C\/p\u003E\n\u003Cdiv class=\"word-footnotes\" style=\"border-top:1px solid #ccc; padding-top:10px; margin-top:20px;\"\u003E\n  \u003Cp class=\"MsoFootnoteText\" style=\"font-size:10.0pt; color:#444;\"\u003E1. Russell, S. ve Norvig, P. Yapay Zeka: Modern Yaklaşım, 4. Baskı, s. 102.\u003C\/p\u003E\n  \u003Cp class=\"MsoFootnoteText\" style=\"font-size:10.0pt; color:#444;\"\u003E2. Turing, A. M. Computing Machinery and Intelligence, Mind, 1950.\u003C\/p\u003E\n  \u003Cp class=\"MsoFootnoteText\" style=\"font-size:10.0pt; color:#444;\"\u003E3. Russell, S. ve Norvig, P. Yapay Zeka: Modern Yaklaşım, 4. Baskı, s. 102.\u003C\/p\u003E\n\u003C\/div\u003E\n`;\n\n    if (currentMode === 'rich') {\n      pasteArea.innerHTML = dirtyWordSample;\n    } else {\n      htmlInput.value = dirtyWordSample;\n    }\n\n    performCleaning();\n  });\n\n  \/\/ Temizle Butonu\n  clearBtn.addEventListener('click', () =\u003E {\n    pasteArea.innerHTML = '';\n    htmlInput.value = '';\n    resultsSection.classList.add('hidden');\n  });\n\n  function escapeHtml(str) {\n    return String(str).replace(\/[\u0026\u003C\u003E\"']\/g, m =\u003E ({ '\u0026': '\u0026amp;', '\u003C': '\u0026lt;', '\u003E': '\u0026gt;', '\"': '\u0026quot;', \"'\": '\u0026#039;' }[m]));\n  }\n\u003C\/script\u003E\n\n\u003C\/body\u003E\n\u003C\/html\u003E"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/122220330648239606"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/122220330648239606"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/09\/semantik-html-temizleyici-tema.html","title":"Semantik HTML Temizleyici \u0026 Tema Uyumluluk Rehberi"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}]},{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-8035433387821517378"},"published":{"$t":"2026-09-05T11:40:12.676+03:00"},"updated":{"$t":"2026-09-05T12:00:22.646+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"tutorial"}],"title":{"type":"text","$t":"Blogger Yedek Dosyasındaki (XML) Tüm Dipnotları Topluca Tamir Etme Sistemi"},"content":{"type":"html","$t":"\u003C!DOCTYPE html\u003E\n\u003Chtml lang=\"tr\"\u003E\n\u003Chead\u003E\n  \u003Cmeta charset=\"UTF-8\"\u003E\n  \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003E\n  \u003Ctitle\u003EBlogger Atom XML Toplu Dipnot Onarıcı \u0026 Sistem Mimarisi\u003C\/title\u003E\n  \u003C!-- JSZip: Düzeltilmiş yazıları veya dosyayı paketlemek için --\u003E\n  \u003Cscript src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jszip\/3.10.1\/jszip.min.js\"\u003E\u003C\/script\u003E\n  \u003Cstyle\u003E\n    :root {\n      --bg: #f8fafc;\n      --surface: #ffffff;\n      --surface-subtle: #f1f5f9;\n      --card-border: #e2e8f0;\n      --card-border-focus: #cbd5e1;\n      --text: #0f172a;\n      --text-body: #334155;\n      --text-muted: #64748b;\n      --primary: #2563eb;\n      --primary-hover: #1d4ed8;\n      --primary-subtle: #eff6ff;\n      --primary-border: #bfdbfe;\n      --accent: #d97706;\n      --accent-subtle: #fffbeb;\n      --accent-border: #fde68a;\n      --success: #16a34a;\n      --success-subtle: #f0fdf4;\n      --success-border: #bbf7d0;\n      --code-bg: #0f172a;\n      --code-text: #f8fafc;\n    }\n\n    * {\n      box-sizing: border-box;\n      margin: 0;\n      padding: 0;\n      font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n    }\n\n    body {\n      background-color: var(--bg);\n      color: var(--text-body);\n      line-height: 1.75;\n      padding: 40px 20px;\n    }\n\n    .max-wrapper {\n      max-width: 900px;\n      margin: 0 auto;\n    }\n\n    header {\n      margin-bottom: 36px;\n      border-bottom: 1px solid var(--card-border);\n      padding-bottom: 28px;\n    }\n\n    .badge-bar {\n      display: flex;\n      gap: 10px;\n      margin-bottom: 14px;\n      flex-wrap: wrap;\n    }\n\n    .tag {\n      font-size: 0.78rem;\n      font-weight: 700;\n      text-transform: uppercase;\n      letter-spacing: 0.05em;\n      padding: 4px 10px;\n      border-radius: 9999px;\n    }\n\n    .tag-blue {\n      background: var(--primary-subtle);\n      color: var(--primary);\n      border: 1px solid var(--primary-border);\n    }\n\n    .tag-amber {\n      background: var(--accent-subtle);\n      color: var(--accent);\n      border: 1px solid var(--accent-border);\n    }\n\n    h1 {\n      font-size: 2.1rem;\n      line-height: 1.35;\n      color: var(--text);\n      margin-bottom: 12px;\n      font-weight: 800;\n    }\n\n    .subtitle {\n      font-size: 1.1rem;\n      color: var(--text-muted);\n      line-height: 1.6;\n    }\n\n    .card {\n      background: var(--surface);\n      border: 1px solid var(--card-border);\n      border-radius: 12px;\n      padding: 32px;\n      margin-bottom: 30px;\n      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 6px -2px rgba(0, 0, 0, 0.02);\n    }\n\n    h2 {\n      font-size: 1.38rem;\n      color: var(--text);\n      margin-bottom: 16px;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    p {\n      margin-bottom: 16px;\n      color: var(--text-body);\n      font-size: 1rem;\n    }\n\n    ul, ol {\n      margin: 14px 0 20px 24px;\n      color: var(--text-body);\n      font-size: 0.98rem;\n    }\n\n    li {\n      margin-bottom: 8px;\n    }\n\n    code {\n      background: #f1f5f9;\n      color: #0f172a;\n      padding: 2px 6px;\n      border-radius: 4px;\n      font-size: 0.88em;\n      font-family: Consolas, Monaco, \"Courier New\", monospace;\n      border: 1px solid #e2e8f0;\n    }\n\n    \/* Adım Gridleri *\/\n    .step-grid {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n      gap: 16px;\n      margin: 22px 0;\n    }\n\n    .step-box {\n      background: var(--surface-subtle);\n      border: 1px solid var(--card-border);\n      border-radius: 8px;\n      padding: 18px;\n    }\n\n    .step-num {\n      font-size: 0.78rem;\n      font-weight: 800;\n      color: var(--primary);\n      text-transform: uppercase;\n      letter-spacing: 0.06em;\n      margin-bottom: 6px;\n    }\n\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      color: var(--text);\n      margin-bottom: 8px;\n    }\n\n    .step-box p {\n      font-size: 0.9rem;\n      color: var(--text-muted);\n      margin-bottom: 0;\n    }\n\n    \/* Araç Kutusu *\/\n    .tool-box {\n      background: #ffffff;\n      border: 2px solid var(--primary-border);\n      border-radius: 12px;\n      padding: 32px;\n      margin: 35px 0;\n      box-shadow: 0 4px 12px rgba(37, 99, 235, 0.06);\n    }\n\n    .warning-box {\n      background: var(--accent-subtle);\n      border: 1px solid var(--accent-border);\n      border-left: 5px solid var(--accent);\n      border-radius: 8px;\n      padding: 18px 20px;\n      margin: 20px 0;\n      display: flex;\n      gap: 14px;\n      align-items: flex-start;\n    }\n\n    .warning-box strong {\n      color: #92400e;\n      display: block;\n      margin-bottom: 4px;\n      font-size: 1rem;\n    }\n\n    .warning-box p {\n      color: #78350f;\n      margin-bottom: 0;\n      font-size: 0.92rem;\n      line-height: 1.6;\n    }\n\n    .warning-icon {\n      font-size: 1.6rem;\n      line-height: 1;\n      flex-shrink: 0;\n    }\n\n    .dropzone {\n      border: 2px dashed #94a3b8;\n      border-radius: 10px;\n      background: #f8fafc;\n      padding: 38px 20px;\n      text-align: center;\n      cursor: pointer;\n      transition: all 0.2s ease;\n      margin-top: 18px;\n    }\n\n    .dropzone:hover, .dropzone.dragover {\n      border-color: var(--primary);\n      background: #eff6ff;\n    }\n\n    .drop-title {\n      font-size: 1.15rem;\n      font-weight: 700;\n      color: var(--text);\n      margin-bottom: 6px;\n    }\n\n    .btn {\n      background: var(--primary);\n      color: #ffffff;\n      font-weight: 600;\n      border: none;\n      padding: 9px 18px;\n      border-radius: 6px;\n      cursor: pointer;\n      font-size: 0.9rem;\n      transition: all 0.15s ease;\n      display: inline-flex;\n      align-items: center;\n      gap: 6px;\n      text-decoration: none;\n    }\n\n    .btn:hover {\n      background: var(--primary-hover);\n    }\n\n    .btn-outline {\n      background: #ffffff;\n      border: 1px solid var(--card-border-focus);\n      color: var(--text);\n    }\n\n    .btn-outline:hover {\n      background: var(--surface-subtle);\n      border-color: #94a3b8;\n    }\n\n    .stats-bar {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n      gap: 14px;\n      margin: 22px 0;\n    }\n\n    .stat-card {\n      background: var(--surface-subtle);\n      border: 1px solid var(--card-border);\n      border-radius: 8px;\n      padding: 16px;\n      text-align: center;\n    }\n\n    .stat-val {\n      font-size: 1.8rem;\n      font-weight: 800;\n      color: var(--primary);\n      margin-bottom: 2px;\n    }\n\n    .stat-label {\n      font-size: 0.8rem;\n      color: var(--text-muted);\n      text-transform: uppercase;\n      font-weight: 700;\n      letter-spacing: 0.03em;\n    }\n\n    .post-list {\n      max-height: 480px;\n      overflow-y: auto;\n      margin-top: 20px;\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n      padding-right: 4px;\n    }\n\n    .post-row {\n      background: #ffffff;\n      border: 1px solid var(--card-border);\n      border-radius: 8px;\n      padding: 16px 20px;\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      transition: border-color 0.15s, box-shadow 0.15s;\n    }\n\n    .post-row:hover {\n      border-color: #cbd5e1;\n      box-shadow: 0 2px 4px rgba(0,0,0,0.03);\n    }\n\n    .post-info-title {\n      font-weight: 700;\n      color: var(--text);\n      font-size: 0.98rem;\n      margin-bottom: 4px;\n    }\n\n    .post-meta {\n      font-size: 0.84rem;\n      color: var(--text-muted);\n    }\n\n    .badge-count {\n      background: var(--success-subtle);\n      color: var(--success);\n      border: 1px solid var(--success-border);\n      font-size: 0.76rem;\n      font-weight: 700;\n      padding: 2px 8px;\n      border-radius: 4px;\n      margin-left: 6px;\n    }\n\n    .hidden {\n      display: none !important;\n    }\n\n    pre {\n      background: var(--code-bg);\n      border: 1px solid #1e293b;\n      border-radius: 8px;\n      padding: 14px 16px;\n      font-size: 0.88rem;\n      color: #e2e8f0;\n      white-space: pre-wrap;\n      word-break: break-word;\n      max-height: 220px;\n      overflow-y: auto;\n      line-height: 1.6;\n    }\n\n    pre code {\n      background: transparent;\n      color: inherit;\n      border: none;\n      padding: 0;\n      font-size: inherit;\n    }\n\n    .info-callout {\n      background: #f0f9ff;\n      border-left: 4px solid #0284c7;\n      padding: 16px 18px;\n      border-radius: 0 8px 8px 0;\n      margin: 18px 0;\n    }\n\n    .info-callout strong {\n      color: #0369a1;\n      display: block;\n      margin-bottom: 4px;\n    }\n\n    .info-callout p {\n      color: #0c4a6e;\n      margin-bottom: 0;\n      font-size: 0.94rem;\n    }\n  \u003C\/style\u003E\n\u003C\/head\u003E\n\u003Cbody\u003E\n\n\u003Cdiv class=\"max-wrapper\"\u003E\n\n  \u003Cheader\u003E\n    \u003Cdiv class=\"badge-bar\"\u003E\n      \u003Cspan class=\"tag tag-blue\"\u003EBlogger \/ Blogspot Otomasyonu\u003C\/span\u003E\n      \u003Cspan class=\"tag tag-amber\"\u003EAtom 1.0 XML Standardı\u003C\/span\u003E\n    \u003C\/div\u003E\n    \u003Cp class=\"subtitle\"\u003EBlogger panelinden indirilen \u003Ccode\u003Eblog-MM-DD-YYYY.xml\u003C\/code\u003E yedeğindeki yüzlerce makaleyi istemci tarafında ayrıştırıp, Word'den aktarılan bozuk ya da linklenmemiş dipnotları çift yönlü HTML bağlantılarına dönüştürme rehberi ve canlı aracı.\u003C\/p\u003E\n  \u003C\/header\u003E\n\n  \u003Cdiv class=\"card\"\u003E\n    \u003Ch2\u003E1. Blogger İçerik Formatı: Atom XML Mimarisi Nasıl Çalışır?\u003C\/h2\u003E\n    \u003Cp\u003E\n      Blogger'ın \u003Cem\u003EAyarlar \u0026gt; İçeriği Yönet \u0026gt; İçeriği Yedekle\u003C\/em\u003E seçeneğiyle indirdiğiniz dosya, Google'ın \u003Cstrong\u003EAtom 1.0 Syndication Format\u003C\/strong\u003E spesifikasyonuna dayalı tek parça bir veritabanı yedeğidir.\n    \u003C\/p\u003E\n\n    \u003Cdiv class=\"info-callout\"\u003E\n      \u003Cstrong\u003EAtom XML İçerik Formatının Temel Özellikleri:\u003C\/strong\u003E\n      \u003Cp\u003EBlogger her bir yayını \u003Ccode\u003E\u0026lt;entry\u0026gt;\u003C\/code\u003E etiketi içine koyar. Makalenin gövdesi ise \u003Ccode\u003E\u0026lt;content type='html'\u0026gt;...\u0026lt;\/content\u0026gt;\u003C\/code\u003E bloğunda saklanır. Ancak bu blok doğrudan açık HTML etiketleri barındırmaz; XML'in bozulmaması için tüm HTML etiketleri \u003Cem\u003EXML Entity\u003C\/em\u003E formatında (örneğin \u003Ccode\u003E\u0026amp;lt;p\u0026amp;gt;\u003C\/code\u003E şeklinde) kodlanarak tutulur.\u003C\/p\u003E\n    \u003C\/div\u003E\n\n    \u003Cp\u003EDosya yapısında üç temel ayrım bulunur:\u003C\/p\u003E\n    \u003Cul\u003E\n      \u003Cli\u003E\u003Cstrong\u003EYayın Türleri:\u003C\/strong\u003E \u003Ccode\u003E\u0026lt;category term=\"...kind#post\"\/\u0026gt;\u003C\/code\u003E gerçek blog yazılarını, \u003Ccode\u003Ekind#page\u003C\/code\u003E statik sayfaları, \u003Ccode\u003Ekind#comment\u003C\/code\u003E ise okuyucu yorumlarını belirtir. Geliştirdiğimiz motor yalnızca \u003Cstrong\u003Ekind#post\u003C\/strong\u003E öğelerini işler; yorum veya şablon verilerine asla dokunmaz.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EDOMParser ile Kayıpsız Çözümleme:\u003C\/strong\u003E Tarayıcının \u003Ccode\u003EDOMParser(\"application\/xml\")\u003C\/code\u003E motoru bu dosyayı bellek üzerinde ağaç yapısına çevirirken, \u003Ccode\u003Econtent.textContent\u003C\/code\u003E çağrısı yapıldığı anda XML entity'leri otomatik olarak tertemiz HTML metnine çözümlenir.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EGeri Yazım Güvencesi:\u003C\/strong\u003E Dipnotlar HTML seviyesinde düzeltildikten sonra aynı içerik düğümüne aktarılır. \u003Ccode\u003EXMLSerializer\u003C\/code\u003E dosyayı dışa aktarırken HTML karakterlerini standartlara uygun olarak yeniden güvenle XML entity'sine dönüştürür. Böylece Blogger paneline geri aktarıldığında hiçbir format çökmesi yaşanmaz.\u003C\/li\u003E\n    \u003C\/ul\u003E\n\n    \u003Cdiv class=\"step-grid\"\u003E\n      \u003Cdiv class=\"step-box\"\u003E\n        \u003Cdiv class=\"step-num\"\u003EAdım 1\u003C\/div\u003E\n        \u003Cdiv class=\"step-title\"\u003EYerel XML Ayrıştırma\u003C\/div\u003E\n        \u003Cp\u003EBlogger Atom feed'i sunucusuz, doğrudan tarayıcı belleğine (DOMParser) alınır.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"step-box\"\u003E\n        \u003Cdiv class=\"step-num\"\u003EAdım 2\u003C\/div\u003E\n        \u003Cdiv class=\"step-title\"\u003EDipnot Tespiti\u003C\/div\u003E\n        \u003Cp\u003ESayfa altındaki \u003Ccode\u003E1. Kaynak\u003C\/code\u003E satırları ile metindeki \u003Ccode\u003E[1]\u003C\/code\u003E veya \u003Ccode\u003E\u0026lt;sup\u0026gt;1\u0026lt;\/sup\u0026gt;\u003C\/code\u003E işaretleri taranır.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"step-box\"\u003E\n        \u003Cdiv class=\"step-num\"\u003EAdım 3\u003C\/div\u003E\n        \u003Cdiv class=\"step-title\"\u003EÇift Yönlü Linkleme\u003C\/div\u003E\n        \u003Cp\u003EMetne tıklandığında nota kayan, nottan metne dönen (\u003Ccode\u003E↩\u003C\/code\u003E) standart HTML bağlantısı yerleştirilir.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"step-box\"\u003E\n        \u003Cdiv class=\"step-num\"\u003EAdım 4\u003C\/div\u003E\n        \u003Cdiv class=\"step-title\"\u003EAtom XML Kaydı\u003C\/div\u003E\n        \u003Cp\u003EDüzeltilmiş tüm içerikler orijinal XML ağacına yazılarak Blogger'a içe aktarılmaya hazır hale gelir.\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003Cdiv class=\"tool-box\"\u003E\n    \u003Ch2\u003E🛠️ Canlı Blogger XML Dipnot Onarıcı\u003C\/h2\u003E\n    \u003Cp\u003EBlogger panelinden indirdiğiniz \u003Ccode\u003E.xml\u003C\/code\u003E yedeğinizi yükleyin veya sistemi denemek için örnek veriyi çalıştırın:\u003C\/p\u003E\n\n    \u003Cdiv class=\"warning-box\"\u003E\n      \u003Cdiv class=\"warning-icon\"\u003E⚠️\u003C\/div\u003E\n      \u003Cdiv\u003E\n        \u003Cstrong\u003EÖnemli Güvenlik Tavsiyesi: Orijinal XML\/Atom Dosyanızı Güvenli Bir Yerde Saklayın!\u003C\/strong\u003E\n        \u003Cp\u003EBlogger panelinden (\u003Cem\u003EAyarlar \u0026gt; İçeriği Yönet \u0026gt; İçeriği Yedekle\u003C\/em\u003E) indirdiğiniz ham dosyanın bir kopyasını masaüstünüzde veya güvenli bir klasörde mutlaka saklayın. İşlenmiş XML dosyasını Blogger'a yüklemeden önce elinizde orijinal bir kopyanın bulunması, olası bir aksilikte blogunuzu tek tıkla eski haline döndürmenizi sağlar.\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n\n    \u003Cdiv style=\"display: flex; gap: 10px; margin-bottom: 12px; flex-wrap: wrap;\"\u003E\n      \u003Cbutton class=\"btn\" type=\"button\" onclick=\"document.getElementById('xmlFileInput').click()\"\u003E📁 Bilgisayardan .atom \/ .xml Dosyası Seç\u003C\/button\u003E\n      \u003Cbutton class=\"btn btn-outline\" id=\"loadSampleBtn\"\u003E🧪 Örnek Atom Verisi Yükle\u003C\/button\u003E\n      \u003C!-- accept kısıtlaması tamamen kaldırıldı; işletim sistemi penceresi tüm dosyaları (.atom dahil) gösterir --\u003E\n      \u003Cinput type=\"file\" id=\"xmlFileInput\" style=\"display:none\"\u003E\n    \u003C\/div\u003E\n\n    \u003Cdiv class=\"dropzone\" id=\"dropzone\" onclick=\"document.getElementById('xmlFileInput').click()\"\u003E\n      \u003Cdiv style=\"font-size: 2.4rem; margin-bottom: 8px;\"\u003E📂\u003C\/div\u003E\n      \u003Cdiv class=\"drop-title\"\u003EBlogger .atom \/ .xml Dosyasını Sürükleyin veya Seçin\u003C\/div\u003E\n      \u003Cp style=\"font-size: 0.9rem; color: var(--text-muted); margin: 0;\"\u003EDosyanız hiçbir sunucuya yüklenmez, tüm işlemler tamamen bilgisayarınızın tarayıcısında gerçekleşir.\u003C\/p\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- Yükleme \/ İlerleme Çubuğu --\u003E\n        \u003Cdiv class=\"stat-card\"\u003E\n          \u003Cdiv class=\"stat-val\" id=\"statTotalPosts\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-label\"\u003EToplam Yazı\u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"stat-card\"\u003E\n          \u003Cdiv class=\"stat-val\" id=\"statFixedPosts\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-label\"\u003EDipnotlu Yazı\u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"stat-card\"\u003E\n          \u003Cdiv class=\"stat-val\" id=\"statTotalNotes\"\u003E0\u003C\/div\u003E\n          \u003Cdiv class=\"stat-label\"\u003EBağlanan Dipnot\u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv style=\"display: flex; justify-content: space-between; align-items: center; margin: 18px 0; flex-wrap: wrap; gap: 12px;\"\u003E\n        \u003Cspan style=\"font-size: 0.95rem; font-weight: 700; color: var(--text);\" id=\"statusNotice\"\u003Eİşlem Tamamlandı\u003C\/span\u003E\n        \u003Cdiv style=\"display: flex; gap: 8px; flex-wrap: wrap;\"\u003E\n          \u003Cbutton class=\"btn\" id=\"downloadXmlBtn\"\u003E💾 Düzeltilmiş Blogger XML İndir\u003C\/button\u003E\n          \u003Cbutton class=\"btn btn-outline\" id=\"downloadZipBtn\"\u003E📦 Yazıları HTML Olarak İndir (ZIP)\u003C\/button\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"post-list\" id=\"postListContainer\"\u003E\u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003Cdiv class=\"card\"\u003E\n    \u003Ch2\u003E2. Dipnotlarda Link Yoksa Sistem Nasıl Tespit Eder?\u003C\/h2\u003E\n    \u003Cp\u003E\n      Word belgelerinden Blogger'a yapıştırma yapıldığında dipnotların altında genellikle hiçbir bağlantı kalmaz; sadece \u003Ccode\u003E1. Yazar, Kitap, s. 45\u003C\/code\u003E şeklinde düz paragraflar oluşur. Sistem bu durumu şu kurallarla yakalar ve dönüştürür:\n    \u003C\/p\u003E\n\n    \u003Cp\u003E\u003Cstrong\u003E1. Metin İçi Referans (Önce \/ Sonra):\u003C\/strong\u003E\u003C\/p\u003E\n    \u003Cpre\u003E\u003Ccode\u003E\u003C!-- Önce: Kırık Word linki veya düz metin [1] --\u003E\nModern yapay zeka modelleri deterministik çalışmaz[1].\n\n\u003C!-- Sonra: Çift yönlü çalışan erişilebilir bağlantı --\u003E\nModern yapay zeka modelleri deterministik çalışmaz\u0026lt;sup class=\"fn-ref\"\u0026gt;\u0026lt;a href=\"#fn-post1-1\" id=\"fnref-post1-1\"\u0026gt;[1]\u0026lt;\/a\u0026gt;\u0026lt;\/sup\u0026gt;.\u003C\/code\u003E\u003C\/pre\u003E\n\n    \u003Cp style=\"margin-top: 18px;\"\u003E\u003Cstrong\u003E2. Sayfa Sonu Dipnot Bloğu (Önce \/ Sonra):\u003C\/strong\u003E\u003C\/p\u003E\n    \u003Cpre\u003E\u003Ccode\u003E\u003C!-- Önce: Düz metin kaynakça satırı (hiçbir link yok) --\u003E\n1. Russell \u0026amp; Norvig, Yapay Zeka Modern Yaklaşım, s. 45.\n\n\u003C!-- Sonra: Temadan bağımsız açık [1] numaralı ve metne dönüş (↩) linkli liste --\u003E\n\u0026lt;div class=\"blogger-footnotes\" style=\"border-top:1px solid #cbd5e1; margin-top:36px; padding-top:18px;\"\u0026gt;\n  \u0026lt;strong style=\"display:block; margin-bottom:12px;\"\u0026gt;Dipnotlar ve Kaynakça\u0026lt;\/strong\u0026gt;\n  \u0026lt;ul style=\"list-style:none; padding:0; margin:0;\"\u0026gt;\n    \u0026lt;li id=\"fn-post1-1\"\u0026gt;\n      \u0026lt;a href=\"#fnref-post1-1\" style=\"text-decoration:none; font-weight:700; color:#2563eb;\"\u0026gt;[1]\u0026lt;\/a\u0026gt;\n      Russell \u0026amp;amp; Norvig, Yapay Zeka Modern Yaklaşım, s. 45.\n      \u0026lt;a href=\"#fnref-post1-1\" title=\"Metne geri dön\" style=\"text-decoration:none;\"\u0026gt; ↩\u0026lt;\/a\u0026gt;\n    \u0026lt;\/li\u0026gt;\n  \u0026lt;\/ul\u0026gt;\n\u0026lt;\/div\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n  \u003C\/div\u003E\n\n\u003C\/div\u003E\n\n\u003Cscript\u003E\n  const dropzone = document.getElementById('dropzone');\n  const xmlFileInput = document.getElementById('xmlFileInput');\n  const loadSampleBtn = document.getElementById('loadSampleBtn');\n  const resultsPanel = document.getElementById('resultsPanel');\n  const statTotalPosts = document.getElementById('statTotalPosts');\n  const statFixedPosts = document.getElementById('statFixedPosts');\n  const statTotalNotes = document.getElementById('statTotalNotes');\n  const statusNotice = document.getElementById('statusNotice');\n  const postListContainer = document.getElementById('postListContainer');\n  const downloadXmlBtn = document.getElementById('downloadXmlBtn');\n  const downloadZipBtn = document.getElementById('downloadZipBtn');\n\n  const loadingIndicator = document.getElementById('loadingIndicator');\n  const loadingText = document.getElementById('loadingText');\n  const loadingSubtext = document.getElementById('loadingSubtext');\n  const progressBar = document.getElementById('progressBar');\n\n  const diagnosticCard = document.getElementById('diagnosticCard');\n  const detectedFormatTitle = document.getElementById('detectedFormatTitle');\n  const detectedFormatBadge = document.getElementById('detectedFormatBadge');\n  const diagnosticDesc = document.getElementById('diagnosticDesc');\n  const fileSnippet = document.getElementById('fileSnippet');\n\n  let currentRepairedXmlString = null;\n  let processedPosts = [];\n  let originalFilename = 'blog_export.xml';\n  let detectedSchemaType = 'unknown';\n\n  ['dragenter', 'dragover'].forEach(name =\u003E {\n    dropzone.addEventListener(name, (e) =\u003E {\n      e.preventDefault();\n      dropzone.classList.add('dragover');\n    });\n  });\n\n  ['dragleave', 'drop'].forEach(name =\u003E {\n    dropzone.addEventListener(name, (e) =\u003E {\n      e.preventDefault();\n      dropzone.classList.remove('dragover');\n    });\n  });\n\n  dropzone.addEventListener('drop', (e) =\u003E {\n    const file = e.dataTransfer.files[0];\n    if (file) {\n      readXmlFile(file);\n    }\n  });\n\n  xmlFileInput.addEventListener('change', (e) =\u003E {\n    const file = e.target.files[0];\n    if (file) {\n      readXmlFile(file);\n    }\n  });\n\n  function readXmlFile(file) {\n    originalFilename = file.name;\n    const fileSizeMB = (file.size \/ (1024 * 1024)).toFixed(1);\n\n    showLoading(true, `Dosya okunuyor (${fileSizeMB} MB)...`, 15, 'Hafızaya alınıyor, lütfen bekleyin...');\n\n    const reader = new FileReader();\n    reader.onprogress = (e) =\u003E {\n      if (e.lengthComputable) {\n        const percent = Math.min(50, Math.round((e.loaded \/ e.total) * 50));\n        updateProgress(percent, `Dosya okunuyor (${percent * 2}%)...`);\n      }\n    };\n\n    reader.onload = (e) =\u003E {\n      updateProgress(60, 'Atom\/XML şeması çözümleniyor...');\n      \/\/ UI donmasını önlemek için bir sonraki tick'te başlat\n      setTimeout(() =\u003E {\n        try {\n          processBloggerXml(e.target.result);\n        } catch (err) {\n          console.error(\"İşleme Hatası:\", err);\n          showInlineNotice('Dosya işlenirken hata oluştu: ' + err.message);\n          showLoading(false);\n        }\n      }, 60);\n    };\n\n    reader.onerror = () =\u003E {\n      showInlineNotice('Dosya okunamadı. Lütfen dosya izinlerinizi kontrol edin.');\n      showLoading(false);\n    };\n\n    reader.readAsText(file);\n  }\n\n  function showLoading(show, text, percent = 10, subtext = '') {\n    if (!loadingIndicator) return;\n    if (show) {\n      loadingIndicator.classList.remove('hidden');\n      if (resultsPanel) resultsPanel.classList.add('hidden');\n      if (loadingText) loadingText.textContent = text;\n      if (progressBar) progressBar.style.width = percent + '%';\n      if (subtext \u0026\u0026 loadingSubtext) loadingSubtext.textContent = subtext;\n    } else {\n      loadingIndicator.classList.add('hidden');\n    }\n  }\n\n  function updateProgress(percent, text) {\n    if (progressBar) progressBar.style.width = percent + '%';\n    if (text \u0026\u0026 loadingText) loadingText.textContent = text;\n  }\n\n  \/\/ DOM Yardımcı Fonksiyonları (Ad Alanı Güvenli)\n  function isPostEntry(entry) {\n    const categories = Array.from(entry.getElementsByTagName('category'));\n    if (categories.length \u003E 0) {\n      const hasPostKind = categories.some(c =\u003E (c.getAttribute('term') || '').includes('kind#post'));\n      const hasExcludedKind = categories.some(c =\u003E {\n        const term = c.getAttribute('term') || '';\n        return term.includes('kind#comment') || term.includes('kind#template') || term.includes('kind#settings');\n      });\n      if (hasPostKind) return true;\n      if (hasExcludedKind) return false;\n    }\n    const contents = getElementsByLocal(entry, 'content');\n    return contents.length \u003E 0;\n  }\n\n  function getElementsByLocal(node, localName) {\n    const results = [];\n    try {\n      const nsNodes = node.getElementsByTagNameNS('*', localName);\n      if (nsNodes \u0026\u0026 nsNodes.length \u003E 0) return Array.from(nsNodes);\n    } catch (e) {}\n\n    const direct = node.getElementsByTagName(localName);\n    if (direct \u0026\u0026 direct.length \u003E 0) return Array.from(direct);\n\n    const all = node.getElementsByTagName('*');\n    for (let i = 0; i \u003C all.length; i++) {\n      const name = all[i].localName || all[i].nodeName.split(':').pop();\n      if (name.toLowerCase() === localName.toLowerCase()) {\n        results.push(all[i]);\n      }\n    }\n    return results;\n  }\n\n  function processBloggerXml(rawXmlString) {\n    updateProgress(70, 'Makaleler taranıyor ve ayıklanıyor...');\n    processedPosts = [];\n\n    const cleanHead = rawXmlString.substring(0, 1200);\n    if (fileSnippet) fileSnippet.textContent = cleanHead.substring(0, 350) + '...';\n    if (diagnosticCard) diagnosticCard.classList.remove('hidden');\n\n    \/\/ Tema yedeği kontrolü\n    if (cleanHead.includes('\u003Cb:skin') || cleanHead.includes('\u003Cb:template') || (cleanHead.includes('xmlns:b=') \u0026\u0026 !cleanHead.includes('\u003Centry') \u0026\u0026 !cleanHead.includes('\u003Citem'))) {\n      showThemeWarning();\n      showLoading(false);\n      return;\n    }\n\n    \/\/ Geçersiz XML kontrol karakterlerini temizle (23 MB dosyalarda çökmeyi önler)\n    const sanitizedXml = rawXmlString.replace(\/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]\/g, '');\n\n    const isWordPress = cleanHead.includes('\u003Crss') || cleanHead.includes('\u003Cchannel') || cleanHead.includes('xmlns:wp=');\n    const isAtom = cleanHead.includes('\u003Centry') || cleanHead.includes('http:\/\/www.w3.org\/2005\/Atom') || originalFilename.toLowerCase().endsWith('.atom');\n\n    if (isWordPress) {\n      detectedSchemaType = 'wordpress_rss';\n      if (detectedFormatTitle) detectedFormatTitle.textContent = 'Format: WordPress WXR \/ RSS 2.0';\n      if (detectedFormatBadge) { detectedFormatBadge.textContent = 'WordPress RSS'; detectedFormatBadge.className = 'tag tag-amber'; }\n      if (diagnosticDesc) diagnosticDesc.textContent = 'Dosya WordPress WXR \/ RSS yapısında. \u003Citem\u003E düğümleri ayrıştırılıyor.';\n      processWordPressRss(sanitizedXml);\n      return;\n    }\n\n    if (isAtom) {\n      detectedSchemaType = 'blogger_atom';\n      if (detectedFormatTitle) detectedFormatTitle.textContent = 'Format: Blogger Atom 1.0 (Feed)';\n      if (detectedFormatBadge) { detectedFormatBadge.textContent = 'Blogger Atom'; detectedFormatBadge.className = 'tag tag-blue'; }\n      if (diagnosticDesc) diagnosticDesc.textContent = 'Standart Blogger Atom yapısı tespit edildi. \u003Centry\u003E blokları taranıyor.';\n    } else {\n      detectedSchemaType = 'generic_xml';\n      if (detectedFormatTitle) detectedFormatTitle.textContent = 'Format: Genel \/ XML Feed';\n      if (detectedFormatBadge) { detectedFormatBadge.textContent = 'Özel XML'; detectedFormatBadge.className = 'tag tag-amber'; }\n      if (diagnosticDesc) diagnosticDesc.textContent = 'Genel XML yapısı taranıyor.';\n    }\n\n    \/\/ Büyük dosyalarda DOMParser bazen bellek sınırına takılır; önce DOM dene, olmazsa yüksek hızlı tarayıcıya geç\n    let success = false;\n    try {\n      success = processAtomOrGenericDom(sanitizedXml);\n    } catch (e) {\n      console.warn(\"DOM ayrıştırma başarısız oldu, hızlı string tarayıcıya geçiliyor:\", e);\n    }\n\n    if (!success || processedPosts.length === 0) {\n      updateProgress(85, 'Gelişmiş hızlı metin motoru ile ayrıştırılıyor...');\n      processAtomOrGenericFastScanner(sanitizedXml);\n    } else {\n      finalizeResults();\n    }\n  }\n\n  \/\/ 23 MB+ Büyük Dosyalar İçin Yüksek Hızlı String Tarayıcı (Regex donması yapmaz)\n  function processAtomOrGenericFastScanner(xmlText) {\n    processedPosts = [];\n    let postIndex = 0;\n    const pieces = [];\n    let lastIdx = 0;\n\n    const entryTag = '\u003Centry';\n    const closeEntryTag = '\u003C\/entry\u003E';\n\n    let entryStart = xmlText.indexOf(entryTag);\n\n    \/\/ Eğer \u003Centry\u003E yoksa \u003Citem\u003E dene\n    const isItemMode = entryStart === -1 \u0026\u0026 xmlText.indexOf('\u003Citem') !== -1;\n    const openTag = isItemMode ? '\u003Citem' : '\u003Centry';\n    const endTag = isItemMode ? '\u003C\/item\u003E' : '\u003C\/entry';\n\n    entryStart = xmlText.indexOf(openTag);\n\n    if (entryStart === -1) {\n      currentRepairedXmlString = xmlText;\n      finalizeResults();\n      return;\n    }\n\n    while (entryStart !== -1) {\n      pieces.push(xmlText.substring(lastIdx, entryStart));\n      const entryEnd = xmlText.indexOf(endTag, entryStart);\n\n      if (entryEnd === -1) {\n        pieces.push(xmlText.substring(entryStart));\n        lastIdx = xmlText.length;\n        break;\n      }\n\n      const fullEntryLen = entryEnd + endTag.length;\n      let entryContent = xmlText.substring(entryStart, fullEntryLen);\n      lastIdx = fullEntryLen;\n\n      \/\/ Yorum veya şablon girişlerini filtrele\n      const isComment = entryContent.includes('kind#comment') || entryContent.includes('kind#template') || entryContent.includes('kind#settings');\n\n      if (!isComment) {\n        postIndex++;\n\n        \/\/ Başlık\n        const tMatch = entryContent.match(\/\u003C(?:[a-zA-Z0-9_-]+:)?title[^\u003E]*\u003E([\\s\\S]*?)\u003C\\\/(?:[a-zA-Z0-9_-]+:)?title\u003E\/i);\n        let title = `Yazı #${postIndex}`;\n        if (tMatch) {\n          title = unescapeXml(tMatch[1].replace(\/\u003C!\\[CDATA\\[([\\s\\S]*?)\\]\\]\u003E\/gi, '$1').trim());\n        }\n\n        \/\/ İçerik düğümü\n        const cRegex = \/(\u003C(?:[a-zA-Z0-9_-]+:)?(?:content|encoded|description)[^\u003E]*\u003E)([\\s\\S]*?)(\u003C\\\/(?:[a-zA-Z0-9_-]+:)?(?:content|encoded|description)\u003E)\/i;\n        const cMatch = entryContent.match(cRegex);\n\n        if (cMatch) {\n          const cOpen = cMatch[1];\n          const rawEncoded = cMatch[2];\n          const cClose = cMatch[3];\n\n          const isCdata = rawEncoded.includes('\u003C![CDATA[');\n          const rawHtml = isCdata ? rawEncoded.replace(\/\u003C!\\[CDATA\\[([\\s\\S]*?)\\]\\]\u003E\/gi, '$1') : unescapeXml(rawEncoded);\n\n          const fixResult = repairFootnotesInHtml(rawHtml, postIndex);\n\n          processedPosts.push({\n            id: postIndex,\n            title: title,\n            originalHtml: rawHtml,\n            repairedHtml: fixResult.repairedHtml,\n            footnoteCount: fixResult.foundCount\n          });\n\n          let newHtmlStr = fixResult.repairedHtml;\n          let serializedContent = isCdata ? `\u003C![CDATA[${newHtmlStr}]]\u003E` : escapeXml(newHtmlStr);\n\n          entryContent = entryContent.replace(cRegex, `${cOpen}${serializedContent}${cClose}`);\n        }\n      }\n\n      pieces.push(entryContent);\n      entryStart = xmlText.indexOf(openTag, lastIdx);\n    }\n\n    if (lastIdx \u003C xmlText.length) {\n      pieces.push(xmlText.substring(lastIdx));\n    }\n\n    currentRepairedXmlString = pieces.join('');\n    finalizeResults();\n  }\n\n  \/\/ --- ATOM VE GENEL XML DOM İŞLEYİCİ ---\n  function processAtomOrGenericDom(sanitizedXml) {\n    try {\n      const parser = new DOMParser();\n      const xmlDoc = parser.parseFromString(sanitizedXml, 'application\/xml');\n\n      if (xmlDoc.getElementsByTagName('parsererror').length \u003E 0) {\n        return false;\n      }\n\n      \/\/ Entry veya Item bul\n      let entries = Array.from(xmlDoc.getElementsByTagNameNS('*', 'entry'));\n      if (entries.length === 0) entries = Array.from(xmlDoc.getElementsByTagName('entry'));\n      if (entries.length === 0) entries = Array.from(xmlDoc.getElementsByTagNameNS('*', 'item'));\n      if (entries.length === 0) entries = Array.from(xmlDoc.getElementsByTagName('item'));\n\n      if (entries.length === 0) return false;\n\n      let postIndex = 0;\n      entries.forEach((entry) =\u003E {\n        if (!isPostEntry(entry)) return;\n        postIndex++;\n\n        const titleNodes = getElementsByLocal(entry, 'title');\n        const title = titleNodes.length \u003E 0 ? titleNodes[0].textContent.trim() : `Yazı #${postIndex}`;\n\n        let contentNodes = getElementsByLocal(entry, 'content');\n        if (contentNodes.length === 0) contentNodes = getElementsByLocal(entry, 'encoded');\n        if (contentNodes.length === 0) contentNodes = getElementsByLocal(entry, 'description');\n        if (contentNodes.length === 0) return;\n\n        const contentNode = contentNodes[0];\n        const rawHtml = contentNode.textContent || '';\n        const fixResult = repairFootnotesInHtml(rawHtml, postIndex);\n\n        if (fixResult.foundCount \u003E 0) {\n          contentNode.textContent = fixResult.repairedHtml;\n        }\n\n        processedPosts.push({\n          id: postIndex,\n          title: title,\n          originalHtml: rawHtml,\n          repairedHtml: fixResult.repairedHtml,\n          footnoteCount: fixResult.foundCount\n        });\n      });\n\n      if (processedPosts.length \u003E 0) {\n        const serializer = new XMLSerializer();\n        currentRepairedXmlString = serializer.serializeToString(xmlDoc);\n        return true;\n      }\n    } catch (e) {\n      console.warn(\"DOM ayrıştırma hatası:\", e);\n    }\n    return false;\n  }\n\n  \/\/ --- ATOM VE GENEL XML REGEX İŞLEYİCİ (YEDEK MOTOR) ---\n  function processAtomOrGenericRegex(xmlText) {\n    processedPosts = [];\n    let postIndex = 0;\n\n    \/\/ Hem \u003Centry\u003E hem \u003Citem\u003E bloklarını yakala\n    const nodeRegex = \/\u003C(?:[a-zA-Z0-9_-]+:)?(entry|item)[\\s\u003E]([\\s\\S]*?)\u003C\\\/(?:[a-zA-Z0-9_-]+:)?\\1\u003E\/gi;\n\n    currentRepairedXmlString = xmlText.replace(nodeRegex, (fullMatch, tagName, inner) =\u003E {\n      if (inner.includes('kind#comment') || inner.includes('kind#template') || inner.includes('kind#settings')) {\n        return fullMatch;\n      }\n\n      postIndex++;\n      const titleMatch = inner.match(\/\u003C(?:[a-zA-Z0-9_-]+:)?title[^\u003E]*\u003E([\\s\\S]*?)\u003C\\\/(?:[a-zA-Z0-9_-]+:)?title\u003E\/i);\n      let title = `Yazı #${postIndex}`;\n      if (titleMatch) {\n        title = unescapeXml(titleMatch[1].replace(\/\u003C!\\[CDATA\\[([\\s\\S]*?)\\]\\]\u003E\/gi, '$1').trim());\n      }\n\n      const contentRegex = \/(\u003C(?:[a-zA-Z0-9_-]+:)?(?:content|encoded|description)[^\u003E]*\u003E)([\\s\\S]*?)(\u003C\\\/(?:[a-zA-Z0-9_-]+:)?(?:content|encoded|description)\u003E)\/i;\n      const contentMatch = inner.match(contentRegex);\n\n      if (!contentMatch) return fullMatch;\n\n      const openTag = contentMatch[1];\n      const encodedHtml = contentMatch[2];\n      const closeTag = contentMatch[3];\n\n      let isCdata = encodedHtml.includes('\u003C![CDATA[');\n      let rawContent = encodedHtml.replace(\/\u003C!\\[CDATA\\[([\\s\\S]*?)\\]\\]\u003E\/gi, '$1');\n      let decodedHtml = isCdata ? rawContent : unescapeXml(rawContent);\n\n      const fixResult = repairFootnotesInHtml(decodedHtml, postIndex);\n\n      processedPosts.push({\n        id: postIndex,\n        title: title,\n        originalHtml: decodedHtml,\n        repairedHtml: fixResult.repairedHtml,\n        footnoteCount: fixResult.foundCount\n      });\n\n      let newContent = fixResult.repairedHtml;\n      if (isCdata) {\n        newContent = `\u003C![CDATA[${newContent}]]\u003E`;\n      } else {\n        newContent = escapeXml(newContent);\n      }\n\n      return `\u003C${tagName}${inner.replace(contentRegex, `${openTag}${newContent}${closeTag}`)}\u003C\/${tagName}\u003E`;\n    });\n\n    finalizeResults();\n  }\n\n  function unescapeXml(str) {\n    return str\n      .replace(\/\u0026lt;\/g, '\u003C')\n      .replace(\/\u0026gt;\/g, '\u003E')\n      .replace(\/\u0026quot;\/g, '\"')\n      .replace(\/\u0026apos;\/g, \"'\")\n      .replace(\/\u0026#39;\/g, \"'\")\n      .replace(\/\u0026amp;\/g, '\u0026');\n  }\n\n  function escapeXml(str) {\n    return str\n      .replace(\/\u0026\/g, '\u0026amp;')\n      .replace(\/\u003C\/g, '\u0026lt;')\n      .replace(\/\u003E\/g, '\u0026gt;')\n      .replace(\/\"\/g, '\u0026quot;')\n      .replace(\/'\/g, '\u0026apos;');\n  }\n\n  function repairFootnotesInHtml(html, postIndex) {\n    if (!html || typeof html !== 'string') return { repairedHtml: html, foundCount: 0 };\n\n    const container = document.createElement('div');\n    container.innerHTML = html;\n\n    const detectedNotes = [];\n    const noteNodesToRemove = [];\n\n    \/\/ Hem innerText hem textContent desteği (Detached DOM güvenliği)\n    const blockElements = Array.from(container.querySelectorAll('p, div, li, tr'));\n\n    for (let i = 0; i \u003C blockElements.length; i++) {\n      const el = blockElements[i];\n      \/\/ innerText boş dönerse textContent kullan\n      const rawText = (el.innerText || el.textContent || '').trim();\n\n      if (!rawText) continue;\n\n      \/\/ \"1. Kaynak...\", \"[1] Kaynak...\", \"(1) Kaynak...\", \"1) Kaynak...\" veya \"1- Kaynak...\"\n      const match = rawText.match(\/^(\\[(\\d+)\\]|\\((\\d+)\\)|(\\d+)[\\.\\-\\)])\\s+([\\s\\S]+)$\/);\n      const isWordFtn = (el.id \u0026\u0026 el.id.toLowerCase().includes('_ftn')) || \n                        (el.className \u0026\u0026 typeof el.className === 'string' \u0026\u0026 el.className.includes('footnote'));\n\n      if (match || isWordFtn) {\n        const num = match ? (match[2] || match[3] || match[4]) : (detectedNotes.length + 1);\n        let bodyText = match ? match[5] : rawText;\n\n        \/\/ Word veya metin başında kalan fazla numara\/boşluk kalıntılarını temizle\n        bodyText = bodyText.replace(\/^(\\[(\\d+)\\]|\\((\\d+)\\)|(\\d+)[\\.\\-\\)])\\s*\/, '');\n\n        detectedNotes.push({ \n          num: parseInt(num, 10), \n          content: bodyText.trim() \n        });\n        noteNodesToRemove.push(el);\n      }\n    }\n\n    if (detectedNotes.length === 0) {\n      return { repairedHtml: html, foundCount: 0 };\n    }\n\n    \/\/ Gövdedeki ayrıştırılan eski dipnot satırlarını kaldır\n    noteNodesToRemove.forEach(node =\u003E {\n      if (node.parentNode) node.parentNode.removeChild(node);\n    });\n\n    let updatedHtml = container.innerHTML;\n\n    \/\/ Metin içindeki [1], (1) veya bozuk Word referans linklerini değiştir\n    detectedNotes.forEach(note =\u003E {\n      const n = note.num;\n      const refId = `fnref-${postIndex}-${n}`;\n      const noteId = `fn-${postIndex}-${n}`;\n\n      const newAnchor = `\u003Csup class=\"fn-ref\"\u003E\u003Ca href=\"#${noteId}\" id=\"${refId}\" style=\"text-decoration:none; font-weight:700; color:#2563eb; padding:0 3px;\"\u003E[${n}]\u003C\/a\u003E\u003C\/sup\u003E`;\n\n      \/\/ Word'ün bozuk anchor linkleri\n      const wordLinkRegex = new RegExp(`\u003Ca[^\u003E]+href=[\"'][^\"']*#_ftn(?:ref)?${n}[\"'][^\u003E]*\u003E(?:\u003Csup[^\u003E]*\u003E)?.*?(?:\u003C\\\\\/sup\u003E)?\u003C\\\\\/a\u003E`, 'gi');\n      \/\/ \u003Csup\u003E1\u003C\/sup\u003E, \u003Csup\u003E[1]\u003C\/sup\u003E veya \u003Csup\u003E(1)\u003C\/sup\u003E (Karakter kümesi ile hatasız ve güvenli)\n      const supRegex = new RegExp(`\u003Csup[^\u003E]*\u003E\\\\s*[\\\\[\\\\(]?\\\\s*${n}\\\\s*[\\\\]\\\\)]?\\\\s*\u003C\\\\\/sup\u003E`, 'gi');\n      \/\/ Düz metin [1] veya (1)\n      const bracketRegex = new RegExp(`\\\\[${n}\\\\]|\\\\(${n}\\\\)`, 'g');\n\n      if (wordLinkRegex.test(updatedHtml)) {\n        wordLinkRegex.lastIndex = 0;\n        updatedHtml = updatedHtml.replace(wordLinkRegex, newAnchor);\n      } else if (supRegex.test(updatedHtml)) {\n        supRegex.lastIndex = 0;\n        updatedHtml = updatedHtml.replace(supRegex, newAnchor);\n      } else if (bracketRegex.test(updatedHtml)) {\n        bracketRegex.lastIndex = 0;\n        updatedHtml = updatedHtml.replace(bracketRegex, newAnchor);\n      }\n    });\n\n    \/\/ Sayfa sonuna açık numaralı ve çift yönlü (↩) dipnot bloğunu ekle\n    let footnotesBlock = `\n\u003Cdiv class=\"blogger-footnotes\" style=\"border-top: 1px solid #cbd5e1; margin-top: 36px; padding-top: 18px; font-size: 0.9em; color: #475569;\"\u003E\n  \u003Cstrong style=\"display:block; margin-bottom:12px; color:#0f172a; font-size: 1.05em;\"\u003EDipnotlar ve Kaynakça\u003C\/strong\u003E\n  \u003Cul style=\"list-style: none; margin: 0; padding: 0;\"\u003E\n`;\n\n    detectedNotes.forEach(note =\u003E {\n      const n = note.num;\n      const refId = `fnref-${postIndex}-${n}`;\n      const noteId = `fn-${postIndex}-${n}`;\n      footnotesBlock += `    \u003Cli id=\"${noteId}\" style=\"margin-bottom: 10px; line-height: 1.6; list-style-type: none; padding-left: 0;\"\u003E\u003Ca href=\"#${refId}\" style=\"text-decoration:none; color:#2563eb; font-weight:700; margin-right:6px;\" title=\"Metindeki yerine dön\"\u003E[${n}]\u003C\/a\u003E ${escapeHtml(note.content)} \u003Ca href=\"#${refId}\" title=\"Metne geri dön\" style=\"text-decoration:none; color:#2563eb; font-weight:bold; margin-left:4px;\"\u003E↩\u003C\/a\u003E\u003C\/li\u003E\\n`;\n    });\n\n    footnotesBlock += `  \u003C\/ul\u003E\\n\u003C\/div\u003E`;\n\n    return {\n      repairedHtml: updatedHtml + footnotesBlock,\n      foundCount: detectedNotes.length\n    };\n  }\n\n  function finalizeResults() {\n    updateProgress(100, 'Tamamlandı!');\n    setTimeout(() =\u003E {\n      showLoading(false);\n\n      const totalPostsCount = processedPosts.length;\n      const fixedPostsCount = processedPosts.filter(p =\u003E p.footnoteCount \u003E 0).length;\n      const totalFootnotes = processedPosts.reduce((acc, p) =\u003E acc + p.footnoteCount, 0);\n\n      statTotalPosts.textContent = totalPostsCount;\n      statFixedPosts.textContent = fixedPostsCount;\n      statTotalNotes.textContent = totalFootnotes;\n\n      renderPostList();\n      resultsPanel.classList.remove('hidden');\n\n      if (totalPostsCount === 0) {\n        showInlineNotice('Yüklenen XML dosyasında blog yazısı bulunamadı. Dosyanın geçerli bir Blogger yedeği olduğundan emin olun.');\n      } else {\n        statusNotice.style.color = 'var(--text)';\n        statusNotice.textContent = `${totalPostsCount} blog yazısı başarıyla tarandı. ${fixedPostsCount} yazıda dipnotlar onarıldı.`;\n      }\n    }, 200);\n  }\n\n  function renderPostList() {\n    postListContainer.innerHTML = '';\n    \/\/ Performans için ilk 100 yazıyı listele\n    const displayPosts = processedPosts.slice(0, 100);\n\n    displayPosts.forEach(post =\u003E {\n      const row = document.createElement('div');\n      row.className = 'post-row';\n      row.innerHTML = `\n        \u003Cdiv\u003E\n          \u003Cdiv class=\"post-info-title\"\u003E${escapeHtml(post.title)}\u003C\/div\u003E\n          \u003Cdiv class=\"post-meta\"\u003E#${post.id} • ${post.footnoteCount \u003E 0 ? `\u003Cspan class=\"badge-count\"\u003E${post.footnoteCount} Dipnot Onarıldı\u003C\/span\u003E` : '\u003Cspan style=\"color:#94a3b8\"\u003EDipnot yok\u003C\/span\u003E'}\u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv\u003E\n          \u003Cbutton class=\"btn btn-outline\" style=\"font-size:0.8rem; padding:6px 12px;\" onclick=\"copyPostHtml(${post.id}, this)\"\u003EHTML Kopyala\u003C\/button\u003E\n        \u003C\/div\u003E\n      `;\n      postListContainer.appendChild(row);\n    });\n\n    if (processedPosts.length \u003E 100) {\n      const moreInfo = document.createElement('div');\n      moreInfo.style.textAlign = 'center';\n      moreInfo.style.padding = '10px';\n      moreInfo.style.fontSize = '0.85rem';\n      moreInfo.style.color = 'var(--text-muted)';\n      moreInfo.textContent = `Toplam ${processedPosts.length} yazıdan ilk 100 tanesi listelendi. Tüm yazılar XML ve ZIP çıktısına dahildir.`;\n      postListContainer.appendChild(moreInfo);\n    }\n  }\n\n  function copyPostHtml(postId, btn) {\n    const post = processedPosts.find(p =\u003E p.id === postId);\n    if (!post) return;\n\n    const tempInput = document.createElement('textarea');\n    tempInput.value = post.repairedHtml;\n    document.body.appendChild(tempInput);\n    tempInput.select();\n    document.execCommand('copy');\n    document.body.removeChild(tempInput);\n\n    const oldText = btn.textContent;\n    btn.textContent = 'Kopyalandı!';\n    btn.style.borderColor = 'var(--success)';\n    btn.style.color = 'var(--success)';\n    setTimeout(() =\u003E { \n      btn.textContent = oldText; \n      btn.style.borderColor = '';\n      btn.style.color = '';\n    }, 1400);\n  }\n\n  downloadXmlBtn.addEventListener('click', () =\u003E {\n    if (!currentRepairedXmlString) return;\n\n    const isAtomExt = originalFilename.toLowerCase().endsWith('.atom');\n    const mimeType = isAtomExt ? 'application\/atom+xml;charset=utf-8' : 'application\/xml;charset=utf-8';\n\n    const blob = new Blob([currentRepairedXmlString], { type: mimeType });\n    const link = document.createElement('a');\n    link.href = URL.createObjectURL(blob);\n    link.download = `tamir_edilmis_${originalFilename}`;\n    link.click();\n    URL.revokeObjectURL(link.href);\n  });\n\n  downloadZipBtn.addEventListener('click', () =\u003E {\n    if (!processedPosts.length) return;\n    const zip = new JSZip();\n\n    processedPosts.forEach((p, idx) =\u003E {\n      const safeName = `${idx + 1}_${p.title.replace(\/[^a-zA-Z0-9_-]\/g, '_').substring(0, 35)}.html`;\n      const htmlDoc = `\u003C!DOCTYPE html\u003E\u003Chtml\u003E\u003Chead\u003E\u003Cmeta charset=\"utf-8\"\u003E\u003Ctitle\u003E${escapeHtml(p.title)}\u003C\/title\u003E\u003C\/head\u003E\u003Cbody\u003E\u003Ch1\u003E${escapeHtml(p.title)}\u003C\/h1\u003E${p.repairedHtml}\u003C\/body\u003E\u003C\/html\u003E`;\n      zip.file(safeName, htmlDoc);\n    });\n\n    zip.generateAsync({ type: 'blob' }).then(blob =\u003E {\n      const link = document.createElement('a');\n      link.href = URL.createObjectURL(blob);\n      link.download = 'blogger_tamir_edilmis_yazilar.zip';\n      link.click();\n      URL.revokeObjectURL(link.href);\n    });\n  });\n\n  loadSampleBtn.addEventListener('click', () =\u003E {\n    const sampleXml = `\u003C?xml version='1.0' encoding='UTF-8'?\u003E\n\u003Cfeed xmlns='http:\/\/www.w3.org\/2005\/Atom'\u003E\n  \u003Ctitle type='text'\u003EÖrnek Akademik Blog\u003C\/title\u003E\n  \u003Centry\u003E\n    \u003Ctitle type='text'\u003EYapay Zeka ve Determinizm Üzerine Bir İnceleme\u003C\/title\u003E\n    \u003Ccategory scheme=\"http:\/\/schemas.google.com\/g\/2005#kind\" term=\"http:\/\/schemas.google.com\/blogger\/2008\/kind#post\"\/\u003E\n    \u003Ccontent type='html'\u003E\u0026lt;p\u0026gt;Modern yapay zeka sistemleri istatistiksel ağırlıklara dayanır ve klasik algoritmalar gibi kesin kurallar içermez[1]. Oysa deterministik yazılımlar her girdi için daima aynı kesin çıktıyı üretir[2].\u0026lt;\/p\u0026gt;\u0026lt;p\u0026gt;1. Russell, S. ve Norvig, P. Yapay Zeka: Modern Yaklaşım, s. 102.\u0026lt;\/p\u0026gt;\u0026lt;p\u0026gt;2. Turing, A. M. Computing Machinery and Intelligence, 1950.\u0026lt;\/p\u0026gt;\u003C\/content\u003E\n  \u003C\/entry\u003E\n  \u003Centry\u003E\n    \u003Ctitle type='text'\u003EWord Dipnotlarının Web Standartlarına Dönüştürülmesi\u003C\/title\u003E\n    \u003Ccategory scheme=\"http:\/\/schemas.google.com\/g\/2005#kind\" term=\"http:\/\/schemas.google.com\/blogger\/2008\/kind#post\"\/\u003E\n    \u003Ccontent type='html'\u003E\u0026lt;p\u0026gt;Word belgelerindeki XML mimarisi oldukça katı kurallara bağlıdır[1]. Bu sayede LLM kullanmadan istemci taraflı çözümler geliştirmek mümkündür.\u0026lt;\/p\u0026gt;\u0026lt;p\u0026gt;1. Microsoft Word OpenXML File Format Specification Guide.\u0026lt;\/p\u0026gt;\u003C\/content\u003E\n  \u003C\/entry\u003E\n\u003C\/feed\u003E`;\n    originalFilename = 'ornek_blogger_yedegi.xml';\n    processBloggerXml(sampleXml);\n  });\n\n  function showInlineNotice(msg) {\n    statusNotice.textContent = msg;\n    statusNotice.style.color = '#ef4444';\n    resultsPanel.classList.remove('hidden');\n  }\n\n  function escapeHtml(str) {\n    return String(str).replace(\/[\u0026\u003C\u003E\"']\/g, m =\u003E ({ '\u0026': '\u0026amp;', '\u003C': '\u0026lt;', '\u003E': '\u0026gt;', '\"': '\u0026quot;', \"'\": '\u0026#039;' }[m]));\n  }\n\u003C\/script\u003E\n\n\u003C\/body\u003E\n\u003C\/html\u003E"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/8035433387821517378"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/8035433387821517378"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/09\/blogger-yedek-dosyasndaki-xml-tum.html","title":"Blogger Yedek Dosyasındaki (XML) Tüm Dipnotları Topluca Tamir Etme Sistemi"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}]},{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-7921938424969816151"},"published":{"$t":"2026-09-03T09:13:40.029+03:00"},"updated":{"$t":"2026-09-03T09:13:40.030+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"tutorial"}],"title":{"type":"text","$t":"Word Dipnotlarını Tek Tıkla Web Uyumlu HTML Bağlantılarına Dönüştürme Rehberi"},"content":{"type":"html","$t":"\u003C!DOCTYPE html\u003E\n\u003Chtml lang=\"tr\"\u003E\n\u003Chead\u003E\n  \u003Cmeta charset=\"UTF-8\"\u003E\n  \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003E\n  \u003Ctitle\u003EMakale İçeriği \u0026 Araç\u003C\/title\u003E\n  \u003C!-- Mammoth.js: İstemci tarafında Word XML parse kütüphanesi --\u003E\n  \u003Cscript src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/mammoth\/1.6.0\/mammoth.browser.min.js\"\u003E\u003C\/script\u003E\n  \u003C!-- JSZip: Toplu ZIP indirme --\u003E\n  \u003Cscript src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jszip\/3.10.1\/jszip.min.js\"\u003E\u003C\/script\u003E\n  \u003Cstyle\u003E\n    :root {\n      --bg: #f8fafc;\n      --surface: #ffffff;\n      --border: #e2e8f0;\n      --text: #334155;\n      --heading: #0f172a;\n      --primary: #2563eb;\n      --primary-hover: #1d4ed8;\n      --code-bg: #0f172a;\n      --code-text: #e2e8f0;\n    }\n\n    * {\n      box-sizing: border-box;\n      margin: 0;\n      padding: 0;\n    }\n\n    body {\n      background-color: var(--bg);\n      color: var(--text);\n      font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n      line-height: 1.8;\n      padding: 40px 20px;\n    }\n\n    .article-body {\n      max-width: 800px;\n      margin: 0 auto;\n      background: var(--surface);\n      padding: 48px;\n      border-radius: 12px;\n      border: 1px solid var(--border);\n      box-shadow: 0 4px 6px -1px rgba(0,0,0,0.04);\n    }\n\n    p {\n      margin-bottom: 20px;\n      font-size: 1.05rem;\n    }\n\n    h2 {\n      font-size: 1.45rem;\n      color: var(--heading);\n      margin: 40px 0 16px;\n      border-left: 4px solid var(--primary);\n      padding-left: 14px;\n    }\n\n    ul {\n      margin: 16px 0 24px 28px;\n    }\n\n    li {\n      margin-bottom: 10px;\n    }\n\n    code {\n      background: #f1f5f9;\n      color: #0f172a;\n      padding: 2px 6px;\n      border-radius: 4px;\n      font-size: 0.9em;\n      font-family: Consolas, Monaco, monospace;\n    }\n\n    \/* Gömülü Araç Alanı *\/\n    .tool-wrapper {\n      background: #f8fafc;\n      border: 2px solid #cbd5e1;\n      border-radius: 10px;\n      padding: 28px;\n      margin: 40px 0;\n    }\n\n    .tool-header h3 {\n      font-size: 1.25rem;\n      color: var(--heading);\n      margin-bottom: 6px;\n    }\n\n    .tool-header p {\n      font-size: 0.92rem;\n      color: #64748b;\n      margin-bottom: 20px;\n    }\n\n    .dropzone {\n      background: var(--surface);\n      border: 2px dashed #94a3b8;\n      border-radius: 8px;\n      padding: 34px 20px;\n      text-align: center;\n      cursor: pointer;\n      transition: all 0.2s ease;\n    }\n\n    .dropzone:hover, .dropzone.dragover {\n      border-color: var(--primary);\n      background: #eff6ff;\n    }\n\n    .btn-zip {\n      background: #0f172a;\n      color: #fff;\n      font-size: 0.82rem;\n      padding: 7px 14px;\n      border-radius: 6px;\n      border: none;\n      cursor: pointer;\n      font-weight: 600;\n    }\n\n    .btn-zip:hover {\n      background: #1e293b;\n    }\n\n    \/* Çıktı Kartları *\/\n    .output-item {\n      background: #ffffff;\n      border: 1px solid var(--border);\n      border-radius: 8px;\n      padding: 20px;\n      margin-top: 20px;\n    }\n\n    .output-head {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-bottom: 16px;\n      padding-bottom: 10px;\n      border-bottom: 1px solid var(--border);\n    }\n\n    .badge-count {\n      font-size: 0.78rem;\n      background: #e0f2fe;\n      color: #0369a1;\n      padding: 3px 8px;\n      border-radius: 4px;\n      font-weight: 600;\n    }\n\n    .code-box-group {\n      margin-bottom: 16px;\n    }\n\n    .code-box-group:last-child {\n      margin-bottom: 0;\n    }\n\n    .code-box-bar {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-bottom: 6px;\n    }\n\n    .box-title {\n      font-size: 0.8rem;\n      font-weight: 700;\n      color: #475569;\n      text-transform: uppercase;\n      letter-spacing: 0.04em;\n    }\n\n    .btn-copy {\n      background: #f1f5f9;\n      border: 1px solid #cbd5e1;\n      font-size: 0.75rem;\n      padding: 4px 10px;\n      border-radius: 4px;\n      cursor: pointer;\n      font-weight: 600;\n      color: #1e293b;\n    }\n\n    .btn-copy:hover {\n      background: #e2e8f0;\n    }\n\n    pre {\n      background: var(--code-bg);\n      color: var(--code-text);\n      border-radius: 6px;\n      padding: 12px;\n      font-size: 0.85rem;\n      font-family: Consolas, Monaco, monospace;\n      overflow-x: auto;\n      white-space: pre-wrap;\n      word-break: break-word;\n      max-height: 180px;\n    }\n\n    .hidden {\n      display: none;\n    }\n  \u003C\/style\u003E\n\u003C\/head\u003E\n\u003Cbody\u003E\n\n  \u003Carticle class=\"article-body\"\u003E\n    \u003Cp\u003E\n      Akademik araştırmalar, sektörel raporlar veya referansı bol makaleler Word üzerinde hazırlanıp web ortamına aktarılmak istendiğinde karşılaşılan en büyük problem dipnotlardır. Standart bir kopyala-yapıştır işleminde dipnot numaraları kaybolur, metinle sayfa altı arasındaki bağ kopar ya da dipnotlar düz bir metin yığınına dönüşür.\n    \u003C\/p\u003E\n\n    \u003Cp\u003E\n      Bu sorunu çözmek için son dönemde geliştiricilerin aklına ilk gelen çözüm bir yapay zeka (LLM) API’sine metni göndermek oluyor. Oysa bu yaklaşım hem yüksek maliyet hem de zaman kaybıdır.\n    \u003C\/p\u003E\n\n    \u003Ch2\u003ENeden Yapay Zeka Yerine İstemci Taraflı Çözüm?\u003C\/h2\u003E\n    \u003Cp\u003E\n      Bir Word belgesi (\u003Ccode\u003E.docx\u003C\/code\u003E) temelde sıkıştırılmış bir XML yapısıdır. Word yazılımı dipnot referansını \u003Ccode\u003E\u0026lt;w:footnoteReference\u0026gt;\u003C\/code\u003E olarak etiketler, dipnotun kendi açıklama gövdesini ise ayrı bir \u003Ccode\u003Eword\/footnotes.xml\u003C\/code\u003E dosyasında saklar.\n    \u003C\/p\u003E\n    \u003Cul\u003E\n      \u003Cli\u003E\u003Cstrong\u003EDeterministik Doğruluk:\u003C\/strong\u003E Yapay zeka referans numaralarını bazen tahmin eder, karıştırabilir ya da metni özetleyebilir. Klasik parser kütüphaneleri ise 1’e 1 eşleştirme yaparak %100 kesinlik sağlar.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EMaliyetsiz ve Sınırsız:\u003C\/strong\u003E Tek seferde 10, 50 veya 100 Word dosyasını doğrudan tarayıcınızın belleğinde dönüştürebilirsiniz. Token ücreti, API faturası veya sunucu maliyeti sıfırdır.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EÇift Yönlü Sayfa İçi Linkleme:\u003C\/strong\u003E Metindeki \u003Ccode\u003E[1]\u003C\/code\u003E numarasına tıklandığında ekran ilgili dipnota kayar; dipnotun yanındaki geri dönüş linkine tıklandığında okuyucu metindeki yerine döner.\u003C\/li\u003E\n    \u003C\/ul\u003E\n\n    \u003Ch2\u003ECanlı Dönüştürücü Aracı Kullanın\u003C\/h2\u003E\n    \u003Cp\u003E\n      Aşağıdaki alana istediğiniz kadar \u003Ccode\u003E.docx\u003C\/code\u003E dosyası bırakabilirsiniz. Araç dosyaları sunucuya göndermeden, doğrudan tarayıcınızda işler ve başlık ile gövde kodlarını CMS'inize rahatça aktarabilmeniz için ayrı ayrı üretir:\n    \u003C\/p\u003E\n\n    \u003C!-- CANLI DÖNÜŞTÜRÜCÜ BİLEŞENİ --\u003E\n    \u003Cdiv class=\"tool-wrapper\"\u003E\n      \u003Cdiv class=\"tool-header\"\u003E\n        \u003Ch3\u003EWord Dipnot Dönüştürücü Paneli\u003C\/h3\u003E\n        \u003Cp\u003EDosyaları sürükleyin; başlık ve gövde HTML kodlarını anında kopyalayın.\u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"dropzone\" id=\"dropzone\" onclick=\"document.getElementById('docxInput').click()\"\u003E\n        \u003Cp style=\"margin: 0; font-weight: 600; color: #1e293b;\"\u003EWord (.docx) dosyalarını buraya bırakın veya tıklayın\u003C\/p\u003E\n        \u003Cspan style=\"font-size: 0.8rem; color: #64748b;\"\u003EToplu dosya yükleme (10+ dosya) desteklenir\u003C\/span\u003E\n        \u003Cinput type=\"file\" id=\"docxInput\" multiple accept=\".docx\" style=\"display: none;\"\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv id=\"actionBar\" class=\"hidden\" style=\"margin-top: 15px; display: flex; justify-content: space-between; align-items: center;\"\u003E\n        \u003Cspan id=\"statusInfo\" style=\"font-size: 0.85rem; color: #475569; font-weight: 600;\"\u003E\u003C\/span\u003E\n        \u003Cbutton class=\"btn-zip\" id=\"zipDownloadBtn\"\u003E📦 Tümünü İndir (.ZIP)\u003C\/button\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv id=\"outputContainer\"\u003E\u003C\/div\u003E\n    \u003C\/div\u003E\n\n    \u003Ch2\u003ENasıl Entegre Edilir?\u003C\/h2\u003E\n    \u003Cp\u003E\n      Oluşturulan çıktıyı WordPress, Ghost, Webflow veya özel bir CMS'e taşırken şu adımları izleyebilirsiniz:\n    \u003C\/p\u003E\n    \u003Cul\u003E\n      \u003Cli\u003E\u003Cstrong\u003EBaşlık Kodu:\u003C\/strong\u003E CMS'inizdeki başlık (H1 \/ Title) kutusuna yapıştırılır.\u003C\/li\u003E\n      \u003Cli\u003E\u003Cstrong\u003EGövde Kodu:\u003C\/strong\u003E CMS'inizin HTML \/ Kod editörü alanına doğrudan yapıştırılır. Sayfa içi kayma (anchor linkler) otomatik olarak çalışmaya devam eder.\u003C\/li\u003E\n    \u003C\/ul\u003E\n  \u003C\/article\u003E\n\n  \u003Cscript\u003E\n    const dropzone = document.getElementById('dropzone');\n    const docxInput = document.getElementById('docxInput');\n    const outputContainer = document.getElementById('outputContainer');\n    const actionBar = document.getElementById('actionBar');\n    const statusInfo = document.getElementById('statusInfo');\n    const zipDownloadBtn = document.getElementById('zipDownloadBtn');\n\n    let processedList = [];\n\n    ['dragenter', 'dragover'].forEach(eName =\u003E {\n      dropzone.addEventListener(eName, e =\u003E { e.preventDefault(); dropzone.classList.add('dragover'); });\n    });\n    ['dragleave', 'drop'].forEach(eName =\u003E {\n      dropzone.addEventListener(eName, e =\u003E { e.preventDefault(); dropzone.classList.remove('dragover'); });\n    });\n\n    dropzone.addEventListener('drop', e =\u003E handleFiles(Array.from(e.dataTransfer.files)));\n    docxInput.addEventListener('change', e =\u003E handleFiles(Array.from(e.target.files)));\n\n    function handleFiles(files) {\n      const docxFiles = files.filter(f =\u003E f.name.endsWith('.docx'));\n      if (!docxFiles.length) return;\n\n      outputContainer.innerHTML = '';\n      processedList = [];\n      actionBar.classList.remove('hidden');\n      actionBar.style.display = 'flex';\n      statusInfo.textContent = `${docxFiles.length} Word dosyası taranıyor...`;\n\n      let count = 0;\n      docxFiles.forEach(file =\u003E {\n        const reader = new FileReader();\n        reader.onload = ev =\u003E {\n          processFile(file, ev.target.result);\n          count++;\n          if (count === docxFiles.length) {\n            statusInfo.textContent = `${docxFiles.length} dosya başarıyla dönüştürüldü.`;\n          }\n        };\n        reader.readAsArrayBuffer(file);\n      });\n    }\n\n    const styleMap = [\n      \"p[style-name='Heading 1'] =\u003E h1:fresh\",\n      \"p[style-name='Heading 2'] =\u003E h2:fresh\",\n      \"p[style-name='Heading 3'] =\u003E h3:fresh\",\n      \"p[style-name='Quote'] =\u003E blockquote:fresh\"\n    ];\n\n    function processFile(file, buffer) {\n      mammoth.convertToHtml({ arrayBuffer: buffer }, { styleMap: styleMap })\n        .then(result =\u003E {\n          const parsed = parseDoc(file.name, result.value);\n          processedList.push({\n            name: file.name.replace(\/\\.docx$\/i, '.html'),\n            title: parsed.title,\n            titleHtml: `\u003Ch1\u003E${escapeHtml(parsed.title)}\u003C\/h1\u003E`,\n            bodyHtml: parsed.bodyHtml\n          });\n          renderCard(file.name, parsed);\n        });\n    }\n\n    function parseDoc(filename, rawHtml) {\n      const el = document.createElement('div');\n      el.innerHTML = rawHtml;\n\n      let title = '';\n      const h1 = el.querySelector('h1');\n      if (h1) {\n        title = h1.innerText.trim();\n        h1.remove();\n      } else {\n        const p1 = el.querySelector('p');\n        if (p1) {\n          title = p1.innerText.trim();\n          p1.remove();\n        } else {\n          title = filename.replace(\/\\.docx$\/i, '');\n        }\n      }\n\n      const footnotes = el.querySelectorAll('li[id^=\"footnote-\"]').length;\n\n      return {\n        title: title,\n        bodyHtml: el.innerHTML.trim(),\n        footnotesCount: footnotes\n      };\n    }\n\n    function renderCard(filename, data) {\n      const card = document.createElement('div');\n      card.className = 'output-item';\n      const cleanId = filename.replace(\/[^a-zA-Z0-9]\/g, '_');\n\n      const titleId = `t_${cleanId}`;\n      const bodyId = `b_${cleanId}`;\n\n      card.innerHTML = `\n        \u003Cdiv class=\"output-head\"\u003E\n          \u003Cspan style=\"font-weight: 600; color: #0f172a;\"\u003E${escapeHtml(filename)}\u003C\/span\u003E\n          \u003Cspan class=\"badge-count\"\u003E${data.footnotesCount} Dipnot Linki\u003C\/span\u003E\n        \u003C\/div\u003E\n\n        \u003Cdiv class=\"code-box-group\"\u003E\n          \u003Cdiv class=\"code-box-bar\"\u003E\n            \u003Cspan class=\"box-title\"\u003EBaşlık HTML Kodu\u003C\/span\u003E\n            \u003Cbutton class=\"btn-copy\" onclick=\"copyBox('${titleId}', this)\"\u003EKopyala\u003C\/button\u003E\n          \u003C\/div\u003E\n          \u003Cpre id=\"${titleId}\"\u003E\u003Ccode\u003E${escapeHtml(`\u003Ch1\u003E` + data.title + `\u003C\/h1\u003E`)}\u003C\/code\u003E\u003C\/pre\u003E\n        \u003C\/div\u003E\n\n        \u003Cdiv class=\"code-box-group\"\u003E\n          \u003Cdiv class=\"code-box-bar\"\u003E\n            \u003Cspan class=\"box-title\"\u003EGövde \u0026 Dipnotlar HTML Kodu\u003C\/span\u003E\n            \u003Cbutton class=\"btn-copy\" onclick=\"copyBox('${bodyId}', this)\"\u003EKopyala\u003C\/button\u003E\n          \u003C\/div\u003E\n          \u003Cpre id=\"${bodyId}\"\u003E\u003Ccode\u003E${escapeHtml(data.bodyHtml)}\u003C\/code\u003E\u003C\/pre\u003E\n        \u003C\/div\u003E\n      `;\n\n      outputContainer.appendChild(card);\n    }\n\n    function copyBox(boxId, btn) {\n      const txt = document.getElementById(boxId).innerText;\n      navigator.clipboard.writeText(txt).then(() =\u003E {\n        const old = btn.textContent;\n        btn.textContent = 'Kopyalandı!';\n        btn.style.background = '#dcfce7';\n        btn.style.color = '#15803d';\n        setTimeout(() =\u003E {\n          btn.textContent = old;\n          btn.style.background = '#f1f5f9';\n          btn.style.color = '#1e293b';\n        }, 1400);\n      });\n    }\n\n    zipDownloadBtn.addEventListener('click', () =\u003E {\n      if (!processedList.length) return;\n      const zip = new JSZip();\n      processedList.forEach(item =\u003E {\n        const full = `\u003C!DOCTYPE html\u003E\u003Chtml\u003E\u003Chead\u003E\u003Cmeta charset=\"utf-8\"\u003E\u003Ctitle\u003E${escapeHtml(item.title)}\u003C\/title\u003E\u003C\/head\u003E\u003Cbody\u003E\u003Carticle\u003E${item.titleHtml}\\n${item.bodyHtml}\u003C\/article\u003E\u003C\/body\u003E\u003C\/html\u003E`;\n        zip.file(item.name, full);\n      });\n      zip.generateAsync({ type: 'blob' }).then(blob =\u003E {\n        const a = document.createElement('a');\n        a.href = URL.createObjectURL(blob);\n        a.download = 'donusturulmus_yazilar.zip';\n        a.click();\n        URL.revokeObjectURL(a.href);\n      });\n    });\n\n    function escapeHtml(str) {\n      return str.replace(\/[\u0026\u003C\u003E\"']\/g, m =\u003E ({ '\u0026': '\u0026amp;', '\u003C': '\u0026lt;', '\u003E': '\u0026gt;', '\"': '\u0026quot;', \"'\": '\u0026#039;' }[m]));\n    }\n  \u003C\/script\u003E\n\n\u003C\/body\u003E\n\u003C\/html\u003E"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/7921938424969816151"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/7921938424969816151"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/09\/word-dipnotlarn-tek-tkla-web-uyumlu.html","title":"Word Dipnotlarını Tek Tıkla Web Uyumlu HTML Bağlantılarına Dönüştürme Rehberi"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}]},{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-3172719834022429105"},"published":{"$t":"2026-08-29T23:01:27.676+03:00"},"updated":{"$t":"2026-08-31T16:35:07.053+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"tutorial"}],"title":{"type":"text","$t":"Google Docs, Sheets ve Drive Link Dönüştürücü | Doğrudan İndirme ve Kopya Oluşturma Rehberi"},"content":{"type":"html","$t":"\u003C!DOCTYPE html\u003E\n\u003Chtml lang=\"tr\" class=\"scroll-smooth\"\u003E\n\u003Chead\u003E\n    \u003Cmeta charset=\"UTF-8\"\u003E\n    \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003E\n    \n    \u003C!-- Primary SEO Meta Tags --\u003E\n    \u003Ctitle\u003EGoogle Docs ve Drive Linklerini Doğrudan İndirme ve Kopya Bağlantısına Dönüştürme Rehberi\u003C\/title\u003E\n    \u003Cmeta name=\"title\" content=\"Google Docs ve Drive Linklerini Doğrudan İndirme ve Kopya Bağlantısına Dönüştürme Rehberi\"\u003E\n    \u003Cmeta name=\"description\" content=\"Google Docs, Sheets, Slides ve Drive linklerini doğrudan indirme (DOCX, PDF, XLSX, PPTX, CSV, EPUB) veya otomatik 'Kopya Oluştur' (\/copy) bağlantılarına dönüştürme rehberi ve gelişmiş dönüştürme aracı.\"\u003E\n    \u003Cmeta name=\"keywords\" content=\"google docs doğrudan indirme linki, google drive direct download link, google docs make a copy linki, google docs kopya oluştur linki, google docs export format docx, google sheets xlsx indirme linki, drive link dönüştürücü, google slides pptx indirme, copy comments drive, google sheets gid csv\"\u003E\n    \u003Cmeta name=\"author\" content=\"Akademik \u0026 Dijital Araçlar\"\u003E\n    \u003Cmeta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\"\u003E\n    \u003Clink rel=\"canonical\" href=\"https:\/\/www.socialintcong.org\/google-drive-docs-link-rehberi-ve-donusturucu.html\"\u003E\n\n    \u003C!-- Open Graph \/ Social Media --\u003E\n    \u003Cmeta property=\"og:type\" content=\"article\"\u003E\n    \u003Cmeta property=\"og:url\" content=\"https:\/\/www.socialintcong.org\/google-drive-docs-link-rehberi-ve-donusturucu.html\"\u003E\n    \u003Cmeta property=\"og:title\" content=\"Google Docs ve Drive Linklerini Doğrudan İndirme ve Kopya Bağlantısına Dönüştürme\"\u003E\n    \u003Cmeta property=\"og:description\" content=\"Google Dokümanlar ve Drive linklerini tek tıkla DOCX\/PDF\/Excel indirme veya kullanıcıya zorunlu kopya çıkartma bağlantısına dönüştürme yöntemi.\"\u003E\n    \u003Cmeta property=\"og:locale\" content=\"tr_TR\"\u003E\n    \u003Cmeta name=\"twitter:card\" content=\"summary\"\u003E\n\n    \u003C!-- Tailwind CSS CDN --\u003E\n    \u003Cscript src=\"https:\/\/cdn.tailwindcss.com\"\u003E\u003C\/script\u003E\n    \u003Cscript\u003E\n        tailwind.config = {\n            theme: {\n                extend: {\n                    colors: {\n                        primary: '#2563eb',\n                        primaryDark: '#1d4ed8'\n                    },\n                    fontFamily: {\n                        sans: ['Plus Jakarta Sans', 'system-ui', '-apple-system', 'sans-serif'],\n                        mono: ['JetBrains Mono', 'Menlo', 'monospace']\n                    }\n                }\n            }\n        }\n    \u003C\/script\u003E\n\n    \u003C!-- Google Fonts \u0026 Font Awesome --\u003E\n    \u003Clink rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"\u003E\n    \u003Clink rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin\u003E\n    \u003Clink href=\"https:\/\/fonts.googleapis.com\/css2?family=JetBrains+Mono:wght@400;500;600\u0026family=Plus+Jakarta+Sans:wght@400;500;600;700;800\u0026display=swap\" rel=\"stylesheet\"\u003E\n    \u003Clink rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.5.1\/css\/all.min.css\"\u003E\n\n    \u003Cstyle\u003E\n        @keyframes shake {\n            0%, 100% { transform: translateX(0); }\n            20%, 60% { transform: translateX(-4px); }\n            40%, 80% { transform: translateX(4px); }\n        }\n        .animate-shake {\n            animation: shake 0.35s cubic-bezier(.36,.07,.19,.97) both;\n        }\n        .format-pill {\n            position: relative;\n            user-select: none;\n            touch-action: manipulation;\n        }\n    \u003C\/style\u003E\n\n    \u003C!-- Schema.org JSON-LD Structured Data for AI \u0026 Search Engines (GEO \/ AIO \/ Google Rich Results) --\u003E\n    \u003Cscript type=\"application\/ld+json\"\u003E\n    {\n      \"@context\": \"https:\/\/schema.org\",\n      \"@graph\": [\n        {\n          \"@type\": \"Article\",\n          \"@id\": \"https:\/\/www.socialintcong.org\/google-drive-docs-link-rehberi-ve-donusturucu.html#article\",\n          \"headline\": \"Google Docs ve Drive Linklerini Doğrudan İndirme ve Kopya Bağlantısına Dönüştürme Rehberi\",\n          \"description\": \"Google Dokümanlar, E-Tablolar, Slaytlar ve Drive URL parametreleri (\/copy, \/export?format=docx, \/preview, \/template\/preview, \/present) ile dosyaları kullanıcıya kopyalatma veya doğrudan indirtme yöntemleri.\",\n          \"inLanguage\": \"tr\",\n          \"author\": {\n            \"@type\": \"Organization\",\n            \"name\": \"Akademik Dijital Araçlar\"\n          },\n          \"datePublished\": \"2026-08-29\",\n          \"dateModified\": \"2026-08-30\"\n        },\n        {\n          \"@type\": \"FAQPage\",\n          \"@id\": \"https:\/\/www.socialintcong.org\/google-drive-docs-link-rehberi-ve-donusturucu.html#faq\",\n          \"mainEntity\": [\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Google Docs linkini doğrudan Word (.docx) olarak indirme linkine nasıl çeviririm?\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Linkin sonundaki '\/edit' veya '\/edit?usp=sharing' kısmını silip yerine '\/export?format=docx' eklemeniz yeterlidir.\"\n              }\n            },\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Kullanıcının linke tıkladığında dosyayı doğrudan kendi Drive hesabına kopyalamasını nasıl sağlarım?\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Google Doküman, E-Tablo veya Slayt linkinin sonundaki '\/edit' kısmını silip yerine '\/copy' yazın. Kullanıcı linki açtığında doğrudan 'Kopya oluşturulsun mu?' ekranı gelir ve orijinal dosyanız değişmeden kendi hesabına kopyalanır.\"\n              }\n            },\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Google Sheets (E-Tablo) dosyasını tek tıkla Excel (.xlsx) veya PDF olarak indirme linki nedir?\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Excel için link sonuna '\/export?format=xlsx', PDF için ise '\/export?format=pdf' parametresi eklenir.\"\n              }\n            },\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Google Drive'daki normal dosyalar (ZIP, MP4, PDF) için doğrudan indirme linki nasıl yapılır?\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Dosya ID'sini alarak 'https:\/\/drive.google.com\/uc?export=download\u0026id=DOSYA_ID' formatında link oluşturabilirsiniz. 100 MB üzeri dosyalarda onay ekranını aşmak için sonuna '\u0026confirm=t' eklenebilir.\"\n              }\n            },\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Google Slides sunumunu doğrudan tam ekran sunum modunda başlatma linki nedir?\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Google Slides linkinin sonundaki '\/edit' kısmını silip yerine '\/present' eklediğinizde sunum doğrudan tam ekran modunda başlar.\"\n              }\n            },\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Linke tıklayan kişinin Google oturumu açık olmak zorunda mı?\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Doğrudan indirme (\/export?format=...) linklerinde oturum açma zorunluluğu yoktur. Ancak \/copy linkinde kopyanın kullanıcının hesabına aktarılabilmesi için Google oturumunun açık olması gerekir.\"\n              }\n            },\n            {\n              \"@type\": \"Question\",\n              \"name\": \"Her Google belgesi her formata dönüştürülebilir mi? (Örn: Docs -\u003E CSV veya Sheets -\u003E Word)\",\n              \"acceptedAnswer\": {\n                \"@type\": \"Answer\",\n                \"text\": \"Hayır. Google Workspace dosya türlerinin her birinin desteklediği dışa aktarma (export) formatları farklıdır. Örneğin Docs metinleri CSV veya XLSX olarak indirilemez; Sheets tabloları ise DOCX olarak indirilemez. Dönüştürücü aracımız yapıştırılan linkin türünü otomatik algılayarak yalnızca uyumlu formatları etkinleştirir.\"\n              }\n            }\n          ]\n        }\n      ]\n    }\n    \u003C\/script\u003E\n\u003C\/head\u003E\n\u003Cbody class=\"bg-slate-50 text-slate-800 antialiased font-sans py-6 md:py-10 px-4\"\u003E\n\n    \u003Carticle class=\"max-w-3xl mx-auto space-y-6\"\u003E\n        \n        \u003C!-- Açıklama Paragrafı --\u003E\n        \u003Cp class=\"text-base text-slate-700 leading-relaxed\"\u003E\n            Google Dokümanlar (Docs), E-Tablolar (Sheets), Slaytlar (Slides) ve Drive dosyalarınızı paylaşırken standart düzenleme linki yerine özel URL parametreleri kullanarak kullanıcıların dosyayı doğrudan \u003Cstrong\u003EWord (.docx)\u003C\/strong\u003E, \u003Cstrong\u003EPDF\u003C\/strong\u003E veya \u003Cstrong\u003EExcel (.xlsx)\u003C\/strong\u003E formatında indirmesini sağlayabilir; ya da orijinal dosyanızı güvenceye alarak karşı tarafın hesabına \u003Cstrong\u003Eotomatik kopya (\/copy)\u003C\/strong\u003E çıkartabilirsiniz.\n        \u003C\/p\u003E\n\n        \u003C!-- SADELEŞTİRİLMİŞ \u0026 GELİŞMİŞ MODLU DÖNÜŞTÜRME ARACI --\u003E\n        \u003Csection class=\"bg-white rounded-xl border border-slate-200 shadow-sm p-4 sm:p-5 space-y-4\"\u003E\n            \n            \u003Cdiv class=\"flex items-center justify-between\"\u003E\n                \u003Ch2 class=\"text-sm sm:text-base font-bold text-slate-900 flex items-center gap-2\"\u003E\n                    \u003Ci class=\"fas fa-wand-magic-sparkles text-blue-600\"\u003E\u003C\/i\u003E Hızlı Link Dönüştürücü\n                \u003C\/h2\u003E\n                \u003Cbutton \n                    type=\"button\" \n                    id=\"btnToggleAdvanced\" \n                    class=\"text-xs font-semibold text-blue-600 hover:text-blue-700 inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md bg-blue-50 hover:bg-blue-100 transition-colors\"\u003E\n                    \u003Ci class=\"fas fa-sliders text-xs\"\u003E\u003C\/i\u003E \u003Cspan\u003EGelişmiş Seçenekler\u003C\/span\u003E\n                    \u003Ci class=\"fas fa-chevron-down text-[10px] transition-transform duration-200\" id=\"advancedChevron\"\u003E\u003C\/i\u003E\n                \u003C\/button\u003E\n            \u003C\/div\u003E\n\n            \u003C!-- Input \u0026 Format Selection Row --\u003E\n            \u003Cdiv class=\"space-y-3\"\u003E\n                \u003Cdiv\u003E\n                    \u003Clabel for=\"inputUrl\" class=\"block text-xs font-semibold text-slate-600 mb-1\"\u003EGoogle Docs \/ Sheets \/ Slides \/ Drive Linkinizi Yapıştırın:\u003C\/label\u003E\n                    \u003Cdiv class=\"relative\"\u003E\n                        \u003Cinput \n                            type=\"text\" \n                            id=\"inputUrl\" \n                            placeholder=\"Örn: https:\/\/docs.google.com\/document\/d\/...\/edit\" \n                            class=\"w-full px-3.5 py-2.5 bg-slate-50 border border-slate-300 rounded-lg text-slate-900 font-mono text-xs sm:text-sm focus:bg-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all\"\n                        \/\u003E\n                        \u003Cbutton id=\"btnClear\" type=\"button\" class=\"absolute right-2.5 top-2.5 text-xs text-slate-400 hover:text-slate-600\" title=\"Temizle\"\u003E\n                            \u003Ci class=\"fas fa-times-circle\"\u003E\u003C\/i\u003E\n                        \u003C\/button\u003E\n                    \u003C\/div\u003E\n                    \u003Cdiv id=\"detectedBadge\" class=\"mt-1 text-[11px] text-slate-500 min-h-[16px]\"\u003E\n                        \u003Cspan id=\"detectText\"\u003EDönüştürmek istediğiniz linki yukarıdaki kutuya yapıştırın.\u003C\/span\u003E\n                    \u003C\/div\u003E\n                \u003C\/div\u003E\n\n                \u003C!-- Standart Format Hapları --\u003E\n                \u003Cdiv\u003E\n                    \u003Clabel class=\"block text-xs font-semibold text-slate-600 mb-1.5\"\u003EHedef Format \/ Eylem Seçin:\u003C\/label\u003E\n                    \u003Cdiv class=\"flex flex-wrap gap-1.5\" id=\"formatPills\"\u003E\n                        \n                        \u003Clabel data-format=\"export_docx\" title=\"Word (.docx) olarak doğrudan indirir (\/export?format=docx)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_docx\" class=\"sr-only peer\" checked\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-blue-600 peer-checked:bg-blue-50 peer-checked:text-blue-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-file-word text-blue-600\"\u003E\u003C\/i\u003E Word (.docx)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"export_pdf\" title=\"PDF olarak doğrudan indirir (\/export?format=pdf)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_pdf\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-rose-600 peer-checked:bg-rose-50 peer-checked:text-rose-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-file-pdf text-rose-600\"\u003E\u003C\/i\u003E PDF (.pdf)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"copy\" title=\"Karşı tarafın hesabına bağımsız bir kopya oluşturmasını sağlar (\/copy)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"copy\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-emerald-600 peer-checked:bg-emerald-50 peer-checked:text-emerald-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-copy text-emerald-600\"\u003E\u003C\/i\u003E Kopya Çıkart (\/copy)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"template_preview\" title=\"Önizleme gösterir ve sağ üstte 'Şablonu Kullan' butonu sunar (\/template\/preview)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"template_preview\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-purple-600 peer-checked:bg-purple-50 peer-checked:text-purple-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-table-columns text-purple-600\"\u003E\u003C\/i\u003E Şablon Modu\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"export_xlsx\" title=\"E-Tabloyu Excel (.xlsx) olarak doğrudan indirir (\/export?format=xlsx)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_xlsx\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-emerald-600 peer-checked:bg-emerald-50 peer-checked:text-emerald-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-file-excel text-emerald-600\"\u003E\u003C\/i\u003E Excel (.xlsx)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"export_pptx\" title=\"Slaytı PowerPoint (.pptx) olarak doğrudan indirir (\/export\/pptx)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_pptx\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-amber-600 peer-checked:bg-amber-50 peer-checked:text-amber-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-file-powerpoint text-amber-600\"\u003E\u003C\/i\u003E PowerPoint (.pptx)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"present\" title=\"Slaytı doğrudan tam ekran sunum modunda başlatır (\/present)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"present\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-indigo-600 peer-checked:bg-indigo-50 peer-checked:text-indigo-700 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-play text-indigo-600\"\u003E\u003C\/i\u003E Sunum Modu (\/present)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"drive_direct\" title=\"Google Drive'daki normal dosyalar (ZIP, MP4, PDF) için doğrudan indirme linki\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"drive_direct\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-red-600 peer-checked:bg-red-50 peer-checked:text-red-700 transition-all\"\u003E\n                                \u003Ci class=\"fab fa-google-drive text-red-500\"\u003E\u003C\/i\u003E Drive İndir\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                        \u003Clabel data-format=\"preview\" title=\"Temiz, araç çubuksuz önizleme modunda açar (\/preview)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                            \u003Cinput type=\"radio\" name=\"formatAction\" value=\"preview\" class=\"sr-only peer\"\u003E\n                            \u003Cspan class=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-slate-200 text-xs font-medium text-slate-700 bg-white hover:bg-slate-50 peer-checked:border-slate-800 peer-checked:bg-slate-100 peer-checked:text-slate-900 transition-all\"\u003E\n                                \u003Ci class=\"fas fa-eye text-slate-600\"\u003E\u003C\/i\u003E Önizleme (\/preview)\n                            \u003C\/span\u003E\n                        \u003C\/label\u003E\n\n                    \u003C\/div\u003E\n                \u003C\/div\u003E\n\n                \u003C!-- GELİŞMİŞ SEÇENEKLER \u0026 EK PARAMETRELER (İSTEĞE BAĞLI AÇILIR) --\u003E\n                \u003Cdiv id=\"advancedPanel\" class=\"hidden pt-3 border-t border-slate-200\/80 space-y-3 bg-slate-50\/70 p-3.5 rounded-lg border\"\u003E\n                    \n                    \u003Cdiv\u003E\n                        \u003Cspan class=\"block text-[11px] font-bold text-slate-700 uppercase tracking-wider mb-1.5\"\u003E\n                            \u003Ci class=\"fas fa-file-export text-slate-500\"\u003E\u003C\/i\u003E Diğer Formatlar:\n                        \u003C\/span\u003E\n                        \u003Cdiv class=\"flex flex-wrap gap-1.5\"\u003E\n                            \n                            \u003Clabel data-format=\"export_csv\" title=\"CSV formatında doğrudan indirme (\/export?format=csv)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_csv\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-teal-600 peer-checked:bg-teal-50 peer-checked:text-teal-700 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-file-csv text-teal-600\"\u003E\u003C\/i\u003E CSV (Tablo)\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel data-format=\"export_tsv\" title=\"TSV formatında doğrudan indirme (\/export?format=tsv)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_tsv\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-teal-600 peer-checked:bg-teal-50 peer-checked:text-teal-700 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-table text-teal-600\"\u003E\u003C\/i\u003E TSV\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel data-format=\"export_epub\" title=\"E-Kitap (EPUB) formatında indir (\/export?format=epub)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_epub\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-blue-600 peer-checked:bg-blue-50 peer-checked:text-blue-700 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-book text-blue-600\"\u003E\u003C\/i\u003E EPUB (E-Kitap)\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel data-format=\"export_odt\" title=\"Açık Belge Metni (ODT) formatında indir (\/export?format=odt)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_odt\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-blue-600 peer-checked:bg-blue-50 peer-checked:text-blue-700 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-file-lines text-blue-600\"\u003E\u003C\/i\u003E ODT (OpenDoc)\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel data-format=\"export_txt\" title=\"Düz Metin (TXT) olarak indir (\/export?format=txt)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_txt\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-slate-700 peer-checked:bg-slate-100 peer-checked:text-slate-900 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-align-left text-slate-500\"\u003E\u003C\/i\u003E Düz Metin (.txt)\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel data-format=\"export_png\" title=\"Sunumun ilk slaytını PNG resim olarak indir (\/export\/png)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"export_png\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-amber-600 peer-checked:bg-amber-50 peer-checked:text-amber-700 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-image text-amber-600\"\u003E\u003C\/i\u003E Slayt Resmi (PNG)\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel data-format=\"htmlview\" title=\"E-Tabloyu araç çubuksuz sade web sayfası görünümünde açar (\/htmlview)\" class=\"cursor-pointer format-pill transition-opacity\"\u003E\n                                \u003Cinput type=\"radio\" name=\"formatAction\" value=\"htmlview\" class=\"sr-only peer\"\u003E\n                                \u003Cspan class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-md border border-slate-200 text-[11px] font-medium text-slate-600 bg-white hover:bg-slate-50 peer-checked:border-emerald-600 peer-checked:bg-emerald-50 peer-checked:text-emerald-700 transition-all\"\u003E\n                                    \u003Ci class=\"fas fa-globe text-emerald-600\"\u003E\u003C\/i\u003E Web Görünümü (\/htmlview)\n                                \u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                        \u003C\/div\u003E\n                    \u003C\/div\u003E\n\n                    \u003C!-- Özel URL Parametre Ayarları --\u003E\n                    \u003Cdiv class=\"pt-2 border-t border-slate-200 space-y-2\"\u003E\n                        \u003Cspan class=\"block text-[11px] font-bold text-slate-700 uppercase tracking-wider\"\u003E\n                            \u003Ci class=\"fas fa-gear text-slate-500\"\u003E\u003C\/i\u003E İsteğe Bağlı Ek Parametreler:\n                        \u003C\/span\u003E\n                        \n                        \u003Cdiv class=\"grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs\"\u003E\n                            \u003C!-- Başlık Parametresi --\u003E\n                            \u003Cdiv\u003E\n                                \u003Clabel for=\"advTitle\" class=\"block text-[11px] font-medium text-slate-600 mb-0.5\"\u003EKopya Dosya Başlığı (?title=...):\u003C\/label\u003E\n                                \u003Cinput \n                                    type=\"text\" \n                                    id=\"advTitle\" \n                                    placeholder=\"Örn: 2026 Makale Sablonu\" \n                                    class=\"w-full px-2.5 py-1.5 bg-white border border-slate-300 rounded text-slate-800 text-xs focus:ring-1 focus:ring-blue-500 focus:outline-none\"\n                                \/\u003E\n                            \u003C\/div\u003E\n\n                            \u003C!-- Sayfa GID Parametresi --\u003E\n                            \u003Cdiv\u003E\n                                \u003Clabel for=\"advGid\" class=\"block text-[11px] font-medium text-slate-600 mb-0.5\"\u003ESheets Sekme ID (?gid=...):\u003C\/label\u003E\n                                \u003Cinput \n                                    type=\"text\" \n                                    id=\"advGid\" \n                                    placeholder=\"Örn: 0 veya 182937419\" \n                                    class=\"w-full px-2.5 py-1.5 bg-white border border-slate-300 rounded text-slate-800 text-xs focus:ring-1 focus:ring-blue-500 focus:outline-none\"\n                                \/\u003E\n                            \u003C\/div\u003E\n                        \u003C\/div\u003E\n\n                        \u003C!-- Checkboxlar --\u003E\n                        \u003Cdiv class=\"flex flex-wrap gap-4 pt-1\"\u003E\n                            \u003Clabel class=\"inline-flex items-center gap-1.5 cursor-pointer text-xs text-slate-700\"\u003E\n                                \u003Cinput type=\"checkbox\" id=\"advComments\" class=\"rounded border-slate-300 text-blue-600 focus:ring-blue-500\"\u003E\n                                \u003Cspan\u003EKopyaya yorumları da dahil et (\u003Ccode class=\"text-[10px] bg-slate-200 px-1 py-0.5 rounded\"\u003EcopyComments=true\u003C\/code\u003E)\u003C\/span\u003E\n                            \u003C\/label\u003E\n\n                            \u003Clabel class=\"inline-flex items-center gap-1.5 cursor-pointer text-xs text-slate-700\"\u003E\n                                \u003Cinput type=\"checkbox\" id=\"advConfirm\" class=\"rounded border-slate-300 text-blue-600 focus:ring-blue-500\"\u003E\n                                \u003Cspan\u003E100MB+ Drive virüs onayını atla (\u003Ccode class=\"text-[10px] bg-slate-200 px-1 py-0.5 rounded\"\u003Econfirm=t\u003C\/code\u003E)\u003C\/span\u003E\n                            \u003C\/label\u003E\n                        \u003C\/div\u003E\n                    \u003C\/div\u003E\n\n                \u003C\/div\u003E\n\n                \u003C!-- Result Box --\u003E\n                \u003Cdiv class=\"pt-1\"\u003E\n                    \u003Clabel class=\"block text-xs font-semibold text-slate-600 mb-1\"\u003EDönüştürülmüş Bağlantı:\u003C\/label\u003E\n                    \u003Cdiv class=\"flex gap-2\"\u003E\n                        \u003Cinput \n                            type=\"text\" \n                            id=\"outputUrl\" \n                            readonly \n                            class=\"w-full px-3 py-2 bg-slate-900 text-emerald-400 font-mono text-xs rounded-lg border border-slate-800 focus:outline-none select-all\"\n                            placeholder=\"Dönüştürülmüş link burada görünecektir...\"\n                        \/\u003E\n                        \u003Cbutton \n                            id=\"btnCopy\" \n                            type=\"button\"\n                            class=\"px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg text-xs transition-all flex items-center justify-center gap-1.5 shrink-0\"\u003E\n                            \u003Ci class=\"fas fa-copy\"\u003E\u003C\/i\u003E Kopyala\n                        \u003C\/button\u003E\n                        \u003Ca \n                            id=\"btnTest\" \n                            href=\"#\" \n                            target=\"_blank\" \n                            rel=\"noopener noreferrer\" \n                            class=\"px-3 py-2 bg-slate-100 hover:bg-slate-200 text-slate-700 font-medium rounded-lg text-xs transition-all flex items-center justify-center gap-1 shrink-0 border border-slate-300\"\n                            title=\"Yeni sekmede aç ve test et\"\u003E\n                            \u003Ci class=\"fas fa-external-link-alt\"\u003E\u003C\/i\u003E Test\n                        \u003C\/a\u003E\n                    \u003C\/div\u003E\n                \u003C\/div\u003E\n\n            \u003C\/div\u003E\n        \u003C\/section\u003E\n\n        \u003C!-- MAKALE BÖLÜMÜ --\u003E\n        \u003Csection class=\"space-y-6 text-slate-700 leading-relaxed text-sm sm:text-base\"\u003E\n            \n            \u003Ch2 class=\"text-xl sm:text-2xl font-bold text-slate-900 tracking-tight pt-2\"\u003E\n                1. Google Drive \u0026 Docs URL Yapısı ve Mantığı\n            \u003C\/h2\u003E\n            \u003Cp\u003E\n                Google Docs, Sheets, Slides ve Drive üzerindeki her dosyanın adres çubuğundaki linkinde benzersiz bir \u003Cstrong\u003EDosya Kimliği (File ID)\u003C\/strong\u003E bulunur. Standart paylaşım linki varsayılan olarak düzenleme (\u003Ccode\u003E\/edit\u003C\/code\u003E) modunda açılır:\n            \u003C\/p\u003E\n\n            \u003Cdiv class=\"p-3 bg-slate-900 rounded-lg font-mono text-xs text-slate-200 overflow-x-auto border border-slate-800\"\u003E\n                https:\/\/docs.google.com\/document\/d\/\u003Cspan class=\"text-amber-400 font-bold\"\u003E1c4f_10bbdsZ-nTUWy9GPCpLhXty00gBr\u003C\/span\u003E\u003Cspan class=\"text-rose-400 font-bold\"\u003E\/edit?usp=sharing\u003C\/span\u003E\n            \u003C\/div\u003E\n\n            \u003Cp\u003E\n                URL sonundaki \u003Ccode class=\"bg-slate-200 px-1 py-0.5 rounded text-rose-600 text-xs font-mono\"\u003E\/edit...\u003C\/code\u003E kısmını silip yerine istenen eylem parametresi eklendiğinde Google sunucusu dosyayı doğrudan istenen formatta sunar.\n            \u003C\/p\u003E\n\n            \u003Cdiv class=\"p-3.5 bg-amber-50 border-l-4 border-amber-500 rounded-r-lg text-amber-900 text-xs sm:text-sm\"\u003E\n                \u003Cstrong\u003EÖnemli Kural:\u003C\/strong\u003E Linklerin sorunsuz çalışması için Google Drive'da dosya paylaşım ayarının \u003Cem\u003E\"Bağlantıya sahip olan herkes görüntüleyebilir\" (Anyone with the link can view)\u003C\/em\u003E olarak ayarlanmış olması gerekir.\n            \u003C\/div\u003E\n\n            \u003Ch2 class=\"text-xl sm:text-2xl font-bold text-slate-900 tracking-tight pt-4\"\u003E\n                2. Kullanıcının Hesabına Otomatik Kopya Çıkartmak (\/copy)\n            \u003C\/h2\u003E\n            \u003Cp\u003E\n                Ödev taslağı, makale şablonu veya bütçe tablosu paylaştığınızda kullanıcıların orijinal dosyanızda değişiklik yapmasını engellemek için linkin sonundaki \u003Ccode\u003E\/edit\u003C\/code\u003E kısmını silip \u003Ccode\u003E\/copy\u003C\/code\u003E yazın:\n            \u003C\/p\u003E\n\n            \u003Cdiv class=\"p-3 bg-slate-900 rounded-lg font-mono text-xs text-slate-200 border border-slate-800\"\u003E\n                \u003Cspan class=\"text-slate-400 block text-[11px] font-sans mb-1\"\u003EKullanıcıya Zorunlu Kopya Linki:\u003C\/span\u003E\n                https:\/\/docs.google.com\/document\/d\/DOSYA_ID\/\u003Cspan class=\"text-emerald-400 font-bold\"\u003Ecopy\u003C\/span\u003E\n            \u003C\/div\u003E\n\n            \u003Cul class=\"list-disc pl-5 space-y-1.5 text-xs sm:text-sm text-slate-600\"\u003E\n                \u003Cli\u003E\u003Cstrong\u003EKopyaya Otomatik Başlık Verme:\u003C\/strong\u003E \u003Ccode\u003E\/copy?title=Yeni+Baslik\u003C\/code\u003E eklenerek dosya adı önceden belirlenebilir.\u003C\/li\u003E\n                \u003Cli\u003E\u003Cstrong\u003EYorumları da Dahil Ederek Kopyalama:\u003C\/strong\u003E \u003Ccode\u003E\/copy?copyComments=true\u003C\/code\u003E eklenerek dokümandaki yorumların da kopyaya aktarılması sağlanabilir.\u003C\/li\u003E\n                \u003Cli\u003E\u003Cstrong\u003EŞablon Önizleme Modu:\u003C\/strong\u003E \u003Ccode\u003E\/template\/preview\u003C\/code\u003E ile dosya önce önizlenir ve sağ üstte mavi renkli \u003Cem\u003E\"Şablonu Kullan\" (Use Template)\u003C\/em\u003E butonu gösterilir.\u003C\/li\u003E\n            \u003C\/ul\u003E\n\n            \u003Ch2 class=\"text-xl sm:text-2xl font-bold text-slate-900 tracking-tight pt-4\"\u003E\n                3. Doğrudan İndirme (Direct Download) Formatları\n            \u003C\/h2\u003E\n            \u003Cp\u003E\n                Kullanıcıların Google Docs arayüzüyle uğraşmadan dosyayı anında bilgisayarına veya telefonuna indirmesi için aşağıdaki parametreler kullanılır:\n            \u003C\/p\u003E\n\n            \u003Cdiv class=\"grid grid-cols-1 sm:grid-cols-2 gap-3 text-xs sm:text-sm\"\u003E\n                \u003Cdiv class=\"p-3.5 bg-white border border-slate-200 rounded-lg\"\u003E\n                    \u003Ch3 class=\"font-bold text-slate-900 mb-1 flex items-center gap-1.5\"\u003E\u003Ci class=\"fas fa-file-word text-blue-600\"\u003E\u003C\/i\u003E Google Docs (Dokümanlar)\u003C\/h3\u003E\n                    \u003Cul class=\"space-y-1 font-mono text-xs text-slate-600\"\u003E\n                        \u003Cli\u003EWord (.docx): \u003Ccode class=\"text-blue-700 font-bold\"\u003E\/export?format=docx\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EPDF Belgesi: \u003Ccode class=\"text-blue-700 font-bold\"\u003E\/export?format=pdf\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EDüz Metin: \u003Ccode class=\"text-blue-700\"\u003E\/export?format=txt\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EE-Kitap (EPUB): \u003Ccode class=\"text-blue-700\"\u003E\/export?format=epub\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EOpenDocument: \u003Ccode class=\"text-blue-700\"\u003E\/export?format=odt\u003C\/code\u003E\u003C\/li\u003E\n                    \u003C\/ul\u003E\n                \u003C\/div\u003E\n\n                \u003Cdiv class=\"p-3.5 bg-white border border-slate-200 rounded-lg\"\u003E\n                    \u003Ch3 class=\"font-bold text-slate-900 mb-1 flex items-center gap-1.5\"\u003E\u003Ci class=\"fas fa-file-excel text-emerald-600\"\u003E\u003C\/i\u003E Google Sheets (E-Tablolar)\u003C\/h3\u003E\n                    \u003Cul class=\"space-y-1 font-mono text-xs text-slate-600\"\u003E\n                        \u003Cli\u003EExcel (.xlsx): \u003Ccode class=\"text-emerald-700 font-bold\"\u003E\/export?format=xlsx\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EPDF Tablo: \u003Ccode class=\"text-emerald-700 font-bold\"\u003E\/export?format=pdf\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003ECSV (İlk Sayfa): \u003Ccode class=\"text-emerald-700\"\u003E\/export?format=csv\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EBelirli Sayfa: \u003Ccode class=\"text-emerald-700\"\u003E\/export?format=csv\u0026gid=SAYFA_ID\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EWeb Görünümü: \u003Ccode class=\"text-emerald-700\"\u003E\/htmlview\u003C\/code\u003E\u003C\/li\u003E\n                    \u003C\/ul\u003E\n                \u003C\/div\u003E\n\n                \u003Cdiv class=\"p-3.5 bg-white border border-slate-200 rounded-lg\"\u003E\n                    \u003Ch3 class=\"font-bold text-slate-900 mb-1 flex items-center gap-1.5\"\u003E\u003Ci class=\"fas fa-file-powerpoint text-amber-600\"\u003E\u003C\/i\u003E Google Slides (Slaytlar)\u003C\/h3\u003E\n                    \u003Cul class=\"space-y-1 font-mono text-xs text-slate-600\"\u003E\n                        \u003Cli\u003EPowerPoint: \u003Ccode class=\"text-amber-700 font-bold\"\u003E\/export\/pptx\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003EPDF Sunum: \u003Ccode class=\"text-amber-700 font-bold\"\u003E\/export\/pdf\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003ETam Ekran Sunum: \u003Ccode class=\"text-indigo-700 font-bold\"\u003E\/present\u003C\/code\u003E\u003C\/li\u003E\n                        \u003Cli\u003Eİlk Slayt Resmi: \u003Ccode class=\"text-amber-700\"\u003E\/export\/png\u003C\/code\u003E\u003C\/li\u003E\n                    \u003C\/ul\u003E\n                \u003C\/div\u003E\n\n                \u003Cdiv class=\"p-3.5 bg-white border border-slate-200 rounded-lg\"\u003E\n                    \u003Ch3 class=\"font-bold text-slate-900 mb-1 flex items-center gap-1.5\"\u003E\u003Ci class=\"fab fa-google-drive text-red-500\"\u003E\u003C\/i\u003E Genel Drive Dosyaları\u003C\/h3\u003E\n                    \u003Cp class=\"text-slate-600 text-xs mb-1\"\u003EZIP, MP4, PDF dosyaları için doğrudan indirme linki:\u003C\/p\u003E\n                    \u003Ccode class=\"text-slate-800 text-[11px] font-mono block break-all\"\u003Edrive.google.com\/uc?export=download\u0026id=ID\u003C\/code\u003E\n                    \u003Cspan class=\"text-[11px] text-slate-500 block mt-1\"\u003E100MB+ dosyalar için sonuna \u003Ccode\u003E\u0026confirm=t\u003C\/code\u003E ekleyin.\u003C\/span\u003E\n                \u003C\/div\u003E\n            \u003C\/div\u003E\n\n            \u003Ch2 class=\"text-xl sm:text-2xl font-bold text-slate-900 tracking-tight pt-4\"\u003E\n                4. Hızlı Parametre Tablosu (Cheat Sheet)\n            \u003C\/h2\u003E\n            \u003Cdiv class=\"overflow-x-auto border border-slate-200 rounded-lg\"\u003E\n                \u003Ctable class=\"w-full text-left text-xs border-collapse\"\u003E\n                    \u003Cthead class=\"bg-slate-100 text-slate-700 border-b border-slate-200\"\u003E\n                        \u003Ctr\u003E\n                            \u003Cth class=\"py-2.5 px-3 font-bold\"\u003EServis\u003C\/th\u003E\n                            \u003Cth class=\"py-2.5 px-3 font-bold\"\u003EEylem\u003C\/th\u003E\n                            \u003Cth class=\"py-2.5 px-3 font-bold font-mono\"\u003EEklenen Parametre\u003C\/th\u003E\n                        \u003C\/tr\u003E\n                    \u003C\/thead\u003E\n                    \u003Ctbody class=\"divide-y divide-slate-200 text-slate-600\"\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Docs\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EWord (.docx) İndir\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-blue-600 font-bold\"\u003E\/export?format=docx\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Docs\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EPDF İndir\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-rose-600 font-bold\"\u003E\/export?format=pdf\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EDocs \/ Sheets \/ Slides\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EKopya Oluştur\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-emerald-600 font-bold\"\u003E\/copy\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EDocs \/ Sheets \/ Slides\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EŞablon Önizleme\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-purple-600 font-bold\"\u003E\/template\/preview\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Sheets\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EExcel (.xlsx) İndir\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-emerald-600 font-bold\"\u003E\/export?format=xlsx\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Sheets\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003ECSV İndir\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-teal-600 font-bold\"\u003E\/export?format=csv\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Slides\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EPowerPoint (.pptx) İndir\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-amber-600 font-bold\"\u003E\/export\/pptx\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Slides\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003ETam Ekran Sunum Başlat\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-indigo-600 font-bold\"\u003E\/present\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                        \u003Ctr\u003E\n                            \u003Ctd class=\"py-2 px-3 font-medium text-slate-800\"\u003EGoogle Drive Dosyası\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3\"\u003EDoğrudan İndirme\u003C\/td\u003E\n                            \u003Ctd class=\"py-2 px-3 font-mono text-red-600 font-bold\"\u003Euc?export=download\u0026id=ID\u003C\/td\u003E\n                        \u003C\/tr\u003E\n                    \u003C\/tbody\u003E\n                \u003C\/table\u003E\n            \u003C\/div\u003E\n\n            \u003Ch2 class=\"text-xl sm:text-2xl font-bold text-slate-900 tracking-tight pt-4\"\u003E\n                5. Sıkça Sorulan Sorular (S.S.S.)\n            \u003C\/h2\u003E\n            \u003Cdiv class=\"space-y-3\"\u003E\n                \u003Cdetails class=\"group border border-slate-200 rounded-lg p-3.5 bg-white open:bg-slate-50 transition-colors\"\u003E\n                    \u003Csummary class=\"font-bold text-xs sm:text-sm text-slate-900 cursor-pointer list-none flex items-center justify-between\"\u003E\n                        \u003Cspan\u003E1. Linke tıklayan kişinin Google oturumu açık olmak zorunda mı?\u003C\/span\u003E\n                        \u003Ci class=\"fas fa-chevron-down text-slate-400 group-open:rotate-180 transition-transform text-xs\"\u003E\u003C\/i\u003E\n                    \u003C\/summary\u003E\n                    \u003Cp class=\"mt-2 text-xs sm:text-sm text-slate-600\"\u003E\n                        \u003Ccode\u003E\/export?format=docx\u003C\/code\u003E ve \u003Ccode\u003E\/export?format=pdf\u003C\/code\u003E linkleri için oturum açma zorunluluğu yoktur; dosya herkese açıksa indirme doğrudan başlar. Ancak \u003Ccode\u003E\/copy\u003C\/code\u003E linkinde karşı tarafın kendi hesabına kopya oluşturabilmesi için Google oturumunun açık olması gerekir.\n                    \u003C\/p\u003E\n                \u003C\/details\u003E\n\n                \u003Cdetails class=\"group border border-slate-200 rounded-lg p-3.5 bg-white open:bg-slate-50 transition-colors\"\u003E\n                    \u003Csummary class=\"font-bold text-xs sm:text-sm text-slate-900 cursor-pointer list-none flex items-center justify-between\"\u003E\n                        \u003Cspan\u003E2. Karşı taraf kopya oluşturduğunda benim orijinal dosyam değişir mi?\u003C\/span\u003E\n                        \u003Ci class=\"fas fa-chevron-down text-slate-400 group-open:rotate-180 transition-transform text-xs\"\u003E\u003C\/i\u003E\n                    \u003C\/summary\u003E\n                    \u003Cp class=\"mt-2 text-xs sm:text-sm text-slate-600\"\u003E\n                        Hayır. \u003Ccode\u003E\/copy\u003C\/code\u003E işlemi tamamen bağımsız yeni bir dosya üretir. Karşı taraf o dosyayı silse veya düzenlese dahi sizin orijinal belgeniz hiçbir şekilde etkilenmez.\n                    \u003C\/p\u003E\n                \u003C\/details\u003E\n\n                \u003Cdetails class=\"group border border-slate-200 rounded-lg p-3.5 bg-white open:bg-slate-50 transition-colors\"\u003E\n                    \u003Csummary class=\"font-bold text-xs sm:text-sm text-slate-900 cursor-pointer list-none flex items-center justify-between\"\u003E\n                        \u003Cspan\u003E3. Büyük boyutlu Google Drive dosyalarında virüs taraması uyarısı nasıl atlanır?\u003C\/span\u003E\n                        \u003Ci class=\"fas fa-chevron-down text-slate-400 group-open:rotate-180 transition-transform text-xs\"\u003E\u003C\/i\u003E\n                    \u003C\/summary\u003E\n                    \u003Cp class=\"mt-2 text-xs sm:text-sm text-slate-600\"\u003E\n                        Google Drive 100 MB üzerindeki dosyalarda tarama yapamadığı için ara onay ekranı gösterir. İndirme linkinin sonuna \u003Ccode\u003E\u0026confirm=t\u003C\/code\u003E eklemek bu onay sayfasını atlayarak doğrudan indirmeyi başlatır.\n                    \u003C\/p\u003E\n                \u003C\/details\u003E\n\n                \u003Cdetails class=\"group border border-slate-200 rounded-lg p-3.5 bg-white open:bg-slate-50 transition-colors\"\u003E\n                    \u003Csummary class=\"font-bold text-xs sm:text-sm text-slate-900 cursor-pointer list-none flex items-center justify-between\"\u003E\n                        \u003Cspan\u003E4. Google Sheets içinde sadece belirli bir sayfayı CSV olarak nasıl indirebilirim?\u003C\/span\u003E\n                        \u003Ci class=\"fas fa-chevron-down text-slate-400 group-open:rotate-180 transition-transform text-xs\"\u003E\u003C\/i\u003E\n                    \u003C\/summary\u003E\n                    \u003Cp class=\"mt-2 text-xs sm:text-sm text-slate-600\"\u003E\n                        Her alt sekmenin URL'sinde bir \u003Ccode\u003Egid\u003C\/code\u003E parametresi yer alır (örneğin \u003Ccode\u003Egid=123456\u003C\/code\u003E). İndirme bağlantısının sonuna \u003Ccode\u003E\u0026gid=SAYFA_ID\u003C\/code\u003E ekleyerek (örn: \u003Ccode\u003E\/export?format=csv\u0026gid=123456\u003C\/code\u003E) yalnızca o sekmeyi indirebilirsiniz.\n                    \u003C\/p\u003E\n                \u003C\/details\u003E\n\n                \u003Cdetails class=\"group border border-slate-200 rounded-lg p-3.5 bg-white open:bg-slate-50 transition-colors\"\u003E\n                    \u003Csummary class=\"font-bold text-xs sm:text-sm text-slate-900 cursor-pointer list-none flex items-center justify-between\"\u003E\n                        \u003Cspan\u003E5. Her Google belgesi her formata dönüştürülebilir mi? (Örn: Docs -\u003E CSV veya Sheets -\u003E Word)\u003C\/span\u003E\n                        \u003Ci class=\"fas fa-chevron-down text-slate-400 group-open:rotate-180 transition-transform text-xs\"\u003E\u003C\/i\u003E\n                    \u003C\/summary\u003E\n                    \u003Cp class=\"mt-2 text-xs sm:text-sm text-slate-600\"\u003E\n                        Hayır. Google Docs belgeleri yapısal metin içerdiği için CSV\/XLSX olarak indirilemez. Benzer şekilde Google Sheets tabloları da DOCX formatında dışa aktarılamaz. Yukarıdaki akıllı aracımız, yapıştırdığınız linkin türünü otomatik olarak algılar; o dosya için desteklenmeyen formatları pasif hale getirir ve üzerine geldiğinizde neden desteklenmediğini açıklar.\n                    \u003C\/p\u003E\n                \u003C\/details\u003E\n            \u003C\/div\u003E\n\n        \u003C\/section\u003E\n\n    \u003C\/article\u003E\n\n    \u003C!-- JavaScript Interactive Logic --\u003E\n    \u003Cscript\u003E\n        document.addEventListener('DOMContentLoaded', () =\u003E {\n            const inputUrl = document.getElementById('inputUrl');\n            const outputUrl = document.getElementById('outputUrl');\n            const btnClear = document.getElementById('btnClear');\n            const btnCopy = document.getElementById('btnCopy');\n            const btnTest = document.getElementById('btnTest');\n            const detectText = document.getElementById('detectText');\n            \n            \/\/ Advanced controls\n            const btnToggleAdvanced = document.getElementById('btnToggleAdvanced');\n            const advancedPanel = document.getElementById('advancedPanel');\n            const advancedChevron = document.getElementById('advancedChevron');\n            const advTitle = document.getElementById('advTitle');\n            const advGid = document.getElementById('advGid');\n            const advComments = document.getElementById('advComments');\n            const advConfirm = document.getElementById('advConfirm');\n\n            let isAdvancedOpen = false;\n            btnToggleAdvanced.addEventListener('click', () =\u003E {\n                isAdvancedOpen = !isAdvancedOpen;\n                if (isAdvancedOpen) {\n                    advancedPanel.classList.remove('hidden');\n                    advancedChevron.classList.add('rotate-180');\n                    btnToggleAdvanced.classList.add('bg-blue-100');\n                } else {\n                    advancedPanel.classList.add('hidden');\n                    advancedChevron.classList.remove('rotate-180');\n                    btnToggleAdvanced.classList.remove('bg-blue-100');\n                }\n            });\n\n            const FORMAT_RULES = {\n                export_docx: {\n                    name: 'Word (.docx)',\n                    allowedTypes: ['docs'],\n                    defaultTitle: 'Word (.docx) olarak doğrudan indirme linki oluşturur (\/export?format=docx)',\n                    reason: 'Google Docs harici (Sheets, Slides, Drive) dosyalar Word olarak indirilemez. Yalnızca Google Docs belgeleri için geçerlidir.'\n                },\n                export_pdf: {\n                    name: 'PDF (.pdf)',\n                    allowedTypes: ['docs', 'sheets', 'slides'],\n                    defaultTitle: 'PDF olarak doğrudan indirme linki oluşturur (\/export?format=pdf)',\n                    reason: 'Drive genel dosyalarında doğrudan dosya indirme (uc?export=download) parametresi kullanılır.'\n                },\n                copy: {\n                    name: 'Kopya Çıkart (\/copy)',\n                    allowedTypes: ['docs', 'sheets', 'slides'],\n                    defaultTitle: 'Kullanıcının kendi hesabına bağımsız bir kopya oluşturmasını sağlar (\/copy)',\n                    reason: 'Otomatik kopya linki yalnızca Google Docs, Sheets ve Slides belgelerinde geçerlidir.'\n                },\n                template_preview: {\n                    name: 'Şablon Modu',\n                    allowedTypes: ['docs', 'sheets', 'slides'],\n                    defaultTitle: \"Belgeyi önizler ve sağ üstte 'Şablonu Kullan' butonu gösterir (\/template\/preview)\",\n                    reason: 'Şablon modu yalnızca Google Docs, Sheets ve Slides belgelerinde geçerlidir.'\n                },\n                export_xlsx: {\n                    name: 'Excel (.xlsx)',\n                    allowedTypes: ['sheets'],\n                    defaultTitle: 'E-Tabloyu doğrudan Excel (.xlsx) olarak indirme linki oluşturur (\/export?format=xlsx)',\n                    reason: 'Excel formatı yalnızca Google Sheets (E-Tablolar) için geçerlidir; Docs veya Slides için kullanılamaz.'\n                },\n                export_pptx: {\n                    name: 'PowerPoint (.pptx)',\n                    allowedTypes: ['slides'],\n                    defaultTitle: 'Sunumu doğrudan PowerPoint (.pptx) olarak indirme linki oluşturur (\/export\/pptx)',\n                    reason: 'PowerPoint formatı yalnızca Google Slides (Sunumlar) için geçerlidir.'\n                },\n                present: {\n                    name: 'Sunum Modu (\/present)',\n                    allowedTypes: ['slides'],\n                    defaultTitle: 'Sunumu doğrudan tam ekran sunum modunda başlatır (\/present)',\n                    reason: 'Tam ekran sunum modu yalnızca Google Slides sunumları için geçerlidir.'\n                },\n                drive_direct: {\n                    name: 'Drive Doğrudan İndir',\n                    allowedTypes: ['drive'],\n                    defaultTitle: \"Google Drive'daki normal dosyalar (ZIP, MP4, PDF) için doğrudan indirme linki (uc?export=download)\",\n                    reason: 'Google Dokümanları doğrudan dosya indirme yerine format export parametresi gerektirir.'\n                },\n                preview: {\n                    name: 'Önizleme (\/preview)',\n                    allowedTypes: ['docs', 'sheets', 'slides', 'drive'],\n                    defaultTitle: 'Temiz, araç çubuksuz ve sade önizleme modunda açar (\/preview)',\n                    reason: ''\n                },\n                \/\/ Advanced Formats\n                export_csv: {\n                    name: 'CSV (Tablo)',\n                    allowedTypes: ['sheets'],\n                    defaultTitle: 'E-Tablonun ilk sayfasını CSV formatında doğrudan indirir (\/export?format=csv)',\n                    reason: 'CSV formatı yalnızca Google Sheets (E-Tablolar) için geçerlidir; metin belgeleri veya sunumlarda kullanılamaz.'\n                },\n                export_tsv: {\n                    name: 'TSV',\n                    allowedTypes: ['sheets'],\n                    defaultTitle: 'E-Tablonun ilk sayfasını TSV formatında doğrudan indirir (\/export?format=tsv)',\n                    reason: 'TSV formatı yalnızca Google Sheets (E-Tablolar) için geçerlidir.'\n                },\n                export_epub: {\n                    name: 'EPUB (E-Kitap)',\n                    allowedTypes: ['docs'],\n                    defaultTitle: 'Dokümanı E-Kitap (EPUB) formatında indirir (\/export?format=epub)',\n                    reason: 'EPUB (E-Kitap) formatı yalnızca Google Docs (Dokümanlar) için geçerlidir.'\n                },\n                export_odt: {\n                    name: 'ODT (OpenDocument)',\n                    allowedTypes: ['docs'],\n                    defaultTitle: 'Açık Belge Metni (ODT) formatında indirir (\/export?format=odt)',\n                    reason: 'ODT formatı yalnızca Google Docs (Dokümanlar) için geçerlidir.'\n                },\n                export_txt: {\n                    name: 'Düz Metin (.txt)',\n                    allowedTypes: ['docs', 'slides'],\n                    defaultTitle: 'Düz Metin (TXT) olarak indirir (\/export?format=txt)',\n                    reason: 'Düz Metin (.txt) dışa aktarımı yalnızca Google Docs ve Slides için geçerlidir.'\n                },\n                export_png: {\n                    name: 'Slayt Resmi (PNG)',\n                    allowedTypes: ['slides'],\n                    defaultTitle: 'Sunumun ilk slaytını yüksek çözünürlüklü PNG resim olarak indirir (\/export\/png)',\n                    reason: 'Slayt resmi (PNG) dışa aktarımı yalnızca Google Slides (Sunumlar) için geçerlidir.'\n                },\n                htmlview: {\n                    name: 'Web Görünümü (\/htmlview)',\n                    allowedTypes: ['sheets'],\n                    defaultTitle: 'E-Tabloyu araç çubuksuz sade HTML web sayfası görünümünde açar (\/htmlview)',\n                    reason: 'Web görünümü (\/htmlview) yalnızca Google Sheets için geçerlidir.'\n                }\n            };\n\n            const DEFAULT_FORMAT_BY_TYPE = {\n                docs: 'export_docx',\n                sheets: 'export_xlsx',\n                slides: 'export_pptx',\n                drive: 'drive_direct',\n                unknown_id: 'export_docx'\n            };\n\n            const TYPE_LABELS = {\n                docs: 'Google Docs (Doküman)',\n                sheets: 'Google Sheets (E-Tablo)',\n                slides: 'Google Slides (Sunum)',\n                drive: 'Google Drive Dosyası',\n                unknown_id: 'Google Dosyası'\n            };\n\n            \/\/ Create Floating Tooltip DOM Element\n            const customTooltip = document.createElement('div');\n            customTooltip.id = 'customTooltip';\n            customTooltip.className = 'fixed hidden z-[99999] pointer-events-none transition-all duration-150 transform -translate-x-1\/2 opacity-0 scale-95 shadow-2xl rounded-xl p-3 max-w-[290px] sm:max-w-xs text-xs';\n            document.body.appendChild(customTooltip);\n\n            let currentDetectedType = null;\n            let tooltipHideTimeout = null;\n\n            function parseGoogleUrl(url) {\n                if (!url || typeof url !== 'string') return null;\n                const trimmed = url.trim();\n\n                const docsMatch = trimmed.match(\/docs\\.google\\.com\\\/document\\\/d\\\/([a-zA-Z0-9_-]+)\/);\n                if (docsMatch) return { type: 'docs', id: docsMatch[1] };\n\n                const sheetsMatch = trimmed.match(\/docs\\.google\\.com\\\/spreadsheets\\\/d\\\/([a-zA-Z0-9_-]+)\/);\n                if (sheetsMatch) return { type: 'sheets', id: sheetsMatch[1] };\n\n                const slidesMatch = trimmed.match(\/docs\\.google\\.com\\\/presentation\\\/d\\\/([a-zA-Z0-9_-]+)\/);\n                if (slidesMatch) return { type: 'slides', id: slidesMatch[1] };\n\n                const driveFileMatch = trimmed.match(\/drive\\.google\\.com\\\/(?:file\\\/d\\\/|open\\?id=|uc\\?id=)([a-zA-Z0-9_-]+)\/);\n                if (driveFileMatch) return { type: 'drive', id: driveFileMatch[1] };\n\n                if (\/^[a-zA-Z0-9_-]{25,50}$\/.test(trimmed)) return { type: 'unknown_id', id: trimmed };\n\n                return null;\n            }\n\n            function showFloatingTooltip(pill, isAllowed, rule) {\n                clearTimeout(tooltipHideTimeout);\n                const rect = pill.getBoundingClientRect();\n                const typeName = currentDetectedType ? (TYPE_LABELS[currentDetectedType] || currentDetectedType.toUpperCase()) : 'bu dosya';\n\n                if (!isAllowed) {\n                    customTooltip.className = 'fixed z-[99999] pointer-events-none transition-all duration-150 transform -translate-x-1\/2 opacity-100 scale-100 shadow-2xl rounded-xl p-3 max-w-[300px] text-xs bg-slate-900\/95 text-white border border-rose-500\/60 backdrop-blur-md';\n                    customTooltip.innerHTML = `\n                        \u003Cdiv class=\"flex items-center gap-1.5 text-rose-400 font-bold text-xs mb-1\"\u003E\n                            \u003Ci class=\"fas fa-ban text-rose-400\"\u003E\u003C\/i\u003E Bu Dosya Türüyle Uyumsuz!\n                        \u003C\/div\u003E\n                        \u003Cdiv class=\"text-[11px] text-slate-200 leading-snug\"\u003E\n                            \u003Cstrong class=\"text-white\"\u003E${rule.name}\u003C\/strong\u003E, ${typeName} için kullanılamaz.\n                        \u003C\/div\u003E\n                        \u003Cdiv class=\"mt-1 text-[10.5px] text-rose-300\/90 font-medium bg-rose-950\/50 p-1.5 rounded border border-rose-900\/50\"\u003E\n                            ${rule.reason}\n                        \u003C\/div\u003E\n                    `;\n                } else {\n                    customTooltip.className = 'fixed z-[99999] pointer-events-none transition-all duration-150 transform -translate-x-1\/2 opacity-100 scale-100 shadow-2xl rounded-xl p-2.5 max-w-[280px] text-xs bg-slate-900\/95 text-white border border-blue-500\/40 backdrop-blur-md';\n                    customTooltip.innerHTML = `\n                        \u003Cdiv class=\"flex items-center gap-1.5 text-emerald-400 font-bold text-xs mb-0.5\"\u003E\n                            \u003Ci class=\"fas fa-circle-check\"\u003E\u003C\/i\u003E ${rule.name} (Uyumlu)\n                        \u003C\/div\u003E\n                        \u003Cdiv class=\"text-[11px] text-slate-300 leading-snug\"\u003E\n                            ${rule.defaultTitle}\n                        \u003C\/div\u003E\n                    `;\n                }\n\n                \/\/ Position calculation\n                let left = rect.left + (rect.width \/ 2);\n                \/\/ Clamp left to screen bounds\n                const margin = 150;\n                if (left \u003C margin) left = margin;\n                if (left \u003E window.innerWidth - margin) left = window.innerWidth - margin;\n\n                let top = rect.top - 10;\n                if (top \u003C 110) {\n                    \/\/ Show below pill if near top of viewport\n                    top = rect.bottom + 10;\n                    customTooltip.style.transform = 'translate(-50%, 0)';\n                } else {\n                    customTooltip.style.transform = 'translate(-50%, -100%)';\n                }\n\n                customTooltip.style.left = `${left}px`;\n                customTooltip.style.top = `${top}px`;\n                customTooltip.classList.remove('hidden');\n            }\n\n            function hideFloatingTooltip() {\n                customTooltip.classList.add('opacity-0', 'scale-95');\n                tooltipHideTimeout = setTimeout(() =\u003E {\n                    customTooltip.classList.add('hidden');\n                }, 150);\n            }\n\n            function updateFormatAvailability(fileType) {\n                currentDetectedType = fileType;\n                const pills = document.querySelectorAll('.format-pill');\n                let selectedRadio = document.querySelector('input[name=\"formatAction\"]:checked');\n                let isCurrentSelectedValid = false;\n\n                pills.forEach(pill =\u003E {\n                    const formatKey = pill.getAttribute('data-format');\n                    const radio = pill.querySelector('input[type=\\\"radio\\\"]');\n                    const rule = FORMAT_RULES[formatKey];\n                    if (!rule) return;\n\n                    const isAllowed = !fileType || rule.allowedTypes.includes(fileType);\n\n                    if (isAllowed) {\n                        radio.disabled = false;\n                        pill.classList.remove('opacity-25', 'cursor-not-allowed', 'pointer-events-none');\n                        pill.classList.add('cursor-pointer');\n                        pill.setAttribute('data-disabled', 'false');\n                        if (radio.checked) isCurrentSelectedValid = true;\n                    } else {\n                        radio.disabled = true;\n                        pill.classList.add('opacity-25', 'cursor-not-allowed');\n                        pill.classList.remove('cursor-pointer');\n                        pill.setAttribute('data-disabled', 'true');\n                    }\n                });\n\n                \/\/ If currently selected format is not allowed for the detected file type, switch to smart default\n                if (fileType \u0026\u0026 !isCurrentSelectedValid) {\n                    const fallbackFormat = DEFAULT_FORMAT_BY_TYPE[fileType] || 'preview';\n                    const fallbackRadio = document.querySelector(`input[name=\"formatAction\"][value=\"${fallbackFormat}\"]`);\n                    if (fallbackRadio) {\n                        fallbackRadio.checked = true;\n                    }\n                }\n            }\n\n            \/\/ Setup Pill Hover, Click \u0026 Touch Tooltip Handlers\n            document.querySelectorAll('.format-pill').forEach(pill =\u003E {\n                const formatKey = pill.getAttribute('data-format');\n                const rule = FORMAT_RULES[formatKey];\n                if (!rule) return;\n\n                const handleEnter = () =\u003E {\n                    const isDisabled = pill.getAttribute('data-disabled') === 'true';\n                    showFloatingTooltip(pill, !isDisabled, rule);\n                };\n\n                const handleLeave = () =\u003E {\n                    hideFloatingTooltip();\n                };\n\n                pill.addEventListener('mouseenter', handleEnter);\n                pill.addEventListener('mouseleave', handleLeave);\n\n                \/\/ Click \/ Touch feedback (especially when disabled)\n                pill.addEventListener('click', (e) =\u003E {\n                    const isDisabled = pill.getAttribute('data-disabled') === 'true';\n                    if (isDisabled) {\n                        e.preventDefault();\n                        e.stopPropagation();\n                        \n                        \/\/ Shake animation\n                        pill.classList.remove('animate-shake');\n                        void pill.offsetWidth; \/\/ trigger reflow\n                        pill.classList.add('animate-shake');\n                        setTimeout(() =\u003E pill.classList.remove('animate-shake'), 400);\n\n                        \/\/ Show tooltip firmly\n                        showFloatingTooltip(pill, false, rule);\n\n                        \/\/ Keep visible for 3 seconds on mobile tap\n                        clearTimeout(tooltipHideTimeout);\n                        tooltipHideTimeout = setTimeout(hideFloatingTooltip, 3000);\n                    }\n                });\n            });\n\n            function generateLink() {\n                const rawInput = inputUrl.value;\n                if (!rawInput.trim()) {\n                    detectText.textContent = \"Dönüştürmek istediğiniz linki yukarıdaki kutuya yapıştırın.\";\n                    updateFormatAvailability(null);\n                    outputUrl.value = \"\";\n                    btnTest.href = \"#\";\n                    return;\n                }\n\n                const parsed = parseGoogleUrl(rawInput);\n                if (!parsed) {\n                    detectText.innerHTML = '\u003Cspan class=\"text-rose-600 font-medium\"\u003E\u003Ci class=\"fas fa-exclamation-circle\"\u003E\u003C\/i\u003E Geçersiz Google bağlantısı! Lütfen docs.google.com veya drive.google.com linki yapıştırın.\u003C\/span\u003E';\n                    updateFormatAvailability(null);\n                    outputUrl.value = \"\";\n                    btnTest.href = \"#\";\n                    return;\n                }\n\n                \/\/ Update availability based on parsed type\n                updateFormatAvailability(parsed.type);\n\n                const selectedAction = document.querySelector('input[name=\"formatAction\"]:checked')?.value || (DEFAULT_FORMAT_BY_TYPE[parsed.type] || 'export_docx');\n                const typeLabel = TYPE_LABELS[parsed.type] || \"Google Dosyası\";\n\n                detectText.innerHTML = `\u003Cspan class=\"text-emerald-700 font-bold\"\u003E\u003Ci class=\"fas fa-check-circle\"\u003E\u003C\/i\u003E ${typeLabel}\u003C\/span\u003E tespit edildi. Yalnızca uyumlu formatlar seçilebilir.`;\n\n                const fileId = parsed.id;\n                let resultUrl = \"\";\n\n                \/\/ Query modifiers\n                const titleVal = advTitle.value.trim();\n                const gidVal = advGid.value.trim();\n                const includeComments = advComments.checked;\n                const confirmLarge = advConfirm.checked;\n\n                switch (selectedAction) {\n                    case 'export_docx':\n                        resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/export?format=docx`;\n                        break;\n                    case 'export_pdf':\n                        if (parsed.type === 'slides') resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/export\/pdf`;\n                        else if (parsed.type === 'sheets') {\n                            resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/export?format=pdf`;\n                            if (gidVal) resultUrl += `\u0026gid=${encodeURIComponent(gidVal)}`;\n                        }\n                        else resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/export?format=pdf`;\n                        break;\n                    case 'copy':\n                        let copyParams = [];\n                        if (titleVal) copyParams.push(`title=${encodeURIComponent(titleVal)}`);\n                        if (includeComments) copyParams.push(`copyComments=true`);\n                        const copyQuery = copyParams.length \u003E 0 ? `?${copyParams.join('\u0026')}` : '';\n\n                        if (parsed.type === 'sheets') resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/copy${copyQuery}`;\n                        else if (parsed.type === 'slides') resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/copy${copyQuery}`;\n                        else resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/copy${copyQuery}`;\n                        break;\n                    case 'template_preview':\n                        if (parsed.type === 'sheets') resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/template\/preview`;\n                        else if (parsed.type === 'slides') resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/template\/preview`;\n                        else resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/template\/preview`;\n                        break;\n                    case 'export_xlsx':\n                        resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/export?format=xlsx`;\n                        break;\n                    case 'export_pptx':\n                        resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/export\/pptx`;\n                        break;\n                    case 'present':\n                        resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/present`;\n                        break;\n                    case 'preview':\n                        if (parsed.type === 'sheets') resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/preview`;\n                        else if (parsed.type === 'slides') resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/preview`;\n                        else if (parsed.type === 'drive') resultUrl = `https:\/\/drive.google.com\/file\/d\/${fileId}\/preview`;\n                        else resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/preview`;\n                        break;\n                    case 'drive_direct':\n                        resultUrl = `https:\/\/drive.google.com\/uc?export=download\u0026id=${fileId}`;\n                        if (confirmLarge) resultUrl += `\u0026confirm=t`;\n                        break;\n                    \n                    \/\/ Advanced Formats\n                    case 'export_csv':\n                        resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/export?format=csv`;\n                        if (gidVal) resultUrl += `\u0026gid=${encodeURIComponent(gidVal)}`;\n                        break;\n                    case 'export_tsv':\n                        resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/export?format=tsv`;\n                        if (gidVal) resultUrl += `\u0026gid=${encodeURIComponent(gidVal)}`;\n                        break;\n                    case 'export_epub':\n                        resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/export?format=epub`;\n                        break;\n                    case 'export_odt':\n                        resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/export?format=odt`;\n                        break;\n                    case 'export_txt':\n                        if (parsed.type === 'slides') resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/export\/txt`;\n                        else resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/export?format=txt`;\n                        break;\n                    case 'export_png':\n                        resultUrl = `https:\/\/docs.google.com\/presentation\/d\/${fileId}\/export\/png`;\n                        break;\n                    case 'htmlview':\n                        resultUrl = `https:\/\/docs.google.com\/spreadsheets\/d\/${fileId}\/htmlview`;\n                        if (gidVal) resultUrl += `?gid=${encodeURIComponent(gidVal)}`;\n                        break;\n                    default:\n                        resultUrl = `https:\/\/docs.google.com\/document\/d\/${fileId}\/export?format=docx`;\n                }\n\n                outputUrl.value = resultUrl;\n                btnTest.href = resultUrl;\n            }\n\n            inputUrl.addEventListener('input', generateLink);\n            document.querySelectorAll('input[name=\"formatAction\"]').forEach(radio =\u003E radio.addEventListener('change', generateLink));\n\n            \/\/ Advanced inputs listeners\n            advTitle.addEventListener('input', generateLink);\n            advGid.addEventListener('input', generateLink);\n            advComments.addEventListener('change', generateLink);\n            advConfirm.addEventListener('change', generateLink);\n\n            btnClear.addEventListener('click', () =\u003E {\n                inputUrl.value = '';\n                advTitle.value = '';\n                advGid.value = '';\n                advComments.checked = false;\n                advConfirm.checked = false;\n                updateFormatAvailability(null);\n                generateLink();\n                inputUrl.focus();\n            });\n\n            btnCopy.addEventListener('click', async () =\u003E {\n                const text = outputUrl.value;\n                if (!text) return;\n                try {\n                    await navigator.clipboard.writeText(text);\n                    btnCopy.innerHTML = '\u003Ci class=\"fas fa-check\"\u003E\u003C\/i\u003E Kopyalandı!';\n                    btnCopy.classList.replace('bg-blue-600', 'bg-emerald-600');\n                    setTimeout(() =\u003E {\n                        btnCopy.innerHTML = '\u003Ci class=\"fas fa-copy\"\u003E\u003C\/i\u003E Kopyala';\n                        btnCopy.classList.replace('bg-emerald-600', 'bg-blue-600');\n                    }, 2000);\n                } catch (e) {\n                    outputUrl.select();\n                    document.execCommand('copy');\n                }\n            });\n        });\n    \u003C\/script\u003E\n\u003C\/body\u003E\n\u003C\/html\u003E\n"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/3172719834022429105"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/3172719834022429105"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/08\/google-docs-sheets-ve-drive-link.html","title":"Google Docs, Sheets ve Drive Link Dönüştürücü | Doğrudan İndirme ve Kopya Oluşturma Rehberi"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}]},{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-3013359517416482237"},"published":{"$t":"2026-07-11T12:13:11.770+03:00"},"updated":{"$t":"2026-08-09T08:36:24.986+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"Vibe Coding"}],"title":{"type":"text","$t":"PSY CALCU Profesyonel Ürün Gelişim Raporu"},"content":{"type":"html","$t":"\u003C!--\n  ====================================================================================\n  2. RAPOR: PROFESYONEL ÜRÜN GELİŞİM RAPORU\n  ====================================================================================\n--\u003E\n\n\u003Cdiv id=\"psy-report-2\" class=\"max-w-5xl mx-auto px-4 md:px-6 py-12 font-sans antialiased text-slate-800 bg-[#f8fafc]\"\u003E\n  \u003C!-- Tailwind CSS \u0026 Font CDN --\u003E\n  \u003Clink href=\"https:\/\/cdn.jsdelivr.net\/npm\/tailwindcss@2.2.19\/dist\/tailwind.min.css\" rel=\"stylesheet\"\u003E\n  \u003Clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;500;600;700;800\u0026family=Space+Grotesk:wght@500;700\u0026display=swap\" rel=\"stylesheet\"\u003E\n  \u003Cscript src=\"https:\/\/unpkg.com\/lucide@latest\"\u003E\u003C\/script\u003E\n\n  \u003Cstyle\u003E\n    #psy-report-2 { font-family: 'Inter', sans-serif; }\n    #psy-report-2 h1, #psy-report-2 h2, #psy-report-2 h3, #psy-report-2 h4 { font-family: 'Space Grotesk', sans-serif; }\n    #psy-report-2 * { box-sizing: border-box; }\n  \u003C\/style\u003E\n\n  \u003C!-- Üst Başlık (Header) --\u003E\n  \u003Cdiv class=\"text-center mb-12\"\u003E\n    \u003Cdiv class=\"inline-flex items-center gap-2 bg-[#0f9d58]\/10 text-[#0f9d58] px-4 py-2 rounded-full text-xs font-bold uppercase tracking-wider mb-4 border border-[#0f9d58]\/20\"\u003E\n      \u003Ci data-lucide=\"code-2\" class=\"w-4 h-4\"\u003E\u003C\/i\u003E Teknik Dokümantasyon\n    \u003C\/div\u003E\n    \u003Cp class=\"text-slate-600 text-base md:text-lg leading-relaxed max-w-3xl mx-auto\"\u003E\n      Bu rapor, Psy Calcu'nun ilk prototipinden bugünkü olgun, çoklu kullanıcı uyumlu, bulut entegrasyonlu ve güvenli yapısına kadar geçen gelişim sürecini, mimari tasarım kararlarını ve aşılan teknik zorlukları kapsamaktadır.\n    \u003C\/p\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- BÖLÜM 1 --\u003E\n  \u003Csection class=\"mb-12\"\u003E\n    \u003Ch2 class=\"text-xl md:text-2xl font-extrabold text-[#182C61] mb-6 flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-8 h-8 rounded-lg bg-[#182C61] text-white flex items-center justify-center text-sm\"\u003E1\u003C\/span\u003E\n      Yapılan Çalışmalar ve Sisteme Kazandırılan Özellikler\n    \u003C\/h2\u003E\n    \n    \u003Cdiv class=\"bg-white rounded-3xl border border-slate-200 p-6 md:p-8 shadow-sm space-y-6\"\u003E\n      \u003Cdiv class=\"flex items-start gap-4\"\u003E\n        \u003Ci data-lucide=\"check-circle-2\" class=\"w-6 h-6 text-[#0f9d58] shrink-0 mt-0.5\"\u003E\u003C\/i\u003E\n        \u003Cdiv\u003E\n          \u003Ch4 class=\"font-bold text-slate-800 mb-1\"\u003EÇift Kanallı Veri Kaynağı (Manuel \u0026 Senkronize)\u003C\/h4\u003E\n          \u003Cp class=\"text-sm text-slate-600\"\u003EKullanıcıların manuel seans ekleyebileceği veya harici dijital takvimlerini ICS protokolüyle bağlayarak gerçek zamanlı veri çekebileceği esnek yapı kuruldu.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"flex items-start gap-4\"\u003E\n        \u003Ci data-lucide=\"check-circle-2\" class=\"w-6 h-6 text-[#0f9d58] shrink-0 mt-0.5\"\u003E\u003C\/i\u003E\n        \u003Cdiv\u003E\n          \u003Ch4 class=\"font-bold text-slate-800 mb-1\"\u003EAkıllı Seans Ayrıştırma Algoritması\u003C\/h4\u003E\n          \u003Cp class=\"text-sm text-slate-600\"\u003ETakvimden çekilen başlıklar (\"Ahmet Bey - Online\", \"Merve Hanım - Ofis\") analiz edilerek çevrimiçi\/yüzyüze tespiti otomatik yapılır.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"flex items-start gap-4\"\u003E\n        \u003Ci data-lucide=\"check-circle-2\" class=\"w-6 h-6 text-[#0f9d58] shrink-0 mt-0.5\"\u003E\u003C\/i\u003E\n        \u003Cdiv\u003E\n          \u003Ch4 class=\"font-bold text-slate-800 mb-1\"\u003EGelişmiş Gider Hesaplama Motoru\u003C\/h4\u003E\n          \u003Cp class=\"text-sm text-slate-600\"\u003EOfis kirası (sadece yüzyüze seanslar için) ve Babysitter\/Bakıcı ücreti (dakika bazlı veya sabit) dinamik olarak hesaplanıp net gelirden düşülür.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"flex items-start gap-4\"\u003E\n        \u003Ci data-lucide=\"check-circle-2\" class=\"w-6 h-6 text-[#0f9d58] shrink-0 mt-0.5\"\u003E\u003C\/i\u003E\n        \u003Cdiv\u003E\n          \u003Ch4 class=\"font-bold text-slate-800 mb-1\"\u003EDiğer Sistem Modülleri\u003C\/h4\u003E\n          \u003Cp class=\"text-sm text-slate-600\"\u003Eİnteraktif tanıtım turu (Tour Engine), kapsamlı bildirim merkezi ve şifreli JSON ile tek tıkla yedekleme (Backup\/Restore) mekanizması eklendi.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- BÖLÜM 2 --\u003E\n  \u003Csection class=\"mb-12\"\u003E\n    \u003Ch2 class=\"text-xl md:text-2xl font-extrabold text-[#182C61] mb-6 flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-8 h-8 rounded-lg bg-[#182C61] text-white flex items-center justify-center text-sm\"\u003E2\u003C\/span\u003E\n      Tasarım ve Mantık Kararları\n    \u003C\/h2\u003E\n\n    \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 gap-4\"\u003E\n      \u003Cdiv class=\"bg-slate-50 p-6 rounded-2xl border border-slate-200\"\u003E\n        \u003Ch4 class=\"font-bold text-[#182C61] mb-2 text-sm uppercase tracking-wider\"\u003ERenk ve Tipografi\u003C\/h4\u003E\n        \u003Cp class=\"text-sm text-slate-600\"\u003EAgresif renkler yerine; fildişi (off-white) arka planlar, zeytin yeşili ve derin kömür grisi kullanıldı. Ekran başlıklarında \"Space Grotesk\", gövdede \"Inter\" fontu tercih edildi.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-slate-50 p-6 rounded-2xl border border-slate-200\"\u003E\n        \u003Ch4 class=\"font-bold text-[#182C61] mb-2 text-sm uppercase tracking-wider\"\u003EAçıklamaların Kontrolü\u003C\/h4\u003E\n        \u003Cp class=\"text-sm text-slate-600\"\u003EKullanıcıyı bilgi bombardımanına tutmamak adına tüm rehberlik metinleri \"Açıklamaları Göster\/Gizle\" butonuyla kontrol edilebilir yapıldı.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-slate-50 p-6 rounded-2xl border border-slate-200\"\u003E\n        \u003Ch4 class=\"font-bold text-[#182C61] mb-2 text-sm uppercase tracking-wider\"\u003EDisclosure Pattern\u003C\/h4\u003E\n        \u003Cp class=\"text-sm text-slate-600\"\u003EYanlış eşleşen takvim verilerini toplu silmeye yarayan \"Kurtarma Paneli\", kazara tıklamaları önlemek için gizli bir akordeon tasarımla sunuldu.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-slate-50 p-6 rounded-2xl border border-slate-200\"\u003E\n        \u003Ch4 class=\"font-bold text-[#182C61] mb-2 text-sm uppercase tracking-wider\"\u003EGüvenlik ve Çıkış\u003C\/h4\u003E\n        \u003Cp class=\"text-sm text-slate-600\"\u003EKritik veri silme işlemlerinde büyük harflerle \"TEMİZLE\" yazma zorunluluğu getirildi. Arayüze kırmızı vurgulu bir \"Güvenli Çıkış Yap\" butonu eklendi.\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- BÖLÜM 3 --\u003E\n  \u003Csection class=\"mb-12\"\u003E\n    \u003Ch2 class=\"text-xl md:text-2xl font-extrabold text-[#182C61] mb-6 flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-8 h-8 rounded-lg bg-[#182C61] text-white flex items-center justify-center text-sm\"\u003E3\u003C\/span\u003E\n      Karşılaşılan Temel Zorluklar ve Üretilen Çözümler\n    \u003C\/h2\u003E\n\n    \u003Cdiv class=\"space-y-4\" id=\"tech-accordion\"\u003E\n      \u003C!-- Problem 1 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleAccordion(1)\" class=\"w-full text-left p-5 font-bold text-[#182C61] hover:bg-slate-50 flex items-center justify-between focus:outline-none\"\u003E\n          \u003Cspan class=\"flex items-center gap-3\"\u003E\n            \u003Ci data-lucide=\"alert-circle\" class=\"w-5 h-5 text-amber-500\"\u003E\u003C\/i\u003E\n            Çoklu Kullanıcı Veri Çakışması (Data Contamination)\n          \u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"icon-1\" class=\"w-5 h-5 text-slate-400 transition-transform\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"content-1\" class=\"hidden px-5 pb-5 pt-2 border-t border-slate-100 text-sm space-y-3\"\u003E\n          \u003Cp class=\"text-slate-600\"\u003E\u003Cstrong\u003EProblem:\u003C\/strong\u003E Ortak cihazlarda farklı hesaplarla giriş yapanların yerel önbellekteki (localStorage) verileri birbirine karışıyordu.\u003C\/p\u003E\n          \u003Cp class=\"text-slate-600\"\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E Sisteme \u003Cstrong class=\"text-[#0f9d58]\"\u003E\"User-Scoped Local Caching\"\u003C\/strong\u003E altyapısı kuruldu. Yerel veriler kullanıcı ID'si ile etiketlendi ve güvenli çıkışta tarayıcıdan tamamen kazınacak şekilde programlandı.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Problem 2 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleAccordion(2)\" class=\"w-full text-left p-5 font-bold text-[#182C61] hover:bg-slate-50 flex items-center justify-between focus:outline-none\"\u003E\n          \u003Cspan class=\"flex items-center gap-3\"\u003E\n            \u003Ci data-lucide=\"alert-circle\" class=\"w-5 h-5 text-amber-500\"\u003E\u003C\/i\u003E\n            Mobil Tarayıcılarda Giriş Sıkıntıları (Safari\/ITP)\n          \u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"icon-2\" class=\"w-5 h-5 text-slate-400 transition-transform\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"content-2\" class=\"hidden px-5 pb-5 pt-2 border-t border-slate-100 text-sm space-y-3\"\u003E\n          \u003Cp class=\"text-slate-600\"\u003E\u003Cstrong\u003EProblem:\u003C\/strong\u003E iOS cihazlardaki \"Siteler Arası Takip Engelleme\" (ITP) özelliği Google Popup girişlerini bozuyordu.\u003C\/p\u003E\n          \u003Cp class=\"text-slate-600\"\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E Sadece mobilde tetiklenen \"Mobil Kullanıcı Uyarısı\" entegre edilerek, bu cihazlarda %100 kararlı çalışan \"E-posta \u0026 Şifre\" alternatifi ön plana çıkarıldı.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Problem 3 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleAccordion(3)\" class=\"w-full text-left p-5 font-bold text-[#182C61] hover:bg-slate-50 flex items-center justify-between focus:outline-none\"\u003E\n          \u003Cspan class=\"flex items-center gap-3\"\u003E\n            \u003Ci data-lucide=\"alert-circle\" class=\"w-5 h-5 text-amber-500\"\u003E\u003C\/i\u003E\n            Takvim Senkronizasyonunun Veri Bütünlüğü\n          \u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"icon-3\" class=\"w-5 h-5 text-slate-400 transition-transform\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"content-3\" class=\"hidden px-5 pb-5 pt-2 border-t border-slate-100 text-sm space-y-3\"\u003E\n          \u003Cp class=\"text-slate-600\"\u003E\u003Cstrong\u003EProblem:\u003C\/strong\u003E Hatalı bir takvim eşleşmesi, kullanıcının elle girdiği seans verilerini bozabilirdi.\u003C\/p\u003E\n          \u003Cp class=\"text-slate-600\"\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E Veriler yazılmadan önce \"Origin\" (Kaynak) bilgisiyle (manual, google_calendar vb.) etiketlendi. Takvim sıfırlandığında sadece senkronize edilen veriler silinir, manuel girişler korunur.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- BÖLÜM 4 --\u003E\n  \u003Csection\u003E\n    \u003Ch2 class=\"text-xl md:text-2xl font-extrabold text-[#182C61] mb-6 flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-8 h-8 rounded-lg bg-[#182C61] text-white flex items-center justify-center text-sm\"\u003E4\u003C\/span\u003E\n      Son Kullanıcıya Sağladığı Temel Faydalar\n    \u003C\/h2\u003E\n\n    \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4\"\u003E\n      \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col items-start gap-3 hover:-translate-y-1 transition-transform\"\u003E\n        \u003Cdiv class=\"w-10 h-10 rounded-full bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-bold\"\u003E1\u003C\/div\u003E\n        \u003Ch4 class=\"font-extrabold text-[#182C61]\"\u003EZaman Tasarrufu\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-600 leading-relaxed\"\u003ESaatler süren manuel Excel güncellemeleri, ICS senkronizasyonu sayesinde 5 saniyeye iner.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col items-start gap-3 hover:-translate-y-1 transition-transform\"\u003E\n        \u003Cdiv class=\"w-10 h-10 rounded-full bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-bold\"\u003E2\u003C\/div\u003E\n        \u003Ch4 class=\"font-extrabold text-[#182C61]\"\u003EFinansal Farkındalık\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-600 leading-relaxed\"\u003EBrüt kazancın ofis kirasına, bakıcıya vb. dağılımı netleşir. Ay sonu \"Net Kâr\" kuruşu kuruşuna bilinir.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col items-start gap-3 hover:-translate-y-1 transition-transform\"\u003E\n        \u003Cdiv class=\"w-10 h-10 rounded-full bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-bold\"\u003E3\u003C\/div\u003E\n        \u003Ch4 class=\"font-extrabold text-[#182C61]\"\u003ESıfır Hesap Hatası\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-600 leading-relaxed\"\u003EDakika bazlı bakıcı veya seans bazlı ofis kirası; tüm hesaplamalar bilgisayar hassasiyetindedir.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col items-start gap-3 hover:-translate-y-1 transition-transform\"\u003E\n        \u003Cdiv class=\"w-10 h-10 rounded-full bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-bold\"\u003E4\u003C\/div\u003E\n        \u003Ch4 class=\"font-extrabold text-[#182C61]\"\u003EGizlilik ve Güvenlik\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-600 leading-relaxed\"\u003EDanışan adları ve detayları modern şifreleme ve Firestore Security Rules ile tam güvenceye alınır.\u003C\/p\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col items-start gap-3 hover:-translate-y-1 transition-transform md:col-span-2 lg:col-span-1\"\u003E\n        \u003Cdiv class=\"w-10 h-10 rounded-full bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-bold\"\u003E5\u003C\/div\u003E\n        \u003Ch4 class=\"font-extrabold text-[#182C61]\"\u003ECihaz Bağımsızlık\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-600 leading-relaxed\"\u003Eİster ofisteki PC'den, ister yoldayken telefondan erişin. Veriler bulutta senkronize edilir, kaybolmaz.\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- Footer --\u003E\n  \u003Cdiv class=\"text-center mt-12 py-6 border-t border-slate-200\"\u003E\n    \u003Cp class=\"text-xs text-slate-400 font-mono uppercase tracking-widest\"\u003ERapor Sonu • Psy Calcu Ekibi\u003C\/p\u003E\n  \u003C\/div\u003E\n\n\u003C\/div\u003E\n\n\u003C!-- Scripts --\u003E\n\u003Cscript\u003E\n  window.addEventListener('DOMContentLoaded', () =\u003E { lucide.createIcons(); });\n\n  function toggleAccordion(index) {\n    const content = document.getElementById(`content-${index}`);\n    const icon = document.getElementById(`icon-${index}`);\n    \n    if (content.classList.contains('hidden')) {\n      content.classList.remove('hidden');\n      icon.style.transform = 'rotate(180deg)';\n    } else {\n      content.classList.add('hidden');\n      icon.style.transform = 'rotate(0deg)';\n    }\n  }\n\u003C\/script\u003E\n\n\u003C!-- ====================================================================================\n     PSYCALCU STİLİ YÖNLENDİRME (CTA) KART BİLEŞENİ\n     * Arka plandan ayrışan stroke\/border yapısı\n     * Tanıtım sitesine yönlendirme metinleri (Panele gitmediği vurgusu)\n     ==================================================================================== --\u003E\n\n\u003Cdiv class=\"max-w-4xl mx-auto my-16 px-4 md:px-6 font-sans antialiased\" style=\"font-family: 'Inter', sans-serif;\"\u003E\n  \n  \u003C!-- Tailwind CSS \u0026 Lucide Icons CDN --\u003E\n  \u003Clink href=\"https:\/\/cdn.jsdelivr.net\/npm\/tailwindcss@2.2.19\/dist\/tailwind.min.css\" rel=\"stylesheet\"\u003E\n  \u003Clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700;800\u0026display=swap\" rel=\"stylesheet\"\u003E\n  \u003Cscript src=\"https:\/\/unpkg.com\/lucide@latest\"\u003E\u003C\/script\u003E\n\n  \u003Cstyle\u003E\n    \/* Toprak\/Bronz Gradyan Metin Efekti *\/\n    .text-gradient-earth {\n      background-clip: text;\n      -webkit-background-clip: text;\n      -webkit-text-fill-color: transparent;\n      background-image: linear-gradient(90deg, #8B7355 0%, #C19A6B 100%);\n    }\n    \n    \/* Yüzen Element Animasyonları *\/\n    @keyframes float-card {\n      0% { transform: translateY(0px) rotate(0deg); }\n      50% { transform: translateY(-10px) rotate(2deg); }\n      100% { transform: translateY(0px) rotate(0deg); }\n    }\n    @keyframes float-card-alt {\n      0% { transform: translateY(0px) rotate(0deg); }\n      50% { transform: translateY(-12px) rotate(-3deg); }\n      100% { transform: translateY(0px) rotate(0deg); }\n    }\n    .animate-float-card { animation: float-card 5s ease-in-out infinite; }\n    .animate-float-card-alt { animation: float-card-alt 6s ease-in-out infinite; animation-delay: 1.5s; }\n  \u003C\/style\u003E\n\n  \u003C!-- CTA KART KONTEYNERİ (Arka plandan ayrışan kutu yapısı) --\u003E\n  \u003Cdiv class=\"relative bg-white rounded-[2.5rem] p-8 md:p-14 text-center border-2 border-[#e8dfd5] shadow-[0_20px_60px_-15px_rgba(0,0,0,0.05)] overflow-hidden\"\u003E\n    \n    \u003C!-- Kart İçi Dekoratif Arka Plan (Çok hafif krem radial geçiş) --\u003E\n    \u003Cdiv class=\"absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-[#fbf9f6] via-white to-white opacity-80 pointer-events-none\"\u003E\u003C\/div\u003E\n\n    \u003C!-- Dekoratif Yüzen Semboller (Kartın içinde köşelere yakın) --\u003E\n    \u003Cdiv class=\"absolute top-8 left-8 hidden md:flex w-16 h-16 bg-[#f4ece3] rounded-[1.25rem] items-center justify-center animate-float-card shadow-sm border border-[#e8dfd5]\/60 z-0\"\u003E\n      \u003Cspan class=\"text-[#a8866d] text-2xl font-serif\"\u003EΨ\u003C\/span\u003E\n    \u003C\/div\u003E\n    \u003Cdiv class=\"absolute bottom-8 right-8 hidden md:flex w-16 h-16 bg-[#e8efe9] rounded-[1.25rem] items-center justify-center animate-float-card-alt shadow-sm border border-[#d5e2d7]\/60 z-0\"\u003E\n      \u003Cspan class=\"text-[#5a7d61] text-2xl font-semibold\"\u003E₺\u003C\/span\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- İçerik --\u003E\n    \u003Cdiv class=\"relative z-10 flex flex-col items-center\"\u003E\n      \n      \u003C!-- Kategori\/Bilgi Etiketi --\u003E\n      \u003Cdiv class=\"inline-flex items-center gap-2 bg-[#f9f8f6] px-4 py-2 rounded-full border border-[#e8dfd5] shadow-sm mb-6\"\u003E\n        \u003Cdiv class=\"relative flex h-2 w-2\"\u003E\n          \u003Cspan class=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75\"\u003E\u003C\/span\u003E\n          \u003Cspan class=\"relative inline-flex rounded-full h-2 w-2 bg-amber-500\"\u003E\u003C\/span\u003E\n        \u003C\/div\u003E\n        \u003Cspan class=\"text-[10px] md:text-xs font-extrabold text-[#7a6855] uppercase tracking-widest\"\u003E\n          DETAYLI BİLGİ \u0026 TANITIM\n        \u003C\/span\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Ana Başlık --\u003E\n      \u003Ch2 class=\"text-3xl md:text-4xl lg:text-5xl font-extrabold text-[#111827] tracking-tight leading-[1.2] mb-5\"\u003E\n        PsyCalcu Hakkında \u003Cbr class=\"hidden sm:block\"\u003E\n        \u003Cspan class=\"text-gradient-earth\"\u003EDaha Fazlasını Keşfedin\u003C\/span\u003E\n      \u003C\/h2\u003E\n\n      \u003C!-- Açıklama Metni (Özellikle Panele gitmediği belirtiliyor) --\u003E\n      \u003Cdiv class=\"bg-blue-50\/50 border border-blue-100\/50 rounded-2xl p-5 mb-8 max-w-2xl mx-auto\"\u003E\n        \u003Cp class=\"text-sm md:text-base text-gray-600 leading-relaxed font-medium\"\u003E\n          Sistemin tüm özelliklerini, sunduğu avantajları ve çalışma mantığını detaylıca incelemek için resmi tanıtım sitemize göz atın.\n        \u003C\/p\u003E\n        \u003Cp class=\"text-[13px] text-blue-800 font-semibold mt-2 flex items-center justify-center gap-1.5\"\u003E\n          \u003Ci data-lucide=\"info\" class=\"w-4 h-4\"\u003E\u003C\/i\u003E\n          Not: Bu bağlantı yönetim paneline (uygulamaya) değil, projenin tanıtım sayfasına yönlendirir.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Buton Aksiyonu --\u003E\n      \u003Cdiv class=\"flex justify-center w-full\"\u003E\n        \u003Ca href=\"https:\/\/psy-calcu.blogspot.com\/\" target=\"_blank\" rel=\"noopener noreferrer\" \n           class=\"group flex items-center justify-center gap-3 bg-[#0f172a] hover:bg-[#1e293b] text-white px-8 py-4 rounded-full font-bold text-base transition-all duration-300 shadow-[0_10px_20px_rgba(15,23,42,0.15)] hover:shadow-[0_15px_30px_rgba(15,23,42,0.25)] hover:-translate-y-1 w-full sm:w-auto\"\u003E\n          \u003Cspan\u003ETanıtım Sitesine Git\u003C\/span\u003E\n          \u003Cdiv class=\"bg-white\/10 p-1.5 rounded-full transition-transform duration-300 group-hover:translate-x-1\"\u003E\n            \u003Ci data-lucide=\"arrow-right\" class=\"w-4 h-4 text-white\"\u003E\u003C\/i\u003E\n          \u003C\/div\u003E\n        \u003C\/a\u003E\n      \u003C\/div\u003E\n      \n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- İkonları Başlat --\u003E\n  \u003Cscript\u003E\n    if (typeof lucide !== 'undefined') {\n      lucide.createIcons();\n    }\n  \u003C\/script\u003E\n\u003C\/div\u003E"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/3013359517416482237"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/3013359517416482237"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/07\/psy-calcu-profesyonel-urun-gelisim.html","title":"PSY CALCU Profesyonel Ürün Gelişim Raporu"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}]},{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-1168791712501861016"},"published":{"$t":"2026-07-11T12:07:44.096+03:00"},"updated":{"$t":"2026-08-09T08:36:17.450+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"Vibe Coding"}],"title":{"type":"text","$t":"Psy Calcu Nedir?"},"content":{"type":"html","$t":"\u003Cdiv id=\"psy-report-1\" class=\"max-w-5xl mx-auto px-4 md:px-6 py-12 font-sans antialiased text-slate-800 bg-[#f8fafc]\"\u003E\n  \u003C!-- Tailwind CSS \u0026 Font CDN --\u003E\n  \u003Clink href=\"https:\/\/cdn.jsdelivr.net\/npm\/tailwindcss@2.2.19\/dist\/tailwind.min.css\" rel=\"stylesheet\"\u003E\n  \u003Clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;500;600;700;800\u0026family=Space+Grotesk:wght@500;700\u0026display=swap\" rel=\"stylesheet\"\u003E\n  \u003Cscript src=\"https:\/\/unpkg.com\/lucide@latest\"\u003E\u003C\/script\u003E\n\n  \u003Cstyle\u003E\n    #psy-report-1 { font-family: 'Inter', sans-serif; }\n    #psy-report-1 h1, #psy-report-1 h2, #psy-report-1 h3 { font-family: 'Space Grotesk', sans-serif; }\n    #psy-report-1 * { box-sizing: border-box; }\n    \n    \/* Ensure bottom box text stays white even if external themes try to override *\/\n    #psy-report-1 .bottom-box-white * { color: #ffffff !important; }\n    #psy-report-1 .bottom-box-white .text-white-80 { color: rgba(255, 255, 255, 0.8) !important; }\n  \u003C\/style\u003E\n\n  \u003C!-- Üst Başlık (Header) --\u003E\n  \u003Cdiv class=\"text-center mb-16\"\u003E\n    \u003Cp class=\"text-slate-600 text-base md:text-lg leading-relaxed max-w-3xl mx-auto\"\u003E\n      Bu belge, Psy Calcu platformunun kavramsal çerçevesini, gelişim sürecini, teknik tasarım kararlarını, karşılaşılan kritik zorlukları ve bunların üretilen yaratıcı çözümlerle aşılma hikayesini detaylandırmak üzere hazırlanmıştır.\n    \u003C\/p\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- Tanım ve Kapsam --\u003E\n  \u003Cdiv class=\"bg-white rounded-[2rem] p-8 md:p-10 border border-slate-200 shadow-sm mb-16 relative overflow-hidden\"\u003E\n    \u003Cdiv class=\"absolute top-0 left-0 w-full h-1.5 bg-gradient-to-r from-[#182C61] to-[#0f9d58]\"\u003E\u003C\/div\u003E\n    \n    \u003Cp class=\"text-lg md:text-xl text-slate-700 leading-relaxed mb-6 font-medium\"\u003E\n      \u003Cstrong class=\"text-[#182C61] font-black\"\u003EPsy Calcu;\u003C\/strong\u003E klinik psikologlar, psikoterapistler, psikiyatristler ve benzeri ruh sağlığı profesyonellerinin seans planlamalarını, karmaşık finansal gelir-gider modellerini ve lojistik giderlerini tek bir merkezden, hatasız ve zahmetsizce yönetebilmeleri için özel olarak tasarlanmış \n      \u003Cspan class=\"bg-emerald-50 text-[#0f9d58] font-bold px-2.5 py-0.5 rounded-lg border border-emerald-100\"\u003ENiş bir Finansal Yönetim ve Planlama Platformudur.\u003C\/span\u003E\n    \u003C\/p\u003E\n    \n    \u003Cdiv class=\"flex gap-5 items-start bg-slate-50 p-6 rounded-2xl border border-slate-100\"\u003E\n      \u003Cdiv class=\"w-12 h-12 rounded-full bg-white shadow-sm flex items-center justify-center shrink-0 border border-slate-200\"\u003E\n        \u003Ci data-lucide=\"brain-circuit\" class=\"w-6 h-6 text-[#182C61]\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cp class=\"text-sm md:text-base text-slate-600 leading-relaxed\"\u003E\n        Ruh sağlığı profesyonelleri için danışan takibi yapmaktan çok daha zor olan kısım, her bir seansın lojistik ve operasyonel maliyetlerini (ofis kirası, çocuk bakım\/babysitter ücretleri, online\/yüzyüze seans ayrımından doğan farklı gelir modelleri) manuel olarak hesaplamaktır. Psy Calcu, bu karmaşık yapıyı ortadan kaldırarak terapi süreçlerinin finansal yönetimini \u003Cstrong class=\"text-[#182C61]\"\u003Etamamen otomatikleştirir.\u003C\/strong\u003E\n      \u003C\/p\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- Temel Özellikler --\u003E\n  \u003Cdiv class=\"mb-16\"\u003E\n    \u003Ch2 class=\"text-2xl md:text-3xl font-black text-[#182C61] mb-8 flex items-center gap-3\"\u003E\n      \u003Ci data-lucide=\"layers\" class=\"w-8 h-8 text-[#0f9d58]\"\u003E\u003C\/i\u003E\n      Platformun Temel Özellikleri ve Yetenekleri\n    \u003C\/h2\u003E\n\n    \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 gap-6\"\u003E\n      \u003Cdiv class=\"bg-white p-6 rounded-2xl border border-slate-200 shadow-sm hover:shadow-md transition-shadow\"\u003E\n        \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-3 flex items-center gap-2\"\u003E\n          \u003Cspan class=\"w-6 h-6 rounded bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-mono text-sm\"\u003E1\u003C\/span\u003E\n          Dinamik Finansal Modelleme\n        \u003C\/h3\u003E\n        \u003Cp class=\"text-slate-600 text-sm leading-relaxed\"\u003E\n          Online ve Yüzyüze (Face-to-Face) seansların gelirlerini ayrı ayrı hesaplar. Ofis kirasını yalnızca yüzyüze seanslara yansıtır.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"bg-white p-6 rounded-2xl border border-slate-200 shadow-sm hover:shadow-md transition-shadow\"\u003E\n        \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-3 flex items-center gap-2\"\u003E\n          \u003Cspan class=\"w-6 h-6 rounded bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-mono text-sm\"\u003E2\u003C\/span\u003E\n          Akıllı Bakım \u0026 Kira Entegrasyonu\n        \u003C\/h3\u003E\n        \u003Cp class=\"text-slate-600 text-sm leading-relaxed\"\u003E\n          Seans bazlı veya saatlik olarak değişen bakıcı (babysitter) ücretlerini ve ofis kiralama giderlerini seans saatlerine göre dinamik olarak hesaplar ve net kârdan düşer.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"bg-white p-6 rounded-2xl border border-slate-200 shadow-sm hover:shadow-md transition-shadow\"\u003E\n        \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-3 flex items-center gap-2\"\u003E\n          \u003Cspan class=\"w-6 h-6 rounded bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-mono text-sm\"\u003E3\u003C\/span\u003E\n          Takvim Senkronizasyonu (ICS)\n        \u003C\/h3\u003E\n        \u003Cp class=\"text-slate-600 text-sm leading-relaxed\"\u003E\n          Google Takvim, Outlook veya Apple Takvim gibi harici takvimlerden .ics linkleri alarak seansları otomatik aktarır. Anahtar kelimelere göre (Örn: \"Online\") seans türünü kendisi tespit eder.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"bg-white p-6 rounded-2xl border border-slate-200 shadow-sm hover:shadow-md transition-shadow\"\u003E\n        \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-3 flex items-center gap-2\"\u003E\n          \u003Cspan class=\"w-6 h-6 rounded bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-mono text-sm\"\u003E4\u003C\/span\u003E\n          Hassas Güvenlik (Çoklu Kullanıcı)\n        \u003C\/h3\u003E\n        \u003Cp class=\"text-slate-600 text-sm leading-relaxed\"\u003E\n          Firebase Firestore ile tam entegre çalışır. Ortak cihazlarda verilerin karışmasını engelleyen özel izole veri önbellekleme (User-Scoped Caching) mimarisine sahiptir.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"bg-white p-6 rounded-2xl border border-slate-200 shadow-sm hover:shadow-md transition-shadow md:col-span-2\"\u003E\n        \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-3 flex items-center gap-2\"\u003E\n          \u003Cspan class=\"w-6 h-6 rounded bg-[#0f9d58]\/10 text-[#0f9d58] flex items-center justify-center font-mono text-sm\"\u003E5\u003C\/span\u003E\n          Açıklayıcı ve Rehberlik Odaklı Arayüz\n        \u003C\/h3\u003E\n        \u003Cp class=\"text-slate-600 text-sm leading-relaxed\"\u003E\n          Her bir finansal kalemin neye göre hesaplandığını gösteren mikro açıklamalar, interaktif tanıtım turu ve göz yormayan, modern İsviçre minimalist (Swiss-Minimalist) tasarım diline sahiptir.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- En Alttaki Kutu (Beyaz Yazılı) --\u003E\n  \u003Cdiv class=\"bg-gradient-to-br from-[#182C61] to-[#111e43] rounded-[2rem] p-8 md:p-10 shadow-xl bottom-box-white relative overflow-hidden\"\u003E\n    \u003C!-- Dekoratif Arka Plan --\u003E\n    \u003Cdiv class=\"absolute top-0 right-0 w-64 h-64 bg-[#0f9d58]\/10 rounded-full blur-3xl -translate-y-1\/2 translate-x-1\/3\"\u003E\u003C\/div\u003E\n    \n    \u003Cdiv class=\"relative z-10 flex flex-col md:flex-row items-center md:items-start gap-6 text-center md:text-left\"\u003E\n      \u003Cdiv class=\"w-16 h-16 rounded-2xl bg-white\/10 flex items-center justify-center shrink-0 border border-white\/20 backdrop-blur-sm\"\u003E\n        \u003Ci data-lucide=\"bot\" class=\"w-8 h-8 text-white\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cdiv\u003E\n        \u003Ch3 class=\"text-2xl font-black mb-3\"\u003EDijital Finans Asistanınız\u003C\/h3\u003E\n        \u003Cp class=\"text-white-80 text-base leading-relaxed md:pr-8\"\u003E\n          Kısacası Psy Calcu, terapistlerin finansal hesap kitap işlerini arka planda sıfır hata ile yürütürken, onların yalnızca danışanlarına ve klinik süreçlerine odaklanmalarına imkan tanıyan dijital bir asistan rolü üstlenmektedir.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n\u003C\/div\u003E\n\n\u003C!-- Icon Init --\u003E\n\u003Cscript\u003E\n  window.addEventListener('DOMContentLoaded', () =\u003E { lucide.createIcons(); });\n\u003C\/script\u003E\n\n\u003C!-- ====================================================================================\n     PSYCALCU STİLİ YÖNLENDİRME (CTA) KART BİLEŞENİ\n     * Arka plandan ayrışan stroke\/border yapısı\n     * Tanıtım sitesine yönlendirme metinleri (Panele gitmediği vurgusu)\n     ==================================================================================== --\u003E\n\n\u003Cdiv class=\"max-w-4xl mx-auto my-16 px-4 md:px-6 font-sans antialiased\" style=\"font-family: 'Inter', sans-serif;\"\u003E\n  \n  \u003C!-- Tailwind CSS \u0026 Lucide Icons CDN --\u003E\n  \u003Clink href=\"https:\/\/cdn.jsdelivr.net\/npm\/tailwindcss@2.2.19\/dist\/tailwind.min.css\" rel=\"stylesheet\"\u003E\n  \u003Clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700;800\u0026display=swap\" rel=\"stylesheet\"\u003E\n  \u003Cscript src=\"https:\/\/unpkg.com\/lucide@latest\"\u003E\u003C\/script\u003E\n\n  \u003Cstyle\u003E\n    \/* Toprak\/Bronz Gradyan Metin Efekti *\/\n    .text-gradient-earth {\n      background-clip: text;\n      -webkit-background-clip: text;\n      -webkit-text-fill-color: transparent;\n      background-image: linear-gradient(90deg, #8B7355 0%, #C19A6B 100%);\n    }\n    \n    \/* Yüzen Element Animasyonları *\/\n    @keyframes float-card {\n      0% { transform: translateY(0px) rotate(0deg); }\n      50% { transform: translateY(-10px) rotate(2deg); }\n      100% { transform: translateY(0px) rotate(0deg); }\n    }\n    @keyframes float-card-alt {\n      0% { transform: translateY(0px) rotate(0deg); }\n      50% { transform: translateY(-12px) rotate(-3deg); }\n      100% { transform: translateY(0px) rotate(0deg); }\n    }\n    .animate-float-card { animation: float-card 5s ease-in-out infinite; }\n    .animate-float-card-alt { animation: float-card-alt 6s ease-in-out infinite; animation-delay: 1.5s; }\n  \u003C\/style\u003E\n\n  \u003C!-- CTA KART KONTEYNERİ (Arka plandan ayrışan kutu yapısı) --\u003E\n  \u003Cdiv class=\"relative bg-white rounded-[2.5rem] p-8 md:p-14 text-center border-2 border-[#e8dfd5] shadow-[0_20px_60px_-15px_rgba(0,0,0,0.05)] overflow-hidden\"\u003E\n    \n    \u003C!-- Kart İçi Dekoratif Arka Plan (Çok hafif krem radial geçiş) --\u003E\n    \u003Cdiv class=\"absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-[#fbf9f6] via-white to-white opacity-80 pointer-events-none\"\u003E\u003C\/div\u003E\n\n    \u003C!-- Dekoratif Yüzen Semboller (Kartın içinde köşelere yakın) --\u003E\n    \u003Cdiv class=\"absolute top-8 left-8 hidden md:flex w-16 h-16 bg-[#f4ece3] rounded-[1.25rem] items-center justify-center animate-float-card shadow-sm border border-[#e8dfd5]\/60 z-0\"\u003E\n      \u003Cspan class=\"text-[#a8866d] text-2xl font-serif\"\u003EΨ\u003C\/span\u003E\n    \u003C\/div\u003E\n    \u003Cdiv class=\"absolute bottom-8 right-8 hidden md:flex w-16 h-16 bg-[#e8efe9] rounded-[1.25rem] items-center justify-center animate-float-card-alt shadow-sm border border-[#d5e2d7]\/60 z-0\"\u003E\n      \u003Cspan class=\"text-[#5a7d61] text-2xl font-semibold\"\u003E₺\u003C\/span\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- İçerik --\u003E\n    \u003Cdiv class=\"relative z-10 flex flex-col items-center\"\u003E\n      \n      \u003C!-- Kategori\/Bilgi Etiketi --\u003E\n      \u003Cdiv class=\"inline-flex items-center gap-2 bg-[#f9f8f6] px-4 py-2 rounded-full border border-[#e8dfd5] shadow-sm mb-6\"\u003E\n        \u003Cdiv class=\"relative flex h-2 w-2\"\u003E\n          \u003Cspan class=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75\"\u003E\u003C\/span\u003E\n          \u003Cspan class=\"relative inline-flex rounded-full h-2 w-2 bg-amber-500\"\u003E\u003C\/span\u003E\n        \u003C\/div\u003E\n        \u003Cspan class=\"text-[10px] md:text-xs font-extrabold text-[#7a6855] uppercase tracking-widest\"\u003E\n          DETAYLI BİLGİ \u0026 TANITIM\n        \u003C\/span\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Ana Başlık --\u003E\n      \u003Ch2 class=\"text-3xl md:text-4xl lg:text-5xl font-extrabold text-[#111827] tracking-tight leading-[1.2] mb-5\"\u003E\n        PsyCalcu Hakkında \u003Cbr class=\"hidden sm:block\"\u003E\n        \u003Cspan class=\"text-gradient-earth\"\u003EDaha Fazlasını Keşfedin\u003C\/span\u003E\n      \u003C\/h2\u003E\n\n      \u003C!-- Açıklama Metni (Özellikle Panele gitmediği belirtiliyor) --\u003E\n      \u003Cdiv class=\"bg-blue-50\/50 border border-blue-100\/50 rounded-2xl p-5 mb-8 max-w-2xl mx-auto\"\u003E\n        \u003Cp class=\"text-sm md:text-base text-gray-600 leading-relaxed font-medium\"\u003E\n          Sistemin tüm özelliklerini, sunduğu avantajları ve çalışma mantığını detaylıca incelemek için resmi tanıtım sitemize göz atın.\n        \u003C\/p\u003E\n        \u003Cp class=\"text-[13px] text-blue-800 font-semibold mt-2 flex items-center justify-center gap-1.5\"\u003E\n          \u003Ci data-lucide=\"info\" class=\"w-4 h-4\"\u003E\u003C\/i\u003E\n          Not: Bu bağlantı yönetim paneline (uygulamaya) değil, projenin tanıtım sayfasına yönlendirir.\n        \u003C\/p\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Buton Aksiyonu --\u003E\n      \u003Cdiv class=\"flex justify-center w-full\"\u003E\n        \u003Ca href=\"https:\/\/psy-calcu.blogspot.com\/\" target=\"_blank\" rel=\"noopener noreferrer\" \n           class=\"group flex items-center justify-center gap-3 bg-[#0f172a] hover:bg-[#1e293b] text-white px-8 py-4 rounded-full font-bold text-base transition-all duration-300 shadow-[0_10px_20px_rgba(15,23,42,0.15)] hover:shadow-[0_15px_30px_rgba(15,23,42,0.25)] hover:-translate-y-1 w-full sm:w-auto\"\u003E\n          \u003Cspan\u003ETanıtım Sitesine Git\u003C\/span\u003E\n          \u003Cdiv class=\"bg-white\/10 p-1.5 rounded-full transition-transform duration-300 group-hover:translate-x-1\"\u003E\n            \u003Ci data-lucide=\"arrow-right\" class=\"w-4 h-4 text-white\"\u003E\u003C\/i\u003E\n          \u003C\/div\u003E\n        \u003C\/a\u003E\n      \u003C\/div\u003E\n      \n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- İkonları Başlat --\u003E\n  \u003Cscript\u003E\n    if (typeof lucide !== 'undefined') {\n      lucide.createIcons();\n    }\n  \u003C\/script\u003E\n\u003C\/div\u003E"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/1168791712501861016"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/1168791712501861016"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/07\/psy-calcu-nedir.html","title":"Psy Calcu Nedir?"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}]},{"id":{"$t":"tag:blogger.com,1999:blog-6723758798785343725.post-240465725954351231"},"published":{"$t":"2026-07-11T00:14:28.095+03:00"},"updated":{"$t":"2026-07-11T21:54:35.810+03:00"},"category":[{"scheme":"http://www.blogger.com/atom/ns#","term":"Bildirim Entegrasyonu"}],"title":{"type":"text","$t":"E-Tablo \u0026 Firebase Entegrasyonu Bildirim Yönetim Kılavuzu"},"content":{"type":"html","$t":"\u003Cdiv style=\"display: none;\"\u003E\n  \u003Cimg src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEiEiL9FS2Qu6d5j_5fEppwZmworExjejYl9iwjR3u5R7fhSJPFLLS_mr5ALeskdleGoEifYzmGYs9AeeklWeHIpul2S9pKIWaeeaEfLicMHvY_MKX41IDV_iF-HvAo19YRsm3fi5HFbqxJGbNbvtYTV3Lld2AMsnMIuHQoMP4vm6B6f0C4hdf6_WKJ8ppOg\/s1600\/IMG_6349.jpeg\" alt=\"Paylaşım Görseli\" \/\u003E\n\u003C\/div\u003E\n\n\u003C!--\n  ====================================================================================\n  GOOGLE E-TABLO \u0026 FIREBASE FCM V1 BİLDİRİM SİSTEMİ - BLOGGER HTML YAYIN KODU\n  ====================================================================================\n  Bu kod Muhammed Akif Kayacan'ın geliştirdiği sistem kılavuzunu içerir.\n  \n  Nasıl Kullanılır:\n  1. Blogger panelinizde \"Yeni Yayın\" oluşturun.\n  2. Sol üstteki kalem simgesine tıklayıp \"HTML Görünümü\"ne (HTML View) geçin.\n  3. Bu dosyanın tüm içeriğini oraya yapıştırın ve \"Yayınla\" deyin.\n  ====================================================================================\n--\u003E\n\n\u003Cdiv id=\"fcm-guide-container\" class=\"max-w-7xl mx-auto px-4 md:px-6 py-12 font-sans antialiased text-slate-800 bg-[#f8fafc]\"\u003E\n  \u003C!-- Tailwind CSS \u0026 Lucide Icons CDN --\u003E\n  \u003Clink href=\"https:\/\/cdn.jsdelivr.net\/npm\/tailwindcss@2.2.19\/dist\/tailwind.min.css\" rel=\"stylesheet\"\u003E\n  \u003Clink href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@300;400;500;600;700;800\u0026family=Space+Grotesk:wght@500;700\u0026family=JetBrains+Mono:wght@400;500\u0026display=swap\" rel=\"stylesheet\"\u003E\n  \u003Cscript src=\"https:\/\/unpkg.com\/lucide@latest\"\u003E\u003C\/script\u003E\n\n  \u003Cstyle\u003E\n    #fcm-guide-container {\n      font-family: 'Inter', sans-serif;\n    }\n    #fcm-guide-container h1, #fcm-guide-container h2, #fcm-guide-container h3 {\n      font-family: 'Space Grotesk', sans-serif;\n    }\n    #fcm-guide-container .font-mono {\n      font-family: 'JetBrains Mono', monospace;\n    }\n    #fcm-guide-container .scrollbar-thin::-webkit-scrollbar {\n      width: 6px;\n      height: 6px;\n    }\n    #fcm-guide-container .scrollbar-thin::-webkit-scrollbar-track {\n      background: #f1f5f9;\n    }\n    #fcm-guide-container .scrollbar-thin::-webkit-scrollbar-thumb {\n      background: #cbd5e1;\n      border-radius: 3px;\n    }\n    @keyframes pulse-slow {\n      0%, 100% { opacity: 1; }\n      50% { opacity: .6; }\n    }\n    .animate-pulse-slow {\n      animation: pulse-slow 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n    }\n\n    \/* Prevent Blogger theme overrides and preserve correct colors and layout *\/\n    #fcm-guide-container h1,\n    #fcm-guide-container h2,\n    #fcm-guide-container h3,\n    #fcm-guide-container h4,\n    #fcm-guide-container h5,\n    #fcm-guide-container p,\n    #fcm-guide-container span,\n    #fcm-guide-container div,\n    #fcm-guide-container th,\n    #fcm-guide-container td {\n      box-sizing: border-box;\n    }\n    #fcm-guide-container h1 { color: #182C61 !important; }\n    #fcm-guide-container h2 { color: #182C61 !important; }\n    #fcm-guide-container h3 { color: #182C61 !important; }\n    #fcm-guide-container h4 { color: #182C61 !important; }\n    #fcm-guide-container p.text-slate-500, #fcm-guide-container .text-slate-500 { color: #64748b !important; }\n    #fcm-guide-container p.text-slate-600, #fcm-guide-container .text-slate-600 { color: #475569 !important; }\n    #fcm-guide-container p.text-slate-700, #fcm-guide-container .text-slate-700 { color: #334155 !important; }\n    \n    \/* Green Header Text Contrast Fix *\/\n    #fcm-guide-container .bg-\\[\\#0f9d58\\] h3 { color: #ffffff !important; }\n    #fcm-guide-container .bg-\\[\\#0f9d58\\] p { color: rgba(255, 255, 255, 0.85) !important; }\n    #fcm-guide-container .text-white { color: #ffffff !important; }\n    #fcm-guide-container .text-white\\\/80 { color: rgba(255, 255, 255, 0.8) !important; }\n\n    \/* Success Banner Override to prevent Blogger theme dark text color overrides *\/\n    #fcm-guide-container #fcm-success-banner {\n      background: linear-gradient(135deg, #0f9d58 0%, #059669 50%, #182C61 100%) !important;\n    }\n    #fcm-guide-container #fcm-success-banner h3 {\n      color: #ffffff !important;\n    }\n    #fcm-guide-container #fcm-success-banner p {\n      color: rgba(255, 255, 255, 0.9) !important;\n    }\n    #fcm-guide-container #fcm-success-banner span {\n      color: #ffffff !important;\n    }\n    #fcm-guide-container #fcm-success-banner .text-emerald-300 {\n      color: #a7f3d0 !important;\n    }\n    #fcm-guide-container #fcm-success-banner .bg-white\\\/15 {\n      background-color: rgba(255, 255, 255, 0.15) !important;\n    }\n    #fcm-guide-container #fcm-success-banner .border-white\\\/25 {\n      border-color: rgba(255, 255, 255, 0.25) !important;\n    }\n    #fcm-guide-container #fcm-success-banner .bg-emerald-500\\\/20 {\n      background-color: rgba(16, 185, 129, 0.2) !important;\n    }\n    #fcm-guide-container #fcm-success-banner .border-emerald-500\\\/30 {\n      border-color: rgba(16, 185, 129, 0.3) !important;\n    }\n  \u003C\/style\u003E\n\n  \u003C!-- Title \u0026 Intro --\u003E\n  \u003Cdiv class=\"text-center max-w-3xl mx-auto mb-16\"\u003E\n\n    \u003Cp class=\"text-slate-600 text-base md:text-lg leading-relaxed\"\u003E\n      Google E-Tablolar (Sheets) üzerinden anlık ve resimli push bildirimlerinizi yönetmek, Apps Script zaman ayarlı otomatik gönderim alt yapısını kurmak için hazırlanan etkileşimli teknik mimari kılavuzudur.\n    \u003C\/p\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- Quick Stats Grid --\u003E\n  \u003Cdiv class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-16\"\u003E\n    \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-100 shadow-sm flex flex-col items-start gap-3.5 hover:shadow-md transition-all\"\u003E\n      \u003Cdiv class=\"w-10 h-10 rounded-xl bg-indigo-50 text-[#182C61] flex items-center justify-center shrink-0\"\u003E\n        \u003Ci data-lucide=\"layers\" class=\"w-5 h-5\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cdiv\u003E\n        \u003Ch4 class=\"text-sm font-extrabold text-[#182C61] leading-tight mb-1\"\u003EMimarî Yapı\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-500 leading-relaxed\"\u003EÇift sekme entegrasyonu\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n    \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-100 shadow-sm flex flex-col items-start gap-3.5 hover:shadow-md transition-all\"\u003E\n      \u003Cdiv class=\"w-10 h-10 rounded-xl bg-emerald-50 text-emerald-600 flex items-center justify-center shrink-0\"\u003E\n        \u003Ci data-lucide=\"clock\" class=\"w-5 h-5\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cdiv\u003E\n        \u003Ch4 class=\"text-sm font-extrabold text-[#182C61] leading-tight mb-1\"\u003EZamanlayıcılar\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-500 leading-relaxed\"\u003E15 dk hassas tetikleme\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n    \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-100 shadow-sm flex flex-col items-start gap-3.5 hover:shadow-md transition-all\"\u003E\n      \u003Cdiv class=\"w-10 h-10 rounded-xl bg-amber-50 text-amber-600 flex items-center justify-center shrink-0\"\u003E\n        \u003Ci data-lucide=\"shield-check\" class=\"w-5 h-5\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cdiv\u003E\n        \u003Ch4 class=\"text-sm font-extrabold text-[#182C61] leading-tight mb-1\"\u003EFCM v1 Güvenliği\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-500 leading-relaxed\"\u003EJWT OAuth2 imzalama\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n    \u003Cdiv class=\"bg-white p-5 rounded-2xl border border-slate-100 shadow-sm flex flex-col items-start gap-3.5 hover:shadow-md transition-all\"\u003E\n      \u003Cdiv class=\"w-10 h-10 rounded-xl bg-rose-50 text-rose-600 flex items-center justify-center shrink-0\"\u003E\n        \u003Ci data-lucide=\"zap\" class=\"w-5 h-5\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cdiv\u003E\n        \u003Ch4 class=\"text-sm font-extrabold text-[#182C61] leading-tight mb-1\"\u003EOtomasyon\u003C\/h4\u003E\n        \u003Cp class=\"text-xs text-slate-500 leading-relaxed\"\u003EMükerrer gönderim engeli\u003C\/p\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- Sistem Nedir? (Tanım Paragrafı) --\u003E\n  \u003Cdiv class=\"max-w-4xl mx-auto mb-16 animate-fade-in\" style=\"animation-delay: 25ms;\"\u003E\n      \u003Ch2 class=\"text-2xl md:text-3xl font-extrabold text-[#182C61] mb-4\"\u003EBu Sistem Tam Olarak Nedir?\u003C\/h2\u003E\n      \u003Cp class=\"text-slate-600 text-sm md:text-base leading-relaxed\"\u003E\n          Uygulamanıza bildirim gönderme sürecini karmaşık sunucu kodlarından ve panellerinden kurtarıp, herkesin bildiği Google E-Tablolar (Excel) arayüzüne taşıyan tam otomatik bir altyapıdır. Sisteme entegre edilen özel bir Apps Script kodu, tablonuza yazdığınız gün, saat, başlık ve mesajları saniyesi saniyesine takip eder. Vakti gelen mesajı alır ve Firebase (FCM v1) üzerinden doğrudan kullanıcılarınızın telefonuna \u003Cstrong\u003Eresimli bir anlık bildirim (Push Notification)\u003C\/strong\u003E olarak yollar. Kısacası; siz sadece Excel doldurursunuz, gerisini sistem kendi kendine halleder.\n      \u003C\/p\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- Sistemin Avantajları (Neden Bu Sistem?) --\u003E\n  \u003Cdiv class=\"max-w-4xl mx-auto mb-16 animate-fade-in\" style=\"animation-delay: 50ms;\"\u003E\n      \u003Ch2 class=\"text-2xl md:text-3xl font-extrabold text-[#182C61] mb-6\"\u003ESistemin Amacı ve En Büyük Avantajları\u003C\/h2\u003E\n      \n      \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 gap-8\"\u003E\n          \u003C!-- Avantaj 1 --\u003E\n          \u003Cdiv\u003E\n              \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-2 flex items-center gap-2\"\u003E\n                  \u003Cspan class=\"w-2 h-2 rounded-full bg-indigo-600\"\u003E\u003C\/span\u003E\n                  Firebase Konsol Derdine Son\n              \u003C\/h3\u003E\n              \u003Cp class=\"text-sm md:text-base text-slate-600 leading-relaxed\"\u003E\n                  Her bildirim atmak istediğinizde Firebase paneline giriş yapıp karmaşık menüler arasında kaybolmanıza gerek yok. Çok daha pratik ve kullanışlı olan \u003Cstrong\u003EGoogle E-Tablolar (Excel)\u003C\/strong\u003E arayüzünden tüm bildirimleri saniyeler içinde planlayın ve yönetin.\n              \u003C\/p\u003E\n          \u003C\/div\u003E\n          \n          \u003C!-- Avantaj 2 --\u003E\n          \u003Cdiv\u003E\n              \u003Ch3 class=\"text-lg font-bold text-[#182C61] mb-2 flex items-center gap-2\"\u003E\n                  \u003Cspan class=\"w-2 h-2 rounded-full bg-emerald-600\"\u003E\u003C\/span\u003E\n                  Uyuyan Kullanıcıları Geri Kazanın\n              \u003C\/h3\u003E\n              \u003Cp class=\"text-sm md:text-base text-slate-600 leading-relaxed\"\u003E\n                  Uygulamanızı indirip çok ilgisini çekmediği için kenara atan veya girmeyi unutan kullanıcılar için otomasyon kurun. Siz hiçbir şey yapmasanız bile \u003Cstrong\u003Euygulamanız kendi kendini hatırlatır\u003C\/strong\u003E ve aktif kullanıcı (retention) oranınızı canlı tutar.\n              \u003C\/p\u003E\n          \u003C\/div\u003E\n      \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C!-- BÖLÜM 1 WRAPPER --\u003E\n  \u003Cdiv class=\"relative\"\u003E\n    \u003C!-- Geniş ekranlar için sol kenarda asılı duran (floating) Bölüm Göstergesi (Sticky ile birlikte hareket eder) --\u003E\n    \u003Cdiv class=\"hidden lg:flex absolute -left-28 top-0 h-full w-24 pointer-events-none\"\u003E\n      \u003Cdiv class=\"sticky top-32 z-40 bg-[#182C61] text-white rounded-full w-24 h-24 flex flex-col items-center justify-center shadow-xl border-4 border-[#f8fafc] hover:scale-105 transition-transform duration-300 pointer-events-auto\"\u003E\n        \u003Cspan class=\"text-[10px] font-black uppercase tracking-widest text-slate-300 leading-none\"\u003EBÖLÜM\u003C\/span\u003E\n        \u003Cspan class=\"text-4xl font-extrabold font-mono leading-none my-1\"\u003E01\u003C\/span\u003E\n        \u003Ci data-lucide=\"play\" class=\"w-5 h-5 text-emerald-400 animate-pulse\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- BÖLÜM 1 BAŞLIĞI --\u003E\n    \u003Cdiv class=\"my-8 py-4 px-4 md:px-6 bg-[#182C61] border border-[#111e43] rounded-2xl shadow-lg flex items-center gap-3 relative\"\u003E\n      \u003C!-- Mobil için Bölüm Göstergesi (lg:hidden) --\u003E\n      \u003Cspan class=\"lg:hidden px-3 py-1 bg-emerald-500\/15 text-emerald-300 border border-emerald-500\/20 text-[11px] font-black uppercase tracking-widest rounded-lg shadow-sm flex items-center gap-1.5 shrink-0\"\u003E\n        \u003Ci data-lucide=\"play\" class=\"w-3.5 h-3.5 text-emerald-400\"\u003E\u003C\/i\u003E BÖLÜM 1\n      \u003C\/span\u003E\n      \u003Ch2 class=\"text-base md:text-lg lg:text-xl font-black text-white tracking-tight leading-none\"\u003E\n        Kurulum ve Yapılandırma Adımları\n      \u003C\/h2\u003E\n    \u003C\/div\u003E\n  \u003Cp class=\"text-slate-600 text-sm md:text-base leading-relaxed max-w-4xl mb-10 pl-2\"\u003E\n    Sistemin kusursuz çalışması için Google E-Tablo entegrasyonunu, Apps Script kod yüklemesini, dakikalık otomatik tetikleyiciyi ve mobil\/Firebase ayarlarını bu sırayla tamamlayın.\n  \u003C\/p\u003E\n\n  \u003C!-- SECTION 1: DATABASE STRUCTURE --\u003E\n  \u003Csection class=\"mb-16\"\u003E\n    \u003Ch2 class=\"text-2xl md:text-3xl font-bold mb-6 text-[#182C61] flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-10 h-10 rounded-2xl bg-[#182C61]\/5 flex items-center justify-center text-[#182C61] text-lg font-black font-mono\"\u003E01\u003C\/span\u003E\n      E-Tablo Veri Tabanı Mimarisi (Adım 1)\n    \u003C\/h2\u003E\n    \u003Cp class=\"text-slate-600 text-sm md:text-base mb-8 leading-relaxed\"\u003E\n      Sistemin kararlı çalışması için Google E-Tablonuzda mutlaka \u003Cstrong\u003E\"Sürekli\"\u003C\/strong\u003E ve \u003Cstrong\u003E\"TekSeferlik\"\u003C\/strong\u003E adlarında iki ayrı sekme bulunmalıdır. Kolon harfleri ve adları sistem tarafından birebir okunmaktadır. Aşağıdaki etkileşimli tablodan sütunları inceleyebilirsiniz.\n    \u003C\/p\u003E\n\n    \u003C!-- Sheet Switcher --\u003E\n    \u003Cdiv class=\"mb-6 bg-slate-100 p-2 rounded-2xl inline-flex gap-2\"\u003E\n      \u003Cbutton id=\"tab-surekli-btn\" onclick=\"switchSheetTab('surekli')\" class=\"px-5 py-2.5 rounded-xl font-bold text-sm transition-all bg-white text-[#182C61] shadow-sm border border-slate-200\"\u003E\n        Sayfa 1: Sürekli (Haftalık Döngü)\n      \u003C\/button\u003E\n      \u003Cbutton id=\"tab-tekSeferlik-btn\" onclick=\"switchSheetTab('tekSeferlik')\" class=\"px-5 py-2.5 rounded-xl font-bold text-sm transition-all text-slate-600 hover:text-[#182C61] hover:bg-white\/50\"\u003E\n        Sayfa 2: TekSeferlik\n      \u003C\/button\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- Spreadsheet UI Box --\u003E\n    \u003Cdiv class=\"border border-slate-200 rounded-3xl overflow-hidden bg-white shadow-lg mb-8\"\u003E\n      \u003C!-- Google Sheets Header --\u003E\n      \u003Cdiv class=\"bg-[#0f9d58] px-6 py-4 flex flex-col sm:flex-row sm:items-center justify-between gap-4 text-white\"\u003E\n        \u003Cdiv class=\"flex items-center gap-3\"\u003E\n          \u003Ci data-lucide=\"file-spreadsheet\" class=\"text-white w-6 h-6\"\u003E\u003C\/i\u003E\n          \u003Cdiv\u003E\n            \u003Ch3 class=\"font-bold text-sm md:text-base leading-none mb-1\"\u003EE-Tablo Veri Mimarisi Önizlemesi\u003C\/h3\u003E\n            \u003Cp class=\"text-xs text-white\/80\"\u003EGoogle E-Tablolar Sayfa Formatı (Gerçek Görünüm)\u003C\/p\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"flex items-center gap-2\"\u003E\n          \u003Cspan id=\"sheet-label\" class=\"text-[10px] uppercase font-mono tracking-widest bg-white\/20 px-2.5 py-1 rounded-md font-bold\"\u003E\n            Sürekli Sekmesi\n          \u003C\/span\u003E\n          \u003Cspan class=\"text-[10px] bg-yellow-400 text-slate-950 px-2.5 py-1 rounded-md font-extrabold animate-pulse-slow\"\u003E\n            SÜTUNLARA TIKLAYIN\n          \u003C\/span\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Faux Menu --\u003E\n      \u003Cdiv class=\"bg-slate-50 border-b border-slate-200 px-4 py-2 flex items-center gap-3 text-xs text-slate-600 select-none overflow-x-auto\"\u003E\n        \u003Cspan class=\"font-medium\"\u003EDosya\u003C\/span\u003E\n        \u003Cspan class=\"font-medium\"\u003EDüzenle\u003C\/span\u003E\n        \u003Cspan class=\"font-medium\"\u003EGörünüm\u003C\/span\u003E\n        \u003Cspan class=\"font-medium\"\u003EEkle\u003C\/span\u003E\n        \u003Cspan class=\"font-medium\"\u003EBiçim\u003C\/span\u003E\n        \u003Cspan class=\"font-medium\"\u003EVeri\u003C\/span\u003E\n        \u003Cspan class=\"font-medium\"\u003EAraçlar\u003C\/span\u003E\n        \u003Cdiv class=\"h-4 w-[1px] bg-slate-300 mx-1\"\u003E\u003C\/div\u003E\n        \u003Cspan class=\"font-bold\"\u003EB\u003C\/span\u003E\n        \u003Cspan class=\"italic font-serif\"\u003EI\u003C\/span\u003E\n        \u003Cspan class=\"line-through\"\u003ES\u003C\/span\u003E\n        \u003Cspan class=\"text-emerald-600 font-bold\"\u003E田\u003C\/span\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Formula Bar --\u003E\n      \u003Cdiv class=\"bg-white border-b border-slate-200 px-4 py-2 flex items-center gap-2 font-mono text-xs text-slate-700\"\u003E\n        \u003Cdiv id=\"formula-col-id\" class=\"bg-slate-100 border border-slate-300 rounded px-3 py-1 font-bold text-center text-[#182C61]\/80 min-w-[50px] shadow-sm\"\u003E\n          A\n        \u003C\/div\u003E\n        \u003Cdiv class=\"text-slate-400 font-serif font-black italic text-sm pr-1 border-r border-slate-200 h-4 flex items-center\"\u003Efx\u003C\/div\u003E\n        \u003Cdiv id=\"formula-bar-text\" class=\"flex-1 overflow-hidden truncate pl-1 text-slate-800\"\u003E\n          =VERİ_TİPİ(\u003Cstrong\u003EDüz Metin (Metin)\u003C\/strong\u003E) — Değer: \"\u003Cspan class=\"text-emerald-600 font-bold\"\u003EPazartesi\u003C\/span\u003E\"\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Grid wrapper --\u003E\n      \u003Cdiv class=\"overflow-x-auto scrollbar-thin\"\u003E\n        \u003Ctable class=\"w-full text-left border-collapse font-sans text-xs md:text-sm table-fixed min-w-[1100px]\"\u003E\n          \u003Cthead\u003E\n            \u003Ctr id=\"grid-header-row\" class=\"bg-slate-100 text-[#182C61]\/70 select-none border-b border-slate-200 text-center font-bold\"\u003E\n              \u003Cth class=\"p-2 border-r border-b border-slate-200 bg-slate-200 text-center w-12 font-mono text-[10px]\"\u003E#\u003C\/th\u003E\n              \u003C!-- Dynamically populated --\u003E\n            \u003C\/tr\u003E\n          \u003C\/thead\u003E\n          \u003Ctbody\u003E\n            \u003C!-- Row 1: Headers --\u003E\n            \u003Ctr id=\"grid-row-1\" class=\"bg-white border-b border-slate-200 select-none\"\u003E\n              \u003Ctd class=\"p-2 border-r border-slate-200 bg-slate-100 text-center font-bold text-slate-500 text-xs\"\u003E1\u003C\/td\u003E\n              \u003C!-- Dynamically populated --\u003E\n            \u003C\/tr\u003E\n            \u003C!-- Row 2: Sample 1 --\u003E\n            \u003Ctr id=\"grid-row-2\" class=\"bg-white border-b border-slate-200\"\u003E\n              \u003Ctd class=\"p-2 border-r border-slate-200 bg-slate-100 text-center font-bold text-slate-500 text-xs\"\u003E2\u003C\/td\u003E\n              \u003C!-- Dynamically populated --\u003E\n            \u003C\/tr\u003E\n            \u003C!-- Row 3: Sample 2 --\u003E\n            \u003Ctr id=\"grid-row-3\" class=\"bg-white\"\u003E\n              \u003Ctd class=\"p-2 border-r border-slate-200 bg-slate-100 text-center font-bold text-slate-500 text-xs\"\u003E3\u003C\/td\u003E\n              \u003C!-- Dynamically populated --\u003E\n            \u003C\/tr\u003E\n          \u003C\/tbody\u003E\n        \u003C\/table\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- Column Detail Panel --\u003E\n    \u003Cdiv class=\"bg-gradient-to-r from-slate-50 to-slate-100 rounded-3xl p-6 md:p-8 border border-slate-200 shadow-md\"\u003E\n      \u003Cdiv class=\"flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6 border-b border-slate-200 pb-4\"\u003E\n        \u003Cdiv class=\"flex items-center gap-3\"\u003E\n          \u003Cdiv id=\"detail-badge\" class=\"w-12 h-12 rounded-2xl bg-emerald-600 text-white flex items-center justify-center font-mono font-black text-xl shadow-md\"\u003E\n            A\n          \u003C\/div\u003E\n          \u003Cdiv\u003E\n            \u003Ch4 id=\"detail-title\" class=\"text-lg font-extrabold text-slate-900 leading-none\"\u003E\n              Sütun A: Gün\n            \u003C\/h4\u003E\n            \u003Cp class=\"text-xs text-slate-500 mt-1\"\u003EE-Tablo kolon gereksinimleri ve yazılım entegrasyon kuralları\u003C\/p\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n\n        \u003Cdiv class=\"flex gap-2 flex-wrap text-xs\"\u003E\n          \u003Cspan id=\"detail-type\" class=\"px-3 py-1 rounded-full bg-slate-200 text-slate-700 font-bold\"\u003E\n            Tip: Düz Metin (Metin)\n          \u003C\/span\u003E\n          \u003Cspan id=\"detail-req\" class=\"px-3 py-1 rounded-full font-black uppercase tracking-wider bg-rose-100 text-rose-700\"\u003E\n            Zorunlu\n          \u003C\/span\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-12 gap-6\"\u003E\n        \u003Cdiv class=\"md:col-span-8\"\u003E\n          \u003Ch5 class=\"text-sm font-bold text-slate-800 mb-2\"\u003ESütun İşlevi ve Görevi:\u003C\/h5\u003E\n          \u003Cp id=\"detail-desc\" class=\"text-slate-700 text-sm md:text-base leading-relaxed bg-white p-4 rounded-2xl border border-slate-200 shadow-sm\"\u003E\n            Bildirimin haftalık hangi gün gideceği (Düz Metin olarak kaydedilir). Örn: \"Pazartesi\", \"Salı\" vb.\n          \u003C\/p\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"md:col-span-4 flex flex-col justify-between\"\u003E\n          \u003Cdiv\u003E\n            \u003Ch5 class=\"text-sm font-bold text-slate-800 mb-2\"\u003EÖrnek Hücre Değeri:\u003C\/h5\u003E\n            \u003Cdiv id=\"detail-sample\" class=\"bg-slate-950 text-emerald-400 p-4 rounded-2xl font-mono text-sm border border-slate-800 shadow-inner flex items-center justify-center min-h-[60px]\"\u003E\n              \"Pazartesi\"\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"mt-4 bg-emerald-50\/50 p-4 rounded-2xl border border-emerald-100 text-emerald-800 text-xs\"\u003E\n            \u003Cstrong\u003Eİpucu:\u003C\/strong\u003E Sütunun harf adı, Apps Script kodunun hücreleri hatasız okuması için birebir korunmalıdır. Sütunların yerini değiştirmeyiniz.\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- SECTION 2: APPS SCRIPT CODE (ADIM 2) --\u003E\n  \u003Csection class=\"mb-16\"\u003E\n    \u003Ch2 class=\"text-2xl md:text-3xl font-bold mb-6 text-[#182C61] flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-10 h-10 rounded-2xl bg-[#182C61]\/5 flex items-center justify-center text-[#182C61] text-lg font-black font-mono\"\u003E02\u003C\/span\u003E\n      Apps Script (Kod) Kurulumu (Adım 2)\n    \u003C\/h2\u003E\n    \u003Cp class=\"text-slate-600 text-sm md:text-base mb-8 leading-relaxed\"\u003E\n      E-Tablonuz ile Firebase arasında köprü görevi görecek olan Apps Script kodunun kurulumu için aşağıdaki adımları sırasıyla takip edin:\n    \u003C\/p\u003E\n    \u003Cdiv class=\"bg-slate-50 p-6 rounded-3xl border border-slate-200\/60 mb-6 text-sm md:text-base leading-relaxed\"\u003E\n      \u003Col class=\"list-decimal list-inside space-y-3 text-slate-700\"\u003E\n        \u003Cli\u003EGoogle E-Tablonuzda üst menüden \u003Cstrong\u003EUzantılar \u003E Apps Script\u003C\/strong\u003E seçeneğine tıklayın.\u003C\/li\u003E\n        \u003Cli\u003EVarsayılan kodların tamamını silip aşağıdaki kararlı \u003Cstrong\u003EGoogle Apps Script\u003C\/strong\u003E kodunu yapıştırın.\u003C\/li\u003E\n        \u003Cli\u003EKoddaki \u003Ccode\u003EFIREBASE_CONFIG\u003C\/code\u003E nesnesini kendi Firebase Service Account JSON dosyası bilgilerinizle doldurun.\u003C\/li\u003E\n      \u003C\/ol\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- Code Block Display --\u003E\n    \u003Cdiv class=\"border border-slate-200 rounded-3xl overflow-hidden shadow-md\"\u003E\n      \u003Cdiv class=\"bg-slate-900 px-6 py-4 flex items-center justify-between text-white\"\u003E\n        \u003Cdiv class=\"flex items-center gap-2\"\u003E\n          \u003Ci data-lucide=\"file-code\" class=\"text-amber-400 w-5 h-5\"\u003E\u003C\/i\u003E\n          \u003Cspan class=\"font-mono text-xs md:text-sm\"\u003Efcm-kod.gs (Apps Script)\u003C\/span\u003E\n        \u003C\/div\u003E\n        \u003Cbutton onclick=\"copyAppsScriptCode()\" class=\"px-3.5 py-1.5 bg-white\/10 hover:bg-white\/20 active:bg-white\/30 rounded-xl font-bold text-xs transition-all flex items-center gap-1.5 cursor-pointer\"\u003E\n          \u003Cspan id=\"copy-btn-text\"\u003EKopyala\u003C\/span\u003E\n        \u003C\/button\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"bg-slate-950 p-6 overflow-x-auto max-h-[400px] scrollbar-thin\"\u003E\n        \u003Cpre class=\"text-xs md:text-sm text-emerald-400 font-mono leading-relaxed\" id=\"code-block-pre\"\u003E\n\/* Kod kopyalandığında Apps Script'e yapıştırmaya hazırdır *\/\n        \u003C\/pre\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- SECTION 3: AUTOMATION TRIGGER SETUP (ADIM 3) --\u003E\n  \u003Csection class=\"mb-16\"\u003E\n    \u003Ch2 class=\"text-2xl md:text-3xl font-bold mb-6 text-[#182C61] flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-10 h-10 rounded-2xl bg-[#182C61]\/5 flex items-center justify-center text-[#182C61] text-lg font-black font-mono\"\u003E03\u003C\/span\u003E\n      ADIM 3: Otomasyonu Başlatma (Tetikleyici Ayarları)\n    \u003C\/h2\u003E\n    \u003Cp class=\"text-slate-600 text-sm md:text-base mb-8 leading-relaxed\"\u003E\n      Kodun tablodaki saatleri sürekli kontrol etmesi için bir tetikleyici (Trigger) kurmalıyız. Kodda \u003Cstrong\u003E±2 dakikalık\u003C\/strong\u003E tolerans payı ayarlanmıştır, bu yüzden tetikleyici \u003Cstrong\u003Edakikada bir\u003C\/strong\u003E çalışmalıdır.\n    \u003C\/p\u003E\n\n    \u003Cdiv class=\"bg-white border border-slate-200 rounded-3xl p-6 md:p-8 shadow-sm space-y-8\"\u003E\n      \u003Cdiv class=\"space-y-6\"\u003E\n        \u003Cdiv class=\"flex gap-4\"\u003E\n          \u003Cdiv class=\"w-8 h-8 rounded-full bg-indigo-50 text-[#182C61] flex items-center justify-center font-bold shrink-0 mt-0.5\"\u003E1\u003C\/div\u003E\n          \u003Cdiv\u003E\n            \u003Cp class=\"text-slate-700 font-bold mb-1\"\u003ETetikleyiciler Ekranına Geçiş\u003C\/p\u003E\n            \u003Cp class=\"text-slate-500 text-xs md:text-sm\"\u003EApps Script ekranında sol menüden \u003Cstrong class=\"text-slate-700\"\u003E⏰ (Tetikleyiciler - Triggers)\u003C\/strong\u003E ikonuna tıklayın.\u003C\/p\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"flex gap-4\"\u003E\n          \u003Cdiv class=\"w-8 h-8 rounded-full bg-indigo-50 text-[#182C61] flex items-center justify-center font-bold shrink-0 mt-0.5\"\u003E2\u003C\/div\u003E\n          \u003Cdiv\u003E\n            \u003Cp class=\"text-slate-700 font-bold mb-1\"\u003EYeni Tetikleyici Ekleme\u003C\/p\u003E\n            \u003Cp class=\"text-slate-500 text-xs md:text-sm\"\u003ESağ alttaki \u003Cstrong class=\"text-emerald-600 font-bold\"\u003ETetikleyici Ekle\u003C\/strong\u003E butonuna basın.\u003C\/p\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"flex gap-4\"\u003E\n          \u003Cdiv class=\"w-8 h-8 rounded-full bg-indigo-50 text-[#182C61] flex items-center justify-center font-bold shrink-0 mt-0.5\"\u003E3\u003C\/div\u003E\n          \u003Cdiv\u003E\n            \u003Cp class=\"text-slate-700 font-bold mb-1\"\u003EGoogle Güvenlik İzinlerinin Verilmesi\u003C\/p\u003E\n            \u003Cp class=\"text-slate-500 text-xs md:text-sm\"\u003E\u003Cstrong class=\"text-[#0f9d58]\"\u003EKaydet\u003C\/strong\u003E'e basın. Ekrana Google güvenlik uyarısı gelirse \u003Cstrong class=\"text-slate-700\"\u003EGelişmiş \u0026gt; ... projesine git (Güvenli değil)\u003C\/strong\u003E diyerek izinleri onaylayın.\u003C\/p\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003Cdiv class=\"bg-slate-50 rounded-2xl p-6 border border-slate-200\"\u003E\n        \u003Ch4 class=\"font-extrabold text-[#182C61] text-sm mb-4 uppercase tracking-wider flex items-center gap-2\"\u003E\n          \u003Ci data-lucide=\"clock\" class=\"w-4 h-4 text-[#30519E]\"\u003E\u003C\/i\u003E Eksiksiz Yapılacak Ayarlar\n        \u003C\/h4\u003E\n        \u003Cdiv class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 font-mono text-xs text-slate-700\"\u003E\n          \u003Cdiv class=\"bg-white p-4 rounded-xl border border-slate-200\/60 shadow-sm flex flex-col justify-between min-w-0\"\u003E\n            \u003Cspan class=\"text-slate-500 mb-1.5 font-sans font-semibold\"\u003EÇalıştırılacak İşlev:\u003C\/span\u003E\n            \u003Cspan class=\"text-[#182C61] font-bold break-all\"\u003EcheckAndSendAllNotifications\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"bg-white p-4 rounded-xl border border-slate-200\/60 shadow-sm flex flex-col justify-between min-w-0\"\u003E\n            \u003Cspan class=\"text-slate-500 mb-1.5 font-sans font-semibold\"\u003EDağıtım:\u003C\/span\u003E\n            \u003Cspan class=\"text-[#182C61] font-bold break-all\"\u003EHead\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"bg-white p-4 rounded-xl border border-slate-200\/60 shadow-sm flex flex-col justify-between min-w-0\"\u003E\n            \u003Cspan class=\"text-slate-500 mb-1.5 font-sans font-semibold\"\u003EEtkinlik Kaynağı Seçin:\u003C\/span\u003E\n            \u003Cspan class=\"text-[#182C61] font-bold break-all\"\u003EZamana dayalı (Time-driven)\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"bg-white p-4 rounded-xl border border-slate-200\/60 shadow-sm flex flex-col justify-between min-w-0\"\u003E\n            \u003Cspan class=\"text-slate-500 mb-1.5 font-sans font-semibold\"\u003EZamanlayıcı Türü:\u003C\/span\u003E\n            \u003Cspan class=\"text-[#182C61] font-bold break-all\"\u003EDakika zamanlayıcısı (Minutes)\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"bg-white p-4 rounded-xl border border-emerald-200 bg-emerald-50\/10 shadow-sm flex flex-col justify-between min-w-0\"\u003E\n            \u003Cspan class=\"text-slate-500 mb-1.5 font-sans font-semibold\"\u003EZaman Aralığı:\u003C\/span\u003E\n            \u003Cspan class=\"text-emerald-600 font-extrabold break-all\"\u003EHer dakikada bir (Every minute)\u003C\/span\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- SECTION 4: DEVELOPER DIRECTIONS (ADIM 4) --\u003E\n  \u003Csection class=\"mb-16\"\u003E\n    \u003Ch2 class=\"text-2xl md:text-3xl font-bold mb-6 text-[#182C61] flex items-center gap-3\"\u003E\n      \u003Cspan class=\"w-10 h-10 rounded-2xl bg-[#182C61]\/5 flex items-center justify-center text-[#182C61] text-lg font-black font-mono\"\u003E04\u003C\/span\u003E\n      ADIM 4: Yazılımcı İçin Yönergeler (Firebase \u0026 Mobil)\n    \u003C\/h2\u003E\n    \u003Cp class=\"text-slate-600 text-sm md:text-base mb-8 leading-relaxed\"\u003E\n      Bu bölüm doğrudan mobil\/backend yazılımcısına iletilmeli ve entegrasyon sırasında eksiksiz uygulanmalıdır (Yönerge adımlarına tıklayarak detayları görebilirsiniz):\n    \u003C\/p\u003E\n\n    \u003Cdiv class=\"space-y-4\" id=\"dev-steps-group\"\u003E\n      \u003C!-- Dev Step 1 --\u003E\n      \u003Cdiv id=\"dev-card-0\" class=\"border rounded-[2rem] overflow-hidden bg-white border-indigo-200 shadow-md transition-all duration-300\"\u003E\n        \u003Cbutton onclick=\"toggleDevStep(0)\" class=\"w-full text-left p-6 flex items-center justify-between gap-4 cursor-pointer hover:bg-slate-50\/50 transition-colors focus:outline-none\"\u003E\n          \u003Cdiv class=\"flex items-center gap-4 min-w-0\"\u003E\n            \u003Cdiv id=\"dev-badge-0\" class=\"w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg bg-indigo-600 text-white transition-colors duration-300\"\u003E\n              1\n            \u003C\/div\u003E\n            \u003Cdiv class=\"min-w-0\"\u003E\n              \u003Cspan class=\"text-xs font-bold uppercase tracking-wider text-indigo-600 block mb-0.5\"\u003EFirebase Yetkilendirme\u003C\/span\u003E\n              \u003Ch3 class=\"text-base md:text-lg font-extrabold text-[#182C61] flex items-center gap-2 truncate\"\u003E\n                \u003Ci data-lucide=\"cpu\" class=\"w-5 h-5 shrink-0\"\u003E\u003C\/i\u003E Service Account (Hizmet Hesabı) Bilgileri\n              \u003C\/h3\u003E\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cspan id=\"dev-chevron-0\" class=\"text-xl font-mono text-[#30519E] transition-transform duration-300 shrink-0 rotate-180\"\u003E\n            -\n          \u003C\/span\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"dev-content-0\" class=\"px-6 pb-6 pt-2 bg-white text-[#182C61]\/80 border-t border-slate-100 text-sm leading-relaxed space-y-4\"\u003E\n          \u003Cp\u003E\n            Firebase Console \u0026gt; Project Settings \u0026gt; Service Accounts sekmesine gidin. \"Generate new private key\" diyerek .json dosyasını indirin. Bu dosyanın içindeki \u003Ccode\u003Eproject_id\u003C\/code\u003E, \u003Ccode\u003Eclient_email\u003C\/code\u003E ve \u003Ccode\u003Eprivate_key\u003C\/code\u003E değerlerini Apps Script'in en üstündeki FIREBASE_CONFIG içine birebir kopyalayın.\n          \u003C\/p\u003E\n          \u003Cdiv class=\"p-4 bg-amber-50 rounded-2xl border border-amber-100 text-amber-800 text-xs font-medium\"\u003E\n            \u003Cstrong\u003EÖnemli Not:\u003C\/strong\u003E private_key içindeki \\n karakterleri bozulmadan, tam olarak \"-----BEGIN PRIVATE KEY-----\" ile başlayıp \"-----END PRIVATE KEY-----\\n\" ile bitecek şekilde yapıştırılmalıdır.\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Dev Step 2 --\u003E\n      \u003Cdiv id=\"dev-card-1\" class=\"border rounded-[2rem] overflow-hidden bg-slate-50\/50 border-slate-200\/60 transition-all duration-300\"\u003E\n        \u003Cbutton onclick=\"toggleDevStep(1)\" class=\"w-full text-left p-6 flex items-center justify-between gap-4 cursor-pointer hover:bg-slate-50\/50 transition-colors focus:outline-none\"\u003E\n          \u003Cdiv class=\"flex items-center gap-4 min-w-0\"\u003E\n            \u003Cdiv id=\"dev-badge-1\" class=\"w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg bg-emerald-50 text-[#0f9d58] transition-colors duration-300\"\u003E\n              2\n            \u003C\/div\u003E\n            \u003Cdiv class=\"min-w-0\"\u003E\n              \u003Cspan class=\"text-xs font-bold uppercase tracking-wider text-emerald-600 block mb-0.5\"\u003ETopic Entegrasyonu\u003C\/span\u003E\n              \u003Ch3 class=\"text-base md:text-lg font-extrabold text-[#182C61] flex items-center gap-2 truncate\"\u003E\n                \u003Ci data-lucide=\"smartphone\" class=\"w-5 h-5 shrink-0\"\u003E\u003C\/i\u003E Uygulama İçi Topic (Grup) Abonelikleri\n              \u003C\/h3\u003E\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cspan id=\"dev-chevron-1\" class=\"text-xl font-mono text-[#30519E] transition-transform duration-300 shrink-0\"\u003E\n            +\n          \u003C\/span\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"dev-content-1\" class=\"hidden px-6 pb-6 pt-2 bg-white text-[#182C61]\/80 border-t border-slate-100 text-sm leading-relaxed space-y-4\"\u003E\n          \u003Cp\u003E\n            Tablodaki \"Hedef\" sütunu Firebase Topics mimarisiyle çalışır (\u003Ccode\u003E\/topics\/hedef_adi\u003C\/code\u003E). Uygulama başlatıldığında, kullanıcının hesap durumuna göre cihazı mutlaka ilgili Topic'e abone etmelisiniz.\n          \u003C\/p\u003E\n          \u003Cdiv class=\"p-4 bg-emerald-50 rounded-2xl border border-emerald-100 text-emerald-800 text-xs font-medium\"\u003E\n            \u003Cstrong\u003EÖnemli Not:\u003C\/strong\u003E Tabloya hedefler yazılırken başına # (diyez) veya @ konulmayacaktır. Dümdüz All_users, premium_users şeklinde yazılacaktır. Büyük\/küçük harf duyarlılığına dikkat ediniz.\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Dev Step 3 --\u003E\n      \u003Cdiv id=\"dev-card-2\" class=\"border rounded-[2rem] overflow-hidden bg-slate-50\/50 border-slate-200\/60 transition-all duration-300\"\u003E\n        \u003Cbutton onclick=\"toggleDevStep(2)\" class=\"w-full text-left p-6 flex items-center justify-between gap-4 cursor-pointer hover:bg-slate-50\/50 transition-colors focus:outline-none\"\u003E\n          \u003Cdiv class=\"flex items-center gap-4 min-w-0\"\u003E\n            \u003Cdiv id=\"dev-badge-2\" class=\"w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg bg-rose-50 text-rose-600 transition-colors duration-300\"\u003E\n              3\n            \u003C\/div\u003E\n            \u003Cdiv class=\"min-w-0\"\u003E\n              \u003Cspan class=\"text-xs font-bold uppercase tracking-wider text-rose-600 block mb-0.5\"\u003EApple Push Ayarları\u003C\/span\u003E\n              \u003Ch3 class=\"text-base md:text-lg font-extrabold text-[#182C61] flex items-center gap-2 truncate\"\u003E\n                \u003Ci data-lucide=\"zap\" class=\"w-5 h-5 shrink-0\"\u003E\u003C\/i\u003E iOS APNs Ayarları (Badge \u0026 Sound)\n              \u003C\/h3\u003E\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cspan id=\"dev-chevron-2\" class=\"text-xl font-mono text-[#30519E] transition-transform duration-300 shrink-0\"\u003E\n            +\n          \u003C\/span\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"dev-content-2\" class=\"hidden px-6 pb-6 pt-2 bg-white text-[#182C61]\/80 border-t border-slate-100 text-sm leading-relaxed space-y-4\"\u003E\n          \u003Cp\u003E\n            Apple cihazlarda bildirim sesi çıkması ve ikon üzerinde kırmızı sayının (badge) belirmesi için iOS projesinde Push Notifications ve Background Modes \u0026gt; Remote notifications yetkilerinin açık olduğundan emin olun.\n          \u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Dev Step 4 --\u003E\n      \u003Cdiv id=\"dev-card-3\" class=\"border rounded-[2rem] overflow-hidden bg-slate-50\/50 border-slate-200\/60 transition-all duration-300\"\u003E\n        \u003Cbutton onclick=\"toggleDevStep(3)\" class=\"w-full text-left p-6 flex items-center justify-between gap-4 cursor-pointer hover:bg-slate-50\/50 transition-colors focus:outline-none\"\u003E\n          \u003Cdiv class=\"flex items-center gap-4 min-w-0\"\u003E\n            \u003Cdiv id=\"dev-badge-3\" class=\"w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg bg-slate-100 text-slate-700 transition-colors duration-300\"\u003E\n              4\n            \u003C\/div\u003E\n            \u003Cdiv class=\"min-w-0\"\u003E\n              \u003Cspan class=\"text-xs font-bold uppercase tracking-wider text-slate-600 block mb-0.5\"\u003ETeşhis \u0026 Log\u003C\/span\u003E\n              \u003Ch3 class=\"text-base md:text-lg font-extrabold text-[#182C61] flex items-center gap-2 truncate\"\u003E\n                \u003Ci data-lucide=\"shield-check\" class=\"w-5 h-5 shrink-0\"\u003E\u003C\/i\u003E Hata Loglaması \u0026 Teşhis\n              \u003C\/h3\u003E\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cspan id=\"dev-chevron-3\" class=\"text-xl font-mono text-[#30519E] transition-transform duration-300 shrink-0\"\u003E\n            +\n          \u003C\/span\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"dev-content-3\" class=\"hidden px-6 pb-6 pt-2 bg-white text-[#182C61]\/80 border-t border-slate-100 text-sm leading-relaxed space-y-4\"\u003E\n          \u003Cp\u003E\n            Eğer tabloda I sütununda (TekSeferlik sayfası durum) \"Gönderildi\" yerine \"HATA: Kod 403...\" veya benzeri bir log düşerse, bu durum ya Service Account yetkilerinden ya da hedeflenen Topic'e kayıtlı cihaz bulunmamasından kaynaklıdır. Firebase Console üzerinden test mesajı atarak bağlantıyı doğrulayabilirsiniz.\n          \u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C!-- SECTION: SYSTEM READY BANNER (KAPANIŞ MESAJI) --\u003E\n  \u003Cdiv id=\"fcm-success-banner\" class=\"bg-gradient-to-br from-[#0f9d58] via-emerald-600 to-[#182C61] rounded-[2.5rem] p-8 md:p-12 text-white shadow-xl mb-16 relative overflow-hidden\"\u003E\n    \u003C!-- Decorative background patterns --\u003E\n    \u003Cdiv class=\"absolute -right-10 -bottom-10 w-40 h-40 rounded-full bg-white\/5 blur-xl\"\u003E\u003C\/div\u003E\n    \u003Cdiv class=\"absolute -left-10 -top-10 w-40 h-40 rounded-full bg-white\/5 blur-xl\"\u003E\u003C\/div\u003E\n    \n    \u003Cdiv class=\"relative z-10 flex flex-col lg:flex-row items-center gap-8\"\u003E\n      \u003Cdiv class=\"w-16 h-16 rounded-3xl bg-white\/15 flex items-center justify-center shrink-0 border border-white\/25 shadow-inner\"\u003E\n        \u003Ci data-lucide=\"check-circle-2\" class=\"w-10 h-10 text-emerald-300\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n      \u003Cdiv class=\"flex-1\"\u003E\n        \u003Cspan class=\"text-xs font-bold uppercase tracking-widest text-emerald-300 block mb-2\"\u003ETebrikler • Tüm Adımlar Tamamlandı\u003C\/span\u003E\n        \u003Ch3 class=\"text-2xl md:text-3xl font-black mb-3 text-white\"\u003Eİşlem Bu Kadar, Sistem Hazır! 🎉\u003C\/h3\u003E\n        \u003Cp class=\"text-white\/85 text-sm md:text-base leading-relaxed max-w-4xl mb-6\"\u003E\n          Google E-Tablolar (Sheets) ve Firebase FCM v1 altyapısı ile donatılmış anlık bildirim otomasyonunuz başarıyla kuruldu. Artık tabloda belirlediğiniz gün ve saatlerde bildirimleriniz otomatik olarak kullanıcılarınızın cihazlarına anında ulaştırılacaktır.\n        \u003C\/p\u003E\n        \n        \u003C!-- Checklist items --\u003E\n        \u003Cdiv class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-xs font-semibold text-white\/95\"\u003E\n          \u003Cdiv class=\"flex items-center gap-2.5\"\u003E\n            \u003Cspan class=\"w-5 h-5 rounded-full bg-emerald-500\/20 text-emerald-300 flex items-center justify-center font-bold text-[10px] border border-emerald-500\/30\"\u003E✓\u003C\/span\u003E\n            \u003Cspan\u003EE-Tablo Veri Mimarisi (Adım 1)\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"flex items-center gap-2.5\"\u003E\n            \u003Cspan class=\"w-5 h-5 rounded-full bg-emerald-500\/20 text-emerald-300 flex items-center justify-center font-bold text-[10px] border border-emerald-500\/30\"\u003E✓\u003C\/span\u003E\n            \u003Cspan\u003EApps Script Entegrasyon Kodu (Adım 2)\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"flex items-center gap-2.5\"\u003E\n            \u003Cspan class=\"w-5 h-5 rounded-full bg-emerald-500\/20 text-emerald-300 flex items-center justify-center font-bold text-[10px] border border-emerald-500\/30\"\u003E✓\u003C\/span\u003E\n            \u003Cspan\u003EDakikalık Otomatik Tetikleyici (Adım 3)\u003C\/span\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"flex items-center gap-2.5\"\u003E\n            \u003Cspan class=\"w-5 h-5 rounded-full bg-emerald-500\/20 text-emerald-300 flex items-center justify-center font-bold text-[10px] border border-emerald-500\/30\"\u003E✓\u003C\/span\u003E\n            \u003Cspan\u003EMobil Entegrasyon \u0026 Topic Aboneliği (Adım 4)\u003C\/span\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/div\u003E\n\n  \u003C\/div\u003E\n\n  \u003C!-- BÖLÜM 2 WRAPPER --\u003E\n  \u003Cdiv class=\"relative\"\u003E\n    \u003C!-- Geniş ekranlar için sol kenarda asılı duran (floating) Bölüm Göstergesi (Sticky ile birlikte hareket eder) --\u003E\n    \u003Cdiv class=\"hidden lg:flex absolute -left-28 top-0 h-full w-24 pointer-events-none\"\u003E\n      \u003Cdiv class=\"sticky top-32 z-40 bg-[#182C61] text-white rounded-full w-24 h-24 flex flex-col items-center justify-center shadow-xl border-4 border-[#f8fafc] hover:scale-105 transition-transform duration-300 pointer-events-auto\"\u003E\n        \u003Cspan class=\"text-[10px] font-black uppercase tracking-widest text-slate-300 leading-none\"\u003EBÖLÜM\u003C\/span\u003E\n        \u003Cspan class=\"text-4xl font-extrabold font-mono leading-none my-1\"\u003E02\u003C\/span\u003E\n        \u003Ci data-lucide=\"lightbulb\" class=\"w-5 h-5 text-amber-400 animate-pulse\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- BÖLÜM 2 BAŞLIĞI --\u003E\n    \u003Cdiv class=\"my-8 py-4 px-4 md:px-6 bg-[#182C61] border border-[#111e43] rounded-2xl shadow-lg flex items-center gap-3 relative\"\u003E\n      \u003C!-- Mobil için Bölüm Göstergesi (lg:hidden) --\u003E\n      \u003Cspan class=\"lg:hidden px-3 py-1 bg-amber-500\/15 text-amber-300 border border-emerald-500\/20 text-[11px] font-black uppercase tracking-widest rounded-lg shadow-sm flex items-center gap-1.5 shrink-0\"\u003E\n        \u003Ci data-lucide=\"lightbulb\" class=\"w-3.5 h-3.5 text-amber-400\"\u003E\u003C\/i\u003E BÖLÜM 2\n      \u003C\/span\u003E\n      \u003Ch2 class=\"text-base md:text-lg lg:text-xl font-black text-white tracking-tight leading-none\"\u003E\n        Kullanım İpuçları ve Özel Taktikler\n      \u003C\/h2\u003E\n    \u003C\/div\u003E\n  \u003Cp class=\"text-slate-600 text-sm md:text-base leading-relaxed max-w-4xl mb-10 pl-2\"\u003E\n    Sistemin tüm gizli yeteneklerinden faydalanmak, gönderimleri optimize etmek ve ileri düzey senaryoları hayata geçirmek için aşağıdaki teknik ipuçlarını uygulayabilirsiniz.\n  \u003C\/p\u003E\n\n  \u003C!-- BÖLÜM 2: KULLANIM İPUÇLARI VE ÖZEL TAKTİKLER --\u003E\n  \u003Csection class=\"mb-16\"\u003E\n    \u003Cdiv class=\"space-y-6\"\u003E\n      \u003C!-- Taktik 1 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-[2rem] p-6 md:p-8 hover:shadow-md transition-all flex flex-col md:flex-row gap-6\"\u003E\n        \u003Cdiv class=\"w-12 h-12 rounded-2xl bg-indigo-50 text-[#182C61] flex items-center justify-center shrink-0 shadow-sm\"\u003E\n          \u003Ci data-lucide=\"layers\" class=\"w-6 h-6\"\u003E\u003C\/i\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"flex-1\"\u003E\n          \u003Ch3 class=\"text-lg font-extrabold text-[#182C61] mb-3\"\u003E2.1. Hücreleri Boş Bırakma Esnekliği (Hariç Tutmalar)\u003C\/h3\u003E\n          \u003Cp class=\"text-slate-600 text-sm leading-relaxed mb-4\"\u003E\n            Sistem tamamen esnektir. Herhangi bir kısıtlama yapmak istemiyorsanız ilgili hücreyi boş bırakın.\n          \u003C\/p\u003E\n          \u003Cdiv class=\"bg-slate-50 rounded-2xl p-4 border border-slate-100 text-slate-600 text-xs md:text-sm space-y-2\"\u003E\n            \u003Cdiv\u003E• \u003Cstrong\u003EHariç Topic (F) Boşsa:\u003C\/strong\u003E Hedef gruptaki herkese gider. Oraya \u003Ccode class=\"bg-indigo-100\/50 text-indigo-700 px-1.5 py-0.5 rounded font-mono text-xs\"\u003Epremium_users\u003C\/code\u003E yazarsanız, sadece onları gönderimden dışlar.\u003C\/div\u003E\n            \u003Cdiv\u003E• \u003Cstrong\u003EPlatform Hariç (G) Boşsa:\u003C\/strong\u003E Hem iOS hem Android'e gider. Oraya \u003Ccode class=\"bg-indigo-100\/50 text-indigo-700 px-1.5 py-0.5 rounded font-mono text-xs\"\u003EiOS\u003C\/code\u003E yazarsanız bildirim paketi iOS'ları atlar, sadece Android cihazlara gider.\u003C\/div\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Taktik 2 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-[2rem] p-6 md:p-8 hover:shadow-md transition-all flex flex-col md:flex-row gap-6\"\u003E\n        \u003Cdiv class=\"w-12 h-12 rounded-2xl bg-emerald-50 text-emerald-600 flex items-center justify-center shrink-0 shadow-sm\"\u003E\n          \u003Ci data-lucide=\"user-check\" class=\"w-6 h-6\"\u003E\u003C\/i\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"flex-1\"\u003E\n          \u003Ch3 class=\"text-lg font-extrabold text-[#182C61] mb-3\"\u003E2.2. Kişiselleştirilmiş Bildirim (\"Merhaba Ahmet\") Taktiği\u003C\/h3\u003E\n          \u003Cp class=\"text-slate-600 text-sm leading-relaxed mb-4\"\u003E\n            Panelden binlerce kişiye aynı anda gönderim yaparken her kullanıcıya kendi adıyla hitap edebilirsiniz:\n          \u003C\/p\u003E\n          \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 gap-4\"\u003E\n            \u003Cdiv class=\"bg-slate-50 rounded-2xl p-4 border border-slate-100\"\u003E\n              \u003Cspan class=\"text-xs font-bold text-[#182C61] block mb-1\"\u003EYöneticinin Yapacağı:\u003C\/span\u003E\n              \u003Cp class=\"text-slate-600 text-xs leading-relaxed\"\u003E\n                Başlık veya Mesaj hücresine \u003Ccode class=\"bg-emerald-100\/50 text-emerald-700 px-1.5 py-0.5 rounded font-mono text-xs\"\u003E[ISIM]\u003C\/code\u003E etiketini yazın. \u003Cbr\u003E\u003Cem\u003E(Örn: \"Merhaba [ISIM], bu fırsatı kaçırma!\")\u003C\/em\u003E\n              \u003C\/p\u003E\n            \u003C\/div\u003E\n            \u003Cdiv class=\"bg-slate-50 rounded-2xl p-4 border border-slate-100\"\u003E\n              \u003Cspan class=\"text-xs font-bold text-emerald-700 block mb-1\"\u003EUygulama Yazılımcısının Yapacağı:\u003C\/span\u003E\n              \u003Cp class=\"text-slate-600 text-xs leading-relaxed\"\u003E\n                Mobil uygulama, Firebase'den gelen bildirimi ekrana basmadan hemen önce intercept eder. Metindeki \u003Ccode class=\"bg-emerald-100\/50 text-emerald-700 px-1.5 py-0.5 rounded font-mono text-xs\"\u003E[ISIM]\u003C\/code\u003E etiketini, uygulamaya giriş yapmış kullanıcının adıyla değiştirip ekrana basar.\n              \u003C\/p\u003E\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cp class=\"text-xs text-indigo-600 font-semibold mt-3 flex items-center gap-1.5\"\u003E\n            \u003Ci data-lucide=\"info\" class=\"w-4 h-4\"\u003E\u003C\/i\u003E Bu işlem tamamen Client-Side'da (mobil uygulamada) yapılır, E-Tablo tarafında ek bir koda ihtiyaç yoktur.\n          \u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- Taktik 3 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-[2rem] p-6 md:p-8 hover:shadow-md transition-all flex flex-col md:flex-row gap-6\"\u003E\n        \u003Cdiv class=\"w-12 h-12 rounded-2xl bg-amber-50 text-amber-600 flex items-center justify-center shrink-0 shadow-sm\"\u003E\n          \u003Ci data-lucide=\"hash\" class=\"w-6 h-6\"\u003E\u003C\/i\u003E\n        \u003C\/div\u003E\n        \u003Cdiv class=\"flex-1\"\u003E\n          \u003Ch3 class=\"text-lg font-extrabold text-[#182C61] mb-3\"\u003E2.3. Aralık (J) ve Grup (K) Sütunu Mantığı (0'dan Sayma Kuralı)\u003C\/h3\u003E\n          \u003Cp class=\"text-slate-600 text-sm leading-relaxed mb-4\"\u003E\n            Bilgisayarlar saymaya 1'den değil, 0'dan başlar. Bu yüzden rotasyon döngülerini kurarken aşağıdaki mantığı uygulayın:\n          \u003C\/p\u003E\n          \u003Cdiv class=\"bg-slate-50 rounded-2xl p-4 border border-slate-100 text-slate-600 text-xs md:text-sm space-y-2 mb-4\"\u003E\n            \u003Cdiv\u003E• \u003Cstrong\u003EHer Hafta Gidecekse:\u003C\/strong\u003E Aralık \u003Ccode class=\"font-mono bg-slate-200 px-1 py-0.5 rounded\"\u003E1\u003C\/code\u003E, Grup \u003Ccode class=\"font-mono bg-slate-200 px-1 py-0.5 rounded\"\u003E0\u003C\/code\u003E yazılır.\u003C\/div\u003E\n            \u003Cdiv\u003E• \u003Cstrong\u003E2 Haftada Bir Nöbetleşe Gidecekse:\u003C\/strong\u003E Aralık \u003Ccode class=\"font-mono bg-slate-200 px-1 py-0.5 rounded\"\u003E2\u003C\/code\u003E yapılır. Birinci grup için Grup \u003Ccode class=\"font-mono bg-slate-200 px-1 py-0.5 rounded\"\u003E0\u003C\/code\u003E, ikinci grup için Grup \u003Ccode class=\"font-mono bg-slate-200 px-1 py-0.5 rounded\"\u003E1\u003C\/code\u003E verilir.\u003C\/div\u003E\n          \u003C\/div\u003E\n          \u003Cdiv class=\"text-amber-800 bg-amber-50\/80 p-4 rounded-2xl border border-amber-200\/60 leading-relaxed text-xs md:text-sm flex items-start gap-2.5\"\u003E\n            \u003Ci data-lucide=\"alert-triangle\" class=\"w-5 h-5 text-amber-600 shrink-0 mt-0.5\"\u003E\u003C\/i\u003E\n            \u003Cdiv\u003E\n              \u003Cstrong\u003ESistem Yanlışlık Koruması:\u003C\/strong\u003E Aralık 2 iken yanlışlıkla Grup değerine 2 yazarsanız, kod sistemi çökertmez; o 2'yi otomatik olarak 0 kabul edip rotasyonu güvenle kurtarır.\n            \u003C\/div\u003E\n          \u003C\/div\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n\n  \u003C\/div\u003E\n\n  \u003C!-- BÖLÜM 3 WRAPPER --\u003E\n  \u003Cdiv class=\"relative\"\u003E\n    \u003C!-- Geniş ekranlar için sol kenarda asılı duran (floating) Bölüm Göstergesi (Sticky ile birlikte hareket eder) --\u003E\n    \u003Cdiv class=\"hidden lg:flex absolute -left-28 top-0 h-full w-24 pointer-events-none\"\u003E\n      \u003Cdiv class=\"sticky top-32 z-40 bg-[#182C61] text-white rounded-full w-24 h-24 flex flex-col items-center justify-center shadow-xl border-4 border-[#f8fafc] hover:scale-105 transition-transform duration-300 pointer-events-auto\"\u003E\n        \u003Cspan class=\"text-[10px] font-black uppercase tracking-widest text-slate-300 leading-none\"\u003EBÖLÜM\u003C\/span\u003E\n        \u003Cspan class=\"text-4xl font-extrabold font-mono leading-none my-1\"\u003E03\u003C\/span\u003E\n        \u003Ci data-lucide=\"help-circle\" class=\"w-5 h-5 text-rose-400 animate-pulse\"\u003E\u003C\/i\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n\n    \u003C!-- BÖLÜM 3 BAŞLIĞI --\u003E\n    \u003Cdiv class=\"my-8 py-4 px-4 md:px-6 bg-[#182C61] border border-[#111e43] rounded-2xl shadow-lg flex items-center gap-3 relative\"\u003E\n      \u003C!-- Mobil için Bölüm Göstergesi (lg:hidden) --\u003E\n      \u003Cspan class=\"lg:hidden px-3 py-1 bg-rose-500\/15 text-rose-300 border border-rose-500\/20 text-[11px] font-black uppercase tracking-widest rounded-lg shadow-sm flex items-center gap-1.5 shrink-0\"\u003E\n        \u003Ci data-lucide=\"help-circle\" class=\"w-3.5 h-3.5 text-rose-400\"\u003E\u003C\/i\u003E BÖLÜM 3\n      \u003C\/span\u003E\n      \u003Ch2 class=\"text-base md:text-lg lg:text-xl font-black text-white tracking-tight leading-none\"\u003E\n        Yolda Karşılaşılabilecek Sorunlar ve Çözümleri\n      \u003C\/h2\u003E\n    \u003C\/div\u003E\n  \u003Cp class=\"text-slate-600 text-sm md:text-base leading-relaxed max-w-4xl mb-10 pl-2\"\u003E\n    Sistem çalışmadığında veya hata verdiğinde panik yapmayın. İşte en sık karşılaşılan 4 tipik durum ve bunların nokta atışı kesin çözümleri.\n  \u003C\/p\u003E\n\n  \u003C!-- SECTION 5: FAQ \/ SIK SORULAN SORULAR --\u003E\n  \u003Csection class=\"mb-16\"\u003E\n    \u003Cdiv class=\"space-y-4\" id=\"faq-accordion-group\"\u003E\n      \u003C!-- FAQ Item 1 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleFaqAccordion(0)\" class=\"w-full text-left p-6 font-bold text-sm md:text-base text-[#182C61] hover:bg-slate-50 flex items-center justify-between gap-4 focus:outline-none transition-colors\"\u003E\n          \u003Cspan\u003E1. Bildirim Saati Geldi Ama Hiçbir Şey Göndermedi (Sütun Boş Kaldı)\u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"faq-icon-0\" class=\"w-5 h-5 transition-transform duration-300 text-slate-400\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"faq-content-0\" class=\"hidden px-6 pb-6 pt-4 bg-slate-50 border-t border-slate-100 text-slate-700 text-xs md:text-sm space-y-3\"\u003E\n          \u003Cp\u003E\u003Cstrong\u003ESebep:\u003C\/strong\u003E E-Tablo saat veya gün formatını okuyamamıştır veya sunucu saati yanlıştır.\u003C\/p\u003E\n          \u003Cp\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E\u003C\/p\u003E\n          \u003Cul class=\"list-disc list-inside space-y-2 text-slate-600 pl-2\"\u003E\n            \u003Cli\u003ESaat sütununu (B) tamamen seçip üst menüden \u003Cstrong\u003EBiçim \u003E Sayı \u003E Saat\u003C\/strong\u003E yapın.\u003C\/li\u003E\n            \u003Cli\u003ESürekli sayfasındaki Gün sütununu (A) seçip \u003Cstrong\u003EBiçim \u003E Sayı \u003E Düz Metin\u003C\/strong\u003E yapın. Kelimenin sonunda boşluk \u003Cem\u003E(Örn: \"Pazartesi \")\u003C\/em\u003E kalmadığından emin olun.\u003C\/li\u003E\n            \u003Cli\u003EApps Script ekranında sol menüden \u003Cstrong\u003EProje Ayarları (Dişli Çark)\u003C\/strong\u003E kısmına girip Saat Dilimi'nin \u003Cstrong\u003E(GMT+03:00) İstanbul\u003C\/strong\u003E olduğundan emin olun.\u003C\/li\u003E\n          \u003C\/ul\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- FAQ Item 2 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleFaqAccordion(1)\" class=\"w-full text-left p-6 font-bold text-sm md:text-base text-[#182C61] hover:bg-slate-50 flex items-center justify-between gap-4 focus:outline-none transition-colors\"\u003E\n          \u003Cspan\u003E2. Durum Sütununda \"HATA: Kod 403\" Yazıyor\u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"faq-icon-1\" class=\"w-5 h-5 transition-transform duration-300 text-slate-400\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"faq-content-1\" class=\"hidden px-6 pb-6 pt-4 bg-slate-50 border-t border-slate-100 text-slate-700 text-xs md:text-sm space-y-3\"\u003E\n          \u003Cp\u003E\u003Cstrong\u003ESebep:\u003C\/strong\u003E Google Cloud veya Firebase yetki sorunu.\u003C\/p\u003E\n          \u003Cp\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E Firebase Service Account (JSON) e-posta adresinizin (client_email) ve Private Key'inizin kodun en üstüne tam ve eksiksiz kopyalandığından emin olun. Ayrıca projenizde Cloud Messaging API'nin (V1) aktif olup olmadığını Google Cloud Console'dan kontrol edin.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- FAQ Item 3 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleFaqAccordion(2)\" class=\"w-full text-left p-6 font-bold text-sm md:text-base text-[#182C61] hover:bg-slate-50 flex items-center justify-between gap-4 focus:outline-none transition-colors\"\u003E\n          \u003Cspan\u003E3. Durum Sütununda \"HATA: Kod 400\" Yazıyor\u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"faq-icon-2\" class=\"w-5 h-5 transition-transform duration-300 text-slate-400\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"faq-content-2\" class=\"hidden px-6 pb-6 pt-4 bg-slate-50 border-t border-slate-100 text-slate-700 text-xs md:text-sm space-y-3\"\u003E\n          \u003Cp\u003E\u003Cstrong\u003ESebep:\u003C\/strong\u003E Hatalı paket formatı. Genellikle \"Platform Hariç\" veya \"Hariç Topic\" kısımlarına olmaması gereken karakterler yazıldığında veya sütunlar kaydığında (Örn: Resim linkinin yanlışlıkla Hedef sütununa yazılması) Firebase paketi reddeder.\u003C\/p\u003E\n          \u003Cp\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E Satırdaki verileri silin ve sütun başlıklarına uygun şekilde (URL yerine URL, kelime yerine kelime) tekrar doldurun.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n\n      \u003C!-- FAQ Item 4 --\u003E\n      \u003Cdiv class=\"bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm\"\u003E\n        \u003Cbutton onclick=\"toggleFaqAccordion(3)\" class=\"w-full text-left p-6 font-bold text-sm md:text-base text-[#182C61] hover:bg-slate-50 flex items-center justify-between gap-4 focus:outline-none transition-colors\"\u003E\n          \u003Cspan\u003E4. Bildirim Android'e Resimli Geliyor, iOS'a Sadece Metin Düşüyor\u003C\/span\u003E\n          \u003Ci data-lucide=\"chevron-down\" id=\"faq-icon-3\" class=\"w-5 h-5 transition-transform duration-300 text-slate-400\"\u003E\u003C\/i\u003E\n        \u003C\/button\u003E\n        \u003Cdiv id=\"faq-content-3\" class=\"hidden px-6 pb-6 pt-4 bg-slate-50 border-t border-slate-100 text-slate-700 text-xs md:text-sm space-y-3\"\u003E\n          \u003Cp\u003E\u003Cstrong\u003ESebep:\u003C\/strong\u003E iOS (Apple) işletim sisteminin güvenlik kısıtlamaları. Biz koddan iOS uyanma komutunu (mutable-content: 1) göndersek bile uygulama tarafında eksiklik vardır.\u003C\/p\u003E\n          \u003Cp\u003E\u003Cstrong\u003EÇözüm:\u003C\/strong\u003E Bu bir kod veya tablo hatası değildir. Mobil yazılımcının iOS (Xcode) projesine \"Notification Service Extension\" kurması ve gelen resim URL'sini arka planda indirip bildirime ekleyecek (attach edecek) Swift\/Objective-C kodlarını yazması gerekmektedir. Aksi halde Apple resmi yutacak ve sadece yazıyı gösterecektir.\u003C\/p\u003E\n        \u003C\/div\u003E\n      \u003C\/div\u003E\n    \u003C\/div\u003E\n  \u003C\/section\u003E\n  \u003C\/div\u003E\n\u003C\/div\u003E\n\n\u003C!-- CLIENT JAVASCRIPT FOR BLOGGER COMPATIBILITY --\u003E\n\u003Cscript\u003E\n  \/\/ Spreadsheet Columns Data Mock\n  const columnDataSurekli = [\n    { id: 'A', name: 'Gün', sample: 'Pazartesi', desc: 'Bildirimin haftalık hangi gün gideceği (Düz Metin olarak kaydedilir). Örn: \"Pazartesi\", \"Salı\" vb.', type: 'Düz Metin (Metin)', req: 'Zorunlu' },\n    { id: 'B', name: 'Saat', sample: '08:30', desc: 'Gönderim saati. E-tabloda mutlaka Saat formatında biçimlendirilmelidir. Saniyeler önemsizdir.', type: 'Saat Biçimi (HH:mm)', req: 'Zorunlu' },\n    { id: 'C', name: 'Başlık', sample: 'Merhaba [ISIM]', desc: 'Bildirim başlığı. Mobil uygulamada \"[ISIM]\" kelimesi kullanıcının gerçek adıyla otomatik olarak değiştirilebilir (Kişiselleştirme desteği).', type: 'Düz Metin (Metin)', req: 'Zorunlu' },\n    { id: 'D', name: 'Mesaj', sample: 'Harika bir gün olsun!', desc: 'Kullanıcının telefonuna düşecek asıl bildirim mesajı gövdesi.', type: 'Düz Metin (Metin)', req: 'Zorunlu' },\n    { id: 'E', name: 'Hedef Topic', sample: 'All_users', desc: 'Firebase tarafında hedeflenecek abone grubu. Boş bırakılırsa sistem otomatik olarak \"All_users\" kabul eder.', type: 'Düz Metin (Metin)', req: 'İsteğe Bağlı' },\n    { id: 'F', name: 'Hariç Topic', sample: 'premium_users', desc: 'Gönderim dışı bırakılacak kitle topic ismi. Buraya girilen gruba üye olanlara bu bildirim ASLA gitmez. Boş bırakılabilir.', type: 'Düz Metin (Metin)', req: 'İsteğe Bağlı' },\n    { id: 'G', name: 'Platform Hariç', sample: 'iOS', desc: 'İşletim sistemi filtreleme hücresi. Sadece \"iOS\" veya \"Android\" girilebilir. Örneğin \"iOS\" yazılırsa bildirim sadece Android cihazlara gider.', type: 'Düz Metin (Metin)', req: 'İsteğe Bağlı' },\n    { id: 'H', name: 'Resim Linki', sample: 'https:\/\/...\/img.jpg', desc: 'Bildirimle beraber mobil cihaza push edilecek görsel URL\\'si. Doğrudan tarayıcıda açılabilen bir resim linki olmalıdır.', type: 'Doğrudan URL Linki', req: 'İsteğe Bağlı' },\n    { id: 'I', name: 'SonGön', sample: '10.07.2026 08:30', desc: 'Son Gönderim Tarihi. Sistem tarafından otomatik olarak gün-saat damgası basılır. Boş bırakılmalı ve elle müdahale edilmemelidir.', type: 'Tarih Saat Biçimi', req: 'SİSTEM TARAFINDAN DOLDURULUR' },\n    { id: 'J', name: 'Aralık', sample: '2', desc: 'Haftalık döngü aralığı. \"1\" yazılırsa her hafta, \"2\" yazılırsa iki haftada bir anlamına gelir.', type: 'Sayı (Tamsayı)', req: 'İsteğe Bağlı (Varsayılan 1)' },\n    { id: 'K', name: 'Grup', sample: '0', desc: 'Rotasyondaki hedef grup sırası (0 veya 1). \"Aralık\" 2 olduğunda, \"Grup\" 0 olanlar ilk hafta, 1 olanlar ikinci hafta gider.', type: 'Sayı (Tamsayı)', req: 'İsteğe Bağlı (Varsayılan 0)' }\n  ];\n\n  const columnDataTekSeferlik = [\n    { id: 'A', name: 'Tarih', sample: '29.10.2026', desc: 'Bildirimin gönderileceği günün tam tarihi (dd.MM.yyyy formatında). Günlük tetikleyici bu tarihi kontrol eder.', type: 'Tarih Biçimi (dd.MM.yyyy)', req: 'Zorunlu' },\n    { id: 'B', name: 'Saat', sample: '09:00', desc: 'Gönderim saati. E-tabloda mutlaka Saat formatında biçimlendirilmelidir.', type: 'Saat Biçimi (HH:mm)', req: 'Zorunlu' },\n    { id: 'C', name: 'Başlık', sample: 'Cumhuriyet Bayramı Kutlu Olsun!', desc: 'Tek seferlik özel bildirimin başlığı.', type: 'Düz Metin (Metin)', req: 'Zorunlu' },\n    { id: 'D', name: 'Mesaj', sample: 'Coşkuyla kutluyoruz.', desc: 'Tek seferlik bildirimin ana metni.', type: 'Düz Metin (Metin)', req: 'Zorunlu' },\n    { id: 'E', name: 'Hedef Topic', sample: 'All_users', desc: 'Firebase Messaging topic ismi. Boş bırakılırsa \"All_users\" kabul edilir.', type: 'Düz Metin (Metin)', req: 'İsteğe Bağlı' },\n    { id: 'F', name: 'Hariç Topic', sample: '-', desc: 'Dışlanacak kitle grubu. Boş bırakılabilir veya \"-\" yazılabilir.', type: 'Düz Metin (Metin)', req: 'İsteğe Bağlı' },\n    { id: 'G', name: 'Platform Hariç', sample: '-', desc: 'Platform filtreleme hücresi (Boşsa veya \"-\" ise her iki platforma da gider).', type: 'Düz Metin (Metin)', req: 'İsteğe Bağlı' },\n    { id: 'H', name: 'Resim Linki', sample: 'https:\/\/...\/ataturk.jpg', desc: 'Gönderilecek görsel URL\\'si (Seçeneklidir).', type: 'Doğrudan URL Linki', req: 'İsteğe Bağlı' },\n    { id: 'I', name: 'Durum', sample: 'GÖNDERİLDİ', desc: 'Sistem başarı durumunda buraya otomatik olarak \"GÖNDERİLDİ\", hata durumunda ise hatayı basar. Boş bırakılmalı ve elle müdahale edilmemelidir.', type: 'Düz Metin', req: 'SİSTEM TARAFINDAN DOLDURULUR' }\n  ];\n\n\/\/ Apps Script Code Template\nconst appsScriptCodeString = `\/\/ --- AYARLAR ---\nconst FIREBASE_CONFIG = {\nprojectId: \"PROJE_ID_BURAYA\",\nclientEmail: \"SERVICE_ACCOUNT_EMAIL_BURAYA\",\nprivateKey: \"-----BEGIN PRIVATE KEY-----\\\\nANAHTAR_BURAYA\\\\n-----END PRIVATE KEY-----\"\n};\n\nfunction checkAndSendAllNotifications() {\nconst ss = SpreadsheetApp.getActiveSpreadsheet();\nconst now = new Date();\n\nconst recurringSheet = ss.getSheetByName(\"Sürekli\");\nif (recurringSheet) processRecurring(recurringSheet, now);\n\nconst oneTimeSheet = ss.getSheetByName(\"TekSeferlik\");\nif (oneTimeSheet) processOneTime(oneTimeSheet, now);\n}\n\nfunction processRecurring(sheet, now) {\nconst data = sheet.getDataRange().getValues();\nconst days = [\"Pazar\", \"Pazartesi\", \"Salı\", \"Çarşamba\", \"Perşembe\", \"Cuma\", \"Cumartesi\"];\nconst todayName = days[now.getDay()];\nconst isoWeek = getISOWeek(now);\n\nfor (let i = 1; i \u003C data.length; i++) {\n\/\/ SÜTUNLAR: A:Gün, B:Saat, C:Başlık, D:Mesaj, E:Hedef, F:HariçTopic, G:PlatformHariç, H:Kampanya, I:Resim, J:SonGön, K:Aralık, L:Grup\nlet [day, time, title, msg, target, excludeTopic, excludePlatform, analyticsLabel, image, lastSent, interval, group] = data[i];\n\nif (!target || target.toString().trim() === \"\") continue;\n\nif (day === todayName \u0026\u0026 isTimeMatch(time, now)) {\nlet checkInterval = parseInt(interval) || 1;\nlet checkGroup = parseInt(group) || 0;\n\nif (checkGroup \u003E= checkInterval) checkGroup = 0;\n\nlet todayStr = Utilities.formatDate(now, \"GMT+3\", \"dd.MM.yyyy\");\n\nif (isoWeek % checkInterval === checkGroup \u0026\u0026 formatDate(lastSent) !== todayStr) {\nconst result = sendFCM(title, msg, target, excludeTopic, excludePlatform, analyticsLabel, image);\n\nif (result.success) {\nsheet.getRange(i + 1, 10).setValue(todayStr); \/\/ 10. Sütuna (J) yazar\n} else {\nconsole.error(\\`Sürekli Hata (Satır \\${i+1}): \\${result.error}\\`);\n}\n}\n}\n}\n}\n\nfunction processOneTime(sheet, now) {\nconst data = sheet.getDataRange().getValues();\nconst todayStr = Utilities.formatDate(now, \"GMT+3\", \"dd.MM.yyyy\");\n\nfor (let i = 1; i \u003C data.length; i++) {\n\/\/ SÜTUNLAR: A:Tarih, B:Saat, C:Başlık, D:Mesaj, E:Hedef, F:HariçTopic, G:PlatformHariç, H:Kampanya, I:Resim, J:Durum\nlet [date, time, title, msg, target, excludeTopic, excludePlatform, analyticsLabel, image, status] = data[i];\n\nif (!target || target.toString().trim() === \"\") continue;\n\nif (formatDate(date) === todayStr \u0026\u0026 isTimeMatch(time, now) \u0026\u0026 status !== \"Gönderildi\") {\nconst result = sendFCM(title, msg, target, excludeTopic, excludePlatform, analyticsLabel, image);\n\nif (result.success) {\nsheet.getRange(i + 1, 10).setValue(\"Gönderildi\"); \/\/ 10. Sütuna (J) yazar\n} else {\nsheet.getRange(i + 1, 10).setValue(\\`HATA: \\${result.error}\\`);\n}\n}\n}\n}\n\n\/\/ --- ZAMAN TOLERANSI ---\nfunction isTimeMatch(targetTime, now) {\nconst target = (targetTime instanceof Date) ?\nUtilities.formatDate(targetTime, \"GMT+3\", \"HH:mm\") : targetTime;\n\nconst current = Utilities.formatDate(now, \"GMT+3\", \"HH:mm\");\nconst minus1 = Utilities.formatDate(new Date(now.getTime() - 60000), \"GMT+3\", \"HH:mm\");\nconst minus2 = Utilities.formatDate(new Date(now.getTime() - 120000), \"GMT+3\", \"HH:mm\");\n\nreturn (current === target || minus1 === target || minus2 === target);\n}\n\n\/\/ --- TOKEN CACHE ---\nfunction getCachedAccessToken() {\nconst props = PropertiesService.getScriptProperties();\nlet token = props.getProperty(\"FCM_TOKEN\");\nlet expiry = props.getProperty(\"FCM_TOKEN_EXPIRY\");\n\nif (token \u0026\u0026 expiry \u0026\u0026 Date.now() \u003C parseInt(expiry)) return token;\n\nconst newToken = getManualAccessToken();\nprops.setProperties({\n\"FCM_TOKEN\": newToken,\n\"FCM_TOKEN_EXPIRY\": (Date.now() + 3300000).toString()\n});\nreturn newToken;\n}\n\n\/\/ --- FIREBASE GÖNDERİM MERKEZİ ---\nfunction sendFCM(title, body, target, excludeTopic, excludePlatform, analyticsLabel, image) {\nconst url = \\`https:\/\/fcm.googleapis.com\/v1\/projects\/\\${FIREBASE_CONFIG.projectId}\/messages:send\\`;\ntry {\nconst token = getCachedAccessToken();\nconst payload = { \"message\": {} };\n\n\/\/ 0) KAMPANYA ETİKETİ İÇİN ZIRHLI FİLTRE\nif (analyticsLabel \u0026\u0026 analyticsLabel.toString().trim() !== \"\") {\nlet rawLabel = analyticsLabel.toString().trim();\n\n\/\/ Eğer hücrede \"http\" varsa (yani sütun kaymış ve resim linki buraya gelmişse) bunu yoksay.\nif (!rawLabel.startsWith(\"http\")) {\n\/\/ Firebase kuralı: Boşlukları ve özel karakterleri alt tire (_) yap. Maksimum 50 harf al.\nlet safeLabel = rawLabel.replace(\/[^a-zA-Z0-9-_.~%]\/g, \"_\").substring(0, 50);\n\npayload.message.fcm_options = {\n\"analytics_label\": safeLabel\n};\n}\n}\n\nlet plat = excludePlatform ? excludePlatform.toString().trim().toLowerCase() : \"\";\n\n\/\/ 1) PLATFORMA GÖRE PAKETLEME\nif (plat === 'ios' || plat === 'iphone') {\npayload.message.android = {\n\"notification\": { \"title\": title, \"body\": body }\n};\nif (image \u0026\u0026 image.toString().trim() !== \"\") {\npayload.message.android.notification.image = image.toString().trim();\n}\n}\nelse if (plat === 'android') {\npayload.message.apns = {\n\"payload\": {\n\"aps\": {\n\"alert\": { \"title\": title, \"body\": body },\n\"badge\": 1,\n\"sound\": \"default\"\n}\n}\n};\nif (image \u0026\u0026 image.toString().trim() !== \"\") {\npayload.message.apns.payload.aps[\"mutable-content\"] = 1;\n\/\/ Eğer fcm_options zaten etiket için oluşturulduysa onu bozmamak için birleştiriyoruz\npayload.message.apns.fcm_options = payload.message.fcm_options || {};\npayload.message.apns.fcm_options.image = image.toString().trim();\n}\n}\nelse {\npayload.message.notification = { \"title\": title, \"body\": body };\npayload.message.apns = {\n\"payload\": { \"aps\": { \"alert\": { \"title\": title, \"body\": body }, \"badge\": 1, \"sound\": \"default\" } }\n};\nif (image \u0026\u0026 image.toString().trim() !== \"\") {\nconst imgUrl = image.toString().trim();\npayload.message.notification.image = imgUrl;\npayload.message.apns.payload.aps[\"mutable-content\"] = 1;\n\npayload.message.apns.fcm_options = payload.message.fcm_options || {};\npayload.message.apns.fcm_options.image = imgUrl;\n}\n}\n\n\/\/ 2) GRUP KOŞULU\nlet conditions = [\\`'\\${target}' in topics\\`];\n\nif (excludeTopic \u0026\u0026 excludeTopic.toString().trim() !== \"\") {\nconditions.push(\\`!('\\${excludeTopic.toString().trim()}' in topics)\\`);\n}\n\nif (conditions.length \u003E 1) {\npayload.message.condition = conditions.join(\" \u0026\u0026 \");\n} else {\npayload.message.topic = target;\n}\n\nconst options = {\n\"method\": \"post\",\n\"contentType\": \"application\/json\",\n\"payload\": JSON.stringify(payload),\n\"headers\": { \"Authorization\": \"Bearer \" + token },\n\"muteHttpExceptions\": true\n};\n\nconst response = UrlFetchApp.fetch(url, options);\nconst code = response.getResponseCode();\nif (code === 200) return { success: true };\n\nreturn { success: false, error: \\`Kod \\${code}: \\${response.getContentText()}\\` };\n} catch (e) {\nreturn { success: false, error: e.toString() };\n}\n}\n\nfunction getISOWeek(date) {\nconst d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));\nconst dayNum = d.getUTCDay() || 7;\nd.setUTCDate(d.getUTCDate() + 4 - dayNum);\nconst yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));\nreturn Math.ceil((((d - yearStart) \/ 86400000) + 1) \/ 7);\n}\n\nfunction formatDate(date) {\nif (date instanceof Date) return Utilities.formatDate(date, \"GMT+3\", \"dd.MM.yyyy\");\nreturn date;\n}\n\nfunction getManualAccessToken() {\nconst header = JSON.stringify({ \"alg\": \"RS256\", \"typ\": \"JWT\" });\nconst now = Math.floor(Date.now() \/ 1000);\nconst claimSet = JSON.stringify({\n\"iss\": FIREBASE_CONFIG.clientEmail,\n\"scope\": \"https:\/\/www.googleapis.com\/auth\/firebase.messaging\",\n\"aud\": \"https:\/\/oauth2.googleapis.com\/token\",\n\"exp\": now + 3600,\n\"iat\": now\n});\n\nconst encode = (str) =\u003E Utilities.base64EncodeWebSafe(str).replace(\/=+$\/, '');\nconst signatureInput = encode(header) + \".\" + encode(claimSet);\nconst signature = Utilities.computeRsaSha256Signature(signatureInput, FIREBASE_CONFIG.privateKey);\nconst jwt = signatureInput + \".\" + encode(signature);\n\nconst options = {\n\"method\": \"post\",\n\"payload\": { \"grant_type\": \"urn:ietf:params:oauth:grant-type:jwt-bearer\", \"assertion\": jwt }\n};\n\nconst response = UrlFetchApp.fetch(\"https:\/\/oauth2.googleapis.com\/token\", options);\nreturn JSON.parse(response.getContentText()).access_token;\n}`;\n\n  \/\/ State Management\n  let activeTab = 'surekli';\n  let selectedColumn = 'A';\n\n  \/\/ Initialize\n  window.addEventListener('DOMContentLoaded', () =\u003E {\n    \/\/ Initialize Lucide Icons\n    lucide.createIcons();\n\n    \/\/ Load Apps Script Code into HTML\n    document.getElementById('code-block-pre').textContent = appsScriptCodeString;\n\n    \/\/ Render components\n    renderSpreadsheetGrid();\n    updateFormulaBar();\n    updateColumnDetail();\n  });\n\n  \/\/ Switch Sheet Tab\n  function switchSheetTab(tab) {\n    if (activeTab === tab) return;\n    activeTab = tab;\n    selectedColumn = 'A';\n\n    \/\/ Toggle button styles\n    const btnSurekli = document.getElementById('tab-surekli-btn');\n    const btnTek = document.getElementById('tab-tekSeferlik-btn');\n    const label = document.getElementById('sheet-label');\n\n    if (activeTab === 'surekli') {\n      btnSurekli.className = 'px-5 py-2.5 rounded-xl font-bold text-sm transition-all bg-white text-[#182C61] shadow-sm border border-slate-200';\n      btnTek.className = 'px-5 py-2.5 rounded-xl font-bold text-sm transition-all text-slate-600 hover:text-[#182C61] hover:bg-white\/50';\n      label.textContent = 'Sürekli Sekmesi';\n    } else {\n      btnTek.className = 'px-5 py-2.5 rounded-xl font-bold text-sm transition-all bg-white text-[#182C61] shadow-sm border border-slate-200';\n      btnSurekli.className = 'px-5 py-2.5 rounded-xl font-bold text-sm transition-all text-slate-600 hover:text-[#182C61] hover:bg-white\/50';\n      label.textContent = 'TekSeferlik Sekmesi';\n    }\n\n    renderSpreadsheetGrid();\n    updateFormulaBar();\n    updateColumnDetail();\n  }\n\n  \/\/ Render Grid\n  function renderSpreadsheetGrid() {\n    const columns = activeTab === 'surekli' ? columnDataSurekli : columnDataTekSeferlik;\n    \n    \/\/ Header row\n    const headerRow = document.getElementById('grid-header-row');\n    headerRow.innerHTML = '\u003Cth class=\"p-2 border-r border-b border-slate-200 bg-slate-200 text-center w-12 font-mono text-[10px]\"\u003E#\u003C\/th\u003E';\n    columns.forEach(col =\u003E {\n      const activeClass = selectedColumn === col.id ? 'bg-emerald-50 text-[#0f9d58] border-b-2 border-b-[#0f9d58]' : 'text-slate-600 hover:bg-slate-200\/60';\n      headerRow.innerHTML += `\n        \u003Cth onclick=\"selectColumn('${col.id}')\" class=\"p-2 border-r border-b border-slate-200 font-mono text-center text-xs transition-colors cursor-pointer relative ${activeClass}\"\u003E\n          ${col.id}\n        \u003C\/th\u003E\n      `;\n    });\n\n    \/\/ Row 1: Titles\n    const row1 = document.getElementById('grid-row-1');\n    row1.innerHTML = '\u003Ctd class=\"p-2 border-r border-slate-200 bg-slate-100 text-center font-bold text-slate-500 text-xs\"\u003E1\u003C\/td\u003E';\n    columns.forEach(col =\u003E {\n      const activeClass = selectedColumn === col.id ? 'bg-emerald-50\/40 outline outline-2 outline-[#0f9d58] z-10' : 'hover:bg-slate-50';\n      row1.innerHTML += `\n        \u003Ctd onclick=\"selectColumn('${col.id}')\" class=\"p-3 border-r border-slate-200 text-center font-bold text-slate-800 transition-all cursor-pointer relative ${activeClass}\"\u003E\n          \u003Cspan class=\"inline-block truncate max-w-full text-slate-900 font-extrabold\"\u003E${col.name}\u003C\/span\u003E\n        \u003C\/td\u003E\n      `;\n    });\n\n    \/\/ Row 2: Samples\n    const row2 = document.getElementById('grid-row-2');\n    row2.innerHTML = '\u003Ctd class=\"p-2 border-r border-slate-200 bg-slate-100 text-center font-bold text-slate-500 text-xs\"\u003E2\u003C\/td\u003E';\n    columns.forEach(col =\u003E {\n      const activeClass = selectedColumn === col.id ? 'bg-emerald-50\/40 outline outline-2 outline-[#0f9d58] z-10 font-bold' : 'hover:bg-slate-50';\n      row2.innerHTML += `\n        \u003Ctd onclick=\"selectColumn('${col.id}')\" class=\"p-3 border-r border-slate-200 text-center text-slate-600 font-mono text-xs transition-all cursor-pointer relative ${activeClass}\"\u003E\n          \u003Cspan class=\"inline-block truncate max-w-full\"\u003E${col.sample}\u003C\/span\u003E\n        \u003C\/td\u003E\n      `;\n    });\n\n    \/\/ Row 3: Samples 2\n    const row3 = document.getElementById('grid-row-3');\n    row3.innerHTML = '\u003Ctd class=\"p-2 border-r border-slate-200 bg-slate-100 text-center font-bold text-slate-500 text-xs\"\u003E3\u003C\/td\u003E';\n    columns.forEach(col =\u003E {\n      const activeClass = selectedColumn === col.id ? 'bg-emerald-50\/40 outline outline-2 outline-[#0f9d58] z-10 text-slate-600' : 'hover:bg-slate-50';\n      \n      let sampleVal2 = \"\";\n      if (activeTab === 'surekli') {\n        if (col.id === 'A') sampleVal2 = 'Salı';\n        else if (col.id === 'B') sampleVal2 = '19:45';\n        else if (col.id === 'C') sampleVal2 = 'Hatırlatıcı Seans';\n        else if (col.id === 'D') sampleVal2 = 'Seansınız başlamak üzere!';\n        else if (col.id === 'E') sampleVal2 = 'All_users';\n        else if (col.id === 'F') sampleVal2 = '-';\n        else if (col.id === 'G') sampleVal2 = '-';\n        else if (col.id === 'H') sampleVal2 = '-';\n        else if (col.id === 'I') sampleVal2 = 'BOŞ';\n        else if (col.id === 'J') sampleVal2 = '2';\n        else if (col.id === 'K') sampleVal2 = '1';\n      } else {\n        if (col.id === 'A') sampleVal2 = '10.11.2026';\n        else if (col.id === 'B') sampleVal2 = '09:05';\n        else if (col.id === 'C') sampleVal2 = 'Ata\\'yı Anma Bildirimi';\n        else if (col.id === 'D') sampleVal2 = 'Saygı ve özlemle anıyoruz.';\n        else if (col.id === 'E') sampleVal2 = 'All_users';\n        else if (col.id === 'F') sampleVal2 = '-';\n        else if (col.id === 'G') sampleVal2 = '-';\n        else if (col.id === 'H') sampleVal2 = '-';\n        else if (col.id === 'I') sampleVal2 = 'GÖNDERİLDİ';\n      }\n\n      row3.innerHTML += `\n        \u003Ctd onclick=\"selectColumn('${col.id}')\" class=\"p-3 border-r border-slate-200 text-center text-slate-400 font-mono text-xs transition-all cursor-pointer relative ${activeClass}\"\u003E\n          \u003Cspan class=\"inline-block truncate max-w-full italic\"\u003E${sampleVal2}\u003C\/span\u003E\n        \u003C\/td\u003E\n      `;\n    });\n  }\n\n  \/\/ Select Column\n  function selectColumn(colId) {\n    selectedColumn = colId;\n    renderSpreadsheetGrid();\n    updateFormulaBar();\n    updateColumnDetail();\n  }\n\n  \/\/ Update Formula Bar\n  function updateFormulaBar() {\n    const colBox = document.getElementById('formula-col-id');\n    const textBar = document.getElementById('formula-bar-text');\n    const columns = activeTab === 'surekli' ? columnDataSurekli : columnDataTekSeferlik;\n    const col = columns.find(c =\u003E c.id === selectedColumn);\n\n    if (col) {\n      colBox.textContent = col.id;\n      textBar.innerHTML = `=VERİ_TİPİ(\u003Cstrong\u003E${col.type}\u003C\/strong\u003E) — Değer: \"\u003Cspan class=\"text-emerald-600 font-bold\"\u003E${col.sample}\u003C\/span\u003E\"`;\n    }\n  }\n\n  \/\/ Update Detail Panel\n  function updateColumnDetail() {\n    const columns = activeTab === 'surekli' ? columnDataSurekli : columnDataTekSeferlik;\n    const col = columns.find(c =\u003E c.id === selectedColumn);\n\n    if (col) {\n      document.getElementById('detail-badge').textContent = col.id;\n      document.getElementById('detail-title').textContent = `Sütun ${col.id}: ${col.name}`;\n      document.getElementById('detail-type').textContent = `Tip: ${col.type}`;\n      \n      const reqBadge = document.getElementById('detail-req');\n      reqBadge.textContent = col.req;\n      if (col.req.includes('Zorunlu')) {\n        reqBadge.className = 'px-3 py-1 rounded-full font-black uppercase tracking-wider bg-rose-100 text-rose-700';\n      } else if (col.req.includes('SİSTEM')) {\n        reqBadge.className = 'px-3 py-1 rounded-full font-black uppercase tracking-wider bg-amber-100 text-amber-800';\n      } else {\n        reqBadge.className = 'px-3 py-1 rounded-full font-black uppercase tracking-wider bg-emerald-100 text-emerald-800';\n      }\n\n      document.getElementById('detail-desc').textContent = col.desc;\n      document.getElementById('detail-sample').textContent = `\"${col.sample}\"`;\n    }\n  }\n\n  \/\/ Copy Apps Script Code Action\n  function copyAppsScriptCode() {\n    navigator.clipboard.writeText(appsScriptCodeString).then(() =\u003E {\n      const btnText = document.getElementById('copy-btn-text');\n      btnText.textContent = 'Kopyalandı! ✓';\n      setTimeout(() =\u003E {\n        btnText.textContent = 'Kopyala';\n      }, 2000);\n    });\n  }\n\n  \/\/ Developer Step Accordion Toggle with Exclusive Open Mode\n  function toggleDevStep(index) {\n    const totalSteps = 4;\n    const badgesInfo = [\n      { id: 'dev-badge-0', activeBg: 'bg-indigo-600', activeText: 'text-white', inactiveBg: 'bg-indigo-50', inactiveText: 'text-[#182C61]' },\n      { id: 'dev-badge-1', activeBg: 'bg-emerald-600', activeText: 'text-white', inactiveBg: 'bg-emerald-50', inactiveText: 'text-[#0f9d58]' },\n      { id: 'dev-badge-2', activeBg: 'bg-rose-600', activeText: 'text-white', inactiveBg: 'bg-rose-50', inactiveText: 'text-rose-600' },\n      { id: 'dev-badge-3', activeBg: 'bg-slate-700', activeText: 'text-white', inactiveBg: 'bg-slate-100', inactiveText: 'text-slate-700' }\n    ];\n\n    for (let i = 0; i \u003C totalSteps; i++) {\n      const card = document.getElementById(`dev-card-${i}`);\n      const content = document.getElementById(`dev-content-${i}`);\n      const chevron = document.getElementById(`dev-chevron-${i}`);\n      const badge = document.getElementById(badgesInfo[i].id);\n\n      if (i === index) {\n        \/\/ Toggle the clicked step\n        if (content.classList.contains('hidden')) {\n          content.classList.remove('hidden');\n          chevron.textContent = '-';\n          chevron.style.transform = 'rotate(180deg)';\n          card.className = `border rounded-[2rem] overflow-hidden bg-white border-${i === 0 ? 'indigo' : i === 1 ? 'emerald' : i === 2 ? 'rose' : 'slate-400'}-200 shadow-md transition-all duration-300`;\n          badge.className = `w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg transition-colors duration-300 ${badgesInfo[i].activeBg} ${badgesInfo[i].activeText}`;\n        } else {\n          content.classList.add('hidden');\n          chevron.textContent = '+';\n          chevron.style.transform = 'rotate(0deg)';\n          card.className = 'border rounded-[2rem] overflow-hidden bg-slate-50\/50 border-slate-200\/60 transition-all duration-300';\n          badge.className = `w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg transition-colors duration-300 ${badgesInfo[i].inactiveBg} ${badgesInfo[i].inactiveText}`;\n        }\n      } else {\n        \/\/ Close all other steps\n        content.classList.add('hidden');\n        chevron.textContent = '+';\n        chevron.style.transform = 'rotate(0deg)';\n        card.className = 'border rounded-[2rem] overflow-hidden bg-slate-50\/50 border-slate-200\/60 transition-all duration-300';\n        badge.className = `w-12 h-12 rounded-2xl flex items-center justify-center shrink-0 font-bold font-mono text-lg transition-colors duration-300 ${badgesInfo[i].inactiveBg} ${badgesInfo[i].inactiveText}`;\n      }\n    }\n  }\n\n  \/\/ FAQ Accordion Toggles\n  function toggleFaqAccordion(index) {\n    const content = document.getElementById(`faq-content-${index}`);\n    const icon = document.getElementById(`faq-icon-${index}`);\n    \n    if (content.classList.contains('hidden')) {\n      content.classList.remove('hidden');\n      icon.style.transform = 'rotate(180deg)';\n    } else {\n      content.classList.add('hidden');\n      icon.style.transform = 'rotate(0deg)';\n    }\n  }\n\u003C\/script\u003E\n"},"link":[{"rel":"edit","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/240465725954351231"},{"rel":"self","type":"application/atom+xml","href":"https:\/\/www.blogger.com\/feeds\/6723758798785343725\/posts\/default\/240465725954351231"},{"rel":"alternate","type":"text/html","href":"https:\/\/www.aakif.net\/2026\/07\/e-tablo-firebase-entegrasyonu-bildirim.html","title":"E-Tablo \u0026 Firebase Entegrasyonu Bildirim Yönetim Kılavuzu"}],"author":[{"name":{"$t":"muhammed akifkayacan"},"uri":{"$t":"http:\/\/www.blogger.com\/profile\/05111891138190652811"},"email":{"$t":"noreply@blogger.com"},"gd$image":{"rel":"http://schemas.google.com/g/2005#thumbnail","width":"16","height":"16","src":"https:\/\/img1.blogblog.com\/img\/b16-rounded.gif"}}],"media$thumbnail":{"xmlns$media":"http://search.yahoo.com/mrss/","url":"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEiEiL9FS2Qu6d5j_5fEppwZmworExjejYl9iwjR3u5R7fhSJPFLLS_mr5ALeskdleGoEifYzmGYs9AeeklWeHIpul2S9pKIWaeeaEfLicMHvY_MKX41IDV_iF-HvAo19YRsm3fi5HFbqxJGbNbvtYTV3Lld2AMsnMIuHQoMP4vm6B6f0C4hdf6_WKJ8ppOg\/s72-c\/IMG_6349.jpeg","height":"72","width":"72"}}]}}