Kadim Sesler: Edebiyatın Dinsel ve Mistik Köklerini Çözümlemek

Kadim Sesler: Edebiyatın Dinsel ve Mistik Köklerini Çözümlemek

Edebiyatın en derin ve en eski kaynağı, mitoloji, kutsal metinler, ritüel ve mistisizmde yatar. Bu derste, vahiyden mistik yolculuğa, arketiplerden metafizik anlatıya uzanan kadim kökleri keşfedecek ve büyük eserlerin arkasındaki gizli anlam mimarisini çözmeyi öğreneceksiniz.

Bu Derste Ne Öğreneceksiniz?

Bu temel ders, edebiyatı yalnızca hikâye olarak değil, kutsal ve mistik bir deneyim olarak okumayı sağlar. Ders sonunda şunları kazanacaksınız:

  • Dinsel ve mistik kökün edebiyatın doğuşundaki kurucu rolünü net biçimde tanımlama yeteneği
  • Mitlerin, ritüellerin ve kutsal metinlerin anlatı yapısı üzerindeki güçlü etkisini kavrama
  • Mistik yolculuğu bir inisiyasyon ve ruhsal aydınlanma süreci olarak analiz etme becerisi
  • Günah, düşüş, kurtuluş ve ahlak yasası gibi temaların edebi çatışmalardaki yerini anlama
  • Kadim sembollerin ve arketiplerin modern edebiyattaki izlerini sürme becerisi

Neden Bu Dersi Almalısınız?

Çünkü yüzeysel okumanın ötesine geçmek ve klasikleri gerçekten anlamak istiyorsanız bu ders tam size göre. Mitoloji ve mistisizmin edebiyata kattığı evrensel gücü keşfedecek, metinleri çok daha derin katmanlarıyla yorumlayabileceksiniz.

Bu ders, edebiyatı bir tutku haline getirmek, anlam arayışınızı zenginleştirmek ve kült eserleri bilinçli okumak isteyen herkes için tasarlandı.

Davet

Kadim sesleri duymaya ve edebiyatın en gizemli köklerine inmeye hazır mısınız?

Bu aydınlatıcı yolculuğa birlikte çıkalım. Derin bir farkındalık ve yeni bir okuma deneyimi sizi bekliyor.

KOD (52.899 karakter)
HTML
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Antik Külliyat Ders Sistemi — Türkçe ve İngilizce metinleri karşılıklı levhalarda, isteğe bağlı ses eşliğinde sunan akademik ders sunum aracı.">
<title>DERS SİSTEMİ  </title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Gideon+Roman&display=swap" rel="stylesheet">

<style>
:root{
  --parchment:#ece2c8;
  --parchment-dark:#d9cba3;
  --ink:#2b1d10;
  --ink-soft:#4a3520;
  --sepia:#7a5230;
  --gold:#a9772f;
  --wine:#5c1f1f;
  --rule:#8a6c3f;
  --shadow: 0 10px 30px rgba(20,12,4,.45);
  --serif-display:'Gideon Roman', serif;
  --serif-body:'Gideon Roman', serif;
  --blackletter:'Gideon Roman', serif;
  --focus-ring: 0 0 0 3px rgba(169,119,47,.55);
  --bg-img-tr: url('https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTA1L3B4MTA1NzQwNC1pbWFnZS1qb2I2MzAtYV8xLmpwZw.jpg');
  --bg-opacity-tr: 0.86;
  --bg-img-en: url('https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTA1L3B4MTA1NzQwNC1pbWFnZS1qb2I2MzAtYV8xLmpwZw.jpg');
  --bg-opacity-en: 0.86;
}
*{box-sizing:border-box;}
html,body{height:100%;margin:0;}
body{
  font-family:var(--serif-body);
  color:var(--ink);
  background:
    linear-gradient(rgba(40,26,10,.20), rgba(40,26,10,.35)),
    url('https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTA1L3B4MTA1NzQwNC1pbWFnZS1qb2I2MzAtYV8xLmpwZw.jpg') center/cover fixed;
  overflow:hidden;
}
button, input, textarea, [tabindex]{ font: inherit; }
button:focus-visible, input:focus-visible, textarea:focus-visible, [tabindex]:focus-visible{
  outline:none; box-shadow:var(--focus-ring);
}
@media (prefers-reduced-motion: reduce){
  *{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; }
}

/* ═══════════════ MODAL ═══════════════ */
#start-modal{
  position:fixed; inset:0; z-index:200;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(ellipse at center, rgba(10,6,2,.78), rgba(5,3,1,.94));
  opacity:0; pointer-events:none; transition:opacity .35s ease;
}
#start-modal.open{opacity:1; pointer-events:auto;}
.sm-card{
  width:min(580px, 92vw);
  max-height:88vh;
  overflow-y:auto;
  background:
    radial-gradient(ellipse at 30% 0%, rgba(255,250,230,.55), transparent 60%),
    repeating-linear-gradient(0deg, rgba(120,90,40,.035) 0 2px, transparent 2px 4px),
    linear-gradient(rgba(236,226,200,.97), rgba(236,226,200,.97)),
    url('https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTA1L3B4MTA1NzQwNC1pbWFnZS1qb2I2MzAtYV8xLmpwZw.jpg');
  border:3px double var(--gold);
  border-radius:6px;
  padding:40px 44px 36px;
  box-shadow: 0 24px 70px rgba(0,0,0,.75), inset 0 0 60px rgba(60,38,12,.35);
  position:relative;
  transform:scale(.97) translateY(14px);
  opacity:0;
  transition:transform .4s cubic-bezier(.2,.8,.2,1), opacity .4s ease;
}
#start-modal.open .sm-card{ transform:scale(1) translateY(0); opacity:1; }

