İSG Risk Analizi – L Tipi Matris

İş sağlığı ve güvenliğinin (İSG) temel amaçlarından biri, işyerlerinde meydana gelebilecek kazaları ve meslek hastalıklarını henüz oluşmadan önlemektir. Bunun için tehlikelerin belirlenmesi, risklerin değerlendirilmesi ve gerekli güvenlik önlemlerinin planlanması büyük önem taşır.

İSG Risk Analizi – L Tipi Matris HTML Uygulaması, işyerindeki tehlikelerin sistematik biçimde değerlendirilmesini, risklerin puanlanmasını, alınacak tedbirlerin takip edilmesini ve sonuçların kayıt altına alınmasını sağlayan dinamik bir risk değerlendirme aracıdır.

Uygulama, 5×5 L Tipi Matris yöntemini kullanır. Risk hesaplamalarını otomatik gerçekleştirir, renkli risk matrisi üzerinden sonuçları gösterir ve risk kayıtlarının Excel ile yönetilmesine olanak sağlar.

1. L Tipi Matris Risk Analizi Nedir?

L Tipi Matris, iş sağlığı ve güvenliğinde kullanılan yarı nicel risk değerlendirme yöntemlerinden biridir. Bir tehlikenin zarara yol açma olasılığı ile ortaya çıkabilecek sonucun şiddeti birlikte değerlendirilerek risk puanı hesaplanır.

Risk Puanı = Olasılık × Şiddet

Olasılık ve şiddet değerleri 1 ile 5 arasında belirlenir. Hesaplama sonucunda 1 ile 25 arasında risk puanı elde edilir.

Uygulamada kullanılan örnek sınıflandırma şu şekildedir:

Risk puanıRisk seviyesiRenk
1–2Çok düşükKoyu yeşil
3–5DüşükAçık yeşil
6–10OrtaSarı
11–15YüksekTuruncu
16–25Çok yüksekKırmızı

Risk seviyesi yükseldikçe kontrol önlemlerinin önceliği artar. Ancak yalnızca sayısal puanlama yeterli değildir. Mevzuatın gerektirdiği güvenlik tedbirleri ve tehlikenin niteliği ayrıca değerlendirilmelidir.

2. HTML Risk Analizi Uygulaması Ne İşe Yarar?

Uygulamanın amacı, risk değerlendirmesinin yalnızca bir tablo doldurma işlemi olarak kalmasını önleyerek tehlikelerin, tedbirlerin, sorumluların ve sonuçların bir arada takip edilmesini sağlamaktır.

Uygulamayla işyerindeki farklı bölümlere ait riskler ayrı ayrı kaydedilebilir. Risklerin mevcut durumu ve alınacak tedbirler sonrasında hedeflenen seviyeleri karşılaştırılabilir.

Otomatik puanlama özelliği sayesinde hesaplama hatalarının azaltılması hedeflenir. Ayrıca risk kayıtları üzerinde arama, düzenleme, silme ve aksiyon takibi yapılabilir.

Program, tek bir HTML dosyası olarak çalışır. İnternet bağlantısına veya ayrı bir program kurulumuna ihtiyaç duymaz.

3. Risk Analizi Formu Nasıl Doldurulur?

Form doğrudan HTML uygulaması üzerinden doldurulur. Önceden Excel tablosu hazırlamak zorunlu değildir. Excel içeri aktarma özelliği, önceden hazırlanmış veya daha önce dışarı aktarılmış risk kayıtlarını yüklemek için kullanılır.

Aşama 1 – İşyeri ve değerlendirme bilgileri

İlk bölümde değerlendirmenin hangi işyerine ait olduğunu gösteren temel bilgiler doldurulur.

  • İşyeri / Firma: İşletmenin adı yazılır.
  • Tesis / Birim: Değerlendirmenin yapıldığı fabrika, tesis veya birim belirtilir.
  • Hazırlayan / Ekip: Risk değerlendirmesini hazırlayan kişi veya ekip bilgileri girilir.
  • Değerlendirme Tarihi: Çalışmanın yapıldığı tarih seçilir.
  • Revizyon / Belge No.: Değerlendirmeye ait belge veya revizyon numarası yazılır.

Bu bölüm, risk değerlendirme çalışmasının kimlik bilgilerini oluşturur.

Aşama 2 – Riskin tanımlanması

Bu bölümde değerlendirmeye konu olan iş, faaliyet ve tehlike tanımlanır.

  • Bölüm / Alan: Tehlikenin bulunduğu çalışma alanı belirtilir. Örneğin üretim atölyesi, depo veya bakım bölümü.
  • Faaliyet / İş Adımı: Yapılan iş açıklanır. Örneğin malzeme taşıma, makine kullanımı veya bakım işlemi.
  • Etkilenebilecek Kişiler: Çalışanlar, bakım personeli, ziyaretçiler veya diğer ilgili kişiler belirtilir.
  • Tehlike Kaynağı: Zarar oluşturabilecek durum tanımlanır. Örneğin korumasız makine hareketli parçaları.
  • Risk / Olası Zarar: Tehlikenin oluşturabileceği sonuç yazılır. Örneğin elin makineye sıkışması ve ciddi yaralanma.
  • Mevcut Kontroller / Önlemler: Tehlikeye karşı hâlihazırda uygulanan güvenlik tedbirleri belirtilir.

Tehlike ve olası zarar alanlarının açık, anlaşılır ve birbirinden ayrı tanımlanması sağlıklı risk değerlendirmesi için önemlidir.

Aşama 3 – Mevcut riskin hesaplanması

Tehlike belirlendikten sonra mevcut riskin olasılık ve şiddet değerleri seçilir.

Örneğin bir makinede sıkışma tehlikesi bulunduğunu düşünelim.

  • Olasılık: 4
  • Şiddet: 5
  • Risk puanı: 4 × 5 = 20

Uygulama risk puanını otomatik hesaplar ve sonucu Çok Yüksek Risk olarak gösterir.

Bu riskin öncelikle ele alınması ve etkili kontrol tedbirlerinin belirlenmesi gerekir.

Aşama 4 – Alınacak tedbirlerin belirlenmesi

Bu bölümde riski azaltmak için yapılması gereken çalışmalar kayıt altına alınır.

  • Alınacak Tedbirler / Düzeltici Faaliyet: Planlanan önlemler açıklanır.
  • Sorumlu Kişi / Birim: Tedbirin uygulanmasından sorumlu kişi veya bölüm belirtilir.
  • Hedef Tamamlanma Tarihi: Önlemin hangi tarihe kadar uygulanacağı seçilir.
  • Aksiyon Durumu: Açık, Devam Ediyor veya Tamamlandı seçeneklerinden uygun olanı işaretlenir.
  • Ek Açıklamalar / Doğrulama Kanıtı: Yapılan çalışmalar ve bunların doğrulanmasına ilişkin bilgiler girilir.

Bu sayede riskin yalnızca tespit edilmesi değil, giderilmesine yönelik çalışmaların da takip edilmesi sağlanır.

Aşama 5 – Önlem sonrası hedef riskin değerlendirilmesi

Planlanan güvenlik tedbirlerinin riski ne ölçüde azaltacağı değerlendirilerek hedef olasılık ve şiddet değerleri seçilir.

Örneğin uygun makine koruyucuları takıldıktan ve güvenli çalışma prosedürleri uygulandıktan sonra olasılığın 4'ten 1'e düşmesi hedeflenebilir.

Şiddet değeri 5 olarak kalırsa:

Hedef risk puanı = 1 × 5 = 5

Bu değer uygulamada Düşük Risk seviyesine karşılık gelir.

Ancak önemli bir ayrım vardır: Önlem sonrası hedef risk, tedbir uygulanıp etkinliği doğrulanıncaya kadar gerçekleşmiş sonuç olarak kabul edilmez.

Uygulamadaki “Kalan risk doğrulandı” seçeneği yalnızca ilgili aksiyon tamamlandığında ve önlemin etkinliği kontrol edildiğinde kullanılmalıdır.

Aşama 6 – Risk kaydının oluşturulması

Gerekli alanlar doldurulduktan sonra Riski Kaydet butonuna basılır.

Kaydedilen risk, uygulamanın “Risk Kayıtları ve Aksiyon Takibi” bölümüne eklenir.

Yeni bir risk değerlendirmek için aynı işlem tekrarlanır. Önceden oluşturulmuş kayıtlar gerektiğinde düzenlenebilir veya silinebilir.

4. 5×5 Renkli Risk Matrisi Nasıl Kullanılır?

Uygulamanın önemli özelliklerinden biri, risklerin görsel olarak değerlendirilmesini sağlayan 5×5 renkli matristir.

Matrisin dikey ekseninde olasılık, yatay ekseninde şiddet değerleri bulunur.

Sol alt bölümden sağ üst bölüme doğru risk puanı yükseldikçe renkler koyu yeşilden kırmızıya doğru değişir.

Uygulamada iki farklı matris görünümü bulunur.

Tekil Risk Matrisi

Bu görünüm, üzerinde çalışılan tek bir risk kaydını gösterir.

Mevcut risk mavi çerçeveyle, önlem sonrası hedef risk mor kesik çerçeveyle işaretlenir.

Olasılık veya şiddet değerleri değiştirildiğinde ilgili hücre otomatik güncellenir. Böylece alınması planlanan tedbirlerin hedef risk seviyesini nasıl değiştireceği görülebilir.

Genel Risk Dağılımı

Bu görünüm, uygulamada kayıtlı olan bütün risklerin 5×5 matris üzerindeki dağılımını gösterir.

Örneğin Excel'den 15 risk kaydı aktarıldığında, her kaydın mevcut olasılık ve şiddet değerleri dikkate alınarak matris hücrelerinde kaç risk bulunduğu hesaplanır.

Bir hücrede 3 yazıyorsa, o olasılık ve şiddet birleşiminde üç ayrı risk kaydı bulunmaktadır.

Genel Risk Dağılımı, risk puanlarının ortalamasını değil, risk kayıtlarının sayısal dağılımını gösterir.

Bu özellik, yüksek ve çok yüksek risklerin hangi bölgelerde yoğunlaştığını belirlemeyi kolaylaştırır.

5. Excel İçeri Aktar ve Excel Dışarı Aktar Nasıl Kullanılır?

Uygulamada risk kayıtlarının dosya üzerinden yönetilebilmesi için iki Excel işlemi bulunur.

Excel İçeri Aktar: Daha önce hazırlanmış veya uygulamadan dışarı aktarılmış Excel dosyasındaki risk kayıtlarının HTML formuna yüklenmesini sağlar. Mevcut kayıtlar varsa içeri aktarma bunları değiştireceğinden işlem öncesinde yedek alınmalıdır.

Excel Dışarı Aktar: Uygulamada oluşturulan risk kayıtlarını Excel dosyası olarak bilgisayara kaydeder.

Excel dosyası daha sonra yeniden içeri aktarılabilir. Böylece kayıtların düzenlenmesi ve farklı zamanlarda değerlendirmeye devam edilmesi mümkün olur.

Form üzerinden giriş yapılabildiği için Excel kullanımı zorunlu değildir.

6. PDF / Yazdır Özelliği Ne İşe Yarar?

Uygulamadaki PDF / Yazdır butonu, hazırlanan risk değerlendirme çalışmasının raporlanmasını sağlar.

Yazdırma sırasında formun başlık yapısı, dış çerçevesi, bölüm düzeni, renkli risk matrisi ve kayıt bilgileri korunacak şekilde çıktı hazırlanır.

Çok sayfalı raporlarda başlık ve logo tekrar eder. Sayfa numaraları sağ alt bölümde gösterilir. Excel ve PDF işlem butonları ise çıktı üzerinde yer almaz.

PDF oluşturmak için yazdırma penceresinde PDF olarak kaydet seçeneği kullanılabilir.

Bu özellik, risk değerlendirme raporunun arşivlenmesini, incelenmesini ve ilgili kişilerle paylaşılmasını kolaylaştırır.

7. Veriler Nerede Saklanır?

Uygulama çevrimdışı çalışacak şekilde hazırlanmıştır.

Oluşturulan kayıtlar kullanılan tarayıcının yerel depolama alanında saklanır. Uygulamanın temel kayıt işlemleri için internet bağlantısı veya harici sunucu gerekmez.

Ancak tarayıcı verilerinin silinmesi, farklı tarayıcı kullanılması veya cihazın değiştirilmesi durumunda yerel kayıtlar kullanılamayabilir.

Bu nedenle çalışmaların düzenli olarak Excel Dışarı Aktar seçeneğiyle yedeklenmesi önerilir.

8. Kimler Kullanabilir?

İSG Risk Analizi – L Tipi Matris uygulaması; iş güvenliği uzmanları, işverenler, işletme yöneticileri, bölüm sorumluları, bakım ekipleri ve risk değerlendirme çalışmalarına katılan diğer yetkili kişiler tarafından kullanılabilir.

Özellikle ofisler, küçük ve orta ölçekli işletmeler, atölyeler, depolar ve üretim alanlarında 5×5 yönteminin uygun görüldüğü risk değerlendirmelerinde yararlı bir araçtır.

Ancak karmaşık prosesler, patlama tehlikeleri veya özel mühendislik analizleri gerektiren faaliyetlerde yalnızca 5×5 yöntemi yeterli olmayabilir. İşyerinin özelliklerine uygun ek risk analizi yöntemlerinin kullanılması gerekebilir.

Sonuç

İSG Risk Analizi – L Tipi Matris HTML Uygulaması, işyerindeki tehlikelerin belirlenmesi, risklerin puanlanması, kontrol tedbirlerinin planlanması ve aksiyonların takip edilmesi için geliştirilmiş pratik bir dijital araçtır.

