Files
3d-trpay/index.html
T
yilsem 765d84f00a Kod temizligi + hata yonetimi: olu OFFSET/2D roles alanlari kaldirildi, script/audio onerror handler'lari eklendi
- index.html: kullanilmayan OFFSET sabiti kaldirildi
- data.js: roles icindeki olu 2D x/y/durum alanlari temizlendi (sadece renk kullaniliyordu)
- three.min.js/OrbitControls.js/data.js icin onerror -> gorunur hata ekrani (loadErr)
- toplanti_orijinal.mp3 icin onerror -> gorunur hata ekrani
- toplanti_turkce.mp3 icin onerror -> sayfa kilitlenmiyor, TR_READY() artik dinamik
  fonksiyon olup TR_AUDIO_FAILED bayragini da kontrol ediyor
- three.min.js/OrbitControls.js icin de cache-busting versiyonu eklendi (tutarlilik)
2026-07-04 06:31:15 +03:00

310 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Toplantı 3D — Orijinal / Türkçe</title>
<style>
:root{ --bg:#0d1117; --panel:#161b22cc; --border:#30363d; --txt:#e6edf3; --mut:#8b949e; --accent:#2f81f7; }
*{box-sizing:border-box}
html,body{margin:0;height:100%;background:var(--bg);color:var(--txt);font-family:"Segoe UI",system-ui,sans-serif;overflow:hidden}
#scene{position:fixed;inset:0}
#topbar{position:fixed;top:0;left:0;right:0;height:52px;display:flex;align-items:center;gap:14px;
padding:0 16px;background:linear-gradient(#0d1117ee,#0d111700);z-index:10;pointer-events:none}
#topbar h1{font-size:15px;margin:0;font-weight:600;pointer-events:auto}
#topbar .sub{font-size:12px;color:var(--mut);font-weight:400}
.spacer{flex:1}
.toggle{pointer-events:auto;display:flex;background:#21262d;border:1px solid var(--border);border-radius:20px;overflow:hidden}
.toggle button{background:none;border:0;color:var(--mut);padding:7px 15px;font-size:13px;cursor:pointer;font-weight:600}
.toggle button.on{background:var(--accent);color:#fff}
.toggle button.on.trm{background:#8957e5}
#legend{position:fixed;top:60px;left:12px;z-index:10;background:var(--panel);border:1px solid var(--border);
border-radius:10px;padding:10px 12px;font-size:11.5px;backdrop-filter:blur(6px);max-width:220px}
#legend .row{display:flex;align-items:center;gap:7px;margin-top:5px}
#legend .dot{width:11px;height:11px;border-radius:50%;flex:none}
#subtitle{position:fixed;left:50%;transform:translateX(-50%);bottom:90px;width:min(760px,94vw);z-index:10;
background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:6px 14px;backdrop-filter:blur(8px);
text-align:center;transition:opacity .2s}
#subtitle .who{font-weight:700;font-size:12px;margin-bottom:1px}
#subtitle .orig{font-size:12.5px;line-height:1.24}
#subtitle .tr{font-size:12.5px;line-height:1.24;color:var(--mut);margin-top:1px}
#subtitle.trmode .orig{color:var(--mut);font-size:12.5px}
#subtitle.trmode .tr{color:var(--txt)}
.badge{display:inline-block;font-size:10px;background:#3d2a00;color:#e0b400;border:1px solid #6b4a00;
border-radius:6px;padding:1px 6px;margin-left:6px;vertical-align:middle}
#controls{position:fixed;left:0;right:0;bottom:0;z-index:10;background:linear-gradient(#0d111700,#0d1117ee 42%);padding:12px 18px 14px}
#tl{width:100%;height:34px;display:block;cursor:pointer;border-radius:6px}
#bar{display:flex;align-items:center;gap:12px;margin-top:8px}
.btn{background:#21262d;border:1px solid var(--border);color:var(--txt);width:40px;height:40px;border-radius:50%;
font-size:15px;cursor:pointer;display:flex;align-items:center;justify-content:center}
.btn:hover{border-color:var(--accent)}
.btn.play{width:46px;height:46px;font-size:17px;background:var(--accent);border-color:var(--accent)}
#time{font-variant-numeric:tabular-nums;font-size:13px;color:var(--mut);min-width:120px}
#hint{font-size:11px;color:var(--mut)}
@media(max-width:640px){
#subtitle{bottom:138px}
#hint{display:none}
#bar{flex-wrap:wrap}
#topbar h1{font-size:13px}
#topbar .sub{display:none}
.toggle button{padding:6px 10px;font-size:12px}
#legend{max-width:150px;font-size:10px;padding:7px 9px;top:56px}
#legend b{font-size:10.5px}
}
</style>
</head>
<body>
<div id="scene"></div>
<div id="topbar">
<h1>Toplantı — 3D Oda <span class="sub">· uzlaşma görüşmesi (düzenlenmiş kayıt)</span></h1>
<div class="spacer"></div>
<div class="toggle" id="langToggle">
<button data-m="orig" class="on">🔊 Orijinal</button>
<button data-m="tr">🇹🇷 Türkçe</button>
</div>
</div>
<div id="legend"><b>Masadaki kişiler</b><div id="legendRows"></div></div>
<div id="subtitle">
<div class="who" id="subWho"></div>
<div class="orig" id="subOrig">Başlamak için ▶ tuşuna bas</div>
<div class="tr" id="subTr"></div>
</div>
<div id="controls">
<canvas id="tl"></canvas>
<div id="bar">
<button class="btn play" id="play"></button>
<button class="btn" id="prev" title="Önceki konuşma"></button>
<button class="btn" id="next" title="Sonraki konuşma"></button>
<span id="time">00:00 / 00:00</span>
<div class="spacer"></div>
<span id="hint">Zaman çizelgesine tıkla/sürükle · fareyle sahneyi döndür · çift tık kişi→ilk sözü</span>
</div>
</div>
<div id="loadErr" style="display:none;position:fixed;inset:0;z-index:999;background:#0d1117;color:#e6edf3;
font-family:'Segoe UI',system-ui,sans-serif;align-items:center;justify-content:center;text-align:center;padding:24px">
<div>
<div style="font-size:15px;font-weight:600;margin-bottom:8px">⚠️ Bir dosya yüklenemedi</div>
<div id="loadErrMsg" style="font-size:13px;color:#8b949e"></div>
<div style="font-size:12px;color:#8b949e;margin-top:10px">Sayfayı yeniden yüklemeyi deneyin veya bir yerel sunucu üzerinden açın (file:// kısıtlamaları olabilir).</div>
</div>
</div>
<script>
function showLoadErr(msg){
const box=document.getElementById('loadErr'), m=document.getElementById('loadErrMsg');
if(m)m.textContent=msg; if(box){box.style.display='flex';}
}
</script>
<audio id="ao" src="toplanti_orijinal.mp3?v=20260704d" preload="metadata" onerror="showLoadErr('toplanti_orijinal.mp3 yüklenemedi')"></audio>
<audio id="at" preload="metadata" onerror="window.TR_AUDIO_FAILED=true"></audio>
<script src="three.min.js?v=20260704d" onerror="showLoadErr('three.min.js (3D motoru) yüklenemedi')"></script>
<script src="OrbitControls.js?v=20260704d" onerror="showLoadErr('OrbitControls.js (kamera kontrolü) yüklenemedi')"></script>
<script src="data.js?v=20260704d" onerror="showLoadErr('data.js (toplantı verisi) yüklenemedi')"></script>
<script>
if(typeof MEET==='undefined'){ showLoadErr('data.js yüklenemedi veya bozuk (MEET tanımsız)'); throw new Error('MEET tanımsız — data.js yüklenemedi'); }
const ROLES=MEET.roles, TL=MEET.TL;
const POS3D={
"Kaan":{x:-1.6,z:2.3,stand:false}, "Marissa":{x:1.6,z:2.3,stand:false},
"Dolandırıcı (D-)":{x:-1.6,z:-2.3,stand:false}, "Uzlaşmacı (U)":{x:0.4,z:-2.3,stand:false},
"Yaşlı adam (V)":{x:-3.7,z:0,stand:false}, "Lider Uzlaşmacı (L.U)":{x:3.7,z:0,stand:false},
"Kayınvalide":{x:3.3,z:-2.6,stand:true}
};
const SHORT={"Kaan":"Kaan","Marissa":"Marissa","Dolandırıcı (D-)":"Scammer Litoy","Uzlaşmacı (U)":"Kuya 2",
"Yaşlı adam (V)":"Manong","Lider Uzlaşmacı (L.U)":"Kuya 1","Kayınvalide":"Daisy ⬆"};
function roundRect(g,x,y,w,h,r){g.beginPath();g.moveTo(x+r,y);g.arcTo(x+w,y,x+w,y+h,r);g.arcTo(x+w,y+h,x,y+h,r);g.arcTo(x,y+h,x,y,r);g.arcTo(x,y,x+w,y,r);g.closePath();}
function makeLabel(text,color,scale){ scale=scale||1;
const c=document.createElement('canvas'); c.width=256; c.height=64; const g=c.getContext('2d');
g.fillStyle="rgba(13,17,23,0.85)"; roundRect(g,4,10,248,44,10); g.fill();
g.strokeStyle=color; g.lineWidth=2; roundRect(g,4,10,248,44,10); g.stroke();
g.fillStyle=color; g.font="bold 24px Segoe UI"; g.textAlign="center"; g.textBaseline="middle"; g.fillText(text,128,33);
const spr=new THREE.Sprite(new THREE.SpriteMaterial({map:new THREE.CanvasTexture(c),transparent:true,depthTest:false}));
spr.scale.set(1.9*scale,0.48*scale,1); return spr;
}
const scene=new THREE.Scene();
scene.background=new THREE.Color(0x0d1117);
scene.fog=new THREE.Fog(0x0d1117,16,34);
const camera=new THREE.PerspectiveCamera(48,innerWidth/innerHeight,0.1,100);
function fitCamera(){
const narrow=innerWidth<700;
camera.position.set(0, narrow?8.6:6.2, narrow?14.5:9.6);
camera.aspect=innerWidth/innerHeight; camera.updateProjectionMatrix();
}
fitCamera();
const renderer=new THREE.WebGLRenderer({antialias:true});
renderer.setSize(innerWidth,innerHeight); renderer.setPixelRatio(Math.min(devicePixelRatio,2));
document.getElementById('scene').appendChild(renderer.domElement);
const controls=new THREE.OrbitControls(camera,renderer.domElement);
controls.enableDamping=true; controls.dampingFactor=0.08; controls.target.set(0,1,0);
controls.maxPolarAngle=Math.PI*0.49; controls.minDistance=5; controls.maxDistance=22;
scene.add(new THREE.AmbientLight(0xffffff,0.55));
const key=new THREE.DirectionalLight(0xffffff,0.9); key.position.set(6,12,8); scene.add(key);
const fill=new THREE.DirectionalLight(0x88aaff,0.35); fill.position.set(-8,6,-6); scene.add(fill);
const floor=new THREE.Mesh(new THREE.PlaneGeometry(40,40),new THREE.MeshStandardMaterial({color:0x1c2230,roughness:0.95}));
floor.rotation.x=-Math.PI/2; scene.add(floor);
const rug=new THREE.Mesh(new THREE.CircleGeometry(7.5,48),new THREE.MeshStandardMaterial({color:0x232a3a,roughness:1}));
rug.rotation.x=-Math.PI/2; rug.position.y=0.01; scene.add(rug);
const TABLE_H=1.0;
const tableTop=new THREE.Mesh(new THREE.BoxGeometry(6.4,0.16,3.2),new THREE.MeshStandardMaterial({color:0x6b4a2b,roughness:0.6}));
tableTop.position.y=TABLE_H; scene.add(tableTop);
[[2.9,1.4],[-2.9,1.4],[2.9,-1.4],[-2.9,-1.4]].forEach(function(p){
const leg=new THREE.Mesh(new THREE.CylinderGeometry(0.11,0.11,TABLE_H,12),new THREE.MeshStandardMaterial({color:0x4a3220}));
leg.position.set(p[0],TABLE_H/2,p[1]); scene.add(leg);
});
const rec=new THREE.Mesh(new THREE.BoxGeometry(0.5,0.12,0.28),new THREE.MeshStandardMaterial({color:0xd21f1f,emissive:0x330000,roughness:0.4}));
rec.position.set(0,TABLE_H+0.14,0); scene.add(rec);
const recLbl=makeLabel("🔴 KAYIT","#ff6666",0.55); recLbl.position.set(0,TABLE_H+0.55,0); scene.add(recLbl);
const SKIN=0xe8b98c, chars={};
function makeChar(role){
const p=POS3D[role], col=new THREE.Color(ROLES[role].renk);
const grp=new THREE.Group();
const cloth=new THREE.MeshStandardMaterial({color:col,roughness:0.7});
const skin=new THREE.MeshStandardMaterial({color:SKIN,roughness:0.6});
const hair=new THREE.MeshStandardMaterial({color:0x2a2018,roughness:0.9});
let headY;
if(p.stand){
const legL=new THREE.Mesh(new THREE.CylinderGeometry(0.1,0.1,0.85,10),cloth); legL.position.set(-0.13,0.42,0);
const legR=legL.clone(); legR.position.x=0.13; grp.add(legL,legR);
const torso=new THREE.Mesh(new THREE.CylinderGeometry(0.22,0.32,0.85,14),cloth); torso.position.y=1.28; grp.add(torso);
const head=new THREE.Mesh(new THREE.SphereGeometry(0.19,20,20),skin); head.position.y=1.86; grp.add(head);
const h=new THREE.Mesh(new THREE.SphereGeometry(0.205,18,18,0,Math.PI*2,0,Math.PI*0.62),hair); h.position.y=1.9; grp.add(h);
headY=1.86;
} else {
const seat=new THREE.Mesh(new THREE.BoxGeometry(0.56,0.1,0.56),new THREE.MeshStandardMaterial({color:0x394150,roughness:0.8}));
seat.position.set(0,0.5,-0.08); grp.add(seat);
const back=new THREE.Mesh(new THREE.BoxGeometry(0.56,0.62,0.08),new THREE.MeshStandardMaterial({color:0x394150,roughness:0.8}));
back.position.set(0,0.8,-0.34); grp.add(back);
const thigh=new THREE.Mesh(new THREE.BoxGeometry(0.34,0.14,0.42),cloth); thigh.position.set(0,0.6,0.14); grp.add(thigh);
const shinL=new THREE.Mesh(new THREE.CylinderGeometry(0.08,0.08,0.5,10),cloth); shinL.position.set(-0.12,0.3,0.32); grp.add(shinL);
const shinR=shinL.clone(); shinR.position.x=0.12; grp.add(shinR);
const torso=new THREE.Mesh(new THREE.CylinderGeometry(0.2,0.3,0.62,14),cloth); torso.position.y=0.98; grp.add(torso);
const head=new THREE.Mesh(new THREE.SphereGeometry(0.185,20,20),skin); head.position.y=1.44; grp.add(head);
const h=new THREE.Mesh(new THREE.SphereGeometry(0.2,18,18,0,Math.PI*2,0,Math.PI*0.6),hair); h.position.y=1.48; grp.add(h);
headY=1.44;
}
const ring=new THREE.Mesh(new THREE.TorusGeometry(0.55,0.06,10,32),new THREE.MeshStandardMaterial({color:col,emissive:col,emissiveIntensity:1.4}));
ring.rotation.x=-Math.PI/2; ring.position.y=0.04; ring.visible=false; grp.add(ring);
// konuşan kişinin üstünde ampul + ışık
const bulb=new THREE.Mesh(new THREE.SphereGeometry(0.1,16,16),new THREE.MeshStandardMaterial({color:0xfff6c0,emissive:0xffca28,emissiveIntensity:2.2}));
bulb.position.y=headY+1.05; bulb.visible=false; grp.add(bulb);
const halo=new THREE.Mesh(new THREE.SphereGeometry(0.17,16,16),new THREE.MeshBasicMaterial({color:0xffd23a,transparent:true,opacity:0.25}));
halo.position.y=headY+1.05; halo.visible=false; grp.add(halo);
const blight=new THREE.PointLight(0xffd23a,0,4,2); blight.position.set(0,headY+1.0,0); grp.add(blight);
const lbl=makeLabel(SHORT[role],"#"+col.getHexString()); lbl.position.y=headY+0.55; grp.add(lbl);
grp.position.set(p.x,0,p.z); grp.rotation.y=Math.atan2(-p.x,-p.z);
scene.add(grp); chars[role]={grp:grp,ring:ring,bulb:bulb,halo:halo,blight:blight,active:false};
}
Object.keys(POS3D).forEach(makeChar);
// ---- audio + timeline ----
const ao=document.getElementById('ao'), at=document.getElementById('at');
let mode='orig';
const TL_TR=MEET.TL_tr||null;
if(MEET.trAudio){ at.src=MEET.trAudio+'?v=20260704d'; }
function TR_READY(){ return !!MEET.trAudio && !!TL_TR && !window.TR_AUDIO_FAILED; }
function A(){ return (mode==='tr'&&TR_READY())?at:ao; }
function curTL(){ return (mode==='tr'&&TR_READY())?TL_TR:TL; }
const lr=document.getElementById('legendRows');
Object.keys(POS3D).forEach(function(r){
const d=document.createElement('div'); d.className='row';
d.innerHTML='<span class="dot" style="background:'+ROLES[r].renk+'"></span>'+SHORT[r]+(POS3D[r].stand?' <span style="color:#8b949e">(ayakta)</span>':'');
lr.appendChild(d);
});
const tl=document.getElementById('tl'), tg=tl.getContext('2d');
function curDur(){ const d=A().duration, T=curTL(); return (Number.isFinite(d)&&d>0) ? d : T[T.length-1].e; }
function fitTL(){ tl.width=tl.clientWidth*devicePixelRatio; tl.height=34*devicePixelRatio; tg.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0); drawTL(); }
function drawTL(){
const T=curTL(), dur=curDur(), W=tl.clientWidth, H=34;
tg.clearRect(0,0,W,H);
tg.fillStyle="#21262d"; roundRect(tg,0,11,W,12,6); tg.fill();
tg.globalAlpha=0.85;
T.forEach(function(b){ const x=b.t/dur*W, w=Math.max(1,(b.e-b.t)/dur*W); tg.fillStyle=(ROLES[b.rol]&&ROLES[b.rol].renk)||"#888"; tg.fillRect(x,11,w,12); });
tg.globalAlpha=1;
const ph=(A().currentTime/dur)*W; tg.fillStyle="#fff"; tg.fillRect(ph-1,6,2,22); tg.beginPath(); tg.arc(ph,6,4,0,7); tg.fill();
}
function seekAtClientX(clientX){ const r=tl.getBoundingClientRect(); const x=(clientX-r.left)/r.width; const a=A(); a.currentTime=Math.max(0,Math.min(1,x))*curDur(); update(); }
let drag=false;
tl.addEventListener('mousedown',function(e){drag=true;seekAtClientX(e.clientX);});
addEventListener('mousemove',function(e){if(drag)seekAtClientX(e.clientX);});
addEventListener('mouseup',function(){drag=false;});
tl.addEventListener('touchstart',function(e){drag=true;seekAtClientX(e.touches[0].clientX);e.preventDefault();},{passive:false});
addEventListener('touchmove',function(e){if(drag){seekAtClientX(e.touches[0].clientX);e.preventDefault();}},{passive:false});
addEventListener('touchend',function(){drag=false;});
function curIndex(){
const t=A().currentTime, T=curTL();
if(t<T[0].t) return -1;
let ans=0;
for(let i=0;i<T.length;i++){ if(T[i].t<=t) ans=i; else break; }
return ans;
}
let lastRole=null;
function highlight(role){ if(role===lastRole)return; lastRole=role; for(const r in chars){ const on=(r===role); chars[r].active=on; chars[r].ring.visible=on; chars[r].bulb.visible=on; chars[r].halo.visible=on; if(!on)chars[r].blight.intensity=0; } }
const fmt=function(s){s=Math.max(0,s|0);return String(s/60|0).padStart(2,'0')+':'+String(s%60).padStart(2,'0');};
const sub=document.getElementById('subtitle'),sW=document.getElementById('subWho'),sO=document.getElementById('subOrig'),sT=document.getElementById('subTr');
function update(){
const a=A(), T=curTL(), dur=curDur();
document.getElementById('time').textContent=fmt(a.currentTime)+' / '+fmt(dur);
const i=curIndex();
if(i>=0){ const b=T[i]; highlight(b.rol);
let badge=(mode==='tr'&&!TR_READY())?' <span class="badge">ses hazırlanıyor</span>':'';
sW.innerHTML=(SHORT[b.rol]||b.rol)+badge; sW.style.color=(ROLES[b.rol]&&ROLES[b.rol].renk)||'#fff';
sO.textContent=b.orig; sT.textContent=b.tr; sub.style.opacity=1;
} else { highlight(null); sub.style.opacity=.6; }
drawTL();
}
ao.addEventListener('timeupdate',function(){if(mode==='orig'||!TR_READY())update();});
at.addEventListener('timeupdate',function(){if(mode==='tr'&&TR_READY())update();});
ao.addEventListener('loadedmetadata',function(){fitTL();update();});
at.addEventListener('loadedmetadata',function(){if(mode==='tr')fitTL();});
const playBtn=document.getElementById('play');
playBtn.onclick=function(){ const a=A(); if(a.paused){a.play();playBtn.textContent='⏸';}else{a.pause();playBtn.textContent='▶';} };
document.getElementById('prev').onclick=function(){ const T=curTL(); let i=curIndex(); const a=A(); if(i>0&&a.currentTime-T[i].t<0.4)i--; a.currentTime=T[Math.max(0,i)].t; update(); };
document.getElementById('next').onclick=function(){ const T=curTL(); let i=curIndex(); const a=A(); a.currentTime=T[Math.min(T.length-1,i+1)].t; update(); };
document.addEventListener('keydown',function(e){ if(e.code==='Space'){e.preventDefault();playBtn.onclick();} if(e.code==='ArrowRight')A().currentTime+=5; if(e.code==='ArrowLeft')A().currentTime-=5; });
document.getElementById('langToggle').addEventListener('click',function(e){
const btn=e.target.closest('button'); if(!btn)return; const m=btn.dataset.m; if(m===mode)return;
[].forEach.call(e.currentTarget.children,function(b){ b.classList.toggle('on',b===btn); b.classList.toggle('trm',b===btn&&m==='tr'); });
const wasPlaying=!A().paused; const idx=curIndex(); A().pause();
mode=m; sub.classList.toggle('trmode',m==='tr');
const T=curTL(); const b=T[Math.max(0,idx)]; if(b)A().currentTime=b.t;
fitTL(); update(); if(wasPlaying){A().play();playBtn.textContent='⏸';}
});
renderer.domElement.addEventListener('dblclick',function(ev){
const rc=new THREE.Raycaster(), m=new THREE.Vector2((ev.clientX/innerWidth)*2-1,-(ev.clientY/innerHeight)*2+1);
rc.setFromCamera(m,camera);
const gs=Object.keys(chars).map(function(r){return chars[r].grp;});
const hit=rc.intersectObjects(gs,true)[0]; if(!hit)return;
let g=hit.object; while(g.parent&&gs.indexOf(g)<0)g=g.parent;
const role=Object.keys(chars).find(function(r){return chars[r].grp===g;});
const T=curTL(), b=T.find(function(x){return x.rol===role;}); if(b){A().currentTime=b.t;update();}
});
function loop(){
requestAnimationFrame(loop);
const t=performance.now()/1000;
for(const r in chars){ const c=chars[r];
if(c.active){ c.grp.position.y=Math.sin(t*4)*0.04; c.ring.rotation.z+=0.02; c.ring.material.emissiveIntensity=1.1+Math.sin(t*6)*0.5;
c.bulb.material.emissiveIntensity=1.6+Math.sin(t*6)*0.9; c.blight.intensity=1.4+Math.sin(t*6)*0.9;
c.halo.material.opacity=0.22+Math.sin(t*6)*0.12; c.halo.scale.setScalar(1+Math.sin(t*6)*0.12); }
else if(c.grp.position.y!==0){ c.grp.position.y*=0.85; if(Math.abs(c.grp.position.y)<0.002)c.grp.position.y=0; }
}
controls.update(); renderer.render(scene,camera);
}
loop();
addEventListener('resize',function(){ fitCamera(); renderer.setSize(innerWidth,innerHeight); fitTL(); });
fitTL();
</script>
</body>
</html>