.sm-close{
    position:absolute; top:14px; right:14px; width:34px; height:34px;
    border:1px solid var(--rule); border-radius:50%; cursor:pointer;
    background:rgba(0,0,0,.06); color:var(--wine); font-size:15px; transition:.2s;
}
.sm-close:hover{ background:var(--wine); color:#fff; border-color:var(--wine); }

.seal{
  width:56px; height:56px; border-radius:50%; margin:0 auto 12px;
  display:flex; align-items:center; justify-content:center;
  border:2px solid var(--gold);
  box-shadow:0 0 0 4px rgba(169,119,47,.14), inset 0 0 12px rgba(169,119,47,.28);
  background:radial-gradient(circle, rgba(255,250,230,.6), transparent 72%);
  font-size:24px; color:var(--wine); letter-spacing:0;
}
.seal.completed{ color:var(--gold); border-color:var(--gold); animation: completePulse 2.2s ease-in-out infinite; }
@keyframes completePulse { 0%,100%{ box-shadow:0 0 0 4px rgba(169,119,47,.14), inset 0 0 12px rgba(169,119,47,.28);} 50%{ box-shadow:0 0 0 8px rgba(169,119,47,.22), inset 0 0 16px rgba(169,119,47,.4);} }

.sm-overline{
  text-align:center; font-family:var(--serif-display); font-size:12px;
  color:var(--sepia); letter-spacing:5px; margin-bottom:2px; opacity:.85;
}
.sm-title{
  text-align:center; font-family:var(--serif-display);
  color:#1a0f06; font-size:29px; letter-spacing:3px; margin:0 0 8px;
}
.sm-title.completed{ color: var(--wine); }
.sm-rule{
  height:2px; margin:6px auto 12px; width:64%;
  background:linear-gradient(90deg, transparent, var(--rule), transparent);
}
.sm-subtitle{
  text-align:center; font-size:13.5px; color:var(--ink-soft); font-style:italic;
  margin-bottom:22px; opacity:.85;
}
.sm-completed-note{
  text-align:center; font-size:15.5px; color:var(--ink-soft); margin-bottom:8px; display:none; line-height:1.5;
}
.sm-completed-sub{
  text-align:center; font-size:12px; color:var(--ink-soft); margin-bottom:22px; display:none; opacity:.7; font-style:italic;
}
.sm-field{display:flex; flex-direction:column; gap:6px; margin-bottom:14px; position:relative; z-index:2;}
.sm-field label{
  font-family:var(--serif-display); color:var(--wine); font-size:13px; letter-spacing:2px;
}
.sm-field input, .sm-field textarea{
  font-family:var(--serif-body); font-size:16px; color:var(--ink);
  background:rgba(255,253,245,.75); border:1.5px solid var(--rule); border-radius:3px;
  padding:10px 12px; outline:none; width:100%;
}
.sm-field textarea{resize:vertical; min-height:70px;}
.sm-field input:focus, .sm-field textarea:focus{border-color:var(--gold); background:#fff9e8;}
.sm-play{
  display:block; width:100%; margin-top:18px;
  padding:15px 22px; font-family:var(--serif-display); font-size:19px; letter-spacing:3px;
  color:var(--parchment); background:linear-gradient(180deg, var(--wine), #3c1414);
  border:2px solid var(--gold); border-radius:4px; cursor:pointer;
  box-shadow: 0 6px 18px rgba(0,0,0,.4), inset 0 0 20px rgba(0,0,0,.3);
  transition:.15s; position:relative; z-index:2;
}
.sm-play:hover{ background:linear-gradient(180deg, #732828, #4a1717); transform:translateY(-1px);}
.sm-play:disabled{ opacity:.55; cursor:not-allowed; transform:none; }

/* ═══════════════ CROWN ═══════════════ */
#crown{
  position:fixed; top: 0; left:0; right:0; z-index:40;
  height:64px; display:flex; align-items:center; justify-content:space-between;
  padding:0 22px;
  background:linear-gradient(180deg, rgba(43,29,16,.92), rgba(43,29,16,.75));
  border-bottom:3px double var(--gold);
  box-shadow:0 4px 18px rgba(0,0,0,.35);
}
#crown .title{
  font-family:var(--serif-display);
  color:var(--parchment);
  font-size:24px;
  letter-spacing:2px;
  text-shadow:0 2px 0 rgba(0,0,0,.5);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  max-width:65vw;
}
#crown .actions{display:flex; gap:10px; align-items:center;}
.icon-btn{
  background:transparent; color:var(--parchment); border:1.5px solid var(--gold);
  border-radius:3px; font-family:var(--serif-body); font-weight:600; font-size:14px;
  padding:7px 14px; cursor:pointer; letter-spacing:.5px;
  transition:.15s;
}
.icon-btn:hover{background:var(--gold); color:#2b1d10;}

/* ═══════════════ STAGE / LEAVES ═══════════════ */
#stage{
  position:absolute; top:64px; bottom:0; left:0; right:0;
  display:flex;
}
.leaf{
  flex:1; position:relative; display:flex; flex-direction:column;
  isolation:isolate; z-index:0;
  background-blend-mode: normal, normal, multiply, normal;
  border:1px solid rgba(80,55,20,.4);
}
.leaf + .leaf{ border-left:3px double var(--rule); }
.leaf-bg-layer{
  position:absolute; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  background: var(--parchment-dark);
}
.leaf-bg-photo{
  position:absolute; inset:0;
  background-size:cover; background-position:center;
  transition:opacity .2s ease;
}
#tr-bg-photo{ background-image: var(--bg-img-tr); opacity: var(--bg-img-opacity-tr, 1); }
#en-bg-photo{ background-image: var(--bg-img-en); opacity: var(--bg-img-opacity-en, 1); }
.leaf::before{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none; opacity:.85;
  background-image:
    radial-gradient(circle at 12% 18%, rgba(120,80,30,.16) 0%, transparent 7%),
    radial-gradient(circle at 88% 12%, rgba(110,70,25,.13) 0%, transparent 9%),
    radial-gradient(circle at 22% 86%, rgba(100,65,25,.15) 0%, transparent 8%),
    radial-gradient(circle at 78% 78%, rgba(120,80,30,.12) 0%, transparent 10%),
    radial-gradient(circle at 55% 45%, rgba(90,60,20,.06) 0%, transparent 30%);
  box-shadow: inset 0 0 90px rgba(60,38,12,.45), inset 0 0 18px rgba(0,0,0,.25);
}
.leaf::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(135deg, rgba(0,0,0,.10) 0%, transparent 6%),
    linear-gradient(-45deg, rgba(0,0,0,.08) 0%, transparent 7%);
  mix-blend-mode:multiply;
}

.candle-light{
  position:absolute; inset:0; z-index:2; pointer-events:none; overflow:hidden;
}
.candle-light::before,
.candle-light::after{
  content:''; position:absolute; top:-18%; left:-18%; width:72%; height:72%;
  border-radius:50%;
  background:radial-gradient(circle at 32% 30%,
      rgba(255,224,170,.85) 0%,
      rgba(255,190,110,.45) 22%,
      rgba(255,160,70,.18) 42%,
      rgba(255,160,70,0) 68%);
  mix-blend-mode:soft-light;
  filter:blur(3px);
  transform-origin:20% 20%;
  will-change:opacity, transform;
}
.candle-light::before{
  animation:candleFlickerA 6.4s ease-in-out infinite;
}
.candle-light::after{
  width:46%; height:46%; top:-8%; left:-8%; filter:blur(6px);
  background:radial-gradient(circle at 35% 35%,
      rgba(255,238,205,.9) 0%,
      rgba(255,205,140,.4) 40%,
      rgba(255,205,140,0) 70%);
  mix-blend-mode:screen;
  opacity:.5;
  animation:candleFlickerB 4.1s ease-in-out infinite;
}
#en-leaf .candle-light::before{ animation-delay:-3.1s; }
#en-leaf .candle-light::after{ animation-delay:-1.6s; }

@keyframes candleFlickerA{
  0%,100%{ opacity:.62; transform:scale(1) translate(0,0); }
  12%{ opacity:.74; transform:scale(1.035) translate(2px,-1px); }
  24%{ opacity:.55; transform:scale(.97) translate(-2px,1px); }
  37%{ opacity:.7; transform:scale(1.02) translate(1px,2px); }
  49%{ opacity:.6; transform:scale(.99) translate(-1px,-1px); }
  61%{ opacity:.78; transform:scale(1.05) translate(2px,1px); }
  73%{ opacity:.58; transform:scale(.98) translate(-1px,0); }
  86%{ opacity:.7; transform:scale(1.02) translate(1px,-2px); }
}
@keyframes candleFlickerB{
  0%,100%{ opacity:.42; transform:scale(1) translate(0,0); }
  15%{ opacity:.55; transform:scale(1.06) translate(-1px,1px); }
  33%{ opacity:.35; transform:scale(.95) translate(1px,-1px); }
  50%{ opacity:.6; transform:scale(1.04) translate(0,2px); }
  67%{ opacity:.4; transform:scale(.97) translate(-1px,0); }
  84%{ opacity:.52; transform:scale(1.03) translate(1px,1px); }
}
@media (prefers-reduced-motion: reduce){
  .candle-light::before, .candle-light::after{ animation:none; }
}

#tr-leaf{
  transform:rotate(-0.35deg);
  background:
    radial-gradient(ellipse at 30% 0%, rgba(255,250,230,.45), transparent 60%),
    repeating-linear-gradient(0deg, rgba(120,90,40,.035) 0 2px, transparent 2px 4px);
}
#en-leaf{
  transform:rotate(0.3deg);
  background:
    radial-gradient(ellipse at 30% 0%, rgba(255,250,230,.45), transparent 60%),
    repeating-linear-gradient(0deg, rgba(120,90,40,.035) 0 2px, transparent 2px 4px);
}
.leaf-head{
  padding:14px 28px 8px; text-align:center; flex-shrink:0; position:relative; z-index:3;
}
.leaf-head .lang{
  font-family:var(--serif-display); font-size:18px; color:var(--wine); letter-spacing:4px;
}
.leaf-head .rule{
  margin:8px auto 0; width:64%; height:2px;
  background:linear-gradient(90deg, transparent, var(--rule), transparent);
}
.leaf-body{
  flex:1; overflow:hidden; position:relative; z-index:3;
  display:flex; align-items:center; justify-content:center;
  padding:10px 6% 34px;
}
.leaf-text{
  font-family:var(--blackletter);
  font-weight:700;
  font-size:clamp(24px, 3.3vw, 50px);
  line-height:1.22;
  color:#0d0a05;
  text-align:center;
  letter-spacing:-1.2px;
  word-spacing:-2px;
  max-height:100%;
  overflow:hidden;
  word-break:keep-all;
  overflow-wrap:normal;
  white-space:normal;
  opacity:1;
  transition:opacity .22s ease;
}
.ink-char.word-start{
  font-size:1.4em;
  line-height:.8;
}
.leaf-text .cursor{
  display:inline-block; width:2px; margin-left:2px;
  background:var(--wine); animation:blink 1s steps(1) infinite;
}
@keyframes blink{0%,49%{opacity:1;}50%,100%{opacity:0;}}
.ink-word{ display:inline-block; white-space:nowrap; }
.ink-char{
  display:inline-block;
  transform: rotate(var(--r,0deg)) translateY(var(--ty,0px)) scale(var(--s,1));
  text-shadow:
    1.5px 1.5px 0 rgba(43,29,16,.18),
    2.5px 3px 3px rgba(43,29,16,.10),
    .5px .5px 0 rgba(43,29,16,.22);
}
#en-leaf .leaf-head .lang{color:var(--sepia);}
.slide-mark{
  position:absolute; top:10px; left:18px; z-index:4;
  font-family:var(--serif-display); font-size:13px; color:var(--ink-soft); opacity:.55;
  letter-spacing:1px;
}
#empty-state{
  position:absolute; inset:64px 0 0; display:flex; align-items:center; justify-content:center;
  flex-direction:column; gap:14px; color:var(--parchment); text-align:center; z-index:5;
}
#empty-state h2{font-family:var(--serif-display); font-size:34px; margin:0; letter-spacing:3px; text-shadow:0 3px 10px rgba(0,0,0,.6);}
#empty-state p{font-size:18px; opacity:.85; max-width:520px; text-shadow:0 2px 6px rgba(0,0,0,.6);}
#empty-state button{
  margin-top:4px; font-family:var(--serif-display); letter-spacing:2px; font-size:14px;
  color:var(--parchment); background:linear-gradient(180deg, var(--wine), #3c1414);
  border:2px solid var(--gold); border-radius:4px; padding:11px 22px; cursor:pointer; transition:.15s;
}
#empty-state button:hover{ background:linear-gradient(180deg, #732828, #4a1717); }