Otomatik risk hesaplama, tekil ve genel risk matrisi, Excel veri alışverişi, PDF raporlama ve yerel kayıt özellikleri sayesinde risk değerlendirme sürecinin daha düzenli, anlaşılır ve izlenebilir yürütülmesini destekler.

Uygulamanın en önemli faydası, hangi riskin ne kadar önemli olduğunu ve bu riski azaltmak için hangi tedbirlerin alınması gerektiğini tek bir sistem üzerinden takip edebilmesidir.

Önemli not: Uygulama bir değerlendirme ve kayıt aracıdır. Tek başına işyerinin mevzuat kapsamındaki tüm risk değerlendirme yükümlülüklerinin yerine getirildiği anlamına gelmez. Risk seviyeleri, alınacak tedbirler ve değerlendirme sonuçları yetkili kişilerce işyerinin gerçek koşullarına göre doğrulanmalıdır.


Bilgisayarda kullanmak için;
Bir Not defteri açarak, aşağıdaki (Mavi satırlar) html kodu içine kaydedin. Not defteri uzantısını .txt yerine ".html" olarak değiştirip kaydedin. Ör: "İSG Risk Analizi – L Tipi Matris.html" sayfayı kapatıp tekrar açtığınızda, web browser üzerinden sayfanız açılacaktır. Tüm kurum ve işletmelerde kullanabilecek bir formdur.

Sol tarafta görünen logo için, html dosyanız nerede ise, masaüstü veya oluşturulan bir klasör. Logonuzda aynı yerde olursa forma yansır. Logo ismi "logo.jpg" olmalı. Çift tıklayarak açtığınızda, browser üzerinde form açılışı gerçekleşir. Veya alanına 5 kez peş peşe tıklayarak çalışma esnasında logo değişimi de yapılabilir.

Başlık, başlığın altındaki, başlığın sağındaki ve alttaki yazıları, not defteri içinde "Ctrl + F" tuşları ile kelime yazarak bulabilir, ilgili metinleri kendinize göre uyarlayarak kaydederek kullanabilirsiniz. Başlık alanındaki "OLGUN BAŞKANLIĞI" alanına 5 kez peş peşe tıklayarak; Departman, Müdürlük veya Başkanlığınıza ait bilgiyi manuel girebilirsiniz.

Formun boş hali;

Formun dolu hali:

PDF / Yazdır

Dışarı Aktarılan Excel Verisi:

+ Projenin Android telefonlar için mobil uygulamaya dönüştürülmüş hali aşağıdaki paylaşımdadır. "L_Tipi_Matris.apk" indir.

