Güvenlik Mimarisi İnceleme Talep ve Karar Formu

Güvenlik Mimarisi İnceleme Talep ve Karar Formu, kurumun bilgi sistemleri, uygulamaları ve altyapılarının siber güvenlik açısından değerlendirilmesini sağlar. Güvenlik kontrollerini, olası riskleri, düzeltici faaliyetleri ve onay süreçlerini kayıt altına alarak güvenli sistem tasarımını, risklerin azaltılmasını ve kararların izlenebilirliğini hedefler. 

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: "Güvenlik Mimarisi İnceleme Talep ve Karar Formu.html" sayfayı kapatıp tekrar açtığınızda, web browser üzerinden sayfanız açılacaktır. 

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:

HTML Kod:
<!doctype html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light">
<meta name="olgun-ui2-version" content="2026-10-10-ui2-gri-cerceve-ust-cizgisiz-v5">
<title>Güvenlik Mimarisi İnceleme Talep ve Karar Formu</title>
<style>
/* OLGUN UI2 · TEKİL KURUMSAL TEMA (önceki tekrar eden stiller kaldırıldı) */
:root {
  --ui-bg: #f8fafc;
  --ui-canvas: #e9eff5;
  --ui-panel: #ffffff;
  --ui-primary: #0284c7;
  --ui-primary-deep: #075985;
  --ui-border: #cbd5e1;
  --ui-text: #142437;
  --ui-muted: #64748b;
  --ui-shadow: 0 2px 8px rgba(30,58,86,.075);
}
*,*::before,*::after { box-sizing:border-box; }
html { min-height:100%; background:var(--ui-canvas); }
body { min-height:100vh; margin:0; color:var(--ui-text); background:var(--ui-canvas); font:13px/1.45 'Segoe UI',Arial,sans-serif; }
[hidden] { display:none!important; }
.app {
  display:block; width:100%; max-width:none; min-height:100vh; min-height:100dvh;
  height:auto; margin:0; padding:15px 18px 20px; background:var(--ui-bg);
  border:3px solid #94a3b8;
  box-shadow:inset 0 0 0 1px #d9e4ee,0 4px 18px rgba(15,23,42,.11);
}
/* Bağımsız beyaz başlık paneli */
.top {
  display:block; margin:0 0 12px; padding:0; background:#fff;
  border:1.5px solid #b7c8d8; border-radius:6px; box-shadow:0 2px 9px rgba(30,58,86,.085);
  overflow:hidden;
}
.brand {
  display:grid; grid-template-columns:70px minmax(0,1fr) minmax(170px,35%);
  gap:13px; align-items:center; min-height:92px; padding:14px 15px;
  background:#fff; border-left:4px solid var(--ui-primary);
}
.brand-logo {
  appearance:none; width:68px; height:62px; display:flex; align-items:center; justify-content:center;
  border:1px solid #cbd5e1; border-radius:5px; background:#fff; color:#64748b;
  cursor:pointer; padding:4px; overflow:hidden; font:700 10px 'Segoe UI',Arial,sans-serif;
}
.brand-logo:hover { background:#f8fafc; border-color:#93c5fd; }
.brand-logo:focus-visible,.agency:focus-visible { outline:2px solid var(--ui-primary); outline-offset:2px; }
.brand-logo img { display:block; width:100%; height:100%; object-fit:contain; }
.logo-placeholder { display:flex; flex-direction:column; gap:2px; align-items:center; line-height:1.2; }
.logo-placeholder small { font-size:9px; font-weight:500; color:var(--ui-primary); }
.brand-main { min-width:0; }
.brand-main h1 { margin:0; font-size:21px; line-height:1.24; color:#102c45; letter-spacing:-.3px; }
.brand-main p { margin:5px 0 0; font-size:11.5px; color:#64748b; }
.agency {
  justify-self:end; min-width:0; max-width:100%; width:max-content;
  color:#000; font-size:19.667px; font-weight:700; line-height:1.25;
  text-align:right; overflow-wrap:anywhere; cursor:pointer; user-select:none; touch-action:manipulation;
}
.agency[contenteditable=true] {
  cursor:text; user-select:text; outline:2px solid var(--ui-primary);
  min-width:120px; border-radius:4px; background:#fff; padding:4px;
}
/* Olgun UI2: buton grubu basligin ALTINDA SOLDA; cerceve YALNIZCA grubun etrafindadir. */
.actions-row {
  display:flex; align-items:flex-start; justify-content:flex-start;
  width:100%; padding:0; margin:0 0 15px; background:transparent;
}
.actions-panel {
  display:inline-flex; align-items:center; justify-content:flex-start;
  flex:0 1 auto; width:max-content; max-width:100%; min-height:56px;
  margin:0; padding:10px 12px;
  background:#ffffff; border:1.5px solid #adbfce;
  border-radius:6px; box-shadow:0 2px 9px rgba(30,58,86,.10);
}
.toolbar {
  display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-start;
  width:auto; max-width:100%; gap:9px; margin:0; padding:0;
  border:0; border-radius:0; box-shadow:none; background:transparent;
}
button { font:600 12px 'Segoe UI',Arial,sans-serif; cursor:pointer; transition:background .14s,border-color .14s; }
.action {
  min-height:35px; padding:8px 13px; border:1px solid var(--ui-border);
  border-radius:5px; box-shadow:0 1px 2px rgba(15,23,42,.04);
  white-space:nowrap; color:#334155;
}
.action:focus-visible,.small-button:focus-visible { outline:2px solid var(--ui-primary); outline-offset:2px; }
#importBtn { background:#dbeafe; border-color:#93c5fd; color:#075985; }
#importBtn:hover { background:#c7dffe; }
#exportBtn { background:#dcfce7; border-color:#86efac; color:#166534; }
#exportBtn:hover { background:#bbf7d0; }
#printBtn { background:#f1f5f9; border-color:#cbd5e1; color:#334155; }
#printBtn:hover { background:#e2e8f0; }
.toolbar-tip { margin-left:auto; color:#64748b; font-size:11px; text-align:right; }
.statusline { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:8px; padding:0 4px 9px; color:#64748b; font-size:11px; }
.status-note { color:var(--ui-primary-deep); font-weight:700; }
/* Beyaz içerik panelleri ve kurumsal mavi başlıkları */
.panel { margin:0 0 11px; background:var(--ui-panel); border:1px solid #c5d3df; border-radius:6px; box-shadow:var(--ui-shadow); overflow:visible; height:auto; min-height:0; }
.panel-head {
  display:flex; gap:9px; align-items:center; padding:8px 12px;
  border-bottom:1px solid #dbe5ef; border-left:3px solid var(--ui-primary);
  background:#eaf4fb; border-radius:5px 5px 0 0;
}
.panel-head h2 { margin:0; font-size:13.5px; line-height:1.3; color:var(--ui-primary-deep); }
.num { display:inline-flex; flex:0 0 auto; align-items:center; justify-content:center; width:25px; height:24px; border-radius:4px; background:#dbeefa; color:#0369a1; font-size:11px; font-weight:700; }
.panel-head .description { margin-left:auto; text-align:right; font-size:10.5px; color:#64748b; }
.panel-content { padding:12px 14px; height:auto; max-height:none; overflow:visible; }
.grid { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:10px 12px; align-items:start; height:auto; }
.field { display:flex; flex-direction:column; gap:4px; min-width:0; height:auto; align-self:start; }
.w2 { grid-column:span 2; }.w3 { grid-column:span 3; }.w4 { grid-column:1/-1; }
label { font-size:11px; font-weight:600; color:#35475a; }.required { color:#b91c1c; }
input,textarea,select {
  width:100%; min-width:0; min-height:33px; padding:7px 8px;
  border:1px solid var(--ui-border); border-radius:5px;
  outline:none; background:#fff; color:#0f172a; font:12px/1.4 'Segoe UI',Arial,sans-serif;
}
textarea { display:block; min-height:55px; height:auto; max-height:none; resize:vertical; overflow-y:hidden; white-space:pre-wrap; overflow-wrap:anywhere; line-height:1.45; }
input::placeholder,textarea::placeholder { color:#94a3b8; }
input:focus,textarea:focus,select:focus { border-color:var(--ui-primary); box-shadow:0 0 0 2px #0284c722; }
.table-scroll { width:100%; max-width:100%; height:auto; max-height:none; overflow-x:auto; overflow-y:visible; border:1px solid #dee7ef; border-radius:5px; }
.simple-table { width:100%; border-collapse:collapse; table-layout:fixed; }
.simple-table thead { background:#edf6fc; }
.simple-table th { padding:7px 8px; text-align:left; color:#35566e; font-size:11px; font-weight:700; border-bottom:1px solid #dbe5ef; }
.simple-table td { padding:5px 7px; vertical-align:top; font-size:12px; border-bottom:1px solid #e9eff4; height:auto; }
.simple-table tr:last-child td { border-bottom:0; }
.simple-table select,.simple-table input,.simple-table textarea { min-height:31px; padding:5px 6px; font-size:12px; }
.simple-table textarea { width:100%; height:auto; min-height:35px; max-height:none; overflow:hidden; resize:vertical; }
.controls td:first-child { font-weight:500; }
.controls th:nth-child(1) { width:42%; }.controls th:nth-child(2) { width:22%; }.controls th:nth-child(3) { width:36%; }
.controls select[data-status='Uygun'] { color:#166534; background:#f0fdf4; }
.controls select[data-status='Kısmen Uygun'] { color:#92400e; background:#fffbeb; }
.controls select[data-status='Uygun Değil'] { color:#b91c1c; background:#fff1f2; }
.risks { min-width:1100px; }
.risks th:nth-child(1) { width:19%; }
.risks th:nth-child(2),.risks th:nth-child(3) { width:7%; }
.risks th:nth-child(4) { width:12%; }.risks th:nth-child(5) { width:19%; }
.risks th:nth-child(6) { width:12%; }.risks th:nth-child(7) { width:12%; }
.risks th:nth-child(8) { width:10%; }.risks th:nth-child(9) { width:30px; }
.risk-level { white-space:nowrap; font-size:11px; font-weight:700; }
.risk-level.low { color:#166534; }.risk-level.medium { color:#92400e; }
.risk-level.high,.risk-level.critical { color:#b91c1c; }
.table-bottom { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:9px; }
.hint { font-size:11px; color:#64748b; }
.small-button { padding:7px 11px; background:#e8f5fd; border:1px solid #9cc9e4; color:#075985; border-radius:5px; white-space:nowrap; }
.small-button:hover { background:#d9eefb; }
.remove { padding:6px 9px; border-radius:4px; border:1px solid #fecaca; background:#fff5f5; color:#b91c1c; }
.risk-empty { padding:11px 12px; border:1px dashed #cbdfea; border-radius:5px; color:#64748b; background:#f8fbfe; font-size:12px; }
.conditional { padding:11px 12px; border:1px solid #bcdcf0; border-radius:5px; background:#f2f9fe; margin-top:11px; }
.compact-details { margin-top:9px; border-top:1px solid #e1ebf2; }
.compact-details > summary { display:flex; align-items:center; justify-content:space-between; gap:9px; min-height:35px; padding:8px 10px 4px; border-radius:4px; cursor:pointer; list-style:none; color:#075985; font-size:12px; font-weight:600; }
.compact-details > summary::-webkit-details-marker { display:none; }
.compact-details > summary small { font-size:10px; color:#64748b; font-weight:400; }
.compact-details[open] > summary { margin:6px 0 9px; padding:8px 10px; background:#f0f8fe; }
.details-content { padding:4px 1px; }
.toast { display:none; position:fixed; z-index:50; right:20px; bottom:18px; max-width:min(460px,90vw); padding:11px 15px; border:1px solid #9bd0e8; border-radius:6px; color:#075985; background:#e7f5fd; box-shadow:0 5px 24px #0f172a2a; font-weight:600; }
.toast.show { display:block; }.toast.error { color:#991b1b; background:#fff1f2; border-color:#fecdd3; }
.footnote { padding:0 3px; text-align:right; color:#7b8ba0; font-size:10px; }
.sr-only { position:absolute; left:-10000px; width:1px; height:1px; overflow:hidden; }
.print-textarea-mirror,.print-value-mirror { display:none; }
@media (max-width:1100px) {
  .brand { grid-template-columns:60px minmax(0,1fr) minmax(120px,33%); }
  .brand-logo { width:60px; height:56px; }.brand-main h1 { font-size:18px; }.agency { font-size:16.667px; }
  .grid { grid-template-columns:repeat(2,minmax(0,1fr)); }.w3,.w4 { grid-column:1/-1; }
}
@media (max-width:760px) {
  .app { padding:9px; border-width:2px; }
  .top { margin-bottom:8px; }.actions-row { margin-bottom:9px; }.actions-panel { padding:8px; }
  .brand { grid-template-columns:52px minmax(0,1fr); grid-template-rows:auto auto; gap:5px 9px; padding:9px 10px; }
  .brand-logo { width:52px; height:50px; grid-column:1; grid-row:1/3; }
  .brand-main { grid-column:2; grid-row:1; }.brand-main h1 { font-size:15px; }.brand-main p { font-size:10px; }
  .agency { grid-column:2; grid-row:2; font-size:13.667px; }
  .panel-head .description { display:none; }.toolbar-tip { display:none; }
  .grid { grid-template-columns:repeat(2,minmax(0,1fr)); }.w2,.w3,.w4 { grid-column:1/-1; }
  /* Telefon ve dar ekranlarda kontrol tablosu satirlari dikey kartlara donusur. */
  .controls { min-width:0; table-layout:auto; }
  .controls thead { display:none; }
  .controls tbody tr { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:7px 10px; padding:10px; border-bottom:1px solid #dce7f0; background:#fff; }
  .controls tbody tr:nth-child(odd) { background:#f8fbff; }
  .controls tbody td { display:flex; flex-direction:column; gap:4px; min-width:0; border:0; padding:0; }
  .controls tbody td:first-child { grid-column:1/-1; color:#164e70; font-weight:700; }
  .controls tbody td:nth-child(2)::before { content:'Değerlendirme'; font-size:10px; color:#64748b; font-weight:600; }
  .controls tbody td:nth-child(3)::before { content:'Açıklama / Eksiklik'; font-size:10px; color:#64748b; font-weight:600; }
  .controls tbody td:nth-child(3) { grid-column:1/-1; }

  .risks { min-width:0; table-layout:auto; }.risks thead { display:none; }
  .risks tbody tr { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:7px 9px; padding:10px; background:#fafdff; border-bottom:1px solid #dde7ee; }
  .risks tbody td { display:flex; flex-direction:column; gap:3px; min-width:0; padding:0!important; border:0; }
  .risks tbody td::before { content:attr(data-label); font-size:10.5px; color:#516678; font-weight:600; }
  .risks tbody td:first-child,.risks tbody td:nth-child(5) { grid-column:1/-1; }
  .risks tbody td:last-child { justify-content:flex-end; }.risks tbody td:last-child::before { display:none; }
  .risks tbody td:nth-child(4) { justify-content:center; }.risks tbody td:nth-child(4) .risk-level { padding:7px 0; }
  .table-bottom { flex-wrap:wrap; }
}
@media (max-width:490px) {
  .grid { grid-template-columns:1fr; }.w2,.w3,.w4 { grid-column:1/-1; }
  .panel-content { padding:10px; }.brand-main h1 { font-size:13.5px; }
  .action { flex:1 1 130px; padding:8px 9px; font-size:11px; }
  .actions-panel { width:100%; }.toolbar { width:100%; gap:6px; }.controls { min-width:0; }
}
/* Her gerçek yazdırma sayfasının sağ altında dinamik sayfa numarası */
@page {
  size:A4 landscape; margin:9mm 10mm 14mm;
  @bottom-right {
    content:'Sayfa ' counter(page) ' / ' counter(pages);
    font-family:'Segoe UI',Arial,sans-serif; font-size:9pt; font-weight:700;
    color:#075985; text-align:right; vertical-align:middle;
    border-top:.45pt solid #cbd5e1; padding-top:1mm;
  }
}
@media print {
  html,body { height:auto!important; min-height:0!important; overflow:visible!important; background:#fff!important; color:#111; print-color-adjust:exact!important; -webkit-print-color-adjust:exact!important; }
  .app { width:100%!important; min-height:0!important; height:auto!important; padding:0!important; margin:0!important; border:0!important; box-shadow:none!important; background:#fff!important; overflow:visible!important; }
  .top { margin:0 0 6px!important; padding:0!important; border:1px solid #cbd5e1!important; background:#fff!important; border-radius:4px!important; box-shadow:none!important; overflow:visible!important; break-inside:avoid-page; }
  .brand { min-height:56px!important; padding:6px 9px!important; gap:7px!important; grid-template-columns:52px minmax(0,1fr) minmax(130px,32%)!important; grid-template-rows:auto!important; border-left:4px solid #0284c7!important; background:#fff!important; }
  .brand-logo { width:52px!important; height:46px!important; grid-column:1!important; grid-row:1!important; cursor:default; }
  .brand-main { grid-column:2!important; grid-row:1!important; }.brand-main h1 { font-size:13pt!important; }.brand-main p { font-size:8.5px!important; }
  .agency { grid-column:3!important; grid-row:1!important; font-size:12pt!important; }
  .actions-row,.actions-panel,.toolbar,.toast,.footnote,.table-bottom,.remove,.no-print { display:none!important; }
  .statusline { padding:1px 0 5px!important; font-size:9px!important; }
  .panel { margin-bottom:7px!important; border:1px solid #cbd5e1!important; border-radius:4px; box-shadow:none!important; background:#fff!important; overflow:visible!important; break-inside:auto!important; }
  .panel-head { padding:5px 9px!important; background:#eef6fc!important; border-left:3px solid #0284c7!important; break-after:avoid-page!important; break-inside:avoid!important; }
  .panel-head h2 { font-size:11px!important; }.panel-head .description { display:none!important; }
  .panel-content { padding:7px 9px!important; overflow:visible!important; break-inside:auto!important; }
  .grid { grid-template-columns:repeat(4,minmax(0,1fr))!important; gap:4px 8px!important; }
  .w2 { grid-column:span 2!important; }.w3 { grid-column:span 3!important; }.w4 { grid-column:1/-1!important; }
  .field { gap:2px!important; break-inside:avoid-page; }.field:has(textarea) { break-inside:auto!important; }
  label { font-size:8.5px!important; }
  .compact-details { margin-top:5px!important; border-top:1px solid #dfebf4!important; }
  .compact-details > summary { display:none!important; }.compact-details:not([open]) > .details-content { display:grid!important; }
  .compact-details .details-content { padding:5px 0 0!important; }
  .table-scroll { overflow:visible!important; border:0!important; break-inside:auto!important; }
  .simple-table { min-width:0!important; width:100%!important; table-layout:fixed!important; }
  .simple-table thead,.risks thead,.controls thead { display:table-header-group!important; }.simple-table tbody { display:table-row-group!important; }
  .controls tbody tr { display:table-row!important; background:#fff!important; padding:0!important; border-bottom:0!important; }
  .controls tbody td { display:table-cell!important; padding:3px 5px!important; border-bottom:1px solid #e9eff4!important; }
  .controls tbody td::before { display:none!important; }
  .simple-table th { padding:4px 5px!important; font-size:8px!important; }.simple-table td { padding:3px 5px!important; font-size:8.5px!important; }
  .simple-table tr { break-inside:avoid-page!important; height:auto!important; }
  .controls th:nth-child(1) { width:47%; }.controls th:nth-child(2) { width:20%; }.controls th:nth-child(3) { width:33%; }
  .risks { min-width:0!important; table-layout:fixed!important; }.risks tbody tr { display:table-row!important; background:#fff!important; }
  .risks tbody td { display:table-cell!important; padding:3px 4px!important; border-bottom:1px solid #e9eff4!important; }
  .risks tbody td::before { display:none!important; }
  .risks th:nth-child(1) { width:17%; }.risks th:nth-child(2),.risks th:nth-child(3) { width:6%; }
  .risks th:nth-child(4) { width:11%; }.risks th:nth-child(5) { width:17%; }.risks th:nth-child(6) { width:10%; }
  .risks th:nth-child(7) { width:12%; }.risks th:nth-child(8) { width:11%; }.risks th:nth-child(9) { width:0; }
  .risks td:last-child,.risks th:last-child { display:none!important; }
  .risk-level { font-size:8px!important; }.risk-empty { display:none!important; }
  .conditional { padding:6px!important; margin-top:6px!important; }
  textarea,.panel input,.panel select { display:none!important; }
  .print-value-mirror,.print-textarea-mirror { display:block!important; min-height:14px; padding:2px 4px; border:1px solid #d9e3ea; border-radius:3px; background:#fff; color:#111; font-size:8.5px; line-height:1.25; white-space:pre-wrap; overflow-wrap:anywhere; break-inside:auto!important; }
  .print-textarea-mirror { min-height:22px; font-size:9px; }
  .controls .print-value-mirror { font-size:8px; padding:2px 3px; }
  .print-value-mirror[data-state='Uygun'] { color:#166534; background:#f0fdf4; }
  .print-value-mirror[data-state='Uygun Değil'] { color:#991b1b; background:#fff1f2; }
  .print-value-mirror[data-state='Kısmen Uygun'] { color:#92400e; background:#fffbeb; }
}
</style>
</head>
<body>
<!-- Olgun UI2 v4: Tam genişlikli gri dış çerçeve; AYRI beyaz başlık; başlığın altında yalnızca sol düğmeleri saran AYRI beyaz çerçeve. -->

<div class="app" id="formRoot">
  <div class="top">
    <header class="brand">
      <button class="brand-logo" id="logoPicker" type="button" title="Logo varsa 5 kez tıklayarak değiştirin; yoksa tıklayarak seçin" aria-label="Kurum logosunu seç veya değiştir"><img id="logoImage" src="logo.jpg" alt="Kurum logosu" hidden><span class="logo-placeholder" id="logoPlaceholder">LOGO<small>Logo seç</small></span></button>
      <input class="sr-only" type="file" id="logoFile" accept="image/png,image/jpeg,image/webp,image/gif,.png,.jpg,.jpeg,.webp,.gif" aria-label="Kurum logosu dosyası">
      <div class="brand-main"><h1>Güvenlik Mimarisi İnceleme Talep ve Karar Formu</h1><p>(Talep, temel kontroller, riskler ve güvenlik kararı)</p></div>
      <div id="agency" class="agency" role="button" tabindex="0" aria-label="Kurum adını düzenlemek için art arda beş kez tıklayın veya Enter tuşuna basın" title="Kurum adını düzenlemek için art arda 5 kez tıklayın / dokunun">OLGUN BAŞKANLIĞI</div>
    </header>
  </div>
  <div class="actions-row">
    <div class="actions-panel" role="group" aria-label="İşlem düğmeleri paneli">
      <nav class="toolbar" aria-label="Form işlemleri">
      <button class="action" id="importBtn" type="button">↧ Excel İçeri Aktar</button>
      <button class="action" id="exportBtn" type="button">↥ Excel Dışarı Aktar</button>
      <button class="action" id="printBtn" type="button">▤ PDF / Yazdır</button>
      <input class="sr-only" id="excelFile" type="file" accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
      </nav>
    </div>
  </div>

  <div class="statusline"><span>Güvenlik mimarisi hızlı değerlendirme</span><span id="progress" class="status-note">Kontroller: 0/10 • Risk: 0</span></div>

  <section class="panel" aria-labelledby="sec1"><div class="panel-head"><span class="num">01</span><h2 id="sec1">Talep ve Mimari Özet</h2><span class="description">Temel bilgiler ve inceleme kapsamı</span></div>
    <div class="panel-content"><div class="grid">
      <div class="field"><label for="refNo">İnceleme No</label><input id="refNo" data-label="İnceleme No" placeholder="SAR-2026-001"></div>
      <div class="field"><label for="requestDate">Talep Tarihi</label><input id="requestDate" data-label="Talep Tarihi" type="date"></div>
      <div class="field"><label for="requester">Talep Eden</label><input id="requester" data-label="Talep Eden" placeholder="Adı Soyadı"></div>
      <div class="field"><label for="requestType">Talep Türü</label><select id="requestType" data-label="Talep Türü"><option value="">Seçiniz</option><option>Yeni Sistem / Proje</option><option>Mimari Değişiklik</option><option>Bulut / SaaS</option><option>Entegrasyon</option><option>Diğer</option></select></div>
      <div class="field w2"><label for="systemName">Proje / Sistem Adı <span class="required">*</span></label><input id="systemName" data-label="Proje / Sistem Adı" placeholder="İncelenen sistem veya proje"></div>
      <div class="field"><label for="architecture">Mimari Türü</label><select id="architecture" data-label="Mimari Türü"><option value="">Seçiniz</option><option>On-Premise</option><option>Bulut</option><option>Hibrit</option><option>SaaS</option><option>Diğer</option></select></div>
      <div class="field"><label for="classification">Veri Sınıfı</label><select id="classification" data-label="Veri Sınıfı"><option value="">Seçiniz</option><option>Genel</option><option>Kurum İçi</option><option>Hizmete Özel</option><option>Gizli</option><option>Kişisel Veri</option><option>Özel Nitelikli Kişisel Veri</option></select></div>
      <div class="field w4"><label for="description">İnceleme Konusu / Mimari Açıklaması <span class="required">*</span></label><textarea id="description" data-label="Mimari Açıklaması / İş Gerekçesi" rows="2" placeholder="Sistem ne yapıyor, hangi değişiklik yapılacak ve başlıca güvenlik etkileri neler?"></textarea></div>
    </div>
    <details class="compact-details" id="requestMore"><summary><span>+ Ek talep ve mimari bilgileri</span><small>Gerekirse açın</small></summary><div class="details-content grid">
      <div class="field"><label for="unit">Birim / Departman</label><input id="unit" data-label="Birim / Departman" placeholder="Birim"></div>
      <div class="field"><label for="systemOwner">Sistem Sahibi</label><input id="systemOwner" data-label="Sistem Sahibi" placeholder="Sorumlu kişi"></div>
      <div class="field"><label for="exposure">İnternet Erişimi</label><select id="exposure" data-label="İnternet Erişimi"><option value="">Seçiniz</option><option>İnternete Açık</option><option>Yalnızca Kurum İçi</option><option>Kontrollü Harici Erişim</option></select></div>
      <div class="field"><label for="goLive">Planlanan Canlıya Alma</label><input id="goLive" data-label="Planlanan Canlıya Alma" type="date"></div>
      <div class="field w2"><label for="integrations">Kritik Bileşenler / Entegrasyonlar</label><input id="integrations" data-label="Kritik Bileşenler / Entegrasyonlar" placeholder="API, veritabanı, üçüncü taraf bağlantıları"></div>
      <div class="field w2"><label for="documentLink">Mimari Diyagram / Doküman Referansı</label><input id="documentLink" data-label="Mimari Diyagram / Doküman Referansı" placeholder="Doküman bağlantısı veya referans"></div>
    </div></details>
  </div></section>

  <section class="panel"><div class="panel-head"><span class="num">02</span><h2>Güvenlik Kontrol Özeti</h2><span class="description">10 temel kontrol • Eksiklik varsa kısa not</span></div><div class="panel-content"><div class="table-scroll"><table class="simple-table controls"><thead><tr><th>Güvenlik Kontrolü</th><th>Değerlendirme</th><th>Açıklama / Eksiklik</th></tr></thead><tbody id="controlsBody"></tbody></table></div></div></section>

  <section class="panel"><div class="panel-head"><span class="num">03</span><h2>Risk / Aksiyon Takibi</h2><span class="description">Yalnızca tespit edilen riskleri ekleyin</span></div><div class="panel-content"><div id="riskEmpty" class="risk-empty">Henüz risk eklenmedi. Gerekirse aşağıdaki butonla risk/bulgu ekleyin.</div><div id="riskTableWrap" class="table-scroll" hidden><table class="simple-table risks"><thead><tr><th>Risk / Bulgu</th><th>Olasılık</th><th>Etki</th><th>Risk Puanı</th><th>Önerilen Aksiyon</th><th>Sorumlu</th><th>Hedef Tarih</th><th>Durum</th><th class="no-print"></th></tr></thead><tbody id="riskBody"></tbody></table></div><div class="table-bottom"><span class="hint">Puan = Olasılık × Etki · 1–4 Düşük · 5–9 Orta · 10–16 Yüksek · 17–25 Kritik</span><button class="small-button" type="button" id="addRisk">+ Risk / Bulgu Ekle</button></div></div></section>

  <section class="panel" aria-labelledby="sec4"><div class="panel-head"><span class="num">04</span><h2 id="sec4">İnceleme Kararı ve Onay</h2><span class="description">Karar, gerekçe ve sorumlular</span></div><div class="panel-content">
    <div class="grid">
      <div class="field"><label for="decision">Güvenlik Kararı <span class="required">*</span></label><select id="decision" data-label="Mimari Güvenlik Kararı"><option value="">Seçiniz</option><option>Onaylandı</option><option>Şartlı Onaylandı</option><option>Revizyon Gerekli</option><option>Reddedildi</option><option>İnceleme Devam Ediyor</option></select></div>
      <div class="field"><label for="production">Canlıya Geçiş İzni</label><select id="production" data-label="Canlıya Geçiş İzni"><option value="">Seçiniz</option><option>Verildi</option><option>Şartlı</option><option>Verilmedi</option></select></div>
      <div class="field"><label for="reviewer">Güvenlik İnceleyeni</label><input id="reviewer" data-label="İnceleyen (Güvenlik)" placeholder="Adı Soyadı"></div>
      <div class="field"><label for="decisionDate">Karar Tarihi</label><input id="decisionDate" data-label="Karar Tarihi" type="date"></div>
      <div class="field w4"><label for="decisionReason">Karar Gerekçesi ve Özet Değerlendirme</label><textarea id="decisionReason" data-label="Karar Gerekçesi / Genel Değerlendirme" rows="2" placeholder="Başlıca riskler, şartlar ve kararın gerekçesi..."></textarea></div>
    </div>
    <div class="conditional" id="conditionsArea" hidden><div class="grid">
      <div class="field w2"><label for="conditions">Şartlı Onay Koşulları <span class="required">*</span></label><textarea id="conditions" data-label="Şartlı Onay Koşulları" rows="2" placeholder="Canlıya geçişten önce tamamlanacak kontroller"></textarea></div>
      <div class="field"><label for="conditionOwner">Aksiyon Sorumlusu</label><input id="conditionOwner" data-label="Şartlı Onay Aksiyon Sorumlusu" placeholder="Adı Soyadı"></div>
      <div class="field"><label for="conditionDue">Koşulların Son Tarihi</label><input id="conditionDue" data-label="Şartlı Onay Koşullarının Son Tarihi" type="date"></div>
    </div></div>
    <details class="compact-details" id="decisionMore"><summary><span>+ Onay ve takip bilgileri</span><small>Gerekirse açın</small></summary><div class="details-content grid">
      <div class="field"><label for="approver">Onaylayan Yetkili</label><input id="approver" data-label="Onaylayan Yetkili" placeholder="Adı Soyadı"></div>
      <div class="field"><label for="riskAcceptance">Risk Kabul Referansı / Yetkilisi</label><input id="riskAcceptance" data-label="Risk Kabul Referansı / Yetkilisi" placeholder="Varsa referans"></div>
      <div class="field"><label for="nextReview">Yeniden İnceleme Tarihi</label><input id="nextReview" data-label="Yeniden İnceleme Tarihi" type="date"></div>
      <div class="field"><label for="status">Kayıt Durumu</label><select id="status" data-label="Kayıt Durumu"><option value="">Seçiniz</option><option>Açık</option><option>İncelemede</option><option>Aksiyon Bekliyor</option><option>Kapatıldı</option></select></div>
    </div></details>
  </div></section>
  <div class="footnote">Güvenlik mimarisi teknik kararı, yetkili risk kabulünün yerine geçmez.</div>
</div>
<div id="toast" class="toast" role="status" aria-live="polite"></div>
<script>
'use strict';
const $=id=>document.getElementById(id);
const controlNames=['Ağ segmentasyonu ve güvenlik duvarı','Kimlik doğrulama / MFA','Yetkilendirme ve en az ayrıcalık','Veri şifreleme (aktarım ve depolama)','Uygulama / API güvenliği','Zafiyet ve yama yönetimi','Merkezi loglama / SIEM','Yedekleme ve kurtarma','Üçüncü taraf / bulut güvenliği','Tehdit modelleme ve güvenli mimari'];
const riskFields=[['risk','Risk / Bulgu'],['likelihood','Olasılık'],['impact','Etki'],['action','Önerilen Aksiyon'],['owner','Sorumlu'],['due','Hedef Tarih'],['status','Durum']];
let toastTimer;
function notify(message,error=false){const el=$('toast');el.textContent=message;el.className='toast show'+(error?' error':'');clearTimeout(toastTimer);toastTimer=setTimeout(()=>el.className='toast',4200)}
function txt(tag,text,attrs={}){const e=document.createElement(tag);e.textContent=text;for(const [key,value] of Object.entries(attrs))e.setAttribute(key,value);return e}
function initControls(){const body=$('controlsBody');controlNames.forEach((name,i)=>{const tr=document.createElement('tr');tr.dataset.control=i;tr.appendChild(txt('td',String(i+1).padStart(2,'0')+'  '+name));let td=document.createElement('td');let sel=document.createElement('select');sel.dataset.part='status';['','Uygun','Kısmen Uygun','Uygun Değil','Uygulanamaz'].forEach((s,i)=>sel.add(new Option(i===0?'Seçiniz':s,s)));sel.setAttribute('aria-label',name+' değerlendirmesi');sel.addEventListener('change',()=>{sel.dataset.status=sel.value;updateProgress()});td.appendChild(sel);tr.appendChild(td);td=document.createElement('td');const input=document.createElement('textarea');input.rows=1;input.dataset.minHeight='35';input.placeholder='Varsa kısa not';input.dataset.part='note';input.setAttribute('aria-label',name+' açıklaması');td.appendChild(input);tr.appendChild(td);body.appendChild(tr)})}
function makeControlValue(i,part){return $('controlsBody').querySelector(`[data-control="${i}"] [data-part="${part}"]`)}
function inputForRisk(col){let e;if(col==='likelihood'||col==='impact'){e=document.createElement('select');e.add(new Option('—',''));for(let i=1;i<=5;i++)e.add(new Option(i,i));}else if(col==='status'){e=document.createElement('select');['','Açık','İşlemde','Doğrulamada','Kapatıldı'].forEach((v,i)=>e.add(new Option(i?v:'Seçiniz',v)))}else{e=(col==='risk'||col==='action')?document.createElement('textarea'):document.createElement('input');if(e.tagName==='TEXTAREA'){e.rows=1;e.dataset.minHeight='35'}else if(col==='due')e.type='date';else e.type='text';if(col==='risk')e.placeholder='Risk açıklaması';if(col==='action')e.placeholder='Düzeltici önlem';if(col==='owner')e.placeholder='Adı Soyadı'}e.dataset.col=col;e.setAttribute('aria-label',riskFields.find(x=>x[0]===col)[1]);return e}
function addRisk(record={}){if($('riskBody').children.length>=40){notify('En fazla 40 risk kaydı eklenebilir.',true);return}const tr=document.createElement('tr');for(const [col] of riskFields){const td=document.createElement('td');const e=inputForRisk(col);e.value=record[col]??'';td.appendChild(e);td.dataset.label=riskFields.find(x=>x[0]===col)[1];tr.appendChild(td);if(col==='impact'){let cell=document.createElement('td');cell.dataset.label='Risk Puanı';cell.appendChild(txt('span','—',{class:'risk-level'}));tr.appendChild(cell)}}const actionCell=document.createElement('td');const remove=txt('button','×',{type:'button',class:'remove','aria-label':'Risk satırını sil',title:'Satırı sil'});remove.addEventListener('click',()=>{tr.remove();updateProgress()});actionCell.dataset.label='İşlem';actionCell.appendChild(remove);tr.appendChild(actionCell);tr.querySelector('[data-col="likelihood"]').addEventListener('change',()=>updateRisk(tr));tr.querySelector('[data-col="impact"]').addEventListener('change',()=>updateRisk(tr));tr.querySelectorAll('input,select,textarea').forEach(e=>e.addEventListener('input',updateProgress));$('riskBody').appendChild(tr);tr.querySelectorAll('textarea').forEach(grow);updateRisk(tr);updateProgress();return tr}
function updateRisk(tr){const a=Number(tr.querySelector('[data-col="likelihood"]').value),b=Number(tr.querySelector('[data-col="impact"]').value);const score=a*b;let name='—',cls='';if(score){if(score<=4){name='Düşük';cls='low'}else if(score<=9){name='Orta';cls='medium'}else if(score<=16){name='Yüksek';cls='high'}else{name='Kritik';cls='critical'}}const tag=tr.querySelector('.risk-level');tag.textContent=score?score+' — '+name:'—';tag.className='risk-level '+cls}
function riskRecords(){return [...$('riskBody').querySelectorAll('tr')].map(tr=>Object.fromEntries(riskFields.map(([k])=>[k,tr.querySelector(`[data-col="${k}"]`).value]))).filter(row=>Object.values(row).some(v=>String(v).trim()))}
function updateProgress(){const hasRisks=$('riskBody').children.length>0;$('riskTableWrap').hidden=!hasRisks;$('riskEmpty').hidden=hasRisks;const selected=[...$('controlsBody').querySelectorAll('select[data-part="status"]')].filter(e=>e.value).length;$('progress').textContent='Kontroller: '+selected+'/10 • Risk: '+riskRecords().length}
function updateDecision(){const conditional=$('decision').value==='Şartlı Onaylandı';$('conditionsArea').hidden=!conditional}
// İçeriğin tümünü göstermek için yüksekliği metinle birlikte büyüt/küçült.
function grow(el){
  if(!el||el.tagName!=='TEXTAREA'||!el.isConnected)return;
  if(el.getClientRects().length===0)return; // kapalı detay alanı açılınca yeniden ölçülür
  const min=Number(el.dataset.minHeight)||(el.closest('.simple-table')?35:64);
  el.style.height='auto';
  el.style.height=Math.max(min,el.scrollHeight+2)+'px';
}
function growAll(){document.querySelectorAll('textarea').forEach(grow)}
let resizePending=false;
function scheduleGrow(){
  if(resizePending)return;resizePending=true;
  requestAnimationFrame(()=>{resizePending=false;growAll()})
}
// Dinamik oluşturulmuş kontrol / risk açıklamalarını da kapsar.
document.addEventListener('input',e=>{if(e.target?.tagName==='TEXTAREA')grow(e.target)});
document.addEventListener('change',e=>{if(e.target?.tagName==='TEXTAREA')grow(e.target)});
document.addEventListener('toggle',e=>{if(e.target?.matches?.('details'))scheduleGrow()},true);
window.addEventListener('resize',scheduleGrow);

// Olgun UI2 başlık: logo.jpg otomatik yüklenir; yoksa LOGO seçimi gösterilir.
function initLogo(){
  const picker=$('logoPicker'),input=$('logoFile'),img=$('logoImage'),fallback=$('logoPlaceholder');
  function refresh(){const ok=img.complete&&img.naturalWidth>0;img.hidden=!ok;fallback.hidden=ok}
  img.addEventListener('load',refresh);img.addEventListener('error',refresh);
  function display(src){img.hidden=true;fallback.hidden=false;img.src=src;refresh()}
  let saved='';try{saved=localStorage.getItem('olgun_ui2_logo_data')||''}catch{}
  display(saved||'logo.jpg'); // Aynı klasördeki logo.jpg, önbellekten gelse bile gösterilir.
  let logoClicks=0,logoLast=0;
  picker.addEventListener('click',()=>{
    if(img.hidden){input.click();return}
    const t=Date.now();logoClicks=(t-logoLast<2500)?logoClicks+1:1;logoLast=t;
    if(logoClicks>=5){logoClicks=0;input.click()}
    else if(logoClicks===4)notify('Logoyu değiştirmek için bir kez daha tıklayın.');
  });
  input.addEventListener('change',()=>{
    const file=input.files&&input.files[0];input.value='';if(!file)return;
    if(!/^image\/(png|jpeg|webp|gif)$/i.test(file.type)&&!/\.(png|jpe?g|webp|gif)$/i.test(file.name)){notify('PNG, JPG, WebP veya GIF logo seçin.',true);return}
    if(file.size>10*1024*1024){notify('Logo en fazla 10 MB olabilir.',true);return}
    const reader=new FileReader();
    reader.onerror=()=>notify('Logo dosyası okunamadı.',true);
    reader.onload=()=>{
      const selected=new Image();
      selected.onerror=()=>notify('Seçilen logo geçerli bir görsel değil.',true);
      selected.onload=()=>{
        try{
          const scale=Math.min(1,700/Math.max(selected.naturalWidth,selected.naturalHeight));
          const canvas=document.createElement('canvas');
          canvas.width=Math.max(1,Math.round(selected.naturalWidth*scale));
          canvas.height=Math.max(1,Math.round(selected.naturalHeight*scale));
          canvas.getContext('2d').drawImage(selected,0,0,canvas.width,canvas.height);
          let data=canvas.toDataURL('image/png');
          if(data.length>1450000)data=canvas.toDataURL('image/jpeg',.86);
          display(data);
          try{localStorage.setItem('olgun_ui2_logo_data',data);notify('Logo değiştirildi ve bu tarayıcıya kaydedildi.')}catch{notify('Logo değiştirildi; tarayıcı depolaması izin vermediği için kalıcı kaydedilemedi.',true)}
        }catch{notify('Logo işlenemedi.',true)}
      };
      selected.src=String(reader.result||'');
    };
    reader.readAsDataURL(file);
  });
}
// Normal fare tıklaması ve mobil dokunma aynı click olayını üretir: çift sayım yapılmaz.
function initAgency(){
  const el=$('agency'),key='olgun_ui2_agency';let count=0,last=0,original='';
  try{el.textContent=localStorage.getItem(key)||'OLGUN BAŞKANLIĞI'}catch{}
  function edit(){
    if(el.isContentEditable)return;
    original=el.textContent;el.contentEditable='true';el.setAttribute('role','textbox');
    el.setAttribute('aria-label','Kurum adı. Enter ile kaydedin, Escape ile iptal edin');
    el.focus();const sel=window.getSelection();if(sel){const range=document.createRange();range.selectNodeContents(el);sel.removeAllRanges();sel.addRange(range)}
    notify('Kurum adını düzenleyin. Enter: kaydet • Esc: iptal.');
  }
  function advance(){
    if(el.isContentEditable)return;
    const now=Date.now();count=(now-last<=2300)?count+1:1;last=now;
    if(count>=5){count=0;edit()}else if(count===4)notify('Kurum adını düzenlemek için 1 kez daha tıklayın.');
  }
  el.addEventListener('click',advance);
  el.addEventListener('keydown',e=>{
    if(el.isContentEditable){if(e.key==='Enter'){e.preventDefault();el.blur()}else if(e.key==='Escape'){e.preventDefault();el.textContent=original;el.blur()}return}
    if(e.key==='Enter'||e.key===' '){e.preventDefault();advance()}
  });
  el.addEventListener('blur',()=>{
    if(!el.isContentEditable)return;
    el.contentEditable='false';el.setAttribute('role','button');
    el.setAttribute('aria-label','Kurum adını düzenlemek için art arda beş kez tıklayın veya Enter tuşuna basın');
    const value=el.textContent.replace(/\s+/g,' ').trim().slice(0,140);
    el.textContent=value||'OLGUN BAŞKANLIĞI';
    try{localStorage.setItem(key,el.textContent)}catch{notify('Kurum adı değişti, ancak tarayıcıda kalıcı saklanamadı.',true)}
  });
}
function rowsForExcel(){const rows=[['Alan','Değer'],['Kurum Adı',$('agency').textContent.trim()]];let lastSection='';document.querySelectorAll('[data-label]').forEach(el=>{const panel=el.closest('.panel');const section=panel.querySelector('h2').textContent;const cond=el.closest('.conditional');if(cond&&cond.hidden)return;if(section!==lastSection){rows.push(['— '+section+' —','']);lastSection=section}rows.push([el.dataset.label,el.value])});rows.push(['— Güvenlik Kontrolleri —','']);controlNames.forEach((_,i)=>{rows.push([`Kontrol ${String(i+1).padStart(2,'0')} / Durum`,makeControlValue(i,'status').value]);rows.push([`Kontrol ${String(i+1).padStart(2,'0')} / Açıklama`,makeControlValue(i,'note').value])});rows.push(['— Riskler ve Düzeltici Aksiyonlar —','']);riskRecords().forEach((r,i)=>riskFields.forEach(([k,label])=>rows.push([`Risk ${String(i+1).padStart(2,'0')} / ${label}`,r[k]])));return rows}
function excelEscape(s){return String(s??'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/\r/g,'&#13;').replace(/\n/g,'&#10;')}
// Çevrimdışı çalışan, Excel uyumlu gerçek .xlsx (ZIP/OOXML) oluşturucu.
const enc=new TextEncoder();const decoder=new TextDecoder();const utf8=s=>enc.encode(s);
function write16(b,i,v){b[i]=v&255;b[i+1]=(v>>>8)&255}function write32(b,i,v){write16(b,i,v&65535);write16(b,i+2,v>>>16)}
const crcTable=(()=>{const t=new Uint32Array(256);for(let i=0;i<256;i++){let c=i;for(let k=0;k<8;k++)c=(c&1)?0xEDB88320^(c>>>1):c>>>1;t[i]=c>>>0}return t})();
function crc32(b){let c=0xffffffff;for(const v of b)c=crcTable[(c^v)&255]^(c>>>8);return(c^0xffffffff)>>>0}
function join(parts){const out=new Uint8Array(parts.reduce((n,b)=>n+b.length,0));let off=0;for(const part of parts){out.set(part,off);off+=part.length}return out}
function zipFiles(files){const local=[],central=[];let offset=0;for(const [filename,content] of Object.entries(files)){const name=utf8(filename),data=utf8(content),crc=crc32(data);const l=new Uint8Array(30+name.length);write32(l,0,0x04034b50);write16(l,4,20);write16(l,6,0x0800);write16(l,8,0);write32(l,14,crc);write32(l,18,data.length);write32(l,22,data.length);write16(l,26,name.length);l.set(name,30);local.push(l,data);const c=new Uint8Array(46+name.length);write32(c,0,0x02014b50);write16(c,4,20);write16(c,6,20);write16(c,8,0x0800);write32(c,16,crc);write32(c,20,data.length);write32(c,24,data.length);write16(c,28,name.length);write32(c,42,offset);c.set(name,46);central.push(c);offset+=l.length+data.length}const end=new Uint8Array(22);write32(end,0,0x06054b50);write16(end,8,central.length);write16(end,10,central.length);write32(end,12,central.reduce((n,b)=>n+b.length,0));write32(end,16,offset);return new Blob([...local,...central,end],{type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})}
function xlsxBlob(rows){const columns=['A','B'];const sheetRows=rows.map((line,i)=>'<row r="'+(i+1)+'">'+line.map((v,j)=>{const name=columns[j]+(i+1);return `<c r="${name}" t="inlineStr"><is><t xml:space="preserve">${excelEscape(v)}</t></is></c>`}).join('')+'</row>').join('');const sheet=`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><dimension ref="A1:B${rows.length}"/><cols><col min="1" max="1" width="51" customWidth="1"/><col min="2" max="2" width="79" customWidth="1"/></cols><sheetData>${sheetRows}</sheetData></worksheet>`;
return zipFiles({'[Content_Types].xml':'<?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"/></Types>','_rels/.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>','xl/workbook.xml':'<?xml version="1.0" encoding="UTF-8"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Form Verileri" sheetId="1" r:id="rId1"/></sheets></workbook>','xl/_rels/workbook.xml.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/worksheet" Target="worksheets/sheet1.xml"/></Relationships>','xl/worksheets/sheet1.xml':sheet})}
function exportExcel(){try{const rows=rowsForExcel();const blob=xlsxBlob(rows),url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download='Guvenlik_Mimarisi_Inceleme_'+($('refNo').value||'Form').replace(/[^\w-]/g,'_')+'.xlsx';document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),1200);notify('Dikey Excel dosyası oluşturuldu (internet gerektirmez).')}catch(e){notify('Excel dışa aktarılamadı: '+e.message,true)}}
function read16(v,i){return v.getUint16(i,true)}function read32(v,i){return v.getUint32(i,true)}
async function unzipEntries(buffer){const bytes=new Uint8Array(buffer),v=new DataView(buffer);let eocd=-1;for(let i=bytes.length-22;i>=Math.max(0,bytes.length-65557);i--)if(read32(v,i)===0x06054b50){eocd=i;break}if(eocd<0)throw Error('Geçerli XLSX/ZIP dosyası değil.');const count=read16(v,eocd+10);let p=read32(v,eocd+16);const result={};for(let i=0;i<count;i++){if(read32(v,p)!==0x02014b50)throw Error('Excel dosyası dizini bozuk.');const method=read16(v,p+10),compressed=read32(v,p+20),nlen=read16(v,p+28),extra=read16(v,p+30),comment=read16(v,p+32),localOffset=read32(v,p+42),path=decoder.decode(bytes.subarray(p+46,p+46+nlen));if(path==='xl/worksheets/sheet1.xml'||path==='xl/sharedStrings.xml'){if(read32(v,localOffset)!==0x04034b50)throw Error('Excel sayfası okunamadı.');const start=localOffset+30+read16(v,localOffset+26)+read16(v,localOffset+28),chunk=bytes.slice(start,start+compressed);if(method===0)result[path]=decoder.decode(chunk);else if(method===8&&typeof DecompressionStream!=='undefined'){const stream=new Blob([chunk]).stream().pipeThrough(new DecompressionStream('deflate-raw'));result[path]=await new Response(stream).text()}else throw Error('Bu Excel sıkıştırma biçimi tarayıcıda desteklenmiyor.')}p+=46+nlen+extra+comment}return result}
function xmlRows(sheet,shared=''){const xml=new DOMParser().parseFromString(sheet,'application/xml');if(xml.querySelector('parsererror'))throw Error('Excel çalışma sayfası hatalı.');const strings=[];if(shared){const doc=new DOMParser().parseFromString(shared,'application/xml');for(const si of doc.getElementsByTagNameNS('*','si'))strings.push([...si.getElementsByTagNameNS('*','t')].map(x=>x.textContent).join(''))}const out=[];for(const row of xml.getElementsByTagNameNS('*','row')){let a='',b='';for(const cell of row.getElementsByTagNameNS('*','c')){const r=cell.getAttribute('r')||'',col=r.replace(/[0-9]/g,'');if(col!=='A'&&col!=='B')continue;const type=cell.getAttribute('t')||'';let s='';if(type==='inlineStr')s=[...cell.getElementsByTagNameNS('*','t')].map(e=>e.textContent).join('');else {s=cell.getElementsByTagNameNS('*','v')[0]?.textContent||'';if(type==='s')s=strings[Number(s)]||''}if(col==='A')a=s;else b=s}out.push([a,b])}return out}
async function importExcel(file){if(!file)return;if(!/\.xlsx$/i.test(file.name))throw Error('Lütfen .xlsx dosyası seçin.');if(file.size>8*1024*1024)throw Error('Dosya 8 MB sınırını aşıyor.');const files=await unzipEntries(await file.arrayBuffer());if(!files['xl/worksheets/sheet1.xml'])throw Error('Excel içinde ilk çalışma sayfası bulunamadı.');const rows=xmlRows(files['xl/worksheets/sheet1.xml'],files['xl/sharedStrings.xml']);if(!rows.some(r=>r[0]==='İnceleme No')&&!rows.some(r=>r[0]==='Proje / Sistem Adı'))throw Error('Excel sütunları bu form ile uyuşmuyor. Önce bu formdan Excel dışa aktarın.');const values=new Map(rows);document.querySelectorAll('[data-label]').forEach(el=>{if(values.has(el.dataset.label)){el.value=values.get(el.dataset.label);grow(el)}});if(values.has('Kurum Adı')){const name=values.get('Kurum Adı').trim();if(name){$('agency').textContent=name.slice(0,140);try{localStorage.setItem('olgun_ui2_agency',$('agency').textContent)}catch{}}}controlNames.forEach((_,i)=>{const no=String(i+1).padStart(2,'0');const status=makeControlValue(i,'status'),note=makeControlValue(i,'note');const key='Kontrol '+no+' / Durum';if(values.has(key)){status.value=values.get(key);status.dataset.status=status.value}if(values.has('Kontrol '+no+' / Açıklama')){note.value=values.get('Kontrol '+no+' / Açıklama');grow(note)}});$('riskBody').replaceChildren();const nums=[...new Set(rows.map(([key])=>/^Risk (\d+) \/ /.exec(key)?.[1]).filter(Boolean))].slice(0,40);nums.forEach(no=>{const r={};riskFields.forEach(([field,label])=>r[field]=values.get('Risk '+no+' / '+label)||'');addRisk(r)});updateDecision();updateProgress();
for(const panel of document.querySelectorAll('.compact-details')){
  if([...panel.querySelectorAll('[data-label]')].some(el=>String(el.value||'').trim()))panel.open=true;
}
scheduleGrow();notify('Excel verileri forma aktarıldı.');}
function defaults(){const now=new Date(),iso=[now.getFullYear(),String(now.getMonth()+1).padStart(2,'0'),String(now.getDate()).padStart(2,'0')].join('-');$('requestDate').value=iso;$('refNo').value='SAR-'+now.getFullYear()+'-'+String(now.getTime()).slice(-6)}
initLogo();initAgency();initControls();defaults();scheduleGrow();$('addRisk').addEventListener('click',()=>addRisk());$('decision').addEventListener('change',updateDecision);document.querySelectorAll('textarea').forEach(grow);$('exportBtn').addEventListener('click',exportExcel);$('importBtn').addEventListener('click',()=>$('excelFile').click());$('excelFile').addEventListener('change',async e=>{try{await importExcel(e.target.files[0])}catch(err){notify('Excel içeri aktarılamadı: '+err.message,true)}finally{e.target.value=''}});function syncPrintValues(){document.querySelectorAll('.panel input,.panel select').forEach(el=>{
  let mirror=el.nextElementSibling;
  if(!mirror||!mirror.classList.contains('print-value-mirror')){
    mirror=document.createElement('div');mirror.className='print-value-mirror';
    mirror.setAttribute('aria-hidden','true');el.insertAdjacentElement('afterend',mirror);
  }
  const value=el.tagName==='SELECT'?(el.value?(el.selectedOptions[0]?.textContent||el.value):''):el.value;
  mirror.textContent=String(value||' ');
  mirror.dataset.state=String(el.value||'');
})}
function syncPrintTextareas(){syncPrintValues();document.querySelectorAll('textarea').forEach(el=>{
  let mirror=el.nextElementSibling;
  if(!mirror||!mirror.classList.contains('print-textarea-mirror')){
    mirror=document.createElement('div');mirror.className='print-textarea-mirror';
    mirror.setAttribute('aria-hidden','true');el.insertAdjacentElement('afterend',mirror);
  }
  mirror.textContent=el.value||' ';
})}
let detailsBeforePrint=[];
window.addEventListener('beforeprint',()=>{
  growAll();
  detailsBeforePrint=[...document.querySelectorAll('.compact-details')].map(el=>[el,el.open]);
  detailsBeforePrint.forEach(([el])=>el.open=true);
  syncPrintTextareas();
});
window.addEventListener('afterprint',()=>{detailsBeforePrint.forEach(([el,wasOpen])=>el.open=wasOpen);detailsBeforePrint=[]});
$('printBtn').addEventListener('click',()=>{growAll();syncPrintTextareas();window.print()});updateDecision();updateProgress();scheduleGrow();
</script>
</body>
</html>