/* ═══════════════ DOCK (compact floating transport controls) ═══════════════ */
#dock{
  position:fixed; left:16px; bottom:16px; z-index:45;
  display:flex; align-items:center; gap:7px;
  background:linear-gradient(180deg, rgba(43,29,16,.94), rgba(43,29,16,.82));
  border:1.5px solid var(--gold); border-radius:30px;
  padding:7px 14px 7px 8px;
  box-shadow:0 6px 18px rgba(0,0,0,.4);
}
#dock-progress{
  position:absolute; left:16px; right:16px; top:-8px; height:4px;
  background:rgba(255,255,255,.15); border-radius:3px; cursor:pointer; overflow:hidden;
}
#progress-fill{height:100%; width:0%; background:linear-gradient(90deg,var(--gold),var(--wine));}
.dock-btn{
  width:30px; height:30px; border-radius:50%; flex-shrink:0;
  border:1.5px solid var(--gold); background:transparent; color:var(--parchment);
  font-size:11px; cursor:pointer; display:flex; align-items:center; justify-content:center;
  transition:.15s;
}
.dock-btn:hover{background:var(--gold); color:#2b1d10;}
.dock-btn:disabled{ opacity:.4; cursor:not-allowed; }
.dock-btn:disabled:hover{ background:transparent; color:var(--parchment); }
.dock-main{width:34px; height:34px; font-size:13px; background:var(--wine);}
.dock-main:hover{background:#732828;}
.dock-main.active{background:#2e7d32;}
#dock-badge{
  font-family:var(--serif-display); color:var(--gold); font-size:12px;
  letter-spacing:.5px; min-width:42px; text-align:center;
}
#dock-time{font-size:10px; color:var(--parchment); opacity:.75; min-width:76px; text-align:right;}

/* ═══════════════ SIDE PANEL ═══════════════ */
#oc-overlay{position:fixed; inset:0; background:rgba(10,6,2,.55); opacity:0; pointer-events:none; transition:.2s; z-index:60;}
#oc-overlay.open{opacity:1; pointer-events:auto;}
#side-panel{
  position:fixed; top: 0; right:-420px; width:400px; max-width:92vw; height:100%; z-index:61;
  background:
    repeating-linear-gradient(0deg, rgba(120,90,40,.04) 0 2px, transparent 2px 4px),
    var(--parchment);
  border-left:3px double var(--gold);
  transition:right .25s ease; display:flex; flex-direction:column;
  box-shadow:var(--shadow);
}
#side-panel.open{right:0;}
#panel-header{
  padding:18px 20px; background:linear-gradient(180deg, rgba(43,29,16,.95), rgba(43,29,16,.85));
  color:var(--parchment); font-family:var(--serif-display); font-size:20px; letter-spacing:2px;
  display:flex; justify-content:space-between; align-items:center; border-bottom:2px solid var(--gold);
}
#panel-body{flex:1; overflow-y:auto; padding:20px; display:flex; flex-direction:column; gap:22px;}
.s-sec{display:flex; flex-direction:column; gap:8px;}
.s-lbl{font-family:var(--serif-display); font-size:15px; color:var(--wine); letter-spacing:1px;}
.s-hint{font-size:12px; color:var(--ink-soft); opacity:.75; font-style:italic;}
.s-inp, .s-area{
  font-family:var(--serif-body); font-size:15px; color:var(--ink);
  background:rgba(255,253,245,.7); border:1.5px solid var(--rule); border-radius:3px;
  padding:9px 11px; outline:none; resize:vertical;
}
.s-area{min-height:110px; line-height:1.5;}
.s-btn{
  font-family:var(--serif-body); font-weight:700; letter-spacing:1px; font-size:13px;
  border:1.5px solid var(--gold); border-radius:3px; padding:9px 14px; cursor:pointer; transition:.15s;
}
.s-btn:disabled{ opacity:.5; cursor:not-allowed; }
.s-blk{background:var(--wine); color:var(--parchment);}
.s-blk:hover{background:#732828;}
.s-wht{background:transparent; color:var(--ink); border-color:var(--rule);}
.s-wht:hover{background:rgba(0,0,0,.06);}
.s-grn{background:var(--sepia); color:var(--parchment);}
.s-grn:hover{background:#8b6038;}
#mp3-status{font-size:12px; color:var(--ink-soft); font-style:italic;}
#slide-thumbs{display:flex; flex-direction:column; gap:6px; max-height:300px; overflow-y:auto;}
.th-item{
  border:1px solid var(--rule); border-radius:3px; padding:7px 10px; cursor:pointer; font-size:12.5px;
  background:rgba(255,253,245,.5); display:flex; gap:8px; text-align:left; width:100%;
  font-family:var(--serif-body); color:inherit;
}
.th-item.active{background:rgba(169,119,47,.25); border-color:var(--gold);}
.th-item .th-num{font-family:var(--serif-display); color:var(--wine); flex-shrink:0;}
.th-item .th-txt{color:var(--ink-soft); line-height:1.3; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}

#panel-tab{
  position:fixed; top:50%; right:0; transform:translateY(-50%); z-index:50;
  background:linear-gradient(180deg, var(--wine), #3c1414);
  color:var(--parchment); border:1.5px solid var(--gold); border-right:none;
  border-radius:6px 0 0 6px; padding:16px 8px; cursor:pointer; font-family:var(--serif-display);
  font-size:14px; letter-spacing:2px; writing-mode:vertical-rl;
  box-shadow:-4px 0 12px rgba(0,0,0,.3);
}

#notif{
  position:fixed; bottom:60px; left:50%; transform:translateX(-50%);
  background:rgba(43,29,16,.95); color:var(--parchment); border:1.5px solid var(--gold);
  padding:9px 22px; border-radius:4px; font-family:var(--serif-body); font-weight:600; font-size:13px;
  letter-spacing:1px; display:none; z-index:80; box-shadow:var(--shadow);
}

.s-range{width:100%; accent-color:var(--gold);}

@media (max-width: 720px){
  #crown .title{max-width:48vw; font-size:19px;}
  .icon-btn{padding:6px 10px; font-size:12px;}
  #stage{flex-direction:column;}
  .leaf + .leaf{border-left:none; border-top:3px double var(--rule);}
  .leaf-text{font-size:clamp(18px, 5vw, 32px);}
}
</style>
</head>
<body>

<div id="start-modal" role="dialog" aria-modal="true" aria-labelledby="sm-title">
  <div class="sm-card">
  <button class="sm-close" onclick="closeStartModal()" aria-label="Kapat">✕</button>
    <div class="seal" id="sm-crest" aria-hidden="true">⚜</div>
    <div class="sm-overline">AKADEMİK OTURUM</div>
    <h1 class="sm-title" id="sm-title">DERS OTURUMU</h1>
    <div class="sm-rule"></div>
    <div class="sm-subtitle" id="sm-subtitle">Devam etmeden önce lütfen oturum bilgilerini giriniz.</div>

    <div class="sm-completed-note" id="sm-completed-note">Bu ders başarıyla tamamlanmıştır.</div>
    <div class="sm-completed-sub" id="sm-completed-sub">Oturumu yeniden başlatmak için aşağıdaki düğmeyi kullanabilirsiniz.</div>

    <div id="sm-form-fields">
      <div class="sm-field">
        <label for="sm-kurs">Kurs Adı</label>
        <input type="text" id="sm-kurs" placeholder="Örn. Antik Felsefe">
      </div>
      <div class="sm-field">
        <label for="sm-modul">Modül Adı</label>
        <input type="text" id="sm-modul" placeholder="Örn. Sokrates Öncesi Düşünürler">
      </div>
      <div class="sm-field">
        <label for="sm-ders">Ders Başlığı</label>
        <input type="text" id="sm-ders" placeholder="Örn. Thales ve Herakleitos">
      </div>
      <div class="sm-field">
        <label for="sm-aciklama">Açıklama</label>
        <textarea id="sm-aciklama" placeholder="İsteğe bağlı ders açıklaması"></textarea>
      </div>
    </div>

    <button class="sm-play" id="sm-play-btn" onclick="startLesson()">▶ DERSE BAŞLA</button>
  </div>
</div>

<div id="crown">
  <div class="title" id="kurs-display">KURS ADI</div>
  <div class="actions">
    <button class="icon-btn" onclick="openStartModal()" title="Oturumu Yeniden Başlat" aria-label="Oturumu Yeniden Başlat">⟳</button>
    <button class="icon-btn" onclick="openSidePanel()" title="Yazıhaneyi Aç" aria-label="Yazıhaneyi Aç">OKAN KAPLAN</button>
  </div>
</div>

<div id="empty-state">
  <h2>Levha Boş</h2>
  <p>Sağdaki Yazıhane panelini açın — Türkçe ve İngilizce metinleri girip kürsüyü kurun.</p>
  <button onclick="openSidePanel()">✎ </button>
</div>

<div id="stage" style="display:none">
  <div class="leaf" id="tr-leaf">
    <div class="leaf-bg-layer"><div class="leaf-bg-photo" id="tr-bg-photo"></div></div>
    <div class="candle-light"></div>
    <div class="slide-mark" id="tr-mark">I</div>
    <div class="leaf-head"><div class="lang">TÜRKÇE</div><div class="rule"></div></div>
    <div class="leaf-body"><div class="leaf-text" id="tr-text"><span class="cursor">&nbsp;</span></div></div>
  </div>
  <div class="leaf" id="en-leaf">
    <div class="leaf-bg-layer"><div class="leaf-bg-photo" id="en-bg-photo"></div></div>
    <div class="candle-light"></div>
    <div class="slide-mark" id="en-mark">I</div>
    <div class="leaf-head"><div class="lang">ENGLISH</div><div class="rule"></div></div>
    <div class="leaf-body"><div class="leaf-text" id="en-text"><span class="cursor">&nbsp;</span></div></div>
  </div>
</div>

<div id="dock">
  <div id="dock-progress" onclick="seekAudio(event)" role="slider" aria-label="Konum" tabindex="0"><div id="progress-fill"></div></div>
  <button class="dock-btn" onclick="prevSlide()" title="Önceki Levha" aria-label="Önceki Levha">◀</button>
  <button class="dock-btn dock-main" id="dock-toggle" onclick="dockToggle()" title="Oynat / Duraklat" aria-label="Oynat veya Duraklat">▶</button>
  <button class="dock-btn" onclick="stopAudio()" title="Durdur" aria-label="Durdur">■</button>
  <button class="dock-btn" onclick="nextSlide()" title="Sonraki Levha" aria-label="Sonraki Levha">▶</button>
  <button class="dock-btn" onclick="toggleFullscreen()" title="Tam Ekran" aria-label="Tam Ekran">⛶</button>
  <div id="dock-badge">0/0</div>
  <div id="dock-time">0:00 / 0:00</div>
</div>
<audio id="audio-player" style="display:none"></audio>

<button id="panel-tab" onclick="openSidePanel()" aria-label="Yazıhaneyi Aç">*</button>

<div id="oc-overlay" onclick="closeSidePanel()"></div>
<div id="side-panel" role="dialog" aria-labelledby="panel-header-label">
  <div id="panel-header">
    <span id="panel-header-label">▤ YAZIHANE</span>
    <button class="icon-btn" onclick="closeSidePanel()">✕ Kapat</button>
  </div>
  <div id="panel-body">

    <div class="s-sec">
      <span class="s-lbl">Kurs Adı</span>
      <input class="s-inp" id="kurs-input" type="text" placeholder="Kurs adını girin...">
      <button class="s-btn s-blk" onclick="updateKursAdi()">Uygula</button>
    </div>

    <div class="s-sec">
      <span class="s-lbl">Türkçe Metin</span>
      <span class="s-hint">Nokta/ünlem/soru ile biten her cümle ayrı bir levha olur.</span>
      <textarea class="s-area" id="tr-input" placeholder="Türkçe paragrafı buraya yapıştırın..."></textarea>
    </div>

    <div class="s-sec">
      <span class="s-lbl">İngilizce Çeviri</span>
      <span class="s-hint">Otomatik çevirebilir, ya da elle düzenleyebilirsiniz.</span>
      <textarea class="s-area" id="en-input" placeholder="Otomatik çeviri burada görünecek"></textarea>
      <button class="s-btn s-grn" id="translate-btn" onclick="manualTranslateNow()">⟲ Otomatik Çevir (TR → EN)</button>
      <div id="translate-status" class="s-hint" aria-live="polite"></div>
    </div>

    <button class="s-btn s-blk" id="create-btn" onclick="parseAndCreate()">⚜ Levhaları Oluştur</button>
    <button class="s-btn s-wht" onclick="clearAll()">✕ Temizle</button>

    <div class="s-sec">
      <span class="s-lbl">Ses (MP3)</span>
      <span class="s-hint">Süre, Türkçe ve İngilizce metinlerin karakter sayısına (boşluklar dahil) göre otomatik senkronize edilir.</span>
      <button class="s-btn s-grn" onclick="document.getElementById('mp3-input').click()">▶ MP3 Seç</button>
      <input type="file" id="mp3-input" accept="audio/*" style="display:none" onchange="loadMp3(this)">
      <div id="mp3-status" aria-live="polite">Dosya yüklenmedi</div>
      <button class="s-btn s-wht" onclick="clearMp3()">✕ MP3 Sil</button>
    </div>

    <div class="s-sec">
      <span class="s-lbl">Sol Levha (TR) Arkaplanı</span>
      <button class="s-btn s-grn" onclick="document.getElementById('bg-input-tr').click()">🖼 Görsel Seç</button>
      <input type="file" id="bg-input-tr" accept="image/*" style="display:none" onchange="loadBgImage(this, 'tr')">
      <span class="s-hint" style="margin-top:4px;">Görsel Opaklığı (%)</span>
      <input type="range" class="s-range" id="bg-opacity-range-tr" min="0" max="100" value="100" oninput="updateBgOpacity(this.value, 'tr')" aria-label="Türkçe levha görsel opaklığı">
      <button class="s-btn s-wht" onclick="resetBgImage('tr')">✕ Varsayılana Dön</button>
      <div id="bg-status-tr" class="s-hint">Varsayılan doku kullanılıyor</div>
    </div>

    <div class="s-sec">
      <span class="s-lbl">Sağ Levha (EN) Arkaplanı</span>
      <button class="s-btn s-grn" onclick="document.getElementById('bg-input-en').click()">🖼 Görsel Seç</button>
      <input type="file" id="bg-input-en" accept="image/*" style="display:none" onchange="loadBgImage(this, 'en')">
      <span class="s-hint" style="margin-top:4px;">Görsel Opaklığı (%)</span>
      <input type="range" class="s-range" id="bg-opacity-range-en" min="0" max="100" value="100" oninput="updateBgOpacity(this.value, 'en')" aria-label="İngilizce levha görsel opaklığı">
      <button class="s-btn s-wht" onclick="resetBgImage('en')">✕ Varsayılana Dön</button>
      <div id="bg-status-en" class="s-hint">Varsayılan doku kullanılıyor</div>
    </div>

    <div class="s-sec">
      <span class="s-lbl">Senaryo (JSON)</span>
      <button class="s-btn s-grn" onclick="downloadJson()">⬇ İndir</button>
      <label class="s-btn s-wht" style="text-align:center;">
        📂 JSON Aç
        <input type="file" id="json-file-inp" accept=".json" style="display:none" onchange="loadJsonFile(this)">
      </label>
    </div>

    <div class="s-sec">
      <span class="s-lbl">Levhalar</span>
      <div id="slide-thumbs"></div>
    </div>

  </div>
</div>

<div id="notif" role="status" aria-live="polite"></div>

<script>
// ════════ STATE ════════
let slides=[];
let curIdx=0;
let slideTimes=[];
let notifT=null;
const audioEl=document.getElementById('audio-player');
const DEFAULT_BG = "url('https://images.rawpixel.com/image_800/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIyLTA1L3B4MTA1NzQwNC1pbWFnZS1qb2I2MzAtYV8xLmpwZw.jpg')";

let lessonStarted = false;
let lessonEndedTriggered = false;
let translating = false;
let lessonInfo = {kurs:'', modul:'', ders:'', aciklama:''};

// ════════ PANEL ════════
function openSidePanel(){
  document.getElementById('side-panel').classList.add('open');
  document.getElementById('oc-overlay').classList.add('open');
}
function closeSidePanel(){
  document.getElementById('side-panel').classList.remove('open');
  document.getElementById('oc-overlay').classList.remove('open');
}

// ════════ MODAL FONKSİYONLARI ════════
function resetModalToDefault(){
  document.getElementById('sm-crest').classList.remove('completed');
  document.getElementById('sm-title').classList.remove('completed');
  document.getElementById('sm-title').textContent = 'DERS OTURUMU';
  document.getElementById('sm-subtitle').style.display = 'block';
  document.getElementById('sm-completed-note').style.display = 'none';
  document.getElementById('sm-completed-sub').style.display = 'none';
  document.getElementById('sm-form-fields').style.display = 'flex';
  document.getElementById('sm-form-fields').style.flexDirection = 'column';
  document.getElementById('sm-play-btn').textContent = '▶ DERSE BAŞLA';
  lessonEndedTriggered = false;
}

function openCompletedModal(){
  if(lessonEndedTriggered) return;
  lessonEndedTriggered = true;

  document.getElementById('sm-crest').classList.add('completed');
  document.getElementById('sm-title').classList.add('completed');
  document.getElementById('sm-title').textContent = 'OTURUM TAMAMLANDI';
  document.getElementById('sm-subtitle').style.display = 'none';
  document.getElementById('sm-completed-note').style.display = 'block';
  document.getElementById('sm-completed-sub').style.display = 'block';
  document.getElementById('sm-form-fields').style.display = 'none';

  setTimeout(()=>{
    document.getElementById('start-modal').classList.add('open');
    notify('DERS TAMAMLANDI');
  }, 600);
}

function openStartModal(){
  resetModalToDefault();
  document.getElementById('sm-kurs').value = lessonInfo.kurs;
  document.getElementById('sm-modul').value = lessonInfo.modul;
  document.getElementById('sm-ders').value = lessonInfo.ders;
  document.getElementById('sm-aciklama').value = lessonInfo.aciklama;
  document.getElementById('start-modal').classList.add('open');
}

function closeStartModal(){
  document.getElementById('start-modal').classList.remove('open');
}

function startLesson(){
  resetModalToDefault();

  lessonInfo.kurs = document.getElementById('sm-kurs').value.trim();
  lessonInfo.modul = document.getElementById('sm-modul').value.trim();
  lessonInfo.ders = document.getElementById('sm-ders').value.trim();
  lessonInfo.aciklama = document.getElementById('sm-aciklama').value.trim();

  const parts = [lessonInfo.kurs, lessonInfo.modul, lessonInfo.ders].filter(Boolean).map(s=>s.toUpperCase());
  const label = parts.length ? parts.join('  ·  ') : 'KURS ADI';
  document.getElementById('kurs-display').textContent = label;
  document.getElementById('kurs-input').value = lessonInfo.kurs;

  lessonStarted = true;
  closeStartModal();

  if(!slides.length){
    notify('Önce Yazıhaneden levha oluşturun');
    return;
  }
  setTimeout(playAudio, 200);
}

// ════════ ARKAPLAN GÖRSELİ ════════
function loadBgImage(inp, side){
  const f=inp.files[0]; if(!f) return;
  if(!f.type.startsWith('image/')){ notify('Lütfen bir görsel dosyası seçin'); return; }
  const reader=new FileReader();
  reader.onload=e=>{
    document.documentElement.style.setProperty(`--bg-img-${side}`, 'url("'+e.target.result+'")');
    document.getElementById(`bg-status-${side}`).textContent = '✓ '+f.name+' uygulandı';
    notify(`ARKAPLAN GÜNCELLENDİ (${side.toUpperCase()})`);
  };
  reader.onerror=()=>notify('GÖRSEL OKUNAMADI');
  reader.readAsDataURL(f);
}
function updateBgOpacity(v, side){
  // v, görselin doğrudan görünürlük (opaklık) yüzdesidir (0-100).
  // 100 = görsel tam net görünür, 0 = görsel tamamen soluk (şeffaf), altındaki parşömen rengi görünür.
  const opacity = (v / 100).toFixed(2);
  document.documentElement.style.setProperty(`--bg-img-opacity-${side}`, opacity);
}
function resetBgImage(side){
  document.documentElement.style.setProperty(`--bg-img-${side}`, DEFAULT_BG);
  document.getElementById(`bg-opacity-range-${side}`).value = 100;
  document.documentElement.style.setProperty(`--bg-img-opacity-${side}`, '1');
  document.getElementById(`bg-status-${side}`).textContent = 'Varsayılan doku kullanılıyor';
  notify(`VARSAYILANA DÖNÜLDÜ (${side.toUpperCase()})`);
}

function splitSentences(t){
  return t.trim().split(/(?<=[.!?…])\s+/).map(s=>s.trim()).filter(s=>s.length>0);
}

async function parseAndCreate(){
  const trRaw=document.getElementById('tr-input').value;
  const trS=splitSentences(trRaw);
  if(!trS.length){notify('Türkçe metin girin!');return;}

  let enS=splitSentences(document.getElementById('en-input').value);

  if(enS.length!==trS.length){
    notify('⏳ İngilizceye çevriliyor...');
    try{
      enS = await autoTranslateAll(trS);
      document.getElementById('en-input').value = enS.join(' ');
    }catch(e){
      notify('⚠ Çeviri başarısız, manuel girin');
      enS = trS.map(()=>'');
    }
  }

  slides=[];
  for(let i=0;i<trS.length;i++){
    slides.push({tr: trS[i]||'', en: enS[i]||''});
  }
  computeSlideTimes();
  curIdx=0;
  lessonStarted = false;
  lessonEndedTriggered = false;
  showStage();
  loadSlide(0,true);
  buildThumbs();
  notify('✓ '+slides.length+' LEVHA OLUŞTURULDU');
}

async function translateOne(text){
  if(!text.trim()) return '';
  const url='https://api.mymemory.translated.net/get?q='+encodeURIComponent(text)+'&langpair=tr|en';
  const res=await fetch(url);
  if(!res.ok) throw new Error('translate http '+res.status);
  const data=await res.json();
  return (data && data.responseData && data.responseData.translatedText) ? data.responseData.translatedText : '';
}

async function autoTranslateAll(trSentences){
  const out=[];
  for(let i=0;i<trSentences.length;i++){
    notify('⏳ Çevriliyor… '+(i+1)+'/'+trSentences.length);
    try{ out.push(await translateOne(trSentences[i])); }
    catch(e){ out.push(''); }
    if(i<trSentences.length-1) await new Promise(r=>setTimeout(r,260));
  }
  return out;
}

async function manualTranslateNow(){
  if(translating) return;
  const trS=splitSentences(document.getElementById('tr-input').value);
  if(!trS.length){notify('Önce Türkçe metin girin!');return;}
  translating = true;
  const btn=document.getElementById('translate-btn');
  const statusEl=document.getElementById('translate-status');
  btn.disabled = true;
  statusEl.textContent = 'Çevriliyor…';
  try{
    const enS=await autoTranslateAll(trS);
    document.getElementById('en-input').value=enS.join(' ');
    statusEl.textContent = '✓ Çeviri tamamlandı';
    notify('✓ ÇEVİRİ TAMAMLANDI');
  }catch(e){
    statusEl.textContent = '⚠ Çeviri sırasında bir sorun oluştu';
    notify('⚠ ÇEVİRİ BAŞARISIZ');
  }finally{
    translating = false;
    btn.disabled = false;
  }
}

// MP3 süresi yüklendiğinde veya süre değiştikğinde her levhanın süresi toplam süreye,
// Türkçe ve İngilizce paragrafların toplam karakter uzunluğuna göre tam senkronize dağıtılır.
// MP3 yüklü olmadığında ise ortalama okuma hızından (karakter başına makul bir süre) hesaplama yapılır.
const CHARS_PER_SEC = 10;   // Metnin yavaşlayıp daha doğal akması için saniye başına düşen karakter sayısı azaltıldı
const MIN_SLIDE_SEC = 3.5;  // Okumayı kolaylaştırmak için minimum levha süresi artırıldı
const SLIDE_GAP_SEC = 0.5;  // Levhalar arası duraksama nefes payı artırıldı

function computeSlideTimes(){
  slideTimes=[];
  if (!slides.length) return;

  // MP3 yüklenmişse ve süresi geçerliyse toplam süreyi temel alıyoruz
  if (audioEl.src && !isNaN(audioEl.duration) && audioEl.duration > 0) {
    const totalDuration = audioEl.duration;

    // Her bir levhanın ağırlığını içindeki maksimum karakter sayısına (TR veya EN) göre belirliyoruz
    let totalWeight = 0;
    const weights = slides.map(sl => {
      const len = Math.max(sl.tr.length, sl.en.length, 1);
      totalWeight += len;
      return len;
    });

    let cum = 0;
    for (let i = 0; i < slides.length; i++) {
      slideTimes.push(cum);
      const share = (weights[i] / totalWeight) * totalDuration;
      cum += share;
    }
    slideTimes.push(totalDuration);
  } else {
    // MP3 yüklenmemişse karakter bazlı fallback hesaplama
    let cum = 0;
    slides.forEach(sl => {
      slideTimes.push(cum);
      const len = Math.max(sl.tr.length, sl.en.length, 1);
      cum += Math.max(MIN_SLIDE_SEC, len / CHARS_PER_SEC) + SLIDE_GAP_SEC;
    });
    slideTimes.push(cum);
  }
}

function showStage(){
  document.getElementById('empty-state').style.display='none';
  document.getElementById('stage').style.display='flex';
}
function nextSlide(){ if(slides.length && curIdx<slides.length-1) loadSlide(curIdx+1,true); }
function prevSlide(){ if(slides.length && curIdx>0) loadSlide(curIdx-1,true); }

function loadSlide(idx, jumpAudio){
  if(idx<0||idx>=slides.length) return;
  curIdx=idx;
  refreshSlideChrome();
  buildThumbs();
  resetPaging();
  setLeafText('tr-text', slides[idx].tr, 0);
  setLeafText('en-text', slides[idx].en, 0);
  if(jumpAudio && audioEl.src && !isNaN(audioEl.duration) && audioEl.duration>0){
    const total=slideTimes[slideTimes.length-1]||1;
    const frac=slideTimes[idx]/total;
    audioEl.currentTime = frac*audioEl.duration;
  } else if(jumpAudio){
    fallbackElapsedSec = slideTimes[idx];
    fallbackLastTs = null;
  }
}

function toRoman(n){
  const vals=[[1000,'M'],[900,'CM'],[500,'D'],[400,'CD'],[100,'C'],[90,'XC'],[50,'L'],[40,'XL'],[10,'X'],[9,'IX'],[5,'V'],[4,'IV'],[1,'I']];
  let r=''; for(const [v,s] of vals){ while(n>=v){r+=s;n-=v;} } return r||'I';
}

const pageState={ 'tr-text':{pageStart:0, pageNum:1}, 'en-text':{pageStart:0, pageNum:1} };

function resetPaging(){
  pageState['tr-text'].pageStart=0; pageState['tr-text'].pageNum=1;
  pageState['en-text'].pageStart=0; pageState['en-text'].pageNum=1;
  updateMark('tr-text'); updateMark('en-text');
}

function updateMark(elId){
  const markId = elId==='tr-text' ? 'tr-mark' : 'en-mark';
  const st=pageState[elId];
  const base = toRoman(curIdx+1);
  const txt = st.pageNum>1 ? (base+' · s.'+st.pageNum) : base;
  document.getElementById(markId).textContent = txt;
}

function renderHTML(elId, text){
  document.getElementById(elId).innerHTML = inkify(text) + '<span class="cursor">&nbsp;</span>';
}

function seededRand(seed){
  const x=Math.sin(seed)*43758.5453;
  return x-Math.floor(x);
}
const INK_SHADES=['#241708','#2b1d10','#33220f','#3a2814'];

function inkify(text){
  let out='';
  let wordOpen=false;
  let atWordStart=true;
  for(let i=0;i<text.length;i++){
    const ch=text[i];
    if(ch===' '){
      if(wordOpen){ out+='</span>'; wordOpen=false; }
      out+=' '; atWordStart=true; continue;
    }
    if(ch==='\n'){
      if(wordOpen){ out+='</span>'; wordOpen=false; }
      out+='<br>'; atWordStart=true; continue;
    }
    if(!wordOpen){ out+='<span class="ink-word">'; wordOpen=true; }
    const seed=ch.charCodeAt(0)*131.7 + i*97.3;
    const r1=seededRand(seed), r2=seededRand(seed+11), r3=seededRand(seed+23), r4=seededRand(seed+37), r5=seededRand(seed+53);
    const rot=((r1-0.5)*6).toFixed(2);
    const ty=((r2-0.5)*5).toFixed(2);
    const scale=(0.93+r3*0.14).toFixed(3);
    const opacity=(0.80+r4*0.20).toFixed(2);
    const color=INK_SHADES[Math.floor(r5*INK_SHADES.length)];
    const esc=ch.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
    const cls=atWordStart ? 'ink-char word-start' : 'ink-char';
    out+='<span class="'+cls+'" style="--r:'+rot+'deg;--ty:'+ty+'px;--s:'+scale+';opacity:'+opacity+';color:'+color+'">'+esc+'</span>';
    atWordStart=false;
  }
  if(wordOpen) out+='</span>';
  return out;
}

function fitsInBox(elId){
  const el=document.getElementById(elId);
  const box=el.parentElement;
  return el.scrollHeight <= box.clientHeight + 1;
}

function snapToWordBoundary(full, start, end){
  if(end<=start) return end;
  const seg=full.slice(start,end);
  const lastSpace=seg.lastIndexOf(' ');
  if(lastSpace>0) return start+lastSpace;
  return end;
}

function setLeafText(elId, full, target){
  const st=pageState[elId];
  target=Math.max(st.pageStart, Math.min(target, full.length));

  renderHTML(elId, full.slice(st.pageStart, target));
  if(fitsInBox(elId)) return;

  let lo=st.pageStart, hi=target;
  while(lo<hi){
    const mid=Math.ceil((lo+hi)/2);
    renderHTML(elId, full.slice(st.pageStart, mid));
    if(fitsInBox(elId)) lo=mid; else hi=mid-1;
  }
  let safeLo=snapToWordBoundary(full, st.pageStart, lo);
  if(safeLo<=st.pageStart) safeLo=lo;

  if(safeLo>st.pageStart){
    renderHTML(elId, full.slice(st.pageStart, safeLo));
    if(target<=safeLo) return;
  }

  const el=document.getElementById(elId);
  el.style.opacity='0';

  let nextStart=safeLo;
  while(full[nextStart]===' ') nextStart++;
  st.pageStart=nextStart;
  st.pageNum=(st.pageNum||1)+1;
  updateMark(elId);
  renderHTML(elId, full.slice(st.pageStart, target));
  requestAnimationFrame(()=>{ el.style.opacity='1'; });
  if(fitsInBox(elId)) return;

  let lo2=st.pageStart, hi2=target;
  while(lo2<hi2){
    const mid2=Math.ceil((lo2+hi2)/2);
    renderHTML(elId, full.slice(st.pageStart, mid2));
    if(fitsInBox(elId)) lo2=mid2; else hi2=mid2-1;
  }
  let safeLo2=snapToWordBoundary(full, st.pageStart, lo2);
  if(safeLo2<=st.pageStart) safeLo2=lo2;
  renderHTML(elId, full.slice(st.pageStart, safeLo2));
}

function buildThumbs(){
  const c=document.getElementById('slide-thumbs'); c.innerHTML='';
  slides.forEach((sl,i)=>{
    const btn=document.createElement('button');
    btn.type='button';
    btn.className='th-item'+(i===curIdx?' active':'');
    btn.onclick=()=>loadSlide(i,true);
    const txt=(sl.tr||sl.en).substring(0,46);
    btn.innerHTML='<span class="th-num">'+toRoman(i+1)+'</span><span class="th-txt">'+txt.replace(/&/g,'&amp;').replace(/</g,'&lt;')+'</span>';
    c.appendChild(btn);
  });
}

let fallbackPlaying=false;
let fallbackLastTs=null;
let fallbackElapsedSec=0;

function isPlaying(){
  return audioEl.src ? !audioEl.paused : fallbackPlaying;
}

function dockToggle(){
  if(isPlaying()) pauseAudio(); else playAudio();
}

function updatePlaybackButtons(state){
  const t=document.getElementById('dock-toggle');
  t.textContent = state==='playing' ? '⏸' : '▶';
  t.classList.toggle('active', state==='playing');
}

function refreshSlideChrome(){
  document.getElementById('dock-badge').textContent=(curIdx+1)+'/'+slides.length;
  document.getElementById('tr-mark').textContent=toRoman(curIdx+1);
  document.getElementById('en-mark').textContent=toRoman(curIdx+1);
}

function tick(){
  requestAnimationFrame(tick);
  if(!slides.length) return;

  const total=slideTimes[slideTimes.length-1]||1;
  let curFracTime=null;

  if(audioEl.src && !isNaN(audioEl.duration) && audioEl.duration>0){
    if(audioEl.paused) { return; }
    curFracTime=(audioEl.currentTime/audioEl.duration)*total;
  } else {
    if(!fallbackPlaying) return;
    const now=performance.now();
    if(fallbackLastTs===null) fallbackLastTs=now;
    fallbackElapsedSec += (now-fallbackLastTs)/1000;
    fallbackLastTs=now;
    if(fallbackElapsedSec>=total){
      fallbackElapsedSec=total;
      fallbackPlaying=false;
      curFracTime=total;
    } else {
      curFracTime=fallbackElapsedSec;
    }
  }

  let idx=curIdx;
  for(let i=0;i<slides.length;i++){ if(curFracTime>=slideTimes[i] && curFracTime<slideTimes[i+1]) idx=i; }
  if(curFracTime>=total) idx=slides.length-1;

  if(idx!==curIdx){
    const trEl=document.getElementById('tr-text'), enEl=document.getElementById('en-text');
    trEl.style.opacity='0'; enEl.style.opacity='0';
    curIdx=idx; resetPaging(); buildThumbs(); refreshSlideChrome();
    requestAnimationFrame(()=>{ trEl.style.opacity='1'; enEl.style.opacity='1'; });
  }

  const s0=slideTimes[curIdx], s1=slideTimes[curIdx+1];
  const progressInSlide = Math.max(0, Math.min(1, s1>s0 ? (curFracTime-s0)/(s1-s0) : 1));
  const sl=slides[curIdx];
  setLeafText('tr-text', sl.tr, Math.round(progressInSlide*sl.tr.length));
  setLeafText('en-text', sl.en, Math.round(progressInSlide*sl.en.length));

  if(audioEl.src && audioEl.duration){
    document.getElementById('progress-fill').style.width=(audioEl.currentTime/audioEl.duration*100)+'%';
    document.getElementById('dock-time').textContent=fmt(audioEl.currentTime)+' / '+fmt(audioEl.duration);
  } else {
    document.getElementById('progress-fill').style.width=(fallbackElapsedSec/total*100)+'%';
    document.getElementById('dock-time').textContent=fmt(fallbackElapsedSec)+' / '+fmt(total);
  }

  if(!fallbackPlaying && (!audioEl.src || audioEl.paused) && curFracTime>=total){
    updatePlaybackButtons('paused');
    if(!lessonEndedTriggered && lessonStarted){
      openCompletedModal();
    }
  }
}
requestAnimationFrame(tick);

function loadMp3(inp){
  const f=inp.files[0]; if(!f) return;
  if(!f.type.startsWith('audio/')){ notify('Lütfen bir ses dosyası seçin'); return; }
  if(audioEl._blobUrl) URL.revokeObjectURL(audioEl._blobUrl);
  const url=URL.createObjectURL(f);
  audioEl._blobUrl=url; audioEl.src=url; audioEl.load();
  document.getElementById('mp3-status').textContent='▶ '+f.name;
  fallbackPlaying=false; fallbackLastTs=null;
  lessonEndedTriggered = false;
  updatePlaybackButtons('paused');

  // MP3'ün yüklendiğini ve süresinin okunabilir olduğunu yakaladığımızda süreleri yeniden hesapla
  audioEl.onloadedmetadata = function() {
    computeSlideTimes();
    buildThumbs();
    refreshSlideChrome();
    notify('MP3 YÜKLENDİ VE SENKRONİZE EDİLDİ ✓');
  };
  audioEl.onerror = function(){
    notify('⚠ MP3 OKUNAMADI');
    document.getElementById('mp3-status').textContent='Dosya yüklenemedi';
  };
}
function clearMp3(){
  if(audioEl._blobUrl) URL.revokeObjectURL(audioEl._blobUrl);
  audioEl.removeAttribute('src'); audioEl._blobUrl=null; audioEl.load();
  document.getElementById('mp3-status').textContent='Dosya yüklenmedi';
  document.getElementById('progress-fill').style.width='0%';
  document.getElementById('dock-time').textContent='0:00 / 0:00';
  fallbackElapsedSec = slideTimes.length ? slideTimes[curIdx] : 0;
  fallbackLastTs=null; fallbackPlaying=false;
  lessonEndedTriggered = false;
  updatePlaybackButtons('paused');
  computeSlideTimes();
  notify('MP3 SİLİNDİ');
}

function playAudio(){
  if(!slides.length){ notify('Önce levha oluşturun!'); return; }

  if(!lessonStarted){
    openStartModal();
    return;
  }

  lessonEndedTriggered = false;

  if(audioEl.src){
    const p = audioEl.play();
    if(p && typeof p.catch === 'function'){
      p.then(()=>updatePlaybackButtons('playing'))
       .catch(()=>{ notify('⚠ OYNATMA BAŞLATILAMADI'); updatePlaybackButtons('paused'); });
      return;
    }
  } else {
    fallbackLastTs=null;
    fallbackPlaying=true;
  }
  updatePlaybackButtons('playing');
}

function pauseAudio(){
  if(!slides.length) return;
  if(audioEl.src){
    audioEl.pause();
  } else {
    fallbackPlaying=false; fallbackLastTs=null;
  }
  updatePlaybackButtons('paused');
}

function stopAudio(){
  if(audioEl.src){
    audioEl.pause();
    audioEl.currentTime=0;
  }
  fallbackPlaying=false; fallbackLastTs=null; fallbackElapsedSec=0;
  curIdx=0;
  lessonEndedTriggered = false;
  resetPaging();
  if(slides.length){
    loadSlide(0,false);
  }
  updatePlaybackButtons('paused');
}

function seekAudio(e){
  if(!slides.length) return;
  lessonEndedTriggered = false;
  const r=e.currentTarget.getBoundingClientRect();
  const frac=Math.max(0, Math.min(1, (e.clientX-r.left)/r.width));
  if(audioEl.src && audioEl.duration){
    audioEl.currentTime=frac*audioEl.duration;
  } else {
    const total=slideTimes[slideTimes.length-1]||1;
    fallbackElapsedSec=frac*total;
    fallbackLastTs=null;
  }
}
audioEl.addEventListener('ended', ()=>{
  updatePlaybackButtons('paused');
  if(!lessonEndedTriggered && lessonStarted){
    openCompletedModal();
  }
});

function fmt(s){ if(!s||isNaN(s)) return '0:00'; return Math.floor(s/60)+':'+String(Math.floor(s%60)).padStart(2,'0'); }

function updateKursAdi(){
  const v=document.getElementById('kurs-input').value.trim()||'KURS ADI';
  lessonInfo.kurs = v;
  document.getElementById('kurs-display').textContent=v.toUpperCase();
  notify('KURS ADI GÜNCELLENDİ');
}

function clearAll(){
  if(!confirm('Tüm levhaları sil?')) return;
  slides=[]; curIdx=0; slideTimes=[];
  lessonStarted = false;
  lessonEndedTriggered = false;
  fallbackPlaying=false; fallbackLastTs=null; fallbackElapsedSec=0;
  if(audioEl.src){ audioEl.pause(); audioEl.currentTime=0; }
  updatePlaybackButtons('paused');
  document.getElementById('slide-thumbs').innerHTML='';
  document.getElementById('dock-badge').textContent='0/0';
  document.getElementById('progress-fill').style.width='0%';
  document.getElementById('dock-time').textContent='0:00 / 0:00';
  document.getElementById('stage').style.display='none';
  document.getElementById('empty-state').style.display='flex';
  notify('TEMİZLENDİ');
}

function buildScenario(){
  return { version:'2.4', kursAdi:lessonInfo.kurs, modul:lessonInfo.modul, ders:lessonInfo.ders, aciklama:lessonInfo.aciklama, slides };
}
function downloadJson(){
  if(!slides.length){ notify('İndirilecek levha yok'); return; }
  const blob=new Blob([JSON.stringify(buildScenario(),null,2)],{type:'application/json'});
  const url=URL.createObjectURL(blob);
  const a=document.createElement('a');
  a.href=url; a.download='senaryo_'+((lessonInfo.kurs||'ders').replace(/\s+/g,'_'))+'.json';
  a.click(); URL.revokeObjectURL(url);
  notify('JSON İNDİRİLDİ ✓');
}

function normalizeSlide(sl){
  if(typeof sl === 'string') return {tr: sl, en:''};
  if(!sl || typeof sl !== 'object') return {tr:'', en:''};
  const tr = sl.tr ?? sl.TR ?? sl.turkce ?? sl.turkish ?? sl.tr_text ?? sl.text_tr ?? '';
  const en = sl.en ?? sl.EN ?? sl.ingilizce ?? sl.english ?? sl.en_text ?? sl.text_en ?? '';
  return { tr: (tr||'').toString(), en: (en||'').toString() };
}

function loadJsonFile(inp){
  const f=inp.files[0]; if(!f) return;
  const r=new FileReader();
  r.onload=ev=>{
    let data;
    try{ data=JSON.parse(ev.target.result); }
    catch(e){ notify('JSON OKUNAMADI: '+e.message); return; }

    let rawSlides=null;
    if(Array.isArray(data.slides)) rawSlides=data.slides;
    else if(Array.isArray(data)) rawSlides=data;
    else if(Array.isArray(data.trParagraphs) && Array.isArray(data.enParagraphs)){
      rawSlides=data.trParagraphs.map((t,i)=>({tr:t, en:(data.enParagraphs[i]||'')}));
    }
    if(!rawSlides){ notify('Geçersiz format: "slides" dizisi bulunamadı'); return; }

    const newSlides = rawSlides.map(normalizeSlide);

    document.getElementById('tr-input').value = newSlides.map(s=>s.tr).join(' ');
    document.getElementById('en-input').value = newSlides.map(s=>s.en).join(' ');

    lessonInfo.kurs = data.kursAdi || data.kurs || lessonInfo.kurs || '';
    lessonInfo.modul = data.modul || lessonInfo.modul || '';
    lessonInfo.ders = data.ders || lessonInfo.ders || '';
    lessonInfo.aciklama = data.aciklama || lessonInfo.aciklama || '';

    const parts = [lessonInfo.kurs, lessonInfo.modul, lessonInfo.ders].filter(Boolean).map(s=>s.toUpperCase());
    document.getElementById('kurs-display').textContent = parts.length ? parts.join('  ·  ') : 'KURS ADI';
    document.getElementById('kurs-input').value = lessonInfo.kurs;

    slides = newSlides;
    try{
      computeSlideTimes();
      curIdx=0; lessonStarted=false; lessonEndedTriggered=false;
      showStage(); loadSlide(0,true); buildThumbs();
      notify('✓ '+slides.length+' LEVHA İMPORT EDİLDİ');
    }catch(e){
      notify('Metinler yüklendi, levha kurulumunda sorun: '+e.message);
    }
  };
  r.onerror=()=>notify('DOSYA OKUNAMADI');
  r.readAsText(f);
  inp.value='';
}

function notify(msg){
  const el=document.getElementById('notif');
  el.textContent=msg; el.style.display='block';
  clearTimeout(notifT);
  notifT=setTimeout(()=>{el.style.display='none';},2200);
}

function toggleFullscreen() {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen().catch(err => {
      notify(`Hata: ${err.message}`);
    });
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    }
  }
}

// ════════ KLAVYE KISAYOLLARI ════════
document.addEventListener('keydown', (e)=>{
  const tag=(e.target && e.target.tagName || '').toLowerCase();
  const typing = tag==='input' || tag==='textarea';

  if(e.key==='Escape'){
    if(document.getElementById('start-modal').classList.contains('open')) closeStartModal();
    else if(document.getElementById('side-panel').classList.contains('open')) closeSidePanel();
    return;
  }
  if(typing) return;

  if(e.code==='Space'){ e.preventDefault(); dockToggle(); }
  else if(e.key==='ArrowRight'){ nextSlide(); }
  else if(e.key==='ArrowLeft'){ prevSlide(); }
});
</script>


</body>
</html>
CANLI ÖNİZLEME