HTML Kod:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#0284c7">
<title>ISG Risk Analizi - L_Tipi_Matris</title>
<style>
:root{--bg:#f8fafc;--surface:#fff;--line:#dbe3eb;--text:#17283b;--muted:#64748b;--brand:#0284c7;--brand2:#0369a1;--pale:#eaf6fd;--radius:7px;--shadow:0 2px 10px rgba(22,44,68,.045)}
*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);font:13px/1.45 "Segoe UI",Arial,sans-serif;color:var(--text)}button,input,select,textarea{font:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:not-allowed}input,select,textarea{width:100%;background:#fff;border:1px solid #cbd5e1;border-radius:5px;color:var(--text);padding:8px 10px;outline:none;min-height:36px}textarea{min-height:56px;resize:vertical}input:focus,select:focus,textarea:focus{border-color:var(--brand);box-shadow:0 0 0 3px #0284c71c}label{font-weight:600;color:#334155;display:block;margin-bottom:5px;font-size:12px}label small{font-weight:400;color:var(--muted)}input[type=checkbox]{width:17px;height:17px;min-height:0;accent-color:var(--brand)}.wrap{max-width:1490px;margin:0 auto;padding:16px 22px 30px}.header{background:linear-gradient(120deg,#075985,#0284c7);color:white;border-bottom:3px solid #38bdf8}.headerinner{max-width:1490px;padding:15px 22px;display:flex;align-items:center;gap:14px;margin:auto}.logo{display:grid;place-items:center;background:#ffffff18;border:1px solid #ffffff55;width:45px;height:45px;border-radius:7px;font-size:18px;font-weight:800;letter-spacing:.7px;flex-shrink:0}.header h1{margin:0;font-size:19px;line-height:1.3;letter-spacing:.2px}.header p{margin:3px 0 0;color:#dcf3ff;font-size:12px}.badge-offline{margin-left:auto;border:1px solid #a3e4ff85;border-radius:20px;padding:6px 11px;color:#e0f7ff;font-size:11px;white-space:nowrap}.card{min-width:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}.card-header{display:flex;align-items:center;justify-content:space-between;gap:14px;border-bottom:1px solid #e9eef4;padding:11px 15px}.card-header h2{margin:0;font-size:15px;color:#0f3652;display:flex;align-items:center;gap:8px}.card-body{padding:14px 15px}.eyebrow{color:var(--brand);font-size:11px;font-weight:800;letter-spacing:.08em}.hint{font-size:11px;color:var(--muted)}.muted{color:var(--muted)}.grid{display:grid;gap:11px}.g2{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(3,minmax(0,1fr))}.g4{grid-template-columns:repeat(4,minmax(0,1fr))}.g5{grid-template-columns:repeat(5,minmax(0,1fr))}.span2{grid-column:span 2}.span3{grid-column:span 3}.stack{display:grid;grid-template-columns:minmax(0,1fr);gap:13px}.stack>*{min-width:0}.metrics{margin-bottom:13px}.metric{padding:12px 14px;display:flex;align-items:center;justify-content:space-between;gap:10px}.metric b{font-size:26px;color:#123855;line-height:1.1;display:block;margin-top:4px}.metric .icon{width:37px;height:37px;display:grid;place-items:center;border-radius:8px;background:var(--pale);color:var(--brand2);font-size:20px;font-weight:600}.metric small{font-size:11px;color:var(--muted);font-weight:600}.btn{border:1px solid var(--line);border-radius:5px;padding:8px 12px;min-height:35px;background:#fff;color:#334155;display:inline-flex;align-items:center;justify-content:center;gap:6px;white-space:nowrap;font-weight:600;transition:background .12s,border .12s}.btn:hover{background:#f1f5f9}.btn-primary{background:var(--brand);border-color:var(--brand);color:#fff}.btn-primary:hover{background:var(--brand2)}.btn-soft{background:#eef8ff;color:#0369a1;border-color:#b9def7}.btn-soft:hover{background:#e0f2fe}.btn-danger{color:#b42332;border-color:#f3c8ce}.btn-danger:hover{background:#fff1f2}.btn-small{min-height:27px;padding:5px 8px;font-size:11px}.toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:7px}.section-number{border-radius:4px;background:#e0f2fe;color:#0369a1;font-size:11px;padding:3px 6px}.method-info{background:#f2f9fd;border:1px solid #d6eefa;color:#195071;padding:9px 11px;margin-top:11px;border-radius:5px;font-size:12px}.score-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.score-panel{border:1px solid #dbe6ed;border-radius:6px;overflow:hidden;background:#fcfdff}.score-top{padding:9px 11px;border-bottom:1px solid #e4eaf0;display:flex;align-items:center;justify-content:space-between;gap:7px;background:#f2f7fb}.score-top strong{font-size:12px}.score-fields{padding:11px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.score-result{margin:0 11px 11px;padding:9px 11px;border-radius:5px;display:flex;align-items:center;justify-content:space-between;gap:7px;background:#f2f7fb}.score-result b{font-size:21px;line-height:1.2}.risk-tag{display:inline-block;border:1px solid transparent;border-radius:4px;font-size:11px;font-weight:750;padding:3px 7px;white-space:nowrap}.risk-low{color:#177245;background:#e5f7ec;border-color:#b7e5c7}.risk-medium{color:#8d6010;background:#fff5d9;border-color:#f3dda5}.risk-high{color:#ad5019;background:#fff0e1;border-color:#ffccaa}.risk-critical{color:#a92439;background:#ffe5e8;border-color:#f4b5c0}.status{display:inline-block;padding:3px 7px;border-radius:4px;background:#eef2f6;color:#334155;font-size:11px;white-space:nowrap;font-weight:600}.status-inprogress{background:#e5f3ff;color:#075985}.status-done{background:#e5f7ec;color:#166534}.checkline{display:flex;align-items:center;gap:8px;font-weight:500;margin:4px 0 0}.checkline label{display:inline;margin:0;font-weight:500;font-size:12px}.actionbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:13px}.spacer{flex:1}.tablebox{overflow-x:auto;max-width:100%}table{border-collapse:collapse;width:100%;text-align:left}th,td{padding:9px 9px;border-bottom:1px solid #e9eef3;vertical-align:top}th{background:#f3f7fa;color:#475569;font-weight:750;white-space:nowrap;font-size:11px;position:sticky;top:0;z-index:1}td{font-size:12px}tbody tr:hover{background:#f8fbfd}.tablebox table{min-width:1010px}.tablebox .namecell{min-width:160px;max-width:215px}.tablebox .hazcell{min-width:190px;max-width:280px}.tablebox .scorecell{min-width:110px}.cellsub{color:#64748b;font-size:11px;margin-top:3px;overflow-wrap:anywhere}.truncate2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.filters input{width:230px}.filters select{width:165px}.empty{padding:32px;text-align:center;color:#64748b}.foot{margin:15px 0 0;color:#64748b;font-size:11px;display:flex;gap:10px;justify-content:space-between;flex-wrap:wrap}.explain{margin-top:15px;padding:10px 12px;border:1px solid #dce6ef;border-radius:6px;background:#fff}.explain summary{font-weight:650;cursor:pointer;color:#075985}.explain p{color:#475569}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.required:after{content:' *';color:#c24141}.print-only{display:none}#toast{position:fixed;right:20px;bottom:20px;z-index:20;color:#fff;background:#143d54;border-radius:6px;padding:10px 15px;box-shadow:0 8px 30px #12283c35;max-width:390px;opacity:0;transform:translateY(10px);pointer-events:none;transition:opacity .2s,transform .2s}#toast.show{opacity:1;transform:translateY(0)}.print-note{color:#64748b;font-size:11px} .line{height:1px;background:#e8eef4;margin:10px 0}
/* Yalnızca Excel ve yazdırma işlemlerine ait yumuşak renkler */
.btn-excel-import{background:#e8f4ff;border-color:#b7d8fb;color:#075985}
.btn-excel-import:hover{background:#d7edff;border-color:#8cc5f6}
.btn-excel-export{background:#eaf8ef;border-color:#b9e2c6;color:#166534}
.btn-excel-export:hover{background:#dcf3e4;border-color:#8fcfa5}
.btn-print{background:#f1f3f5;border-color:#d6dbe1;color:#334155}
.btn-print:hover{background:#e5e9ee;border-color:#cbd5e1}
@media(max-width:930px){.g4{grid-template-columns:repeat(2,minmax(0,1fr))}.g5{grid-template-columns:repeat(3,minmax(0,1fr))}.score-grid{grid-template-columns:1fr}.badge-offline{display:none}}@media(max-width:600px){.wrap{padding:10px 10px 22px}.headerinner{padding:12px 10px}.header h1{font-size:15px}.header p{font-size:10px}.logo{width:37px;height:37px;font-size:14px}.g2,.g3,.g4,.g5{grid-template-columns:1fr}.span2,.span3{grid-column:auto}.metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.metric{padding:10px}.metric b{font-size:21px}.metric .icon{display:none}.card-body{padding:11px}.card-header{padding:10px 11px;align-items:flex-start;flex-direction:column}.filters{width:100%}.filters input,.filters select{flex:1;min-width:135px;width:auto}.toolbar{width:100%}.score-fields{grid-template-columns:1fr 1fr}.actionbar .btn{flex:1}}
@page{size:A4 landscape;margin:11mm}


/* L tipi matrise özel bağımsız görünüm */
.static-field{display:flex;align-items:center;justify-content:space-between;gap:10px;background:#eef8ff;border:1px solid #b9def7;color:#075985;font-weight:750;padding:8px 10px;min-height:36px;border-radius:5px}
.static-field span{font-size:11px;font-weight:500;color:#547a96}
/* 5×5 L Tipi Matris: açık, dinamik ve erişilebilir renkli alan */
.matrix-card{margin-top:12px;background:#fff;border:1px solid #d4e3ef;border-radius:7px;overflow:hidden}
.matrix-heading{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap;background:#eff7fc;padding:10px 13px;border-bottom:1px solid #dceaf3}
.matrix-heading h3{font-size:14px;margin:0;color:#0b4669;letter-spacing:.01em}
.matrix-heading .hint{margin:0}
.matrix-layout{display:grid;grid-template-columns:minmax(300px,435px) minmax(0,1fr);gap:18px;padding:15px;align-items:start}
.matrix-scroll{min-width:0;overflow-x:auto}
.matrix-axis{text-align:center;color:#39536c;font-size:11px;font-weight:700;margin-bottom:5px}
.matrix-table{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:4px;text-align:center}
.matrix-table th{font-size:11px;position:static;background:transparent;border:0;white-space:normal;text-align:center;padding:2px;color:#334155}
.matrix-table td{padding:0;border:0;height:49px;vertical-align:middle}
.matrix-cell{width:100%;height:49px;min-height:49px;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;border:3px solid transparent;border-radius:5px;font-size:16px;font-weight:800;cursor:pointer;transition:transform .12s,border-color .12s,box-shadow .12s}
.matrix-cell:hover{transform:scale(1.035);box-shadow:0 2px 8px #18253c35}
.matrix-cell:focus-visible{outline:3px solid #075985;outline-offset:1px}
.matrix-cell.m-dark{background:#167a46;color:#fff}
.matrix-cell.m-light{background:#91d9a3;color:#123c26}
.matrix-cell.m-yellow{background:#ffe179;color:#493509}
.matrix-cell.m-orange{background:#ffa95c;color:#51280a}
.matrix-cell.m-red{background:#e35d60;color:#fff}
.matrix-cell.is-before{border-color:#074a9b;box-shadow:0 0 0 1px #fff inset}
.matrix-cell.is-after{outline:3px dashed #7139ae;outline-offset:-6px}
.matrix-cell.is-before.is-after{border-color:#074a9b;outline:3px dashed #7139ae;outline-offset:-7px}
.matrix-cell .cell-labels{display:flex;gap:3px;position:absolute;bottom:2px;right:2px}
.matrix-cell .cell-labels span{font-size:9px;line-height:13px;height:14px;padding:0 3px;border-radius:2px;background:#fff;color:#154779}
.matrix-cell .cell-labels span.after-marker{background:#f1e5ff;color:#622f98}
.risk-vlow{color:#115735;background:#ccebd4;border-color:#92cc9f}
.matrix-legend{font-size:12px;color:#475569;display:grid;gap:11px;min-width:0}
.matrix-picker{padding:11px;border:1px solid #dfebf2;border-radius:6px;background:#f7fbfe}
.matrix-picker strong{display:block;font-size:12px;margin-bottom:8px;color:#234560}
.matrix-picker-controls{display:flex;gap:7px;flex-wrap:wrap}
.matrix-choice{padding:7px 10px;font-size:12px;min-height:34px;border:1px solid #cbd5e1;border-radius:5px;background:#fff;color:#475569;font-weight:700}
.matrix-choice.active{border-color:#0284c7;background:#dff1ff;color:#075985;box-shadow:0 0 0 1px #0284c7 inset}
.matrix-choice[data-side="after"].active{border-color:#8651b4;background:#f1e9fa;color:#61309c;box-shadow:0 0 0 1px #8651b4 inset}
.matrix-legend h4{font-size:12px;margin:1px 0 0;color:#25435e}
.matrix-legend-list{display:flex;gap:7px;flex-wrap:wrap}
.matrix-legend-item{display:flex;gap:6px;align-items:center;font-size:11px;background:#fff;border:1px solid #e2e8f0;border-radius:4px;padding:5px 7px;color:#34445a}
.matrix-swatch{width:15px;height:15px;flex:none;border-radius:3px;border:1px solid #00000013}
.matrix-swatch.m-dark{background:#167a46}.matrix-swatch.m-light{background:#91d9a3}.matrix-swatch.m-yellow{background:#ffe179}.matrix-swatch.m-orange{background:#ffa95c}.matrix-swatch.m-red{background:#e35d60}
.matrix-outcome{font-size:12px;color:#34445a;line-height:1.8}
.matrix-outcome b{color:#0f3652}
.matrix-legend p{margin:0;color:#64748b;font-size:11px}
.filters{justify-content:flex-end}.filters input{width:min(230px,100%)}
@media(max-width:760px){.matrix-layout{grid-template-columns:1fr}.matrix-legend{gap:10px}.static-field{flex-wrap:wrap}}



/* OLGUN UI2 · kapsamlı kurumsal çerçeve ve üst araç paneli */
:root{--bg:#f8fafc;--line:#cbd5e1;--surface:#fff;--brand:#0284c7;--radius:6px}
body{background:#edf3f8}
.olgun-frame{margin:8px;min-height:calc(100vh - 16px);width:calc(100% - 16px);max-width:none;border:2px solid #7f95a9;border-radius:7px;background:#f8fafc;box-shadow:0 5px 20px #203d5414;overflow:visible}
.header{position:sticky;top:0;z-index:30;border-bottom:1px solid #bfcfdb;border-top:4px solid var(--brand);background:#fff;color:#17283b;box-shadow:0 3px 10px #23405614}
.headerinner{max-width:none;min-height:77px;padding:10px 19px;gap:13px;display:flex;align-items:center}
.logo{width:62px;height:57px;flex:none;border:1px solid #cbd5e1;border-radius:5px;background:#f8fafc;color:#075985;display:grid;place-items:center;padding:3px;overflow:hidden;font-size:12px;line-height:1.15;cursor:pointer}
.logo:hover{background:#e8f4fc;border-color:#74bddf}.logo img{display:block;max-width:100%;max-height:100%;width:100%;height:100%;object-fit:contain}.logo img[hidden],.logo span[hidden]{display:none!important}
.header-titles{min-width:0;flex:1}.header h1{font-size:18px;line-height:1.27;color:#075985;margin:0;font-weight:750}.header p{margin:4px 0 0;color:#475569;font-size:12px;line-height:1.35}
.organization{text-align:right;max-width:42%;min-width:0;font-size:16px;font-weight:750;color:#1e3a57;white-space:nowrap;letter-spacing:.3px;flex-shrink:1;overflow-wrap:normal}
.header [contenteditable="true"]{outline:2px dashed #0284c7;outline-offset:4px;background:#f0f9ff;border-radius:3px;white-space:normal}
.ui2-action-row{display:flex;justify-content:flex-start;padding:12px 17px 3px}
.ui2-action-panel{display:inline-flex;justify-content:flex-start;align-items:center;gap:9px;flex-wrap:wrap;padding:10px 12px;border:1px solid #b9cbd9;border-radius:6px;background:#fff;box-shadow:0 1px 4px #1b476912}
.wrap{max-width:none;width:100%;padding:12px 17px 25px}
.card{border-color:#cbd5e1;border-radius:6px;box-shadow:0 2px 7px #22465b0b}
.card-header{background:#eaf5fc;border-bottom:1px solid #b9d4e6;border-left:4px solid #0284c7;padding:10px 13px;border-radius:5px 5px 0 0}
.card-header h2{color:#084c71}.section-number{background:#d2eafb;color:#075985}
.metric{border-top:3px solid #0284c7}
.matrix-card{border:1px solid #9fbfd1;border-radius:6px}.matrix-heading{background:#e9f4fc}
.print-snapshot{display:none}
@media(max-width:740px){.headerinner{padding:9px 11px;flex-wrap:wrap;gap:8px}.logo{width:49px;height:49px}.header-titles{flex:1 1 58%;}.header h1{font-size:15px}.header p{font-size:11px}.organization{font-size:12px;max-width:100%;flex:1 0 100%;text-align:right;white-space:normal;padding:0 2px}.ui2-action-row{padding:9px 9px 2px}.ui2-action-panel{width:100%;padding:8px;gap:6px}.ui2-action-panel .btn{flex:1 1 130px;white-space:normal}.wrap{padding:10px 9px 18px}.olgun-frame{margin:3px;width:calc(100% - 6px);min-height:calc(100vh - 6px)}}
/* PDF/Yazdır: aynı çerçeve, başlık, mavi bölüm başlıkları, renkli matris ve gerçek alan değerleri */
@page{size:A4 landscape;margin:9mm}
@media print{
 html,body{margin:0!important;padding:0!important;background:#fff!important;color:#17283b!important;font-size:10px!important;-webkit-print-color-adjust:exact!important;print-color-adjust:exact!important}
 *{-webkit-print-color-adjust:exact!important;print-color-adjust:exact!important}
 .olgun-frame{margin:0!important;width:100%!important;min-height:0!important;border:1.6px solid #7f95a9!important;border-radius:4px!important;box-shadow:none!important;overflow:visible!important;background:#f8fafc!important}
 .header{position:static!important;display:block!important;box-shadow:none!important;top:auto!important;border-top:4px solid #0284c7!important}
 .headerinner{padding:8px 12px!important;min-height:62px!important}
 .header .logo{width:52px!important;height:49px!important}
 .header h1{font-size:17px!important}.header p{font-size:11px!important}.organization{font-size:15px!important}
 .ui2-action-row,#app,#toast,#logoChooser{display:none!important}
 .print-snapshot{display:block!important;padding:9px 10px 4px!important}
 .print-snapshot .metrics{grid-template-columns:repeat(4,minmax(0,1fr))!important;gap:7px!important;margin:0 0 9px!important}
 .print-snapshot .metric{padding:7px 10px!important;break-inside:avoid!important}.print-snapshot .metric b{font-size:19px!important}.print-snapshot .metric .icon{display:none!important}
 .print-snapshot .stack{gap:9px!important}.print-snapshot .card{box-shadow:none!important;border:1px solid #bdccd9!important;break-inside:auto!important;page-break-inside:auto!important}
 .print-snapshot .card-header{break-after:avoid!important;page-break-after:avoid!important;padding:8px 10px!important;background:#eaf5fc!important;border-left:4px solid #0284c7!important}
 .print-snapshot .card-header h2{font-size:12px!important}
 .print-snapshot .card-body{padding:9px 11px!important}
 .print-snapshot .g4{grid-template-columns:repeat(4,minmax(0,1fr))!important}.print-snapshot .g3{grid-template-columns:repeat(3,minmax(0,1fr))!important}.print-snapshot .g2{grid-template-columns:repeat(2,minmax(0,1fr))!important}.print-snapshot .span2{grid-column:span 2!important}.print-snapshot .span3{grid-column:span 3!important}
 .print-snapshot .grid{gap:8px!important}
 .print-snapshot .score-grid{grid-template-columns:1fr 1fr!important;gap:9px!important}
 .print-snapshot .score-panel{break-inside:avoid!important;background:#fff!important}
 .print-snapshot .score-fields{gap:5px!important;padding:7px!important}.print-snapshot .score-result{margin:0 7px 7px!important;padding:6px!important}.print-snapshot .score-result b{font-size:17px!important}
 .print-snapshot .matrix-card{break-inside:avoid!important;page-break-inside:avoid!important;border-color:#a8c2d5!important}
 .print-snapshot .matrix-heading{padding:7px 9px!important;background:#e9f4fc!important}
 .print-snapshot .matrix-layout{display:grid!important;grid-template-columns: 44% minmax(0,1fr)!important;gap:9px!important;padding:8px!important}
 .print-snapshot .matrix-cell{height:31px!important;min-height:31px!important;font-size:12px!important;padding:0!important;box-shadow:none!important;transform:none!important}
 .print-snapshot .matrix-table{border-spacing:2px!important}
 .print-snapshot .matrix-table td{height:31px!important}
 .print-snapshot .matrix-picker{display:none!important}
 .print-snapshot .matrix-legend{gap:4px!important;font-size:10px!important}.print-snapshot .matrix-legend-list{gap:4px!important}
 .print-snapshot .matrix-legend-item{font-size:9px!important;padding:3px 4px!important}
 .print-snapshot .matrix-outcome{line-height:1.35!important;font-size:11px!important}
 .print-snapshot .matrix-legend p{font-size:9px!important}
 .print-snapshot .actionbar,.print-snapshot .record-bottom-actions,.print-snapshot .toolbar,.print-snapshot .filters,.print-snapshot .explain,.print-snapshot footer,.print-snapshot .btn{display:none!important}
 .print-snapshot .print-field-value{border:1px solid #cbd5e1;background:#fff;min-height:24px;padding:4px 6px;border-radius:4px;white-space:pre-wrap;overflow-wrap:anywhere;font-size:10px;line-height:1.35}
 .print-snapshot .tablebox{overflow:visible!important}.print-snapshot table:not(.matrix-table){min-width:0!important;width:100%!important;table-layout:fixed}
 .print-snapshot table:not(.matrix-table) th,.print-snapshot table:not(.matrix-table) td{padding:4px!important;font-size:9px!important;overflow-wrap:anywhere;white-space:normal!important}
 .print-snapshot table:not(.matrix-table) thead{display:table-header-group!important}
 .print-snapshot table:not(.matrix-table) tr{break-inside:avoid!important;page-break-inside:avoid!important}
 .print-snapshot table:not(.matrix-table) th{position:static!important;background:#eaf5fc!important}
 .print-snapshot .card-header,.print-snapshot .metric,.print-snapshot .score-panel{break-inside:avoid!important}
 .print-snapshot .foot{display:none!important}
}


/* Olgun UI2 · düzenlenmiş kompakt form, altta tek dosya araç paneli */
.ui2-action-row{padding:2px 17px 18px;justify-content:flex-start}
.ui2-action-panel{background:#fff;border-color:#afc7d7;box-shadow:0 2px 6px #10355010}
.form-segment-label{display:flex;align-items:center;gap:8px;margin:12px 0 9px;color:#075985;font-size:12px;font-weight:800;letter-spacing:.01em;border-bottom:1px solid #dcecf5;padding-bottom:6px}
.form-segment-label:first-child{margin-top:0}
.form-segment-label span{display:grid;place-items:center;flex:none;width:22px;height:22px;border:1px solid #b8daed;border-radius:4px;background:#eaf6fc;color:#0369a1;font-size:10px}
.hazard-fields textarea{min-height:68px}
.assessment-layout{display:grid;grid-template-columns:minmax(350px,.88fr) minmax(420px,1.12fr);gap:13px;align-items:stretch}
.assessment-scores{grid-template-columns:1fr;gap:10px;margin:0}
.assessment-scores .score-panel{transition:border-color .14s,box-shadow .14s;min-width:0}
.assessment-scores .score-panel.active-target{box-shadow:0 0 0 1px #74b0d4}
.assessment-scores .score-before.active-target{border-color:#297bb3}
.assessment-scores .score-after.active-target{border-color:#8651b4;box-shadow:0 0 0 1px #bca2e1}
.score-top strong{display:inline-flex;align-items:center;gap:7px}
.indicator{width:9px;height:9px;border-radius:50%;display:inline-block;background:#125ba9}
.ind-after{background:#8648b3;transform:rotate(45deg);border-radius:2px}
.assessment-layout .matrix-card{margin:0}
.assessment-layout .matrix-heading{padding:9px 12px}
.assessment-layout .matrix-layout{display:block;padding:12px 15px 9px}
.assessment-layout .matrix-scroll{max-width:620px;margin:auto}
.assessment-layout .matrix-axis{font-size:10px;line-height:1.4}
.assessment-layout .matrix-axis-bottom{margin:5px 0 0}
.assessment-layout .matrix-table{border-spacing:5px}
.assessment-layout .matrix-table td,.assessment-layout .matrix-cell{height:49px;min-height:49px}
.table-footer{padding:9px 12px}
#tableTitle{scroll-margin-top:100px}#formTitle{scroll-margin-top:110px}
@media(max-width:1020px){.assessment-layout{grid-template-columns:1fr}.assessment-scores{grid-template-columns:repeat(2,minmax(0,1fr))}.assessment-layout .matrix-scroll{max-width:620px}}
@media(max-width:640px){.assessment-scores{grid-template-columns:1fr}.assessment-layout .matrix-layout{padding:8px}.assessment-layout .matrix-table{border-spacing:2px}.assessment-layout .matrix-cell,.assessment-layout .matrix-table td{height:44px;min-height:44px}.form-segment-label{margin-top:10px}.ui2-action-row{padding:4px 9px 15px}}
/* Tarayıcı PDF çıktısında her sayfanın sağ altındaki gerçek sayfa numarası */
@page{size:A4 landscape;margin:9mm 9mm 16mm 9mm;
 @bottom-right{content:"Sayfa " counter(page) " / " counter(pages);font-family:Arial,sans-serif;font-size:9pt;font-weight:600;color:#34495c;text-align:right;vertical-align:bottom;margin-bottom:1mm}}
@media print{
 .ui2-action-row,.ui2-action-panel,#importBtn,#xlsxBtn,#pdfBtn{display:none!important}
 .print-snapshot .form-segment-label{margin:6px 0 5px!important;font-size:10px!important;padding:0 0 3px!important;break-after:avoid!important}
 .print-snapshot .form-segment-label span{width:18px!important;height:18px!important;font-size:9px!important}
 .print-snapshot .assessment-layout{display:grid!important;grid-template-columns:42% minmax(0,1fr)!important;gap:8px!important;align-items:stretch!important;break-inside:avoid!important}
 .print-snapshot .assessment-scores{display:grid!important;grid-template-columns:1fr!important;gap:6px!important}
 .print-snapshot .assessment-layout .matrix-card{margin:0!important}
 .print-snapshot .assessment-layout .matrix-layout{display:block!important;padding:5px 9px!important}
 .print-snapshot .assessment-layout .matrix-scroll{max-width:none!important}
 .print-snapshot .assessment-layout .matrix-cell,.print-snapshot .assessment-layout .matrix-table td{height:28px!important;min-height:28px!important}
 .print-snapshot .assessment-layout .matrix-cell{font-size:11px!important}
 .print-snapshot .assessment-layout .matrix-table{border-spacing:2px!important}
 .print-snapshot .matrix-axis{font-size:9px!important}
 .print-snapshot .hazard-fields textarea{min-height:0!important}
 .print-snapshot .metrics{display:none!important}
 .print-snapshot .g5{grid-template-columns:repeat(5,minmax(0,1fr))!important}
 .print-snapshot .card-body{padding:6px 9px!important}
 .print-snapshot .grid{gap:5px!important}
 .print-snapshot .print-field-value{min-height:19px!important;padding:3px 4px!important;font-size:9px!important}
 .print-snapshot .score-top{padding:5px 7px!important}
 .print-snapshot .score-fields{padding:5px 7px!important}
 .print-snapshot .score-result{margin:0 7px 5px!important;padding:4px 6px!important}
 .print-snapshot .score-result b{font-size:14px!important}
 .print-snapshot .assessment-layout .matrix-cell,.print-snapshot .assessment-layout .matrix-table td{height:26px!important;min-height:26px!important}
 .print-snapshot .form-segment-label{margin:4px 0 3px!important}
 .print-snapshot .card-header{padding:5px 9px!important}
 .print-snapshot .headerinner{padding:5px 8px!important}
 .print-snapshot .method-info{display:none!important}
 .print-snapshot .table-footer{display:none!important}
 .print-snapshot .form-segment-label + .grid{break-inside:avoid!important}
}


/* Olgun UI2: bütün çevresi kapalı kurumsal başlık */
#pageHeader {
  width:100%; max-width:100%; margin:0; box-sizing:border-box;
  border:1.5px solid #7f95a9; border-top:4px solid #0284c7;
  border-radius:4px 4px 0 0; background:#fff;
}
#pageHeader .headerinner { width:100%; max-width:100%; min-width:0; box-sizing:border-box; }
#pageHeader .organization { margin-left:auto; }
.print-pages {display:none}
@media print{
  #olgunFrame {display:none!important}
  #printPages.print-pages {
    display:table!important; width:100%!important; max-width:100%!important;
    table-layout:fixed!important; border-spacing:0!important;
    border-collapse:separate!important; margin:0!important;
    border:0!important; background:#fff!important;
  }
  #printPages > thead{display:table-header-group!important}
  #printPages > tbody{display:table-row-group!important}
  #printPages > thead > tr, #printPages > tbody > tr{break-inside:auto!important;page-break-inside:auto!important}
  #printPages > thead > tr > td {padding:0 0 7px!important;border:0!important;vertical-align:top!important}
  #printPages > tbody > tr > td {padding:0!important;border:0!important;vertical-align:top!important}
  #printHeader .print-header-duplicate{
    position:static!important;top:auto!important;display:block!important;
    width:100%!important; max-width:100%!important; height:auto!important;
    border:1.5px solid #7f95a9!important;
    border-top:4px solid #0284c7!important;
    border-radius:4px!important; background:#fff!important;
    box-shadow:none!important; margin:0!important;
  }
  #printHeader .headerinner {min-height:63px!important; padding:6px 12px!important;width:100%!important;max-width:100%!important}
  #printHeader .logo{width:52px!important;height:49px!important}
  #printHeader .header-titles h1{font-size:17px!important}
  #printHeader .header-titles p{font-size:11px!important}
  #printHeader .organization{margin-left:auto!important;font-size:15px!important;text-align:right!important}
  #printPages .print-snapshot{display:block!important;padding:0 2px 4px!important;box-sizing:border-box!important}
}


/* PRINT FIX | Başlıkla hizalı Olgun UI2 dış çerçevesi her PDF sayfasında */
#printPageFrame{display:none}
@media print{
  /* Ana uygulama çerçevesi baskıda gizlenerek tablo başlığı her sayfada tekrarlanır.
     Dış çerçeve ise baskı sayfasına sabitlenir; uzun tablo boyunca kaybolmaz. */
  #printPageFrame{
    display:block!important;
    position:fixed!important;
    top:0!important;bottom:0!important;left:0!important;right:0!important;
    width:auto!important;height:auto!important;
    border:1.5px solid #7f95a9!important;
    border-radius:0!important;
    background:transparent!important;
    box-sizing:border-box!important;
    pointer-events:none!important;
    z-index:900!important;
    -webkit-print-color-adjust:exact!important;print-color-adjust:exact!important;
  }
  /* Sadece bir çizgi kümesi kullan: başlığın yan sınırlarını dış çerçeve çizer. */
  #printHeader .print-header-duplicate{
    width:100%!important;
    border-left:0!important;border-right:0!important;
    border-top:4px solid #0284c7!important;
    border-bottom:1.5px solid #7f95a9!important;
    border-radius:0!important;
    margin:0!important;
  }
  #printPages.print-pages{width:100%!important;max-width:100%!important;margin:0!important}
  #printPages > thead > tr > td{padding:0 0 7px!important}
  #printPages > tbody > tr > td{
    padding:0 10px 10px!important;
  }
  #printPages .print-snapshot{padding:0 0 6px!important}
  #printPages .print-document{max-width:100%!important}
}


/* Risk UI: form altında tek satırlık, yalnızca ekranda görünen yöntem özeti */
.wrap.stack{gap:10px;padding-bottom:8px}
.ui2-action-row{padding-top:2px;padding-bottom:5px}
.risk-ui-footer{margin:0 17px 10px;padding:7px 0 5px;border-top:1px solid #dbe3eb;color:#475569;font-size:11px;line-height:1.45;text-align:left;white-space:nowrap;overflow-x:auto;overflow-y:hidden}
@media(max-width:740px){.risk-ui-footer{margin:0 9px 8px;font-size:10px}}
@media print{.risk-ui-footer{display:none!important}}


/* RISK UI | Çift görünüm: tekil risk ve bütün kayıtların 5×5 dağılımı */
.matrix-mode-controls{display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.matrix-mode-btn{border:1px solid #bfd6e7;background:#fff;color:#315d76;padding:6px 9px;border-radius:5px;min-height:30px;font-size:11px;font-weight:700;line-height:1.2;white-space:normal}
.matrix-mode-btn.active,.matrix-mode-btn[aria-pressed="true"]{background:#dcedfb;color:#075985;border-color:#73acd0;box-shadow:inset 0 0 0 1px #87b8d5}
.matrix-mode-btn:focus-visible{outline:2px solid #0284c7;outline-offset:2px}
.matrix-summary[hidden]{display:none!important}
.matrix-summary{margin:5px auto 0;max-width:620px;min-height:22px;display:flex;align-items:center;justify-content:center;text-align:center;gap:6px;flex-wrap:wrap;color:#50677a;font-size:11px;line-height:1.3}
.matrix-summary strong{color:#084d74}
.matrix-cell.matrix-distribution-cell{display:flex;align-items:center;justify-content:center;flex-direction:column;gap:0;cursor:default;padding:2px!important;box-shadow:none}
.matrix-distribution-cell .distribution-qty{font-size:19px;font-weight:900;line-height:1.04;font-variant-numeric:tabular-nums;letter-spacing:.01em}
.matrix-distribution-cell .distribution-score{font-size:9px;font-weight:600;opacity:.86;line-height:1.25}
.matrix-distribution-cell.is-empty .distribution-qty{opacity:.45}
@media(max-width:680px){.matrix-heading{align-items:stretch;flex-direction:column}.matrix-mode-controls{display:grid;grid-template-columns:1fr 1fr;width:100%}.matrix-mode-btn{padding:7px 4px;font-size:10px}.matrix-distribution-cell .distribution-qty{font-size:16px}.matrix-distribution-cell .distribution-score{font-size:8px}.matrix-summary{font-size:10px}}
@media print{.print-snapshot .matrix-mode-controls{display:none!important}.print-snapshot .matrix-distribution-cell .distribution-qty{font-size:13px!important}.print-snapshot .matrix-distribution-cell .distribution-score{font-size:7px!important}.print-snapshot .matrix-summary{font-size:9px!important;margin-top:1px!important;min-height:0!important}}

</style>
</head>
<body>
<div class="olgun-frame" id="olgunFrame">
<header class="header" id="pageHeader" aria-label="Olgun UI2 sabit başlık">
 <div class="headerinner">
  <button class="logo" id="logoTrigger" type="button" title="Logoyu değiştirmek için 5 kez art arda tıklayın" aria-label="Logo; değiştirmek için beş kez tıklayın"><img id="brandLogo" alt="Kurum logosu" hidden><span id="logoFallback" aria-hidden="true">LOGO</span></button>
  <div class="header-titles"><h1 id="brandTitle" title="Başlığı düzenlemek için 5 kez art arda tıklayın">İSG RİSK ANALİZİ – L TİPİ MATRİS</h1><p id="brandSubtitle" title="Alt başlığı düzenlemek için 5 kez art arda tıklayın">(5×5 Olasılık × Şiddet · Risk değerlendirme ve önlem takip formu)</p></div>
  <div class="organization" id="brandOrg" title="Kurum adını değiştirmek için 5 kez art arda tıklayın">OLGUN BAŞKANLIĞI</div>
 </div>
 <input id="logoChooser" class="sr-only" type="file" accept="image/png,image/jpeg,image/webp,image/gif,image/svg+xml" aria-label="Yeni kurumsal logo seç">
</header>
<div id="app" class="wrap stack">
  <section class="grid g4 metrics" aria-label="Özet göstergeler">
    <div class="card metric"><div><small>TOPLAM RİSK KAYDI</small><b id="statTotal">0</b></div><span class="icon">▦</span></div>
    <div class="card metric"><div><small>YÜKSEK / ÇOK YÜKSEK · AÇIK</small><b id="statCritical">0</b></div><span class="icon">!</span></div>
    <div class="card metric"><div><small>HEDEF TARİHİ GEÇEN</small><b id="statOverdue">0</b></div><span class="icon">◷</span></div>
    <div class="card metric"><div><small>ÖNLEMİ DOĞRULANAN</small><b id="statVerified">0</b></div><span class="icon">✓</span></div>
  </section>
  <section class="card" aria-labelledby="metaTitle">
    <div class="card-header"><h2 id="metaTitle"><span class="section-number">01</span> İş Yeri ve Değerlendirme Bilgileri</h2><span class="hint">Bilgiler bu tarayıcıya otomatik kaydedilir.</span></div>
    <div class="card-body grid g5">
      <div><label for="metaCompany">İşyeri / Firma</label><input id="metaCompany" data-meta="company" placeholder="Örn. ABC Üretim A.Ş."></div>
      <div><label for="metaFacility">Tesis / Birim</label><input id="metaFacility" data-meta="facility" placeholder="Örn. Ana Üretim Tesisi"></div>
      <div><label for="metaPrepared">Hazırlayan / Ekip</label><input id="metaPrepared" data-meta="prepared" placeholder="İSG risk değerlendirme ekibi"></div>
      <div><label for="metaDate">Değerlendirme Tarihi</label><input type="date" id="metaDate" data-meta="date"></div>
      <div><label for="metaRevision">Revizyon / Belge No.</label><input id="metaRevision" data-meta="revision" placeholder="Örn. RD-2026 / Rev.00"></div>
    </div>
  </section>
  <section class="card" aria-labelledby="formTitle">
    <div class="card-header"><h2 id="formTitle"><span class="section-number">02</span> <span id="formTitleText">Yeni Risk Kaydı</span></h2><div class="toolbar"><button class="btn btn-small" type="button" id="newBtn">+ Yeni Kayıt</button></div></div>
    <div class="card-body">
      <form id="riskForm" novalidate>
        <div class="form-segment-label"><span>01</span> Riskin Tanımlanması</div>
        <div class="grid g4 compact-intro">
          <div><label>Değerlendirme Yöntemi</label><div class="static-field">5×5 L Tipi Matris <span>Olasılık × Şiddet</span></div><input id="method" type="hidden" value="matrix"></div>
          <div><label for="unit" class="required">Bölüm / Alan</label><input id="unit" required placeholder="Örn. Üretim Bölümü"></div>
          <div><label for="activity" class="required">Faaliyet / İş Adımı</label><input id="activity" required placeholder="Örn. Pres makinesi kullanımı"></div>
          <div><label for="affected">Etkilenebilecek Kişiler</label><input id="affected" placeholder="Çalışan, taşeron, ziyaretçi..."></div>
        </div>
        <div class="grid g3 hazard-fields" style="margin-top:10px">
          <div><label for="hazard" class="required">Tehlike Kaynağı</label><textarea id="hazard" required placeholder="Örn. Koruyucusuz hareketli makine parçaları"></textarea></div>
          <div><label for="risk" class="required">Risk / Olası Zarar</label><textarea id="risk" required placeholder="Örn. Elin sıkışması, uzuv yaralanması"></textarea></div>
          <div><label for="existing">Mevcut Kontroller / Önlemler</label><textarea id="existing" placeholder="Mevcut mühendislik ve idari önlemler"></textarea></div>
        </div>
        <div class="form-segment-label"><span>02</span> Risk Puanlaması ve 5×5 Matris</div>
        <div class="assessment-layout">
          <div class="score-grid assessment-scores">
            <section class="score-panel score-before active-target" data-side="before" aria-label="Mevcut risk puanlaması"><div class="score-top"><strong><i class="indicator ind-before"></i> MEVCUT RİSK</strong><span class="hint">Önlem öncesi</span></div><div class="score-fields" id="beforeFields"></div><div class="score-result"><div><span class="hint">Risk puanı</span><br><b id="beforeScore">—</b></div><span id="beforeLevel" class="risk-tag">—</span></div></section>
            <section class="score-panel score-after" data-side="after" aria-label="Hedef risk puanlaması"><div class="score-top"><strong><i class="indicator ind-after"></i> HEDEF RİSK</strong><span class="hint" id="afterTitle">Planlanan seviye</span></div><div class="score-fields" id="afterFields"></div><div class="score-result"><div><span class="hint">Hedef / kalan risk</span><br><b id="afterScore">—</b></div><span id="afterLevel" class="risk-tag">—</span></div></section>
          </div>
          <section class="matrix-card" id="matrixGuide" aria-labelledby="matrixTitle">
            <div class="matrix-heading"><h3 id="matrixTitle">▦ 5×5 L Tipi Risk Matrisi</h3><div class="matrix-mode-controls" role="group" aria-label="Matris görünümü"><button class="matrix-mode-btn active" id="matrixModeSingle" type="button" aria-pressed="true">Tekil Risk Matrisi</button><button class="matrix-mode-btn" id="matrixModeDistribution" type="button" aria-pressed="false">Genel Risk Dağılımı</button></div></div>
            <div class="matrix-layout">
              <div class="matrix-scroll"><div class="matrix-axis">ŞİDDET →</div><div id="matrixVisual" aria-label="5 çarpı 5 renkli risk matrisi"></div><div id="matrixSummary" class="matrix-summary" aria-live="polite"></div><div class="matrix-axis matrix-axis-bottom">OLASILIK ↑</div></div>
            </div>
          </section>
        </div>
        <div class="form-segment-label"><span>03</span> Önlemler ve Aksiyon Takibi</div>
        <div class="grid g4" style="margin-top:11px">
          <div class="span2"><label for="action" class="required">Alınacak Tedbirler / Düzeltici Faaliyet</label><textarea id="action" required placeholder="Tehlikeyi ortadan kaldırma, mühendislik kontrolü, eğitim, talimat vb."></textarea></div>
          <div><label for="responsible">Sorumlu Kişi / Birim</label><input id="responsible" placeholder="Örn. Bakım Müdürü"></div>
          <div><label for="deadline">Hedef Tamamlanma Tarihi</label><input id="deadline" type="date"></div>
          <div><label for="status">Aksiyon Durumu</label><select id="status"><option value="open">Açık</option><option value="inprogress">Devam Ediyor</option><option value="done">Tamamlandı</option></select></div>
          <div class="span3"><label for="notes">Ek Açıklamalar / Doğrulama Kanıtı</label><input id="notes" placeholder="Kontrol tarihi, kanıt, ölçüm, belge, revizyon notu..."></div>
        </div>
        <div style="margin-top:10px;padding:9px 11px;border:1px solid #d9e7ef;border-radius:5px;background:#f7fbfd"><div class="checkline"><input id="verified" type="checkbox"><label for="verified">Önlem uygulandı ve etkinliği kontrol edilerek <strong>kalan risk doğrulandı</strong></label></div><div class="hint" style="margin-top:4px">Bu seçenek yalnızca “Tamamlandı” durumunda kullanılabilir. İşaretlenmemişse ikinci risk puanı gerçekleşmiş sonuç değil, hedef değerdir.</div></div>
        <div class="actionbar"><button class="btn btn-primary" type="submit" id="saveBtn">+ Riski Kaydet</button><button class="btn" id="cancelBtn" type="button">Vazgeç / Yeni Kayıt</button><div class="spacer"></div><span class="hint" id="formInfo">Yeni kayıt oluşturuluyor.</span></div>
      </form>
    </div>
  </section>
  <section class="card" aria-labelledby="tableTitle">
    <div class="card-header"><h2 id="tableTitle"><span class="section-number">03</span> Risk Kayıtları ve Aksiyon Takibi <span id="recordCount" class="hint"></span></h2><div class="filters"><input type="search" id="searchInput" aria-label="Kayıtlarda ara" placeholder="Kayıtlarda ara..."><select id="statusFilter" aria-label="Duruma göre filtrele"><option value="">Tüm durumlar</option><option value="open">Açık</option><option value="inprogress">Devam ediyor</option><option value="done">Tamamlandı</option></select></div></div>
    <div class="tablebox"><table aria-label="Risk kayıtları"><thead><tr><th>No.</th><th>Bölüm / Faaliyet</th><th>Tehlike / Risk</th><th>İlk Risk (Oת)</th><th>Son Risk (Oת)</th><th>Termin / Sorumlu</th><th>Durum</th><th>İşlemler</th></tr></thead><tbody id="riskRows"></tbody></table><div id="emptyState" class="empty" hidden>Henüz kayıt bulunmuyor. Yukarıdaki formdan risk ekleyebilirsiniz.</div></div>
    <div class="card-body table-footer"><div class="toolbar record-bottom-actions"><button class="btn btn-danger" id="clearBtn" type="button">Tüm Kayıtları Sil</button></div></div>
  </section>
</div>
<div class="ui2-action-row"><div class="ui2-action-panel" aria-label="Dosya ve yazdırma işlemleri">
 <button class="btn btn-excel-import" id="importBtn" type="button">⬆ Excel İçeri Aktar</button>
 <button class="btn btn-excel-export" id="xlsxBtn" type="button">⬇ Excel Dışarı Aktar</button>
 <button class="btn btn-print" id="pdfBtn" type="button">▣ PDF / Yazdır</button>
 <input class="sr-only" id="importFile" type="file" accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
 </div></div>
 <footer class="risk-ui-footer" aria-label="Yöntemin özeti">Temel özelliği: Olasılık × Şiddet&nbsp;&nbsp;&nbsp; Kullanım alanı: Ofisler, küçük ve orta ölçekli işletmeler</footer>
</div><!-- /olgun-frame -->
<!-- YAZDIRMA: tekrarlanan başlık ve her sayfada devam eden dış çerçeve. -->
<table id="printPages" class="print-pages" aria-hidden="true" role="presentation">
 <thead><tr><td class="print-page-header"><div id="printHeader"></div></td></tr></thead>
 <tbody><tr><td class="print-page-content"><div id="printReport" class="print-snapshot"></div></td></tr></tbody>
</table>
<!-- Sabit konumlu dış çerçeve PDF çıktısında her baskı sayfasında yeniden çizilir. -->
<div id="printPageFrame" aria-hidden="true"></div>
<div id="toast" role="status" aria-live="polite"></div>
<script>
'use strict';
(()=>{
// Eski anahtar yalnızca önceki formdan işyeri bilgilerini devralmak içindir.
// Önceki risk verilerini silmeyiz; bu sürümde risk kayıtları yalnızca açık oturumda tutulur.
const LEGACY_STORAGE_KEY='isg-risk-ltipi-matris-offline-v1';
const STORAGE_KEY='isg-risk-ltipi-matris-meta-v2';
const $=id=>document.getElementById(id);
const methodName={matrix:'5×5 L Tipi Matris'};
const statusName={open:'Açık',inprogress:'Devam Ediyor',done:'Tamamlandı'};
const today=()=>{const d=new Date();return [d.getFullYear(),String(d.getMonth()+1).padStart(2,'0'),String(d.getDate()).padStart(2,'0')].join('-')};
const randomId=()=>('R'+Date.now().toString(36)+Math.random().toString(36).slice(2,7)).toUpperCase();
const asText=v=>v===null||v===undefined?'':String(v);
const esc=v=>asText(v).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const safeNumber=(value,fallback)=>{const n=Number(value);return Number.isFinite(n)&&n>0?n:fallback};
const initMeta=()=>({company:'',facility:'',prepared:'',date:today(),revision:''});
const defaults={matrix:{before:{p:3,s:3},after:{p:1,s:3}}};
const clone=v=>JSON.parse(JSON.stringify(v));
const matrixOptions=[{v:1,t:'1 — Çok düşük'},{v:2,t:'2 — Düşük'},{v:3,t:'3 — Orta'},{v:4,t:'4 — Yüksek'},{v:5,t:'5 — Çok yüksek'}];
const severityOptions=[{v:1,t:'1 — Önemsiz'},{v:2,t:'2 — Hafif'},{v:3,t:'3 — Orta'},{v:4,t:'4 — Ciddi'},{v:5,t:'5 — Çok ciddi'}];
const scheme={matrix:[{k:'p',l:'Olasılık (1–5)',opts:matrixOptions},{k:'s',l:'Şiddet (1–5)',opts:severityOptions}]};
let state={meta:initMeta(),records:[]};let editingId=null;let working=clone(defaults.matrix);let toastTimeout;
function normalizeRecord(raw){
 if(!raw||typeof raw!=='object')return null;
 if(raw.method && raw.method!=='matrix')return null;
 const base=clone(defaults.matrix);
 for(const side of ['before','after'])for(const key of ['p','s']){
  const found=raw[side]?.[key];
  if([1,2,3,4,5].includes(Number(found)))base[side][key]=Number(found);
 }
 return {id:asText(raw.id)||randomId(),method:'matrix',unit:asText(raw.unit),activity:asText(raw.activity),hazard:asText(raw.hazard),risk:asText(raw.risk),affected:asText(raw.affected),existing:asText(raw.existing),action:asText(raw.action),responsible:asText(raw.responsible),deadline:/^\d{4}-\d{2}-\d{2}$/.test(asText(raw.deadline))?raw.deadline:'',status:Object.hasOwn(statusName,raw.status)?raw.status:'open',verified:(raw.verified===true||raw.verified==='true'||raw.verified==='Evet') && raw.status==='done',notes:asText(raw.notes),created:asText(raw.created)||today(),before:base.before,after:base.after};
}
/* Risk kayıtları oturumluk: F5 / yeni açılışta 03 Risk Kayıtları boş gelir.
   İşyeri bilgileri ve kurumsal başlık/logonun yerel saklanması devam eder.
   Önceki sürümün kayıtları ayrı anahtarında korunur; otomatik geri yüklenmez. */
function load(){
 state.records=[];
 try{
   const value=localStorage.getItem(STORAGE_KEY)||localStorage.getItem(LEGACY_STORAGE_KEY);
   if(!value)return;
   const parsed=JSON.parse(value);
   if(parsed.meta&&typeof parsed.meta==='object'){
     for(const k of Object.keys(state.meta))if(parsed.meta[k]!=null)state.meta[k]=asText(parsed.meta[k]);
   }
 }catch(e){console.warn('Yerel işyeri bilgileri okunamadı:',e)}
}
function persist(){
 try{
   // Bilerek records alanı yazılmaz; riskler yalnızca bu açık sayfanın belleğindedir.
   localStorage.setItem(STORAGE_KEY,JSON.stringify({meta:state.meta}));
 }catch(e){console.warn('Yerel işyeri bilgileri kaydedilemedi:',e);toast('İşyeri bilgileri saklanamadı; Excel yedeği alın.')}
}
function toast(message){clearTimeout(toastTimeout);const el=$('toast');el.textContent=message;el.classList.add('show');toastTimeout=setTimeout(()=>el.classList.remove('show'),3400)}
function score(method,factors){const f=factors||defaults.matrix.before;return Number(f.p)*Number(f.s)}
function level(method,value){const index=value<=2?0:value<=5?1:value<=10?2:value<=15?3:4;return [{className:'risk-vlow',label:'Çok Düşük',rank:0},{className:'risk-low',label:'Düşük',rank:1},{className:'risk-medium',label:'Orta',rank:2},{className:'risk-high',label:'Yüksek',rank:3},{className:'risk-critical',label:'Çok Yüksek',rank:4}][index]}
function matrixColor(value){return value<=2?'m-dark':value<=5?'m-light':value<=10?'m-yellow':value<=15?'m-orange':'m-red'}
let matrixActiveSide='before';let matrixView='single';
function fmt(v){return Number(v).toLocaleString('tr-TR',{maximumFractionDigits:2})}
function factorFields(side){const method='matrix';return scheme[method].map(f=>`<div><label for="factor-${side}-${f.k}">${esc(f.l)}</label><select id="factor-${side}-${f.k}" data-side="${side}" data-factor="${f.k}">${f.opts.map(o=>`<option value="${o.v}" ${Number(working[side][f.k])===o.v?'selected':''}>${esc(o.t)}</option>`).join('')}</select></div>`).join('')}
function renderScoreFields(){
 $('beforeFields').innerHTML=factorFields('before');$('afterFields').innerHTML=factorFields('after');
 updatePreview();
}
function renderMatrix(){
 const bp=working.before.p,bs=working.before.s,ap=working.after.p,as=working.after.s;
 const isDistribution=matrixView==='distribution';
 const counts=Array.from({length:6},()=>Array(6).fill(0));
 if(isDistribution)for(const record of state.records){
   const p=Number(record.before?.p),s=Number(record.before?.s);
   if(Number.isInteger(p)&&p>=1&&p<=5&&Number.isInteger(s)&&s>=1&&s<=5)counts[p][s]++;
 }
 let html='<table class="matrix-table"><thead><tr><th scope="col">O ↑ / Ş →</th>';
 for(let s=1;s<=5;s++)html+='<th scope="col">'+s+'</th>';html+='</tr></thead><tbody>';
 for(let p=5;p>=1;p--){html+='<tr><th scope="row">'+p+'</th>';for(let s=1;s<=5;s++){
   const v=p*s;
   if(isDistribution){
     const n=counts[p][s];
     html+=`<td><div class="matrix-cell matrix-distribution-cell ${matrixColor(v)} ${n===0?'is-empty':''}" role="img" title="Olasılık ${p} × Şiddet ${s}: ${n} risk kaydı; risk puanı ${v}" aria-label="Olasılık ${p}, şiddet ${s}, ${n} risk kaydı, risk puanı ${v}"><span class="distribution-qty">${n||'—'}</span><span class="distribution-score">${v} puan</span></div></td>`;
   }else{
     const isBefore=bp===p&&bs===s,isAfter=ap===p&&as===s;
     const marks=(isBefore?'<span title="Mevcut">M</span>':'')+(isAfter?'<span class="after-marker" title="Hedef">H</span>':'');
     html+=`<td><button type="button" class="matrix-cell ${matrixColor(v)} ${isBefore?'is-before':''} ${isAfter?'is-after':''}" data-p="${p}" data-s="${s}" title="Olasılık ${p} × Şiddet ${s} = ${v} · ${level('matrix',v).label}" aria-label="Olasılık ${p}, şiddet ${s}, risk puanı ${v}, ${level('matrix',v).label}${isBefore?', mevcut risk':''}${isAfter?', hedef risk':''}"><span>${v}</span><span class="cell-labels">${marks}</span></button></td>`;
   }
 }html+='</tr>'}html+='</tbody></table>';
 $('matrixVisual').innerHTML=html;
 $('matrixModeSingle').classList.toggle('active',!isDistribution);
 $('matrixModeDistribution').classList.toggle('active',isDistribution);
 $('matrixModeSingle').setAttribute('aria-pressed',String(!isDistribution));
 $('matrixModeDistribution').setAttribute('aria-pressed',String(isDistribution));
 const summary=$('matrixSummary');
 summary.hidden=!isDistribution;
 summary.innerHTML=isDistribution
   ? `<strong>Toplam ${state.records.length} risk kaydı</strong> <span>· Önlem öncesi dağılım · Büyük sayı: kayıt adedi</span>`
   : '';
}
function setMatrixView(mode){matrixView=mode==='distribution'?'distribution':'single';renderMatrix()}
function setMatrixActiveSide(side){if(matrixView!=='single')setMatrixView('single');matrixActiveSide=side;document.querySelectorAll('.assessment-scores .score-panel').forEach(panel=>panel.classList.toggle('active-target',panel.dataset.side===side))}
function updatePreview(){for(const side of ['before','after']){const val=score('matrix',working[side]);$(side+'Score').textContent=fmt(val);const info=level('matrix',val),el=$(side+'Level');el.textContent=info.label;el.className='risk-tag '+info.className} $('afterTitle').textContent=$('verified').checked?'Kontrol sonrası doğrulandı':'Planlanan seviye';renderMatrix();}
function updateVerifyState(){const complete=$('status').value==='done';$('verified').disabled=!complete;if(!complete)$('verified').checked=false;updatePreview()}
function clearForm(){editingId=null;working=clone(defaults[$('method').value]);$('riskForm').reset();$('method').value='matrix';working=clone(defaults.matrix);$('formTitleText').textContent='Yeni Risk Kaydı';$('saveBtn').textContent='+ Riski Kaydet';$('formInfo').textContent='Yeni kayıt oluşturuluyor.';renderScoreFields();updateVerifyState()}
function recordFromForm(){const val=id=>$(id).value.trim();return normalizeRecord({id:editingId||randomId(),method:$('method').value,unit:val('unit'),activity:val('activity'),hazard:val('hazard'),risk:val('risk'),affected:val('affected'),existing:val('existing'),action:val('action'),responsible:val('responsible'),deadline:val('deadline'),status:val('status'),verified:$('verified').checked,notes:val('notes'),created:editingId?(state.records.find(x=>x.id===editingId)?.created||today()):today(),before:working.before,after:working.after})}
function startEdit(id){const record=state.records.find(x=>x.id===id);if(!record)return;setMatrixView('single');editingId=id;const fieldNames=['method','unit','activity','hazard','risk','affected','existing','action','responsible','deadline','status','notes'];for(const key of fieldNames)$(key).value=record[key]||'';$('verified').checked=record.verified;working={before:clone(record.before),after:clone(record.after)};$('formTitleText').textContent='Risk Kaydını Düzenle';$('saveBtn').textContent='✓ Değişiklikleri Kaydet';$('formInfo').textContent='Düzenlenen kayıt: '+record.id;renderScoreFields();updateVerifyState();$('formTitle').scrollIntoView({behavior:'smooth',block:'start'});$('unit').focus({preventScroll:true})}
function deleteRecord(id){const r=state.records.find(x=>x.id===id);if(!r)return;if(!confirm('“'+r.hazard.slice(0,80)+'” kaydını kalıcı olarak silmek istiyor musunuz?'))return;state.records=state.records.filter(x=>x.id!==id);if(editingId===id)clearForm();persist();renderDashboard();toast('Risk kaydı silindi.')}
function duplicateRecord(id){const r=state.records.find(x=>x.id===id);if(!r)return;const obj=clone(r);obj.id=randomId();obj.created=today();obj.verified=false;obj.status='open';state.records.push(obj);persist();renderDashboard();startEdit(obj.id);toast('Kopya kayıt oluşturuldu ve düzenlemeye açıldı.')}
function scoreBadge(method,values){const v=score(method,values),l=level(method,v);return `<strong>${fmt(v)}</strong><div style="margin-top:4px"><span class="risk-tag ${l.className}">${l.label}</span></div>`}
function matchingRecords(){const query=$('searchInput').value.toLocaleLowerCase('tr-TR').trim(),status=$('statusFilter').value;return state.records.filter(r=>(!status||r.status===status)&&(!query||[r.unit,r.activity,r.hazard,r.risk,r.action,r.responsible,r.notes,r.affected].join(' ').toLocaleLowerCase('tr-TR').includes(query))).sort((a,b)=>{
 const aOpen=!a.verified,bOpen=!b.verified;if(aOpen!==bOpen)return aOpen?-1:1;
 const delta=level(b.method,score(b.method,b.before)).rank-level(a.method,score(a.method,a.before)).rank;
 if(delta)return delta;
 return (a.deadline||'9999').localeCompare(b.deadline||'9999');
 })}
function renderDashboard(){
 const t=today();$('statTotal').textContent=state.records.length;
 $('statCritical').textContent=state.records.filter(r=>!r.verified&&level(r.method,score(r.method,r.before)).rank>=3).length;
 $('statOverdue').textContent=state.records.filter(r=>!r.verified&&r.deadline&&r.deadline<t).length;
 $('statVerified').textContent=state.records.filter(r=>r.verified).length;
 if(matrixView==='distribution')renderMatrix();
 const rows=matchingRecords();$('recordCount').textContent=`(${rows.length}/${state.records.length})`;
 $('emptyState').hidden=rows.length!==0;
 $('riskRows').innerHTML=rows.map((r,index)=>{
 const late=!r.verified&&r.deadline&&r.deadline<t;const statusClass=r.status==='inprogress'?'status-inprogress':r.status==='done'?'status-done':'';
 return `<tr><td><strong>${index+1}</strong><div class="cellsub">${esc(r.id.slice(-7))}</div></td><td class="namecell"><strong class="truncate2" title="${esc(r.unit)}">${esc(r.unit)}</strong><div class="cellsub truncate2">${esc(r.activity)}</div></td><td class="hazcell"><strong class="truncate2" title="${esc(r.hazard)}">${esc(r.hazard)}</strong><div class="cellsub truncate2" title="${esc(r.risk)}">${esc(r.risk)}</div></td><td class="scorecell">${scoreBadge(r.method,r.before)}</td><td class="scorecell">${scoreBadge(r.method,r.after)}<div class="cellsub">${r.verified?'✓ Doğrulandı':'Hedef'}</div></td><td>${late?'<strong style="color:#be123c">':''}${esc(r.deadline||'—')}${late?'</strong><div class="cellsub" style="color:#be123c">Süresi geçti</div>':''}<div class="cellsub">${esc(r.responsible||'—')}</div></td><td><span class="status ${statusClass}">${esc(statusName[r.status])}</span>${r.verified?'<div class="cellsub">✓ Kalan risk doğrulandı</div>':''}</td><td><div class="toolbar"><button class="btn btn-small btn-soft" type="button" data-act="edit" data-id="${esc(r.id)}" title="Düzenle">Düzenle</button><button class="btn btn-small" type="button" data-act="duplicate" data-id="${esc(r.id)}" title="Kopyala">Kopya</button><button class="btn btn-small btn-danger" type="button" data-act="delete" data-id="${esc(r.id)}" title="Sil">Sil</button></div></td></tr>`
 }).join('');
}
function renderMeta(){document.querySelectorAll('[data-meta]').forEach(el=>el.value=state.meta[el.dataset.meta]||'')}
function downloadBlob(blob,filename){const url=URL.createObjectURL(blob),a=document.createElement('a');a.href=url;a.download=filename;document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),4000)}
function baseFilename(){return 'ISG_Risk_Analizi_L_Tipi_Matris_'+today()}
const EXCEL_COLUMNS=['Kayıt ID','Bölüm','Faaliyet','Tehlike','Olası Zarar / Risk','Etkilenenler','Mevcut Önlemler','Önce Olasılık','Önce Şiddet','Önce Risk Puanı','Önce Risk Seviyesi','Planlanan Tedbir','Sonra Olasılık','Sonra Şiddet','Sonra Risk Puanı','Sonra Risk Seviyesi','Sorumlu','Hedef Tarih','Durum','Doğrulama','Notlar','Kayıt Tarihi'];
function recordToExcelRow(r){return [r.id,r.unit,r.activity,r.hazard,r.risk,r.affected,r.existing,r.before.p,r.before.s,score('matrix',r.before),level('matrix',score('matrix',r.before)).label,r.action,r.after.p,r.after.s,score('matrix',r.after),level('matrix',score('matrix',r.after)).label,r.responsible,r.deadline,statusName[r.status],r.verified?'Evet':'Hayır',r.notes,r.created]}
function xmlEsc(v){return asText(v).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&apos;'}[c])).replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g,'')}
function colLetter(num){let res='';for(let n=num;n>0;n=Math.floor((n-1)/26))res=String.fromCharCode(65+(n-1)%26)+res;return res}
function sheetXml(rows,{width=18,autoFilter=true}={}){
 const maxCols=Math.max(1,...rows.map(r=>r.length));const cols=Array.from({length:maxCols},(_,i)=>{let w=width;if(i===0)w=17;if(i===5||i===6||i===8||i===9||i===26)w=42;if(i===3||i===4||i===10)w=24;return `<col min="${i+1}" max="${i+1}" width="${w}" customWidth="1"/>`}).join('');
 const sheetRows=rows.map((row,i)=>`<row r="${i+1}">${row.map((value,j)=>{const c=colLetter(j+1)+(i+1),st=i===0?' s="1"':'';if(typeof value==='number'&&Number.isFinite(value))return `<c r="${c}"${st}><v>${value}</v></c>`;return `<c r="${c}" t="inlineStr"${st}><is><t xml:space="preserve">${xmlEsc(value)}</t></is></c>`}).join('')}</row>`).join('');
 return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetViews><sheetView workbookViewId="0"><pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/></sheetView></sheetViews><sheetFormatPr defaultRowHeight="16"/><cols>${cols}</cols><sheetData>${sheetRows}</sheetData>${autoFilter?`<autoFilter ref="A1:${colLetter(maxCols)}${Math.max(1,rows.length)}"/>`:''}</worksheet>`
}
const CRC_TABLE=(()=>{const result=[];for(let i=0;i<256;i++){let x=i;for(let j=0;j<8;j++)x=(x&1)?(0xedb88320^(x>>>1)):(x>>>1);result[i]=x>>>0}return result})();
function crc32(data){let crc=0xffffffff;for(const byte of data)crc=CRC_TABLE[(crc^byte)&255]^(crc>>>8);return (crc^0xffffffff)>>>0}
function zipCreate(entries){
 const enc=new TextEncoder(),pieces=[],centers=[];let offset=0;
 const u16=(view,pos,val)=>view.setUint16(pos,val,true),u32=(view,pos,val)=>view.setUint32(pos,val>>>0,true);
 function append(piece){pieces.push(piece);offset+=piece.length}
 for(const [filename,text] of entries){const name=enc.encode(filename),data=enc.encode(text),crc=crc32(data),local=new Uint8Array(30+name.length),dv=new DataView(local.buffer),begin=offset;
  u32(dv,0,0x04034b50);u16(dv,4,20);u16(dv,6,0x0800);u16(dv,8,0);u16(dv,10,0);u16(dv,12,0);u32(dv,14,crc);u32(dv,18,data.length);u32(dv,22,data.length);u16(dv,26,name.length);u16(dv,28,0);local.set(name,30);append(local);append(data);
  const cent=new Uint8Array(46+name.length),cv=new DataView(cent.buffer);u32(cv,0,0x02014b50);u16(cv,4,20);u16(cv,6,20);u16(cv,8,0x0800);u16(cv,10,0);u16(cv,12,0);u16(cv,14,0);u32(cv,16,crc);u32(cv,20,data.length);u32(cv,24,data.length);u16(cv,28,name.length);u16(cv,30,0);u16(cv,32,0);u16(cv,34,0);u16(cv,36,0);u32(cv,38,0);u32(cv,42,begin);cent.set(name,46);centers.push(cent)
 }
 const start=offset;for(const c of centers)append(c);const end=new Uint8Array(22),e=new DataView(end.buffer);u32(e,0,0x06054b50);u16(e,4,0);u16(e,6,0);u16(e,8,centers.length);u16(e,10,centers.length);u32(e,12,offset-start);u32(e,16,start);u16(e,20,0);append(end);return new Blob(pieces,{type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
}
function workbookFiles(rows,summary){const types=`<?xml version="1.0" encoding="UTF-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/xl/worksheets/sheet2.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/></Types>`;
 const rels=`<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>`;
 const workbook=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Risk Kayıtları" sheetId="1" r:id="rId1"/><sheet name="Rapor Bilgileri" sheetId="2" r:id="rId2"/></sheets></workbook>`;
 const wbRels=`<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet2.xml"/><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships>`;
 const styles=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><fonts count="2"><font><sz val="10"/><name val="Calibri"/></font><font><b/><sz val="10"/><color rgb="FFFFFFFF"/><name val="Calibri"/></font></fonts><fills count="3"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill><fill><patternFill patternType="solid"><fgColor rgb="FF0369A1"/><bgColor indexed="64"/></patternFill></fill></fills><borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="2"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/><xf numFmtId="0" fontId="1" fillId="2" borderId="0" xfId="0" applyFont="1" applyFill="1"/></cellXfs><cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles></styleSheet>`;
 return [['[Content_Types].xml',types],['_rels/.rels',rels],['xl/workbook.xml',workbook],['xl/_rels/workbook.xml.rels',wbRels],['xl/styles.xml',styles],['xl/worksheets/sheet1.xml',sheetXml(rows)],['xl/worksheets/sheet2.xml',sheetXml(summary,{width:36,autoFilter:false})]]}
function exportXlsx(){const rows=[EXCEL_COLUMNS,...state.records.map(recordToExcelRow)],m=state.meta;const summary=[['Alan','Değer'],['Yöntem','5×5 L Tipi Matris'],['İşyeri',m.company],['Tesis / Birim',m.facility],['Hazırlayan',m.prepared],['Değerlendirme Tarihi',m.date],['Revizyon',m.revision],['Toplam Risk',state.records.length],['Açık Yüksek / Çok Yüksek',state.records.filter(r=>!r.verified&&level('matrix',score('matrix',r.before)).rank>=3).length],['Doğrulanan Risk',state.records.filter(r=>r.verified).length],['Not','Risk bantları eğitim amaçlı örnektir; kurumsal kriterler geçerlidir.'],['Kaynak','İSG Risk Analizi - L Tipi Matris HTML']];downloadBlob(zipCreate(workbookFiles(rows,summary)),baseFilename()+'.xlsx');toast('Excel raporu oluşturuldu ('+state.records.length+' kayıt).')}
async function unzipEntries(arrayBuffer){const bytes=new Uint8Array(arrayBuffer),view=new DataView(arrayBuffer);let end=-1;for(let i=bytes.length-22;i>=Math.max(0,bytes.length-65557);i--)if(view.getUint32(i,true)===0x06054b50){end=i;break}if(end<0)throw new Error('Geçerli Excel ZIP yapısı bulunamadı.');const count=view.getUint16(end+10,true),base=view.getUint32(end+16,true),decoder=new TextDecoder(),entries={};let cursor=base;
 for(let i=0;i<count;i++){if(view.getUint32(cursor,true)!==0x02014b50)throw new Error('Excel dosyası merkezi dizini okunamadı.');const method=view.getUint16(cursor+10,true),compressed=view.getUint32(cursor+20,true),nameLength=view.getUint16(cursor+28,true),extra=view.getUint16(cursor+30,true),comment=view.getUint16(cursor+32,true),localOffset=view.getUint32(cursor+42,true),name=decoder.decode(bytes.subarray(cursor+46,cursor+46+nameLength));if(view.getUint32(localOffset,true)!==0x04034b50)throw new Error('Excel dosyası veri bölümü bozuk.');const start=localOffset+30+view.getUint16(localOffset+26,true)+view.getUint16(localOffset+28,true);const content=bytes.slice(start,start+compressed);if(method===0)entries[name]=decoder.decode(content);else if(method===8){if(typeof DecompressionStream!=='function')throw new Error('Bu tarayıcı sıkıştırılmış Excel içeri aktarmayı desteklemiyor. Güncel bir Chrome veya Edge tarayıcısı deneyin.');try{const stream=new Blob([content]).stream().pipeThrough(new DecompressionStream('deflate-raw'));entries[name]=decoder.decode(await new Response(stream).arrayBuffer())}catch(e){throw new Error('Excel sıkıştırması açılamadı: '+e.message)}}else throw new Error('Excel dosyasında desteklenmeyen sıkıştırma türü.');cursor+=46+nameLength+extra+comment;
 }return entries}
function parseXml(source){const doc=new DOMParser().parseFromString(source,'application/xml');if(doc.querySelector('parsererror'))throw new Error('Excel XML içeriği okunamadı.');return doc}
function parseXlsxSheet(source,shared=[]){if(!source)return [];const doc=parseXml(source),rows=[];for(const row of doc.getElementsByTagNameNS('*','row')){const cells=[];for(const c of row.getElementsByTagNameNS('*','c')){const ref=c.getAttribute('r')||'';let index=0;for(const letter of (ref.match(/^[A-Z]+/)||[''])[0])index=index*26+letter.charCodeAt(0)-64;index=Math.max(0,index-1);const type=c.getAttribute('t');let value='';if(type==='inlineStr')value=Array.from(c.getElementsByTagNameNS('*','t')).map(n=>n.textContent).join('');else{value=c.getElementsByTagNameNS('*','v')[0]?.textContent||'';if(type==='s')value=shared[Number(value)]||''}cells[index]=value}rows.push(cells)}return rows}
function normalizeDate(value){const str=asText(value);if(/^\d{4}-\d{2}-\d{2}$/.test(str))return str;
 if(/^\d{2}\.\d{2}\.\d{4}$/.test(str)){const a=str.split('.');return a[2]+'-'+a[1]+'-'+a[0]}
 const v=Number(value);if(Number.isFinite(v)&&v>=1&&v<100000){const d=new Date(Date.UTC(1899,11,30)+Math.floor(v)*86400000);return d.toISOString().slice(0,10)}return ''}
function fromExcelRow(row,idx){const read=k=>row[idx.get(k)]??'',isOld=idx.has('Yöntem Kodu');
 if(isOld&&asText(read('Yöntem Kodu')).trim()!=='matrix')return null;
 const statusRaw=read('Durum');const status=Object.keys(statusName).find(k=>statusName[k]===statusRaw)|| (Object.hasOwn(statusName,statusRaw)?statusRaw:'open');
 return normalizeRecord({id:read('Kayıt ID'),method:'matrix',unit:read('Bölüm'),activity:read('Faaliyet'),hazard:read('Tehlike'),risk:read('Olası Zarar / Risk'),affected:read('Etkilenenler'),existing:read('Mevcut Önlemler'),action:read('Planlanan Tedbir'),responsible:read('Sorumlu'),deadline:normalizeDate(read('Hedef Tarih')),status,verified:read('Doğrulama')==='Evet',before:{p:read(isOld?'Önce P/O':'Önce Olasılık'),s:read(isOld?'Önce S':'Önce Şiddet')},after:{p:read(isOld?'Sonra P/O':'Sonra Olasılık'),s:read(isOld?'Sonra S':'Sonra Şiddet')},notes:read('Notlar'),created:normalizeDate(read('Kayıt Tarihi'))||today()});
}
async function importData(file){const lower=file.name.toLowerCase();
 if(lower.endsWith('.xlsx')){const entries=await unzipEntries(await file.arrayBuffer());const strings=[];if(entries['xl/sharedStrings.xml']){const s=parseXml(entries['xl/sharedStrings.xml']);for(const item of s.getElementsByTagNameNS('*','si'))strings.push(Array.from(item.getElementsByTagNameNS('*','t')).map(t=>t.textContent).join(''))}
 const rows=parseXlsxSheet(entries['xl/worksheets/sheet1.xml'],strings);if(!rows.length)throw new Error('Excel dosyasında kayıt sayfası bulunamadı.');const head=new Map(rows[0].map((v,i)=>[v,i]));const common=['Kayıt ID','Tehlike','Bölüm','Faaliyet'];if(!common.every(k=>head.has(k)))throw new Error('Excel sütunları L Tipi Matris veri yapısıyla uyumlu değil.');
 const isOld=head.has('Yöntem Kodu')&&head.has('Önce P/O');if(!isOld&&!['Önce Olasılık','Önce Şiddet','Sonra Olasılık','Sonra Şiddet'].every(k=>head.has(k)))throw new Error('Yalnızca L Tipi Matris şablonu veya önceki risk analizi Excel dosyası desteklenir.');
 const dataRows=rows.slice(1).filter(r=>r.some(v=>asText(v).trim()));const records=dataRows.map(row=>fromExcelRow(row,head)).filter(Boolean);
 const meta=initMeta(),info=parseXlsxSheet(entries['xl/worksheets/sheet2.xml'],strings);const mm=new Map(info.slice(1).map(r=>[r[0],r[1]]));for(const [key,label] of Object.entries({company:'İşyeri',facility:'Tesis / Birim',prepared:'Hazırlayan',date:'Değerlendirme Tarihi',revision:'Revizyon'}))if(mm.has(label))meta[key]=asText(mm.get(label));return {meta,records,skipped:dataRows.length-records.length}}
 throw new Error('Yalnızca .xlsx biçiminde Excel dosyası seçin.')}
async function performImport(file){if(!file)return;
 try{const incoming=await importData(file);if(!incoming.records.length){throw new Error(incoming.skipped?'Dosyada L Tipi Matris kaydı bulunamadı.':'İçeri aktarılacak risk kaydı bulunamadı.');}
 if(state.records.length && !confirm(`Excel dosyasındaki ${incoming.records.length} L Tipi Matris kaydı yüklenecek. Mevcut ${state.records.length} risk kaydı silinip Excel içeriğiyle değiştirilecek. Devam etmeden önce Excel Dışarı Aktar ile yedek almanız önerilir. Onaylıyor musunuz?`))return;
 state={meta:{...initMeta(),...incoming.meta},records:incoming.records};
 persist();renderMeta();clearForm();setMatrixView('distribution');renderDashboard();toast(`${incoming.records.length} L Tipi Matris kaydı içeri aktarıldı.${incoming.skipped?' '+incoming.skipped+' farklı yöntem kaydı atlandı.':''}`);
 }catch(e){console.error(e);alert('İçeri alma başarısız: '+e.message)}finally{$('importFile').value=''}
}
/* OLGUN UI2: Yerel logo, başlık ve kurum adı (5 art arda tıklama) */
const BRAND_KEY='isg-risk-ltipi-matris-olgun-ui2-brand-v1';
const BRAND_DEFAULT={title:'İSG RİSK ANALİZİ – L TİPİ MATRİS',subtitle:'(5×5 Olasılık × Şiddet · Risk değerlendirme ve önlem takip formu)',org:'OLGUN BAŞKANLIĞI',logo:''};
let brand={...BRAND_DEFAULT};
function storeBrand(){try{localStorage.setItem(BRAND_KEY,JSON.stringify(brand));}catch(e){toast('Logo veya başlık cihazda saklanamadı. Daha küçük bir görsel deneyin.')}}
function setBrandLogo(source){const img=$('brandLogo'),fallback=$('logoFallback');img.onload=()=>{img.hidden=false;fallback.hidden=true};img.onerror=()=>{img.hidden=true;fallback.hidden=false};img.hidden=true;fallback.hidden=false;img.src=source||'logo.jpg';}
function initializeBrand(){try{const stored=JSON.parse(localStorage.getItem(BRAND_KEY)||'{}');for(const k of Object.keys(BRAND_DEFAULT))if(typeof stored[k]==='string')brand[k]=stored[k];}catch(e){}
 $('brandTitle').textContent=brand.title||BRAND_DEFAULT.title;$('brandSubtitle').textContent=brand.subtitle||BRAND_DEFAULT.subtitle;$('brandOrg').textContent=brand.org||BRAND_DEFAULT.org;setBrandLogo(brand.logo);
 setupFiveClicks($('logoTrigger'),()=>{$('logoChooser').click()});
 for(const [id,key] of [['brandTitle','title'],['brandSubtitle','subtitle'],['brandOrg','org']])setupFiveClicks($(id),()=>unlockBrandField($(id),key));
 $('logoChooser').addEventListener('change',event=>{const file=event.target.files?.[0];if(!file)return;
   if(!file.type.startsWith('image/')){alert('Lütfen bir resim dosyası seçin.');event.target.value='';return}
   if(file.size>1250000){alert('Logo 1,25 MB’dan küçük olmalıdır.');event.target.value='';return}
   const reader=new FileReader();reader.onload=()=>{brand.logo=String(reader.result||'');setBrandLogo(brand.logo);storeBrand();toast('Kurum logosu güncellendi.');};reader.readAsDataURL(file);event.target.value='';
 });
}
function setupFiveClicks(el,action){let count=0,last=0;el.addEventListener('click',()=>{if(el.isContentEditable)return;const now=Date.now();count=(now-last>1150)?1:count+1;last=now;if(count>=5){count=0;action();}})}
function unlockBrandField(el,key){el.setAttribute('contenteditable','true');el.setAttribute('role','textbox');el.setAttribute('aria-label','Düzenlenebilir başlık alanı');el.focus();
 const sel=window.getSelection(),range=document.createRange();range.selectNodeContents(el);sel.removeAllRanges();sel.addRange(range);let settled=false;
 const save=()=>{if(settled)return;settled=true;el.removeAttribute('contenteditable');el.removeAttribute('role');el.removeAttribute('aria-label');const value=(el.textContent||'').replace(/\s+/g,' ').trim();brand[key]=value||BRAND_DEFAULT[key];el.textContent=brand[key];storeBrand();el.removeEventListener('blur',save);el.removeEventListener('keydown',onKey);toast('Başlık bilgisi kaydedildi.');};
 const onKey=event=>{if(event.key==='Enter'){event.preventDefault();el.blur()}else if(event.key==='Escape'){event.preventDefault();el.textContent=brand[key];el.blur()}};
 el.addEventListener('blur',save);el.addEventListener('keydown',onKey);
}
/* Ekrandaki gerçek alanları ve 5×5 matrisi koruyan yazdırılabilir görünüm */
function renderPrint(){const source=$('app'),clone=source.cloneNode(true);
 // Kullanıcı kaydı kaydedince ekran yeni kayıt için temizlenir. PDF'de son kaydın
 // gerçekten doldurulmuş değerlerini göstermek için salt yazdırma kopyasını doldur.
 const latest=state.records.length && !$('hazard').value.trim() && !editingId?state.records[state.records.length-1]:null;
 if(latest){
   const label=clone.querySelector('#formTitleText');if(label)label.textContent='Son Kaydedilen Risk – Doldurulmuş Form';
   for(const side of ['before','after']){
     const val=score('matrix',latest[side]),info=level('matrix',val);
     const n=clone.querySelector('#'+side+'Score');if(n)n.textContent=fmt(val);
     const l=clone.querySelector('#'+side+'Level');if(l){l.textContent=info.label;l.className='risk-tag '+info.className}
   }
   const aft=clone.querySelector('#afterTitle');if(aft)aft.textContent=latest.verified?'Kontrol sonrası doğrulandı':'Planlanan seviye';
   for(const btn of clone.querySelectorAll('.matrix-cell[data-p][data-s]')){
     const p=Number(btn.dataset.p),v=Number(btn.dataset.s),bef=latest.before.p===p&&latest.before.s===v,aft=latest.after.p===p&&latest.after.s===v;
     btn.classList.toggle('is-before',bef);btn.classList.toggle('is-after',aft);
     btn.querySelector('.cell-labels').innerHTML=(bef?'<span>M</span>':'')+(aft?'<span class="after-marker">H</span>':'');
   }
 }
 const copyValues={unit:'unit',activity:'activity',hazard:'hazard',risk:'risk',affected:'affected',existing:'existing',action:'action',responsible:'responsible',deadline:'deadline',status:'status',notes:'notes'};
 const from=source.querySelectorAll('input,select,textarea'),to=clone.querySelectorAll('input,select,textarea');
 for(let i=to.length-1;i>=0;i--){const src=from[i],dst=to[i];if(!src||!dst)continue;
   if(src.type==='hidden'||src.type==='file'||src.type==='search'){dst.remove();continue}
   let val=src.type==='checkbox'?(src.checked?'☑ Evet':'☐ Hayır'):(src.tagName==='SELECT'?(src.selectedOptions[0]?.textContent||''):src.value);
   if(latest){
     if(Object.hasOwn(copyValues,src.id)){const key=copyValues[src.id];val=key==='status'?(statusName[latest.status]||latest.status):latest[key];}
     else if(src.id==='verified')val=latest.verified?'☑ Evet':'☐ Hayır';
     else {const hit=/^factor-(before|after)-(p|s)$/.exec(src.id);if(hit){const n=latest[hit[1]][hit[2]];val=Array.from(src.options).find(o=>Number(o.value)===n)?.textContent||n}}
   }
   const holder=document.createElement('div');holder.className='print-field-value';holder.textContent=val||'—';dst.replaceWith(holder);
 }
 clone.removeAttribute('id');clone.classList.add('print-document');
 clone.querySelectorAll('.record-bottom-actions').forEach(el=>el.closest('.card-body')?.remove());
 clone.querySelectorAll('.filters,.actionbar,.record-bottom-actions,.toolbar,.explain,footer').forEach(el=>el.remove());
 // Ekranda kısaltılmış satırlar yerine PDF'de tüm tehlike/tedbir kayıtları basılır.
 const table=clone.querySelector('.tablebox table');if(table){
   table.innerHTML='<thead><tr><th>No.</th><th>Bölüm / Faaliyet</th><th>Tehlike / Risk / Mevcut Önlem</th><th>Önce Oת</th><th>Alınacak Tedbir / Aksiyon</th><th>Sonra Oת</th><th>Sorumlu / Tarih / Durum</th></tr></thead>';
   const tbody=document.createElement('tbody');
   tbody.innerHTML=state.records.map((r,i)=>`<tr><td>${i+1}</td><td><b>${esc(r.unit)}</b><br>${esc(r.activity)}</td><td><b>Tehlike:</b> ${esc(r.hazard)}<br><b>Risk:</b> ${esc(r.risk)}<br><b>Etkilenen:</b> ${esc(r.affected||'—')}<br><b>Mevcut önlem:</b> ${esc(r.existing||'—')}</td><td>${r.before.p}×${r.before.s} = <b>${score('matrix',r.before)}</b><br>${esc(level('matrix',score('matrix',r.before)).label)}</td><td>${esc(r.action)}</td><td>${r.after.p}×${r.after.s} = <b>${score('matrix',r.after)}</b><br>${esc(r.verified?'Doğrulandı':'Hedef')}</td><td><b>${esc(r.responsible||'—')}</b><br>${esc(r.deadline||'—')}<br>${esc(statusName[r.status]||r.status)}${r.notes?'<br>'+esc(r.notes):''}</td></tr>`).join('')||'<tr><td colspan="7">Henüz kaydedilmiş risk bulunmuyor.</td></tr>';
   table.append(tbody);
 }
 clone.querySelectorAll('[id]').forEach(el=>el.removeAttribute('id'));
 const target=$('printReport');target.replaceChildren(clone);
 const repeatedHeader=$('pageHeader').cloneNode(true);
 repeatedHeader.removeAttribute('id'); repeatedHeader.classList.add('print-header-duplicate');
 repeatedHeader.querySelector('#logoChooser')?.remove();
 // Yazdırılan tekrarlı başlıkta logo etkileşimli buton değil, statik resim alanıdır.
 const logoButton=repeatedHeader.querySelector('#logoTrigger');
 if(logoButton){
   const printLogo=document.createElement('div');
   printLogo.className=logoButton.className;
   printLogo.innerHTML=logoButton.innerHTML;
   logoButton.replaceWith(printLogo);
 }
 repeatedHeader.querySelectorAll('[id]').forEach(el=>el.removeAttribute('id'));
 $('printHeader').replaceChildren(repeatedHeader);
}
function bind(){
 document.querySelectorAll('[data-meta]').forEach(el=>el.addEventListener('input',()=>{state.meta[el.dataset.meta]=el.value;persist()}));
 // Sabit yöntem: 5×5 L Tipi Matris; yöntem seçimi bulunmaz.
 for(const container of [$('beforeFields'),$('afterFields')])container.addEventListener('change',event=>{const el=event.target;if(el.matches('select[data-factor]')){setMatrixActiveSide(el.dataset.side);working[el.dataset.side][el.dataset.factor]=Number(el.value);updatePreview()}});
 $('status').addEventListener('change',updateVerifyState);$('verified').addEventListener('change',updatePreview);
 document.querySelectorAll('.assessment-scores .score-panel').forEach(panel=>{panel.addEventListener('pointerdown',()=>setMatrixActiveSide(panel.dataset.side));panel.addEventListener('focusin',()=>setMatrixActiveSide(panel.dataset.side));});
 $('matrixModeSingle').addEventListener('click',()=>setMatrixView('single'));
 $('matrixModeDistribution').addEventListener('click',()=>setMatrixView('distribution'));
 $('matrixVisual').addEventListener('click',event=>{const btn=event.target.closest('button[data-p][data-s]');if(!btn)return;const side=matrixActiveSide,p=Number(btn.dataset.p),severity=Number(btn.dataset.s);working[side]={p,s:severity};$('factor-'+side+'-p').value=p;$('factor-'+side+'-s').value=severity;updatePreview()});
 $('riskForm').addEventListener('submit',event=>{event.preventDefault();const form=$('riskForm');if(!form.checkValidity()){form.reportValidity();return}if($('verified').checked&&$('status').value!=='done'){alert('Kalan risk doğrulaması için aksiyon durumu “Tamamlandı” olmalıdır.');return}const r=recordFromForm();const wasEditing=Boolean(editingId);if(editingId){const i=state.records.findIndex(x=>x.id===editingId);if(i<0)return;state.records[i]=r}else state.records.push(r);persist();clearForm();setMatrixView('distribution');renderDashboard();toast(wasEditing?'Risk güncellendi.':'Risk kaydı başarıyla kaydedildi.')});
 $('newBtn').addEventListener('click',clearForm);$('cancelBtn').addEventListener('click',clearForm);
 $('riskRows').addEventListener('click',event=>{const btn=event.target.closest('button[data-act]');if(!btn)return;const id=btn.dataset.id;if(btn.dataset.act==='edit')startEdit(id);if(btn.dataset.act==='delete')deleteRecord(id);if(btn.dataset.act==='duplicate')duplicateRecord(id)});
 for(const id of ['searchInput','statusFilter'])$(id).addEventListener('input',renderDashboard);
 $('xlsxBtn').addEventListener('click',exportXlsx);
 $('pdfBtn').addEventListener('click',()=>{renderPrint();window.print()});window.addEventListener('beforeprint',renderPrint);
 $('importBtn').addEventListener('click',()=>$('importFile').click());$('importFile').addEventListener('change',e=>performImport(e.target.files?.[0]));
 $('clearBtn').addEventListener('click',()=>{if(!state.records.length){toast('Silinecek kayıt bulunmuyor.');return}if(!confirm(`DİKKAT: ${state.records.length} risk kaydının tamamı silinecek. Bu işlem geri alınamaz. Önce Excel Dışarı Aktar ile yedek aldığınızdan emin olun. Devam edilsin mi?`))return;state.records=[];persist();clearForm();renderDashboard();toast('Tüm risk kayıtları silindi.')});
}
load();
$('searchInput').value='';$('statusFilter').value='';
initializeBrand();renderMeta();$('method').value='matrix';renderScoreFields();updateVerifyState();bind();renderDashboard();
// Tarayıcı geri/ileri önbelleğinden yeniden açıldığında da 03 bölümü boşaltılır.
window.addEventListener('pageshow',event=>{
 if(!event.persisted)return;
 state.records=[];
 $('searchInput').value='';$('statusFilter').value='';
 matrixView='single';clearForm();renderDashboard();
});
})();
</script>
</body>
</html>