Files
shooting-event/live Score.html

1012 lines
66 KiB
HTML
Raw Normal View History

2026-03-31 12:49:43 +04:00
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>بطولة دويتوايلر للرماية - Tracker</title>
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Cairo:wght@400;600;700;800&family=DM+Mono:wght@400;500;600;800&display=swap" rel="stylesheet">
<style>
:root {
--navy: #1B1F40;
--red: #EC2F23;
--teal: #008CA8;
--white: #FFFFFF;
--bg:#F5F6FA;--surface:#FFFFFF;--card:#FFFFFF;--border:#D8DCE8;
--accent:var(--red);--gold:#D4920A;--silver:#6B7A99;--bronze:#CD7F32;
--green:#00956A;
--text:var(--navy);--muted:#6B7A99;
--ga:var(--navy);--ga-l:rgba(27,31,64,.08);
--gb:var(--teal);--gb-l:rgba(0,140,168,.08);
--gc:var(--red);--gc-l:rgba(236,47,35,.07);
--gd:#D4920A;--gd-l:rgba(212,146,10,.08);
}
*{box-sizing:border-box;margin:0;padding:0;}
body{background:#F0F2F8;color:var(--text);font-family:'Cairo', sans-serif;font-size:16px;min-height:100vh;}
.masthead{background:#FFFFFF;border-bottom:none;padding:0;position:relative;overflow:hidden;box-shadow:0 2px 20px rgba(13,27,46,.08);}
.masthead::before{content:"";position:absolute;bottom:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--navy) 0%,var(--navy) 33%,var(--teal) 33%,var(--teal) 66%,var(--red) 66%,var(--red) 100%);}
@keyframes pulseDot{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(1.4)}}
@keyframes fadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.masthead-title{font-family:'Cairo',sans-serif;font-size:46px;letter-spacing:1px;color:var(--navy);line-height:1; font-weight: 800;}
.masthead-sub{color:#5A6280;font-size:16px;letter-spacing:1px;text-transform:uppercase;margin-top:8px;font-weight:700;}
.tab-bar{display:flex;background:var(--navy);border-bottom:none;padding:0;overflow-x:auto;position:sticky;top:0;z-index:100;box-shadow:0 4px 16px rgba(27,31,64,.25);}
.tab{flex:1;padding:18px 14px;cursor:pointer;font-size:14px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:rgba(255,255,255,.5);border-bottom:3px solid transparent;border-right:1px solid rgba(255,255,255,.08);white-space:nowrap;transition:all .2s;background:none;border-top:none;border-left:none;text-align:center;font-family:'Cairo',sans-serif;}
.tab:hover{color:#ffffff;background:rgba(255,255,255,.08);}
.tab.active{color:#ffffff;border-bottom:3px solid var(--red);font-weight:700;background:rgba(236,47,35,.15);}
.panel{display:none;padding:32px 32px 64px;animation:fadeIn .25s ease;background:#F0F2F8;}
.panel.active{display:block;}
.sec-title{font-family:'Cairo',sans-serif;font-size:32px;font-weight:800;color:var(--navy);margin-bottom:6px;padding-bottom:10px;border-bottom:3px solid var(--navy);display:inline-block;}
.sec-sub{color:#6B7A99;font-size:15px;margin-bottom:20px;font-family:'Cairo',sans-serif; font-weight:600;}
.tbl-wrap{overflow-x:auto;border-radius:12px;border:2px solid #C8CCD8;margin-bottom:28px;box-shadow:0 4px 16px rgba(27,31,64,.10);background:#FFFFFF;}
table{width:100%;border-collapse:collapse;}
thead tr{background:var(--navy);}
thead th{padding:14px 16px;font-size:12px;text-transform:uppercase;letter-spacing:1px;color:#7AAAD8;font-weight:700;text-align:center;border-left:1px solid rgba(255,255,255,.12);white-space:nowrap;font-family:'Cairo',sans-serif;}
thead th:last-child{border-left:none;}
tbody tr{border-bottom:1px solid #D8DCE8;transition:background .15s;}
tbody tr:last-child{border-bottom:none;}
tbody tr:hover{background:#F5F7FF;}
tbody td{padding:13px 16px;text-align:center;border-left:1px solid #D8DCE8;vertical-align:middle;white-space:nowrap;color:var(--text);}
tbody td:last-child{border-left:none;}
.competitor-cell { display:flex; align-items:center; gap:20px; justify-content:flex-start; }
.competitor-img { width: 84px; height: 84px; border-radius: 50%; object-fit: cover; border: 3px solid #E2E6EF; background: #F0F2F8; flex-shrink: 0; transition: transform 0.2s; box-shadow: 0 4px 12px rgba(0,0,0,0.08);}
.clickable-img { cursor: pointer; border-color: var(--teal); }
.clickable-img:hover { transform: scale(1.05); box-shadow: 0 6px 16px rgba(0,140,168,.3); }
.editable-name { border: 1px dashed transparent; padding: 4px 8px; border-radius: 6px; transition: all 0.2s; outline: none; display: inline-block; min-width: 60px;}
.editable-name:hover { border-color: #B8C8E8; background: #F8FAFC; cursor: text; }
.editable-name:focus { border-color: var(--teal); background: #FFF; box-shadow: 0 0 0 3px rgba(0,140,168,.1); }
.td-name{text-align:right;font-weight:800;font-size:20px;white-space:nowrap;font-family:'Cairo',sans-serif;}
.td-en{text-align:left;color:var(--text);font-family:'DM Mono',monospace;font-size:15px;font-weight:600;white-space:nowrap; direction:ltr; display:inline-block;}
.td-num{font-family:'DM Mono',monospace;font-weight:600;font-size:15px;color:#6B7A99;}
.td-total{font-weight:800;font-size:18px;color:var(--text);font-family:'DM Mono',monospace;}
.td-rank{font-family:'Bebas Neue',monospace;font-size:24px;color:#D4920A;}
.grp-hdr td{font-family:'Cairo',sans-serif;font-size:18px;font-weight:800;letter-spacing:1px;padding:12px 18px;text-align:right!important;color:#fff!important;}
.grp-sep td{padding:6px;background:#F0F2F8!important;border:none!important;}
.grp-a td{background:var(--navy);border-left-color:rgba(255,255,255,.15)!important;}
.grp-b td{background:var(--teal);border-left-color:rgba(255,255,255,.15)!important;}
.grp-c td{background:var(--red);border-left-color:rgba(255,255,255,.15)!important;}
.grp-d td{background:#D4920A;border-left-color:rgba(255,255,255,.15)!important;}
.ga-row{background:rgba(27,31,64,.04);}
.gb-row{background:rgba(0,140,168,.04);}
.gc-row{background:rgba(236,47,35,.03);}
.gd-row{background:rgba(212,146,10,.04);}
.medal-qualify{background:linear-gradient(-90deg,rgba(0,149,106,.08),transparent);}
.medal-icon{font-size:22px;text-align:center;}
.q-badge{display:inline-block;background:rgba(0,140,168,.1);border:1.5px solid var(--teal);color:var(--teal);border-radius:20px;padding:3px 12px;font-size:12px;font-weight:700;letter-spacing:.5px;}
.no-q{color:#A0AABC;font-size:14px;}
.grp-pill{display:inline-block;font-family:'Bebas Neue',sans-serif;font-size:20px;letter-spacing:1px;padding:3px 16px;border-radius:20px;}
.pill-a{background:var(--navy);color:#fff;}.pill-b{background:var(--teal);color:#fff;}.pill-c{background:var(--red);color:#fff;}.pill-d{background:#D4920A;color:#fff;}
.summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:16px;margin-bottom:32px;}
.sum-card{background:#FFFFFF;border:2px solid #D8DCE8;border-radius:16px;padding:24px 16px 20px;text-align:center;box-shadow:0 4px 16px rgba(27,31,64,.10);transition:all .2s;}.sum-card:hover{transform:translateY(-4px);box-shadow:0 10px 32px rgba(27,31,64,.16);}
.sum-card .big{font-family:'Bebas Neue',sans-serif;font-size:56px;line-height:1;}
.sum-card .lbl{font-size:12px;color:#6B7A99;text-transform:uppercase;letter-spacing:1px;margin-top:8px;font-family:'Cairo',sans-serif;font-weight:700;}
.sum-card .st{font-size:14px;margin-top:8px;font-weight:700;}
.sum-card.ca{background:rgba(27,31,64,.04);border-top:5px solid var(--navy);}.sum-card.ca .big{color:var(--navy);}.sum-card.cb{background:rgba(0,140,168,.04);border-top:5px solid var(--teal);}.sum-card.cb .big{color:var(--teal);}.sum-card.cc{background:rgba(236,47,35,.04);border-top:5px solid var(--red);}.sum-card.cc .big{color:var(--red);}.sum-card.cd{background:rgba(212,146,10,.04);border-top:5px solid #D4920A;}.sum-card.cd .big{color:#D4920A;}.sum-card.cu{background:rgba(27,31,64,.04);border-top:5px solid #B0B8CC;}.sum-card.cu .big{color:#8896B0;}
.st-ok{color:#007A60;font-weight:700;font-size:14px;}.st-warn{color:var(--red);font-weight:700;font-size:14px;}
.tie-info{background:#FFF5F6;border:1px solid rgba(236,47,35,.2);border-radius:10px;padding:16px 22px;margin-bottom:24px;font-size:15px;color:var(--red);line-height:1.8;}
.info-note{background:#F0FBFD;border-right:5px solid var(--teal);padding:14px 18px;border-radius:10px 0 0 10px;font-size:15px;color:var(--navy);margin-bottom:22px;font-weight:600;}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:24px;}
@media(max-width:700px){.two-col{grid-template-columns:1fr;}}
.sub-hdr{font-family:'Cairo',sans-serif;font-weight:800;letter-spacing:1px;font-size:20px;margin-bottom:12px;}
.grp-select{background:#FFFFFF;color:var(--text);border:1.5px solid #C8D8F0;border-radius:7px;padding:6px 10px;font-family:'Cairo',sans-serif;font-size:14px;font-weight:700;cursor:pointer;outline:none;transition:border-color .2s;}
.grp-select:focus{border-color:var(--teal);}
.grp-select.sel-a{background:var(--navy);color:#fff;border-color:var(--navy);}
.grp-select.sel-b{background:var(--teal);color:#fff;border-color:var(--teal);}
.grp-select.sel-c{background:var(--red);color:#fff;border-color:var(--red);}
.grp-select.sel-d{background:#D4920A;color:#fff;border-color:#D4920A;}
.btn-reset{background:#FFF8F8;border:2px solid var(--red);color:var(--red);border-radius:8px;padding:9px 22px;font-size:14px;font-weight:700;cursor:pointer;letter-spacing:0.5px;transition:all .2s;font-family:'Cairo',sans-serif;}
.btn-reset:hover{background:#FFE8EB;}
.btn-row{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:16px;align-items:center;}
.btn-set{background:#F0FBFD;border:2px solid var(--teal);color:var(--teal);border-radius:8px;padding:9px 22px;font-size:14px;font-weight:700;cursor:pointer;letter-spacing:0.5px;transition:all .2s;font-family:'Cairo',sans-serif;}
.btn-set:hover{background:#E0F5EE;border-color:#00956A; color:#00956A;}
.btn-save{background:var(--teal);color:#fff;border:2px solid var(--teal);border-radius:8px;padding:9px 22px;font-size:14px;font-weight:700;cursor:pointer;letter-spacing:0.5px;transition:all .2s;font-family:'Cairo',sans-serif; box-shadow: 0 4px 10px rgba(0,140,168,0.2);}
.btn-save:hover{background:#007A94;border-color:#007A94; transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0,140,168,0.3);}
.btn-lock { background: var(--navy); color: #fff; border: 2px solid var(--navy); border-radius: 8px; padding: 9px 22px; font-size: 14px; font-weight: 700; cursor: pointer; transition: all .2s; font-family: 'Cairo', sans-serif;}
.btn-lock:hover { background: #0E132B; border-color: #0E132B; }
.btn-unlock { background: #FFFDF5; border: 2px solid #D4920A; color: #D4920A; border-radius: 8px; padding: 9px 22px; font-size: 14px; font-weight: 700; cursor: pointer; transition: all .2s; font-family: 'Cairo', sans-serif; }
.btn-unlock:hover { background: #FFF8E6; }
.score-input{width:62px;background:#F0FBFD;color:#007A94;font-family:'DM Mono',monospace;font-weight:700;font-size:16px;border:1.5px solid var(--teal);border-radius:6px;padding:5px 8px;text-align:center;outline:none;transition:all .2s;}
.score-input:focus{border-color:var(--teal);background:rgba(0,140,168,.15);box-shadow:0 0 0 3px rgba(0,140,168,.15);}
.score-input.invalid{border-color:var(--red);background:rgba(236,47,35,.12);color:var(--red);}
.score-input:disabled { background: #E2E6EF; color: #6B7A99; border-color: #C8CCD8; cursor: not-allowed; box-shadow: none; }
.tb-none{background:#F0FBF7;border:1.5px solid #00956A;border-radius:10px;padding:18px 24px;color:#00956A;font-size:16px;font-weight:700;margin-bottom:20px;}
.tb-group-title{font-family:'Cairo',sans-serif;font-weight:800;font-size:20px;margin:22px 0 12px;color:var(--navy);}
.tb-tied-score{background:#FFF0F2;border:1px solid rgba(236,47,35,.3);border-radius:6px;padding:4px 12px;font-family:'DM Mono',monospace;font-size:14px;color:var(--red);margin-right:10px;}
/* --- PROFESSIONAL PODIUM CSS --- */
.podium-wrapper { display: flex; justify-content: center; align-items: flex-end; height: 380px; margin-top: 100px; gap: 15px; padding: 0 20px; direction: ltr;}
.podium-col { flex: 1; max-width: 280px; display: flex; flex-direction: column; align-items: center; position: relative; background: #fff; border-radius: 16px 16px 0 0; box-shadow: 0 10px 40px rgba(13,27,46,0.1); transition: transform 0.3s ease; }
.podium-col:hover { transform: translateY(-5px); }
.podium-col.pos-1 { height: 320px; border-top: 8px solid #D4AF37; background: linear-gradient(180deg, #FFFAF0 0%, #FFFFFF 100%); z-index: 3; box-shadow: 0 15px 50px rgba(212, 175, 55, 0.2); }
.podium-col.pos-2 { height: 240px; border-top: 8px solid #C0C0C0; background: linear-gradient(180deg, #F8F9FA 0%, #FFFFFF 100%); z-index: 2; }
.podium-col.pos-3 { height: 180px; border-top: 8px solid #CD7F32; background: linear-gradient(180deg, #FFF5E6 0%, #FFFFFF 100%); z-index: 1; }
.podium-avatar-wrap { position: absolute; top: -65px; left: 50%; transform: translateX(-50%); }
.podium-col.pos-1 .podium-avatar-wrap { top: -85px; }
.podium-img { width: 120px; height: 120px; border-radius: 50%; object-fit: cover; border: 5px solid #fff; box-shadow: 0 8px 24px rgba(0,0,0,0.12); background: #F0F2F8; }
.podium-col.pos-1 .podium-img { width: 160px; height: 160px; border: 6px solid #D4AF37; box-shadow: 0 12px 30px rgba(212, 175, 55, 0.3);}
.podium-col.pos-2 .podium-img { border-color: #C0C0C0; }
.podium-col.pos-3 .podium-img { border-color: #CD7F32; }
.podium-medal-icon { font-size: 46px; margin-top: 65px; line-height: 1; }
.podium-col.pos-1 .podium-medal-icon { font-size: 64px; margin-top: 85px; }
.podium-name { font-family: 'Cairo', sans-serif; font-size: 24px; font-weight: 800; color: var(--navy); margin-top: 10px; text-align: center; line-height: 1.2; padding: 0 10px;}
.podium-col.pos-1 .podium-name { font-size: 28px; }
.podium-name.empty { color: #8896B0; font-weight: 600; font-size: 20px; }
.podium-score { margin-top: auto; margin-bottom: 25px; background: rgba(0,0,0,0.04); padding: 8px 20px; border-radius: 20px; font-family: 'DM Mono', monospace; font-size: 20px; font-weight: 700; color: var(--red); border: 1px solid rgba(0,0,0,0.05); }
/* --- AUTH MODAL CSS --- */
.auth-overlay { position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(13,27,46,0.6); display:none; align-items:center; justify-content:center; z-index:999; backdrop-filter:blur(4px); }
.auth-box { background:#fff; padding:32px; border-radius:16px; width:340px; box-shadow:0 10px 40px rgba(0,0,0,0.2); text-align:center; animation:fadeIn 0.2s ease; border-top: 6px solid var(--red); }
.auth-input { width:100%; background:#F0F2F8; border:2px solid #D8DCE8; border-radius:8px; padding:10px 14px; font-family:'Cairo', sans-serif; font-size:16px; font-weight:600; margin-bottom:12px; outline:none; transition: border-color 0.2s; }
.auth-input:focus { border-color: var(--teal); background: #fff; }
/* --- TOAST NOTIFICATION CSS --- */
.toast-notification {
visibility: hidden;
min-width: 250px;
background-color: var(--green);
color: white;
text-align: center;
border-radius: 8px;
padding: 16px 24px;
position: fixed;
z-index: 1000;
left: 50%;
bottom: 30px;
transform: translateX(-50%);
font-family: 'Cairo', sans-serif;
font-weight: 700;
font-size: 16px;
box-shadow: 0 8px 24px rgba(0,149,106,0.3);
opacity: 0;
transition: opacity 0.3s, bottom 0.3s, visibility 0.3s;
}
.toast-notification.show {
visibility: visible;
opacity: 1;
bottom: 50px;
}
/* --- AIRPORT SCREEN (LIVE GROUPS) CSS --- */
#live-groups.panel {
padding: 0;
background: #0d1226;
min-height: 80vh;
display: none;
flex-direction: column;
position: relative;
}
#live-groups.panel.active {
display: flex;
}
.lg-container {
flex: 1;
display: flex;
flex-direction: column;
padding: 3vh 3vw;
box-sizing: border-box;
justify-content: center;
}
.lg-header {
text-align: center;
font-size: 36px;
font-family: 'Cairo', sans-serif;
font-weight: 800;
letter-spacing: 1px;
margin-bottom: 30px;
color: #D4AF37;
text-shadow: 0 2px 10px rgba(0,0,0,0.6);
}
.lg-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
align-content: center;
}
.lg-card {
background: rgba(255,255,255,0.08);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 12px;
display: flex;
align-items: center;
padding: 15px;
gap: 20px;
}
.lg-card img {
width: 90px;
height: 90px;
border-radius: 50%;
border: 3px solid var(--teal);
object-fit: cover;
flex-shrink: 0;
}
.lg-info { display: flex; flex-direction: column; justify-content: center;}
.lg-num { font-family: 'DM Mono', monospace; font-size: 16px; color: var(--teal); font-weight: 700; margin-bottom: 4px; line-height: 1; }
.lg-name { font-family: 'Cairo', sans-serif; font-size: 24px; font-weight: 800; color: white; line-height: 1.2; margin-bottom: 4px;}
.lg-name-en { font-family: 'DM Mono', monospace; font-size: 14px; color: #8896B0; text-transform: uppercase; letter-spacing: 1px; line-height: 1;}
.lg-empty { grid-column: 1 / -1; text-align: center; color: #8896B0; font-size: 28px; margin-top: 10vh; font-family: 'Cairo', sans-serif; }
.lg-progress-bar {
position: absolute;
bottom: 0;
left: 0;
height: 6px;
background: var(--red);
width: 0%;
box-shadow: 0 0 10px var(--red);
}
@keyframes cardIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.run-progress {
animation: loadProgress 5s linear infinite;
}
@keyframes loadProgress {
0% { width: 0%; }
100% { width: 100%; }
}
</style>
</head>
<body>
<input type="file" id="image-uploader" accept="image/*" style="display:none;">
<div id="toast" class="toast-notification">✓ تم حفظ بنجاح!</div>
<div id="auth-modal" class="auth-overlay">
<div class="auth-box">
<h3 style="color:var(--navy); margin-bottom:6px; font-family:'Cairo',sans-serif; font-size:24px; font-weight:800;">صلاحية الإدارة</h3>
<p style="color:var(--muted); font-size:14px; margin-bottom:20px; font-weight:600;">يرجى إدخال بيانات الدخول للتأكيد</p>
<input type="text" id="auth-user" placeholder="اسم المستخدم (admin)" class="auth-input">
<input type="password" id="auth-pass" placeholder="كلمة المرور (12345)" class="auth-input" style="margin-bottom:16px;">
<div style="color:var(--red); font-size:14px; font-weight:700; margin-bottom:16px; display:none;" id="auth-error">بيانات الدخول غير صحيحة!</div>
<div style="display:flex; gap:12px;">
<button class="btn-set" onclick="confirmAuth()" style="flex:1; padding:10px; font-size:16px;">تأكيد</button>
<button class="btn-reset" onclick="closeAuth()" style="flex:1; padding:10px; font-size:16px; color:#6B7A99; border-color:#C8CCD8;">إلغاء</button>
</div>
</div>
</div>
<div class="masthead">
<div style="display:flex;align-items:flex-start;justify-content:space-between;padding:20px 40px 22px;position:relative;">
<div style="display:flex;flex-direction:column;gap:4px;margin-top:10px; align-items: flex-start;">
<div class="masthead-title">بطولة دويتوايلر للرماية</div>
<div class="masthead-sub" style="font-size:16px;">فئة المسدس · مسافات: 15م ← 20م ← 25م</div>
<div style="margin-top:14px;width:140px;">
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 455.88 86.28"><defs><style>.dtw-1 { fill: #eb3229; }.dtw-2 { fill: #448293; }</style></defs><g id="Layer_1-2" data-name="Layer 1"><polygon class="dtw-2" points="45.08 0 45.2 0 76.12 31.62 73.31 34.51 42.3 2.88 45.08 0"/><path class="dtw-1" d="M311.21,64.43v-15.95s-15.29-25.65-15.29-25.65l-13.64,41.91-10.09.02-3.61-10.5-4.22-12.31-.07-.19-.43-1.27c.02-.17-.05-.27-.15-.06l-8.29,24.34h-10.1s-13.96-42.89-13.96-42.89l12.23-.04,7.29,24.6,8-24.55c.05-.17.19-.15.33-.16h9.7s7.91,24.34,7.91,24.34c.03.28.1.42.23.11l7.18-24.33,24.29-.02,8.6,15.5,8.52-15.26c.07-.19.18-.23.37-.24h12.27c.14,0,.28-.02.36.06.05.06-.03.16-.11.3l-15.73,26.24c.08.14.06.22.06.32v10.59s0,.25,0,.25v4.41s0,.24,0,.24c0,.06,0,.2-.11.2h-11.54Z"/><path class="dtw-1" d="M445.95,49.59l9.93,14.82-13.35.03-8.42-12.9h-5.06s-.03,12.89-.03,12.89h-11.58s0-42.61,0-42.61h20.3c2.31,0,4.44.31,6.63.89,4.82,1.36,8.67,4.81,9.74,9.8,1.17,5.44.01,11.32-4.53,14.89-1.09.88-2.21,1.52-3.63,2.18ZM442.9,36.99c-.05-1.99-1.04-3.63-2.86-4.33-.97-.43-2.01-.55-3.1-.6h-7.89s0,10.21,0,10.21h7.77c3.27,0,6.17-1.56,6.08-5.27Z"/><path class="dtw-1" d="M150.4,48.9c-1.95,7.71-7.93,12.8-15.45,14.66-2.28.53-4.48.86-6.86.87h-16.67s0-42.59,0-42.59h16.55c2.51,0,4.84.3,7.24.87,7.37,1.78,13.23,6.7,15.16,14.18,1.01,3.93,1.05,8.01.03,12.02ZM138.82,39.71c-.74-2.87-2.69-5.1-5.38-6.3-1.66-.72-3.38-1.1-5.22-1.1h-5.2s0,21.63,0,21.63h5.32c1.79,0,3.47-.39,5.09-1.09,5.21-2.23,6.7-8.08,5.38-13.15Z"/><path class="dtw-1" d="M409.65,47.64h-20.06s0,6.75,0,6.75h22.44s0,10.05,0,10.05h-33.91s0-42.6,0-42.6h33.59s.01,10.04.01,10.04h-22.15s0,6.24,0,6.24c0,.15.1.21.26.2h19.8s0,9.32,0,9.32Z"/><polygon class="dtw-1" points="197.02 64.4 184.63 64.45 181.58 56.84 165.46 56.83 162.46 64.45 150.3 64.41 161.97 36.24 173.28 36.25 168.88 47.63 178.21 47.63 173.86 36.25 185.36 36.24 197.02 64.4"/><polygon class="dtw-1" points="217.03 64.41 205.44 64.45 205.44 32.19 192.9 32.18 192.91 21.82 229.56 21.82 229.56 32.18 217.02 32.19 217.03 64.41"/><polygon class="dtw-1" points="373.64 54.08 373.66 64.43 341.84 64.42 341.83 21.83 353.42 21.84 353.41 54.07 373.64 54.08"/><polygon class="dtw-2" points="42.27 83.36 39.48 86.28 0 46.02 2.82 43.13 42.27 83.36"/><polygon class="dtw-2" points="90.24 46.01 59.24 77.63 56.39 74.77 87.4 43.14 90.24 46.01"/><polygon class="dtw-1" points="183.64 32.17 163.66 32.19 168.07 21.52 179.26 21.52 183.64 32.17"/><polygon class="dtw-1" points="76.12 48.88 47.94 20.14 50.75 17.25 78.95 45.99 76.12 48.88"/><polygon class="dtw-1" points="62.04 46.01 42.31 25.91 45.12 23.01 64.85 43.12 62.04 46.01"/><polygon class="dtw-1" points="45.13 80.5 42.29 77.64 62.03 57.51 64.85 60.4 45.13 80.5"/><polygon class="dtw-2" points="22.58 40.24 19.73 37.39 39.47 17.26 42.29 20.14 22.58 40.24"/><polygon class="dtw-2" points="28.21 23 25.37 20.12 39.47 5.75 42.3 8.62 28.21 23"/><polygon class="dtw-2" points="14.09 48.89 5.63 40.27 8.46 37.38 16.91 46 14.09 48.89"/></g></svg>
</div>
</div>
<div style="position:absolute;top:25px;left:40px;display:flex;gap:8px;align-items:center; direction: ltr;">
<div style="width:12px;height:12px;border-radius:50%;background:var(--navy);animation:pulseDot 2s ease-in-out infinite;"></div>
<div style="width:12px;height:12px;border-radius:50%;background:var(--red);animation:pulseDot 2s ease-in-out infinite .5s;"></div>
<div style="width:12px;height:12px;border-radius:50%;background:var(--teal);animation:pulseDot 2s ease-in-out infinite 1s;"></div>
<span style="font-family:'DM Mono',monospace;font-size:16px;font-weight:800;letter-spacing:2px;color:var(--navy);text-transform:uppercase;margin-left:8px;">● LIVE TRACKER</span>
</div>
</div>
</div>
<div class="tab-bar">
<button class="tab active" onclick="show('ga',this)">توزيع المجموعات</button>
<button class="tab" onclick="show('live-groups',this)">📺 عرض المجموعات</button>
<button class="tab" onclick="show('ps',this)">المرحلة التمهيدية</button>
<button class="tab" onclick="show('or',this)">الترتيب العام</button>
<button class="tab" onclick="show('fs',this)">المرحلة النهائية</button>
<button class="tab" onclick="show('tb',this)">كسر التعادل</button>
<button class="tab" onclick="show('podium',this)">🏆 تتويج الأبطال</button>
</div>
<div id="ga" class="panel active">
<div class="sec-title">توزيع المجموعات والتحكم</div>
<div class="sec-sub">توزيع 24 متسابق على 4 مجموعات (A, B, C, D) - 6 لاعبين لكل مجموعة</div>
<div class="info-note">
<strong>إدارة المتسابقين:</strong> انقر على أي اسم لتعديله مباشرة. انقر على صورة المتسابق لرفع صورة جديدة. <strong>يتم الحفظ تلقائياً!</strong>
</div>
<div class="btn-row">
<button class="btn-save" onclick="saveGroupAssignments()">💾 حفظ التوزيع</button>
<button class="btn-reset" onclick="requireAuth(function(){ resetAllGroups(); })">✕ إفراغ المجموعات</button>
<button class="btn-set" onclick="restoreDefaults()">↺ استعادة التوزيع الأصلي</button>
<div style="margin-right:auto; display:flex; gap:12px; flex-wrap:wrap;">
<button class="btn-reset" onclick="requireAuth(function(){ clearSavedNames(); })" style="border-color:#6B7A99; color:#6B7A99; background:#F5F6FA;">🗑️ مسح الأسماء المحفوظة</button>
<button class="btn-reset" onclick="requireAuth(function(){ clearSavedImages(); })" style="border-color:#6B7A99; color:#6B7A99; background:#F5F6FA;">🗑️ مسح الصور المحفوظة</button>
</div>
</div>
<div class="summary-grid">
<div class="sum-card ca"><div class="big" id="cnt-a">0</div><div class="lbl">المجموعة A</div><div class="st" id="st-a"></div></div>
<div class="sum-card cb"><div class="big" id="cnt-b">0</div><div class="lbl">المجموعة B</div><div class="st" id="st-b"></div></div>
<div class="sum-card cc"><div class="big" id="cnt-c">0</div><div class="lbl">المجموعة C</div><div class="st" id="st-c"></div></div>
<div class="sum-card cd"><div class="big" id="cnt-d">0</div><div class="lbl">المجموعة D</div><div class="st" id="st-d"></div></div>
<div class="sum-card cu"><div class="big" id="cnt-u">0</div><div class="lbl">غير معين</div><div class="st" id="st-u"></div></div>
</div>
<div class="tbl-wrap"><table>
<thead><tr><th>الرقم</th><th>صورة واسم المتسابق (انقر للتعديل)</th><th style="text-align:left">الاسم بالإنجليزي (انقر للتعديل)</th><th>المجموعة ▾</th><th>الترتيب بالمجموعة</th></tr></thead>
<tbody id="ga-body"></tbody>
</table></div>
</div>
<div id="live-groups" class="panel">
<div id="lg-container" class="lg-container"></div>
<div id="lg-progress" class="lg-progress-bar"></div>
</div>
<div id="ps" class="panel">
<div class="sec-title">المرحلة التمهيدية</div>
<div class="sec-sub">المسافة: 15 متر · 3 جولات × 10 طلقات · الحد الأقصى 100/جولة · المجموع: 300</div>
<div class="btn-row">
<button class="btn-lock" id="btn-lock-ps" onclick="lockStage('ps')">🔒 حفظ وإقفال النتائج</button>
<button class="btn-unlock" id="btn-unlock-ps" onclick="requireAuth(function(){ unlockStage('ps'); })" style="display:none;">🔓 تعديل النتائج</button>
<button class="btn-reset" onclick="requireAuth(function(){ clearAllScores('ps'); })">✕ مسح جميع النتائج (تصفير)</button>
<button class="btn-set" onclick="undoScores('ps')" id="undo-ps" disabled style="opacity:.4">↩ تراجع</button>
</div>
<div class="tbl-wrap"><table>
<thead><tr><th>الرقم</th><th>اسم المتسابق</th><th style="text-align:left">الاسم بالإنجليزي</th><th>جولة 1</th><th>جولة 2</th><th>جولة 3</th><th>المجموع /300</th><th>ترتيب المجموعة</th></tr></thead>
<tbody id="ps-body"></tbody>
</table></div>
</div>
<div id="or" class="panel">
<div class="sec-title">الترتيب العام</div>
<div class="sec-sub">حساب تلقائي من المرحلة التمهيدية · أفضل 12 يتأهلون للنهائي</div>
<div class="two-col">
<div>
<div class="sub-hdr" style="color:var(--muted)">جميع المتسابقين (24)</div>
<div class="tbl-wrap"><table>
<thead><tr><th>الرقم</th><th>اسم المتسابق</th><th>مجموعة</th><th>النتيجة /300</th><th>الترتيب</th><th>الحالة</th></tr></thead>
<tbody id="or-body"></tbody>
</table></div>
</div>
<div>
<div class="sub-hdr" style="color:var(--teal)">أفضل 12 متأهل للنهائيات</div>
<div class="tbl-wrap"><table>
<thead><tr><th>المركز</th><th>اسم المتسابق</th><th>مجموعة</th><th>النتيجة</th></tr></thead>
<tbody id="top12-body"></tbody>
</table></div>
</div>
</div>
</div>
<div id="fs" class="panel">
<div class="sec-title">المرحلة النهائية</div>
<div class="sec-sub">المسافة: 20 متر · جولتان × 10 طلقات · الحد الأقصى 100/جولة · المجموع: 200</div>
<div class="btn-row">
<button class="btn-lock" id="btn-lock-fs" onclick="lockStage('fs')">🔒 حفظ وإقفال النتائج</button>
<button class="btn-unlock" id="btn-unlock-fs" onclick="requireAuth(function(){ unlockStage('fs'); })" style="display:none;">🔓 تعديل النتائج</button>
<button class="btn-reset" onclick="requireAuth(function(){ clearAllScores('fs'); })">✕ مسح جميع النتائج (تصفير)</button>
<button class="btn-set" onclick="undoScores('fs')" id="undo-fs" disabled style="opacity:.4">↩ تراجع</button>
</div>
<div class="two-col">
<div>
<div class="sub-hdr" style="color:var(--navy)">المجموعة النهائية 1 — تصنيف 1-6</div>
<div class="tbl-wrap"><table>
<thead><tr><th>التصنيف</th><th>اسم المتسابق</th><th>جولة 1</th><th>جولة 2</th><th>المجموع /200</th><th>الترتيب</th></tr></thead>
<tbody id="fg1-body"></tbody>
</table></div>
</div>
<div>
<div class="sub-hdr" style="color:var(--teal)">المجموعة النهائية 2 — تصنيف 7-12</div>
<div class="tbl-wrap"><table>
<thead><tr><th>التصنيف</th><th>اسم المتسابق</th><th>جولة 1</th><th>جولة 2</th><th>المجموع /200</th><th>الترتيب</th></tr></thead>
<tbody id="fg2-body"></tbody>
</table></div>
</div>
</div>
</div>
<div id="tb" class="panel">
<div class="sec-title">مرحلة كسر التعادل</div>
<div class="sec-sub">المسافة: 25 متر · جولة واحدة × 3 طلقات · الحد الأقصى 10/طلقة · المجموع: 30</div>
<div class="tie-info">
<strong>قواعد كسر التعادل:</strong><br>
1. تُطبق فقط عند تعادل لاعبين أو أكثر في المجموع النهائي للبطولة.<br>
2. يقوم المتعادلون برماية <strong>جولة من 3 طلقات</strong> على مسافة <strong>25 متراً</strong>. الفائز هو صاحب المجموع الأعلى (من 30).<br>
3. في حال استمرار التعادل، يتم اللجوء إلى طلقة واحدة (الموت المفاجئ) حتى الحسم.
</div>
<div class="tb-layout">
<div style="position:relative;min-height:200px;">
<div class="btn-row">
<button class="btn-lock" id="btn-lock-tb" onclick="lockStage('tb')">🔒 حفظ وإقفال النتائج</button>
<button class="btn-unlock" id="btn-unlock-tb" onclick="requireAuth(function(){ unlockStage('tb'); })" style="display:none;">🔓 تعديل النتائج</button>
<button class="btn-reset" onclick="requireAuth(function(){ clearAllScores('tb'); })">✕ مسح نتائج التعادل (تصفير)</button>
<button class="btn-set" onclick="undoScores('tb')" id="undo-tb" disabled style="opacity:.4">↩ تراجع</button>
</div>
<div id="tb-status"></div>
<div id="tb-groups"></div>
</div>
</div>
<div style="font-family:'Cairo',sans-serif;font-weight:800;letter-spacing:1px;font-size:22px;color:var(--navy);margin:40px 0 12px;">الترتيب الشامل للنهائيات</div>
<div class="tbl-wrap"><table>
<thead><tr><th>المركز</th><th>اسم المتسابق</th><th>النتيجة النهائية /200</th><th>نتيجة التعادل /30</th><th>الميدالية</th></tr></thead>
<tbody id="tb-ranking-body"></tbody>
</table></div>
</div>
<div id="podium" class="panel">
<div class="sec-title" style="color: var(--gold); border-bottom-color: var(--gold);">تتويج الأبطال</div>
<div class="sec-sub">النتائج النهائية لأصحاب المراكز الثلاثة الأولى في بطولة دويتوايلر للرماية</div>
<div class="podium-wrapper">
<div class="podium-col pos-2">
<div class="podium-avatar-wrap"><img src="" id="pod-img-2" class="podium-img" alt=""></div>
<div class="podium-medal-icon" id="pod-medal-2">🥈</div>
<div class="podium-name empty" id="pod-name-2">— بانتظار النتيجة —</div>
<div class="podium-score" id="pod-score-2">-</div>
</div>
<div class="podium-col pos-1">
<div class="podium-avatar-wrap"><img src="" id="pod-img-1" class="podium-img" alt=""></div>
<div class="podium-medal-icon" id="pod-medal-1">🥇</div>
<div class="podium-name empty" id="pod-name-1">— بانتظار النتيجة —</div>
<div class="podium-score" id="pod-score-1">-</div>
</div>
<div class="podium-col pos-3">
<div class="podium-avatar-wrap"><img src="" id="pod-img-3" class="podium-img" alt=""></div>
<div class="podium-medal-icon" id="pod-medal-3">🥉</div>
<div class="podium-name empty" id="pod-name-3">— بانتظار النتيجة —</div>
<div class="podium-score" id="pod-score-3">-</div>
</div>
</div>
</div>
<script>
const COMPETITORS_BASE=[
[1,"علي العمري","A. AL-OMARI","A"],[2,"عامر المحادين","A. MAHADIN","A"],[3,"علي خليل","A. KHALIL","A"],
[4,"شادي العشي","S. AL-ASHI","A"],[5,"طارق الدويكات","T. AL-DWEIKAT","A"],[6,"حازم العطيات","H. ALATIYYAT","A"],
[7,"علي ابو غزالة","A. ABU GHAZALEH","B"],[8,"فادي الساحوري","F. ALSAHOURI","B"],[9,"احمد ابو صالح","A. ABU SALEH","B"],
[10,"راندي عوده","R. ODEH","B"],[11,"علي الخصاونة","A. KHASAWNEH","B"],[12,"ماهر جالدالله","M. JADALLAH","B"],
[13,"عبدالله الحنيطي","A. HUNEITI","C"],[14,"ايهم الحواتمة","A. HAWATMEH","C"],[15,"معتز الوريكات","M. AL-WREIKAT","C"],
[16,"زيد الجمل","Z. AL-JAMAL","C"],[17,"نسيب وهبه","N. WEHBEH","C"],[18,"محسن العبدلي","M. AL-ABDALI","C"],
[19,"مالك ابو سنينة","M. ABU SNEINEH","D"],[20,"عمر الكيلاني","O. KILANI","D"],[21,"سعادة المراشدة","S. AL-MARASHDEH","D"],
[22,"مطلق الطيب","M. AL-TAYYEB","D"],[23,"محمد الحنيطي","M. HUNEITI","D"],[24,"ابراهيم الشوابكة","I. AL-SHAWABKEH","D"],
];
function showToast(message) {
const toast = document.getElementById("toast");
toast.textContent = message;
toast.className = "toast-notification show";
setTimeout(function() { toast.className = toast.className.replace("show", ""); }, 3000);
}
const ADMIN_USER = "admin";
const ADMIN_PASS = "12345";
let pendingAuthCallback = null;
function requireAuth(callback) {
pendingAuthCallback = callback;
document.getElementById('auth-user').value = "";
document.getElementById('auth-pass').value = "";
document.getElementById('auth-error').style.display = "none";
document.getElementById('auth-modal').style.display = "flex";
document.getElementById('auth-user').focus();
}
function closeAuth() {
document.getElementById('auth-modal').style.display = "none";
pendingAuthCallback = null;
}
function confirmAuth() {
const u = document.getElementById('auth-user').value.trim().toLowerCase();
const p = document.getElementById('auth-pass').value.trim();
if(u === ADMIN_USER.toLowerCase() && p === ADMIN_PASS) {
const callbackToRun = pendingAuthCallback;
closeAuth();
if(callbackToRun) callbackToRun();
} else {
document.getElementById('auth-error').style.display = "block";
}
}
document.getElementById('auth-pass').addEventListener('keypress', function (e) {
if (e.key === 'Enter') confirmAuth();
});
let competitorImages = JSON.parse(localStorage.getItem('dtw_images')) || {};
let customNames = JSON.parse(localStorage.getItem('dtw_names')) || {};
let groupAssign = JSON.parse(localStorage.getItem('dtw_groups'));
if (!groupAssign) { groupAssign = {}; COMPETITORS_BASE.forEach(c => { groupAssign[c[0]] = c[3]; }); }
let scores = JSON.parse(localStorage.getItem('dtw_scores_ps')) || {};
COMPETITORS_BASE.forEach(c => { if(!scores[c[0]]) scores[c[0]] = [0,0,0]; });
let finalScores = JSON.parse(localStorage.getItem('dtw_scores_fs')) || {};
let tbScores = JSON.parse(localStorage.getItem('dtw_scores_tb')) || {};
function saveScoresLocal() {
localStorage.setItem('dtw_scores_ps', JSON.stringify(scores));
localStorage.setItem('dtw_scores_fs', JSON.stringify(finalScores));
localStorage.setItem('dtw_scores_tb', JSON.stringify(tbScores));
}
function lockStage(stage) {
localStorage.setItem('dtw_locked_'+stage, 'true');
showToast("🔒 تم حفظ وإقفال النتائج بنجاح!");
if(stage === 'ps') renderPS();
if(stage === 'fs') renderFS();
if(stage === 'tb') renderFinalMedals();
}
function unlockStage(stage) {
localStorage.setItem('dtw_locked_'+stage, 'false');
showToast("🔓 تم فتح تعديل النتائج!");
if(stage === 'ps') renderPS();
if(stage === 'fs') renderFS();
if(stage === 'tb') renderFinalMedals();
}
function clearSavedImages() {
localStorage.removeItem('dtw_images');
competitorImages = {};
renderAllViews();
showToast("🗑️ تم مسح الصور بنجاح");
}
function clearSavedNames() {
localStorage.removeItem('dtw_names');
customNames = {};
renderAllViews();
showToast("🗑️ تم مسح الأسماء بنجاح");
}
const PILL={A:'<span class="grp-pill pill-a">A</span>',B:'<span class="grp-pill pill-b">B</span>',C:'<span class="grp-pill pill-c">C</span>',D:'<span class="grp-pill pill-d">D</span>','':'<span style="color:var(--muted);font-size:11px;"></span>'};
const GC={A:"ga-row",B:"gb-row",C:"gc-row",D:"gd-row","":""};
let currentUploadingCompetitorId = null;
const uploader = document.getElementById('image-uploader');
function triggerImageUpload(num) { currentUploadingCompetitorId = num; uploader.click(); }
uploader.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file && currentUploadingCompetitorId) {
const reader = new FileReader();
reader.onload = function(event) {
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
let width = img.width, height = img.height; const MAX_SIZE = 200;
if (width > height) { if (width > MAX_SIZE) { height *= MAX_SIZE / width; width = MAX_SIZE; } } else { if (height > MAX_SIZE) { width *= MAX_SIZE / height; height = MAX_SIZE; } }
canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, width, height);
competitorImages[currentUploadingCompetitorId] = canvas.toDataURL('image/jpeg', 0.85);
try { localStorage.setItem('dtw_images', JSON.stringify(competitorImages)); } catch(e) { alert("مساحة المتصفح ممتلئة!"); }
renderAllViews();
}; img.src = event.target.result;
}; reader.readAsDataURL(file);
} e.target.value = '';
});
function getCompetitorData(num) {
const comp = COMPETITORS_BASE.find(c => c[0] === num);
let ar = comp ? comp[1] : "بدون اسم", en = comp ? comp[2] : "No Name";
if (customNames[num]) { if (customNames[num].ar) ar = customNames[num].ar; if (customNames[num].en) en = customNames[num].en; }
return { ar, en, imgSrc: competitorImages[num] || `https://ui-avatars.com/api/?name=${encodeURIComponent(ar)}&background=F0F2F8&color=1B1F40&bold=true&rounded=true&size=128` };
}
function updateName(num, lang, newText) {
if (!customNames[num]) customNames[num] = {ar: null, en: null};
customNames[num][lang] = newText.trim();
localStorage.setItem('dtw_names', JSON.stringify(customNames));
renderAllViews();
}
function renderAllViews() { renderGA(); renderPS(); renderOR(); renderFS(); updateTbPodium(); }
function saveGroupAssignments() { localStorage.setItem('dtw_groups', JSON.stringify(groupAssign)); renderAllViews(); showToast("✓ تم حفظ توزيع المجموعات بنجاح!"); }
function resetAllGroups(){ COMPETITORS_BASE.forEach(c => { groupAssign[c[0]] = ""; }); localStorage.setItem('dtw_groups', JSON.stringify(groupAssign)); renderGA(); showToast("✓ تم إفراغ المجموعات"); }
function restoreDefaults(){
if(confirm("هل أنت متأكد من استعادة التوزيع الأصلي للمجموعات؟")){
localStorage.removeItem('dtw_groups'); groupAssign = {}; COMPETITORS_BASE.forEach(c => { groupAssign[c[0]] = c[3]; });
renderAllViews(); showToast("✓ تم استعادة التوزيع الأصلي");
}
}
function onGroupChange(num, val){
if(val){
const currentCount = COMPETITORS_BASE.filter(c => groupAssign[c[0]] === val).length;
if(currentCount >= 6){
document.getElementById("ga-row-"+num).querySelector(".grp-select").value = groupAssign[num] || "";
alert(`عذراً، المجموعة ${val} ممتلئة (الحد الأقصى 6 لاعبين).`);
return;
}
}
groupAssign[num] = val;
updateSummaryCards();
const row = document.getElementById("ga-row-"+num);
if(row){
row.className = val ? GC[val] : "";
row.querySelector(".grp-select").className = "grp-select " + (val ? "sel-"+val.toLowerCase() : "sel-none");
}
localStorage.setItem('dtw_groups', JSON.stringify(groupAssign));
renderPS();
renderOR();
showToast("✓ تم حفظ تعديل المجموعة بنجاح!");
}
function updateSummaryCards(){
const cnt={A:0,B:0,C:0,D:0,u:0}; COMPETITORS_BASE.forEach(c=>{ const g = groupAssign[c[0]]; if(g && cnt[g]!==undefined) cnt[g]++; else cnt.u++; });
["A","B","C","D"].forEach(g=>{ document.getElementById("cnt-"+g.toLowerCase()).textContent=cnt[g]; const st=document.getElementById("st-"+g.toLowerCase()); if(cnt[g]===6){st.className="st st-ok";st.textContent="✓ مكتمل";} else if(cnt[g]<6){st.className="st st-warn";st.textContent=`⚠ بحاجة لـ ${6-cnt[g]}`;} });
document.getElementById("cnt-u").textContent=cnt.u; const stU=document.getElementById("st-u"); if(cnt.u===0){stU.className="st st-ok";stU.textContent="✓ تم التوزيع";} else{stU.className="st st-warn";stU.textContent=`⚠ ${cnt.u} بلا مجموعة`;}
}
function renderGA(){
const gaBody=document.getElementById("ga-body"); gaBody.innerHTML="";
const groups=["A","B","C","D",""];
groups.forEach((g,gi)=>{
const members=g ? COMPETITORS_BASE.filter(c=>groupAssign[c[0]]===g) : COMPETITORS_BASE.filter(c=>!groupAssign[c[0]]);
if(members.length===0) return;
if(gi>0 && gaBody.children.length>0){ const sep=document.createElement("tr"); sep.className="grp-sep"; sep.innerHTML=`<td colspan="5"></td>`; gaBody.appendChild(sep); }
const hdr=document.createElement("tr"); hdr.className=(g?({A:"grp-a",B:"grp-b",C:"grp-c",D:"grp-d"})[g]:"")+" grp-hdr"; hdr.innerHTML=`<td colspan="5">${g?"المجموعة "+g:"⚠ غير معين"}</td>`; gaBody.appendChild(hdr);
members.forEach(m=>{
const num = m[0];
const {ar, en, imgSrc} = getCompetitorData(num); const grp=groupAssign[num]||""; const tr=document.createElement("tr"); tr.id="ga-row-"+num; tr.className=grp?GC[grp]:"";
const assigned=COMPETITORS_BASE.filter(c=>groupAssign[c[0]]===grp&&grp!=="").map(c=>c[0]); const pos=grp?assigned.indexOf(num)+1:"—";
tr.innerHTML=`<td class="td-num">${num}</td>
<td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img clickable-img" onclick="triggerImageUpload(${num})"> <span class="td-name editable-name" contenteditable="true" spellcheck="false" onblur="updateName(${num}, 'ar', this.innerText)">${ar}</span></div></td>
<td style="text-align:left;"><span class="td-en editable-name" contenteditable="true" spellcheck="false" onblur="updateName(${num}, 'en', this.innerText)">${en}</span></td>
<td><select class="grp-select ${grp?"sel-"+grp.toLowerCase():"sel-none"}" onchange="onGroupChange(${num},this.value)">
<option value="" ${grp===""?"selected":""}>— غير معين</option><option value="A" ${grp==="A"?"selected":""}>مجموعة A</option><option value="B" ${grp==="B"?"selected":""}>مجموعة B</option><option value="C" ${grp==="C"?"selected":""}>مجموعة C</option><option value="D" ${grp==="D"?"selected":""}>مجموعة D</option>
</select></td><td class="td-num" style="color:var(--muted)">${pos}</td>`; gaBody.appendChild(tr);
});
});
updateSummaryCards();
}
renderGA();
function onScoreChange(num, rdIdx, inputEl){
let raw = parseInt(inputEl.value);
if(isNaN(raw)) raw = 0;
if(raw < 0 || raw > 100){ inputEl.classList.add("invalid"); return; }
inputEl.classList.remove("invalid"); scores[num][rdIdx] = raw; saveScoresLocal();
const tot = scores[num].reduce((a,b)=>a+b,0); document.getElementById("ps-tot-"+num).textContent = tot;
const grp = groupAssign[num]; if(!grp) return;
const groupMembers = COMPETITORS_BASE.filter(c=>groupAssign[c[0]]===grp).map(c=>c[0]);
const groupTotals = groupMembers.map(n => scores[n].reduce((a,b)=>a+b,0));
groupMembers.forEach((n, i) => { const myTot = groupTotals[i]; const rk = groupTotals.filter(t => t > myTot).length + 1; const el = document.getElementById("ps-rk-"+n); if(el) el.textContent = rk; });
renderOR();
}
const undoHistory = { ps: null, fs: null, tb: null };
function setUndoBtn(stage, enabled){ const btn = document.getElementById("undo-"+stage); if(btn){ btn.disabled = !enabled; btn.style.opacity = enabled ? "1" : ".4"; } }
function clearAllScores(stage) {
if(stage === 'ps') {
undoHistory.ps = JSON.parse(JSON.stringify(scores));
for (let num in scores) { scores[num] = [0,0,0]; }
saveScoresLocal();
renderPS();
renderOR();
} else if(stage === 'fs') {
undoHistory.fs = JSON.parse(JSON.stringify(finalScores));
for (let num in finalScores) { finalScores[num] = [0,0]; }
saveScoresLocal();
renderFS();
} else if(stage === 'tb') {
undoHistory.tb = JSON.parse(JSON.stringify(tbScores));
for (let k in tbScores) { tbScores[k] = [0,0,0]; }
saveScoresLocal();
renderFinalMedals();
}
setUndoBtn(stage, true);
showToast("🗑️ تم تصفير جميع النتائج بنجاح!");
}
function undoScores(stage){
if(stage === 'ps' && undoHistory.ps){ Object.keys(undoHistory.ps).forEach(num => { scores[num] = [...undoHistory.ps[num]]; }); undoHistory.ps = null; saveScoresLocal(); renderPS(); renderOR(); }
else if(stage === 'fs' && undoHistory.fs){ Object.keys(undoHistory.fs).forEach(num => { finalScores[num] = [...undoHistory.fs[num]]; }); undoHistory.fs = null; saveScoresLocal(); renderFS(); }
else if(stage === 'tb' && undoHistory.tb){ Object.keys(undoHistory.tb).forEach(k => { tbScores[k] = [...undoHistory.tb[k]]; }); undoHistory.tb = null; saveScoresLocal(); renderFinalMedals(); }
setUndoBtn(stage, false);
}
function renderPS(){
const isLocked = localStorage.getItem('dtw_locked_ps') === 'true';
const btnLock = document.getElementById('btn-lock-ps'); const btnUnlock = document.getElementById('btn-unlock-ps');
if(btnLock) btnLock.style.display = isLocked ? 'none' : 'inline-block';
if(btnUnlock) btnUnlock.style.display = isLocked ? 'inline-block' : 'none';
const dis = isLocked ? 'disabled' : '';
const psBody=document.getElementById("ps-body"); psBody.innerHTML="";
const byGrp={A:[],B:[],C:[],D:[]}; COMPETITORS_BASE.forEach(c=>{ const g = groupAssign[c[0]]; if(g) byGrp[g].push(c[0]); });
[{g:"A",cls:"grp-a"},{g:"B",cls:"grp-b"},{g:"C",cls:"grp-c"},{g:"D",cls:"grp-d"}].forEach(({g,cls})=>{
const hdr=document.createElement("tr"); hdr.className=cls+" grp-hdr"; hdr.innerHTML=`<td colspan="8">المجموعة ${g}</td>`; psBody.appendChild(hdr);
const members=byGrp[g]; const totals=members.map(n=>scores[n].reduce((a,b)=>a+b,0));
members.forEach((num)=>{
const {ar, en, imgSrc} = getCompetitorData(num);
const s=scores[num]; const tot=s.reduce((a,b)=>a+b,0); const rk=totals.filter(t=>t>tot).length+1;
const tr=document.createElement("tr"); tr.className=GC[g];
tr.innerHTML=`<td class="td-num">${num}</td>
<td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img" alt="${ar}"> <span class="td-name">${ar}</span></div></td>
<td class="td-en">${en}</td>
<td><input class="score-input" type="number" min="0" max="100" value="${s[0]}" oninput="onScoreChange(${num},0,this)" ${dis}></td>
<td><input class="score-input" type="number" min="0" max="100" value="${s[1]}" oninput="onScoreChange(${num},1,this)" ${dis}></td>
<td><input class="score-input" type="number" min="0" max="100" value="${s[2]}" oninput="onScoreChange(${num},2,this)" ${dis}></td>
<td class="td-total" id="ps-tot-${num}">${tot}</td>
<td class="td-rank" id="ps-rk-${num}">${rk}</td>`;
psBody.appendChild(tr);
});
});
}
renderPS();
let top12 = [];
function renderOR(){
const all = COMPETITORS_BASE.map(c => ({ num: c[0], grp: groupAssign[c[0]]||"", total: scores[c[0]].reduce((a,b)=>a+b,0) })).filter(p => p.grp !== "");
const sorted = [...all].sort((a,b) => b.total - a.total);
const rankMap = {}; sorted.forEach((p,i) => rankMap[p.num] = i+1);
const orBody = document.getElementById("or-body"); orBody.innerHTML = "";
all.forEach(p => {
const {ar, en, imgSrc} = getCompetitorData(p.num);
const rk = rankMap[p.num]; const tr = document.createElement("tr"); tr.className = rk<=12 ? "medal-qualify" : "";
tr.innerHTML = `<td class="td-num">${p.num}</td><td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img" alt="${ar}"> <span class="td-name">${ar}</span></div></td><td>${PILL[p.grp]}</td><td class="td-total">${p.total}</td><td class="td-rank">${rk}</td><td>${rk<=12?'<span class="q-badge">✓ متأهل</span>':'<span class="no-q"></span>'}</td>`;
orBody.appendChild(tr);
});
top12 = sorted.slice(0,12).map((p,i) => ({...p, seed:i+1}));
// التعديل: إزالة عمود الميدالية وتوحيد تنسيق المتأهلين
const top12Body = document.getElementById("top12-body"); top12Body.innerHTML = "";
top12.forEach((p,i) => {
const {ar, en, imgSrc} = getCompetitorData(p.num);
const tr = document.createElement("tr"); tr.className = "medal-qualify"; // توحيد اللون بدون ذهبي/فضي/برونزي
tr.innerHTML = `<td class="td-rank">${i+1}</td><td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img" alt="${ar}"> <span class="td-name">${ar}</span></div></td><td>${PILL[p.grp]}</td><td class="td-total">${p.total}</td>`;
top12Body.appendChild(tr);
});
if(top12.length > 0) renderFS();
}
renderOR();
function renderFS(){
const isLocked = localStorage.getItem('dtw_locked_fs') === 'true';
const btnLock = document.getElementById('btn-lock-fs');
const btnUnlock = document.getElementById('btn-unlock-fs');
if(btnLock) btnLock.style.display = isLocked ? 'none' : 'inline-block';
if(btnUnlock) btnUnlock.style.display = isLocked ? 'inline-block' : 'none';
const dis = isLocked ? 'disabled' : '';
const fg1Body = document.getElementById("fg1-body");
const fg2Body = document.getElementById("fg2-body");
if(fg1Body) fg1Body.innerHTML = "";
if(fg2Body) fg2Body.innerHTML = "";
if(typeof top12 === 'undefined' || top12.length === 0) return;
// تقسيم أفضل 12 لاعب إلى مجموعتين
const g1 = top12.slice(0, 6);
const g2 = top12.slice(6, 12);
const renderGroup = (group, tbody) => {
if(!tbody) return;
const totals = group.map(p => {
if (!finalScores[p.num]) finalScores[p.num] = [0, 0];
return finalScores[p.num].reduce((a, b) => a + b, 0);
});
group.forEach((p) => {
const num = p.num;
const {ar, imgSrc} = getCompetitorData(num);
const s = finalScores[num];
const tot = s.reduce((a,b)=>a+b,0);
const rk = totals.filter(t => t > tot).length + 1;
const tr = document.createElement("tr");
tr.innerHTML = `
<td class="td-num">${p.seed}</td>
<td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img" alt="${ar}"> <span class="td-name">${ar}</span></div></td>
<td><input class="score-input" type="number" min="0" max="100" value="${s[0]}" oninput="onFinalScoreChange(${num},0,this)" ${dis}></td>
<td><input class="score-input" type="number" min="0" max="100" value="${s[1]}" oninput="onFinalScoreChange(${num},1,this)" ${dis}></td>
<td class="td-total" id="fs-tot-${num}">${tot}</td>
<td class="td-rank" id="fs-grk-${num}">${rk}</td>
`;
tbody.appendChild(tr);
});
};
renderGroup(g1, fg1Body);
renderGroup(g2, fg2Body);
}
function onFinalScoreChange(num, rdIdx, inputEl){
let raw = parseInt(inputEl.value);
if(isNaN(raw)) raw = 0;
if(raw < 0 || raw > 100){ inputEl.classList.add("invalid"); return; }
inputEl.classList.remove("invalid"); finalScores[num][rdIdx] = raw; saveScoresLocal();
const tot = finalScores[num].reduce((a,b)=>a+b,0); document.getElementById("fs-tot-"+num).textContent = tot;
const seedIdx = top12.findIndex(p=>p.num===num); const fgGroup = seedIdx < 6 ? top12.slice(0,6) : top12.slice(6,12);
fgGroup.forEach(p => { const t = finalScores[p.num].reduce((a,b)=>a+b,0); const rk = fgGroup.filter(x => finalScores[x.num].reduce((a,b)=>a+b,0) > t).length + 1; const el = document.getElementById("fs-grk-"+p.num); if(el) el.textContent = rk; });
renderFinalMedals();
}
function getTbTotal(grpLabel, num){ const key = grpLabel+"-"+num; return tbScores[key] ? tbScores[key].reduce((a,b)=>a+b,0) : 0; }
let currentTiedPlayers = [];
const MEDAL_SVG = { 1: `🥇`, 2: `🥈`, 3: `🥉`, };
const CLOCK_SVG = { 1: `<span style="opacity:.3;filter:grayscale(1);"></span>`, 2: `<span style="opacity:.3;filter:grayscale(1);"></span>`, 3: `<span style="opacity:.3;filter:grayscale(1);"></span>`, };
function updateTbPodium(){
const standings = [...top12].map(p => { const ft = finalScores[p.num]?finalScores[p.num].reduce((a,b)=>a+b,0):0; const grpLabel = playerTbGroup[p.num]; const tbTot = grpLabel ? getTbTotal(grpLabel, p.num) : 0; return { ...p, ft, tbTot }; });
standings.sort((a,b) => b.ft - a.ft || b.tbTot - a.tbTot);
[1,2,3].forEach(pos => {
const nameEl = document.getElementById("pod-name-"+pos); const scoreEl = document.getElementById("pod-score-"+pos); const medalEl = document.getElementById("pod-medal-"+pos); const imgEl = document.getElementById("pod-img-"+pos);
const p = standings[pos-1];
if(!p || p.ft === 0){
nameEl.textContent="— بانتظار النتيجة —"; nameEl.classList.add("empty"); scoreEl.textContent="-"; imgEl.src = `https://ui-avatars.com/api/?name=?&background=F0F2F8&color=1B1F40&size=150`; if(medalEl) medalEl.innerHTML=CLOCK_SVG[pos]; return;
}
const {ar, imgSrc} = getCompetitorData(p.num);
const isTied = standings.some((x, xi) => { if(x.num === p.num) return false; const xPos = standings.filter(y => y.ft > x.ft || (y.ft===x.ft && y.tbTot > x.tbTot)).length + 1; return xPos <= 3 && x.ft === p.ft && x.tbTot === p.tbTot; });
nameEl.textContent = ar; nameEl.classList.remove("empty"); imgEl.src = imgSrc;
if(isTied){
if(medalEl) medalEl.innerHTML = CLOCK_SVG[pos]; scoreEl.textContent = p.tbTot > 0 ? "تعادل: " + p.tbTot : "النهائي: " + p.ft; scoreEl.style.color = "var(--muted)";
} else {
if(medalEl) medalEl.innerHTML = MEDAL_SVG[pos]; scoreEl.textContent = "النتيجة: " + p.ft + (p.tbTot > 0 ? ` (كسر: +${p.tbTot})` : ""); scoreEl.style.color = pos===1?"#D4AF37":pos===2?"#9DA3AE":"#CD7F32";
}
});
renderTbRankingTable();
}
function onTbScoreChange(key, shotIdx, inputEl){
let raw = parseInt(inputEl.value); if(isNaN(raw)) raw = 0;
if(raw < 0 || raw > 10){ inputEl.classList.add("invalid"); return; }
inputEl.classList.remove("invalid"); tbScores[key][shotIdx] = raw; saveScoresLocal();
const tot = tbScores[key].reduce((a,b)=>a+b,0); const totEl = document.getElementById("tb-tot-"+key); if(totEl) totEl.textContent = tot;
const grpLabel = key.split("-")[0]; const grpKeys = Object.keys(tbScores).filter(k=>k.startsWith(grpLabel+"-"));
grpKeys.forEach(k => { const t = tbScores[k].reduce((a,b)=>a+b,0); const rk = grpKeys.filter(ok => tbScores[ok].reduce((a,b)=>a+b,0) > t).length + 1; const el = document.getElementById("tb-rk-"+k); if(el) el.textContent = t===0 ? "—" : rk; });
updateTbPodium(); updateFinalMedalWithTB();
}
const playerTbGroup = {};
function renderTbRankingTable(){
const body = document.getElementById("tb-ranking-body"); if(!body) return; body.innerHTML = "";
const standings = [...top12].map(p => { const ft = finalScores[p.num]?finalScores[p.num].reduce((a,b)=>a+b,0):0; const grpLabel = playerTbGroup[p.num]; const tbTot = grpLabel ? getTbTotal(grpLabel, p.num) : 0; return { ...p, ft, tbTot }; });
standings.sort((a,b) => b.ft - a.ft || b.tbTot - a.tbTot);
standings.forEach((p, i) => {
const {ar, imgSrc} = getCompetitorData(p.num);
const trueRank = standings.filter(x => x.ft > p.ft || (x.ft===p.ft && x.tbTot > p.tbTot)).length + 1;
const isTied = standings.some(x => { if(x.num === p.num) return false; const xRank = standings.filter(y => y.ft > x.ft || (y.ft===x.ft && y.tbTot > x.tbTot)).length + 1; return xRank <= 3 && x.ft === p.ft && x.tbTot === p.tbTot; });
const tr = document.createElement("tr"); const medalLabels = {1:"🥇",2:"🥈",3:"🥉"}; const medalColors = {1:"#E8784A",2:"#9DA3AE",3:"#CD7F32"};
let rankCell, medalCell, rowClass = "";
if(p.ft === 0) { rankCell = `<td class="td-rank" style="color:var(--muted)"></td>`; medalCell = `<td class="medal-icon" style="color:var(--muted);font-size:13px"></td>`; }
else if(isTied){ rankCell = `<td class="td-rank" style="color:var(--muted)">${trueRank}</td>`; medalCell = `<td><span style="background:rgba(236,47,35,.15);border:1px solid rgba(236,47,35,.4);color:var(--red);border-radius:8px;padding:2px 10px;font-size:12px;font-weight:700;">تعادل</span></td>`; }
else { rowClass = trueRank===1?"medal-gold":trueRank===2?"medal-silver":trueRank===3?"medal-bronze":""; rankCell = `<td class="td-rank">${trueRank}</td>`; const medal = medalLabels[trueRank]; medalCell = medal ? `<td class="medal-icon" style="color:${medalColors[trueRank]}">${medal}</td>` : `<td class="medal-icon" style="color:var(--muted);font-size:13px">#${trueRank}</td>`; }
const tbCell = p.tbTot > 0 ? `<td class="td-total" style="color:#ffffff">${p.tbTot}</td>` : `<td style="color:var(--muted);font-size:13px"></td>`;
const tieBadge = (isTied && p.ft > 0) ? ` <span style="background:rgba(236,47,35,.15);border:1px solid rgba(236,47,35,.4);color:var(--red);border-radius:8px;padding:1px 8px;font-size:11px;font-weight:700;margin-right:6px;">تعادل</span>` : "";
tr.className = rowClass; tr.innerHTML = `${rankCell}<td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img" alt="${ar}"> <span class="td-name">${ar}${tieBadge}</span></div></td><td class="td-total">${p.ft}</td>${tbCell}${medalCell}`; body.appendChild(tr);
});
}
function updateFinalMedalWithTB(){ renderTbRankingTable(); }
function renderFinalMedals(){ updateFinalMedalWithTB(); const fSortedLive = [...top12].sort((a,b)=>{ const ta=finalScores[a.num]?finalScores[a.num].reduce((x,y)=>x+y,0):0; const tb=finalScores[b.num]?finalScores[b.num].reduce((x,y)=>x+y,0):0; return tb-ta; }); renderTiebreaker(fSortedLive); }
function renderTiebreaker(fSortedLive){
const isLocked = localStorage.getItem('dtw_locked_tb') === 'true';
const btnLock = document.getElementById('btn-lock-tb'); const btnUnlock = document.getElementById('btn-unlock-tb');
if(btnLock) btnLock.style.display = isLocked ? 'none' : 'inline-block';
if(btnUnlock) btnUnlock.style.display = isLocked ? 'inline-block' : 'none';
const dis = isLocked ? 'disabled' : '';
const statusEl = document.getElementById("tb-status"); const groupsEl = document.getElementById("tb-groups");
statusEl.innerHTML = ""; groupsEl.innerHTML = ""; currentTiedPlayers = [];
const scored = fSortedLive.map(p => ({ ...p, ft: finalScores[p.num]?finalScores[p.num].reduce((a,b)=>a+b,0):0 }));
const tieGroups = []; let i = 0;
while(i < Math.min(scored.length, 12)){
const sameScore = scored.filter(p => p.ft === scored[i].ft); const positions = sameScore.map(p => scored.indexOf(p) + 1); const inTop3 = positions.some(pos => pos <= 3);
if(sameScore.length > 1 && inTop3 && scored[i].ft > 0){ if(!tieGroups.find(g => g.score === scored[i].ft)){ tieGroups.push({ score: scored[i].ft, players: sameScore, positions }); } }
i += sameScore.length;
}
if(tieGroups.length === 0){ statusEl.innerHTML = `<div class="tb-none">✓ لا يوجد تعادل في المراكز الثلاثة الأولى.</div>`; updateTbPodium(); return; }
tieGroups.forEach((grp, gi) => {
const grpLabel = "g"+gi; grp.players.forEach(p => { playerTbGroup[p.num] = grpLabel; if(!currentTiedPlayers.find(x => x.num === p.num)) currentTiedPlayers.push(p); });
const medalPos = grp.positions.filter(p=>p<=3); const posStr = medalPos.map(p => p===1?"الأول":p===2?"الثاني":"الثالث").join(" و ");
const title = document.createElement("div"); title.className = "tb-group-title"; title.innerHTML = `تعادل — المركز ${posStr} <span class="tb-tied-score">النتيجة النهائية: ${grp.score}</span>`; groupsEl.appendChild(title);
const wrap = document.createElement("div"); wrap.className = "tbl-wrap"; const table = document.createElement("table");
table.innerHTML = `<thead><tr><th>#</th><th>صورة واسم المتسابق</th><th>طلقة 1 /10</th><th>طلقة 2 /10</th><th>طلقة 3 /10</th><th>المجموع /30</th><th>الترتيب</th></tr></thead>`;
const tbody = document.createElement("tbody");
grp.players.forEach((p, pi) => {
const {ar, imgSrc} = getCompetitorData(p.num);
const key = grpLabel+"-"+p.num; if(!tbScores[key]) tbScores[key] = [0,0,0]; const s = tbScores[key]; const tot = s.reduce((a,b)=>a+b,0);
const rk = grp.players.filter(op => (tbScores[grpLabel+"-"+op.num]||[0,0,0]).reduce((a,b)=>a+b,0) > tot).length + 1;
const tr = document.createElement("tr");
tr.innerHTML = `<td class="td-num">${pi+1}</td><td><div class="competitor-cell"><img src="${imgSrc}" class="competitor-img" alt="${ar}"> <span class="td-name">${ar}</span></div></td><td><input class="score-input" type="number" min="0" max="10" value="${s[0]}" oninput="onTbScoreChange('${key}',0,this)" ${dis}></td><td><input class="score-input" type="number" min="0" max="10" value="${s[1]}" oninput="onTbScoreChange('${key}',1,this)" ${dis}></td><td><input class="score-input" type="number" min="0" max="10" value="${s[2]}" oninput="onTbScoreChange('${key}',2,this)" ${dis}></td><td class="td-total" id="tb-tot-${key}">${tot}</td><td class="td-rank" id="tb-rk-${key}">${tot===0?"—":rk}</td>`;
tbody.appendChild(tr);
});
table.appendChild(tbody); wrap.appendChild(table); groupsEl.appendChild(wrap);
});
updateTbPodium();
}
// === برمجة الشاشة المباشرة (النسخة الجديدة والمستقرة) ===
let liveGroupTimer = null;
let liveGroupIdx = 0;
const LIVE_GROUPS = ["A", "B", "C", "D"];
function renderLiveGroup() {
const container = document.getElementById("lg-container");
if (!container) return;
const g = LIVE_GROUPS[liveGroupIdx];
const members = COMPETITORS_BASE.filter(c => groupAssign[c[0]] === g);
let html = `<div class="lg-header">المجموعة ${g} - GROUP ${g}</div><div class="lg-grid">`;
if(members.length === 0) {
html += `<div class="lg-empty">لا يوجد متسابقين في هذه المجموعة</div>`;
} else {
members.forEach((m, i) => {
const d = getCompetitorData(m[0]);
html += `
<div class="lg-card" style="animation: cardIn 0.5s ease forwards; animation-delay: ${i*0.1}s; opacity: 0;">
<img src="${d.imgSrc}" alt="${d.ar}">
<div class="lg-info">
<div class="lg-num">#${m[0]}</div>
<div class="lg-name">${d.ar}</div>
<div class="lg-name-en">${d.en}</div>
</div>
</div>`;
});
}
html += `</div>`;
container.innerHTML = html;
// إعادة تشغيل شريط التقدم المرئي
const bar = document.getElementById("lg-progress");
if (bar) {
bar.classList.remove("run-progress");
void bar.offsetWidth; // لتنشيط الأنيميشن مجدداً
bar.classList.add("run-progress");
}
liveGroupIdx = (liveGroupIdx + 1) % LIVE_GROUPS.length;
}
function startLiveGroups() {
stopLiveGroups();
liveGroupIdx = 0;
renderLiveGroup();
liveGroupTimer = setInterval(renderLiveGroup, 5000);
}
function stopLiveGroups() {
if (liveGroupTimer) {
clearInterval(liveGroupTimer);
liveGroupTimer = null;
}
}
function show(id, btn){
document.querySelectorAll('.panel').forEach(p=>p.classList.remove('active'));
document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));
document.getElementById(id).classList.add('active');
btn.classList.add('active');
if(id === 'live-groups') {
startLiveGroups();
} else {
stopLiveGroups();
}
}
// Init
updateTbPodium();
</script>
</body>
</html>