laravel-project/templates/taekwondo-match-video.html

1423 lines
45 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="en">
<head>
<meta charset="UTF-8" />
<title>Taekwondo Match Card</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; background: #020617; color: #e5e7eb; } /* [page:1] */
.page { max-width: 1280px; margin: 0 auto; padding: 24px 16px 64px; }
.video-shell {
background: #020617;
border-radius: 16px;
padding: 16px;
box-shadow: 0 18px 60px rgba(0,0,0,.75);
position: relative;
overflow: hidden;
border: 1px solid #111827;
}
.video-wrapper { position: relative; }
video { width: 100%; border-radius: 12px; background: #000; }
video::-webkit-media-controls { display:none !important; }
.controls { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.controls-top { display: flex; align-items: center; gap: 10px; }
.play-btn {
width: 26px; height: 26px;
border-radius: 999px; border: 1px solid #111827;
background: #020314;
display:flex; align-items:center; justify-content:center;
cursor:pointer; color:#e5e7eb; font-size:14px;
}
.time-labels { font-size: 0.8rem; color: #9ca3af; display:flex; gap:8px; align-items:center; }
.progress-wrapper { position:relative; width:100%; height:16px; display:flex; align-items:center; cursor:pointer; }
.progress-bar {
position:relative; width:100%; height:4px;
border-radius:999px; background:#020314; border:1px solid #111827;
overflow:hidden;
}
.progress-fill { position:absolute; left:0; top:0; bottom:0; width:0%; background:linear-gradient(90deg,#06b6d4,#22d3ee); }
.progress-handle {
position:absolute; top:50%; width:10px; height:10px;
border-radius:999px; background:#e5e7eb; box-shadow:0 0 0 2px #020314;
transform:translate(-50%,-50%); pointer-events:none;
}
.event-header {
display:flex;
align-items:center;
justify-content:space-between;
gap:12px;
margin-top:16px;
}
.event-header-left {
display:flex;
align-items:center;
gap:12px;
min-width:0;
}
.event-logo {
width:56px;
height:56px;
border-radius:14px;
overflow:hidden;
background:#020314;
border:1px solid #1f2937;
flex-shrink:0;
display:flex;
align-items:center;
justify-content:center;
}
.event-logo img { width:100%; height:100%; object-fit:contain; }
.event-text {
display:flex;
flex-direction:column;
gap:2px;
min-width:0;
}
.title { font-size: 1.4rem; margin: 0; }
.meta { font-size: 0.85rem; color: #9ca3af; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.event-header-actions {
display:flex;
align-items:center;
gap:6px;
flex-shrink:0;
}
.btn-icon {
border:none;
border-radius:999px;
padding:5px 10px;
font-size:0.78rem;
cursor:pointer;
background:#020314;
border:1px solid #1f2937;
color:#d1d5db;
display:flex;
align-items:center;
gap:4px;
}
.btn-icon span:first-child { font-size:0.9rem; }
.match-card {
margin-top: 16px;
padding: 16px 18px;
border-radius: 14px;
border: 1px solid #111827;
background: radial-gradient(circle at top, #020314 0, #020617 45%, #020617 100%);
}
.match-header {
display:flex;
justify-content:space-between;
align-items:center;
margin-bottom:12px;
}
.match-label {
font-size:0.8rem;
text-transform:uppercase;
letter-spacing:0.16em;
color:#9ca3af;
}
.fighters-row {
display:grid;
grid-template-columns: 1.1fr 0.8fr 1.1fr;
align-items:stretch;
gap: 16px;
}
.fighter-card {
background: #020314;
border-radius: 14px;
padding: 10px;
border: 1px solid #111827;
display:flex;
flex-direction:column;
align-items:center;
gap: 8px;
}
.fighter-top {
display:flex;
align-items:center;
justify-content:center;
gap:10px;
width:100%;
}
.fighter-photo {
width:110px; height:145px;
border-radius:12px;
overflow:hidden;
box-shadow:0 0 0 1px #020617;
flex-shrink:0;
}
.fighter-photo img { width:100%; height:100%; object-fit:cover; }
.fighter-logo {
width:64px; height:64px;
border-radius:20px;
overflow:hidden;
background:#020617;
}
.fighter-logo img { width:100%; height:100%; object-fit:contain; }
.fighter-badge {
font-size:0.75rem;
text-transform:uppercase;
letter-spacing:0.12em;
padding:3px 8px;
border-radius:999px;
border:1px solid #1f2937;
color:#e5e7eb;
}
.fighter-badge.blue { background:rgba(37,99,235,.15); border-color:#1d4ed8; }
.fighter-badge.red { background:rgba(239,68,68,.14); border-color:#b91c1c; }
.fighter-info {
display:flex;
flex-direction:column;
gap:2px;
width:100%;
text-align:center;
font-size:0.8rem;
}
.fighter-name { font-weight:600; font-size:0.95rem; }
.fighter-team { color:#9ca3af; }
.fighter-country {
display:inline-flex;
justify-content:center;
align-items:center;
gap:4px;
color:#9ca3af;
margin-top:2px;
}
.fighter-country-flag { font-size:0.9rem; }
.match-center {
display:flex;
flex-direction:column;
align-items:center;
justify-content:space-between;
gap:10px;
}
.score-pill {
display:flex;
align-items:center;
justify-content:center;
gap:8px;
padding:6px 12px;
border-radius:999px;
background:#020314;
border:1px solid #111827;
}
.score-number { font-size:2.0rem; font-weight:700; }
.score-label { font-size:0.75rem; color:#9ca3af; }
.referee-block {
display:flex;
flex-direction:column;
align-items:center;
gap:4px;
}
.ref-photo {
width:54px; height:54px;
border-radius:999px;
overflow:hidden;
border:2px solid #020314;
box-shadow:0 0 0 1px #020617;
}
.ref-photo img { width:100%; height:100%; object-fit:cover; }
.ref-name { font-size:0.75rem; color:#e5e7eb; }
.ref-label { font-size:0.7rem; color:#9ca3af; }
.match-footer {
margin-top:12px;
font-size:0.8rem;
color:#6b7280;
text-align:center;
}
.markdown-body { font-size: 0.95rem; line-height: 1.6; margin-top: 16px; }
.markdown-body h2 { font-size: 1.05rem; margin-top: 14px; }
.description-panel {
margin-top: 16px;
border-radius: 12px;
border: 1px solid #111827;
background: #020314;
padding: 8px 10px 10px;
}
.description-toggle {
width: 100%;
border: none;
background: transparent;
color: #e5e7eb;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 0.85rem;
cursor: pointer;
padding: 4px 0;
}
.description-toggle:hover {
color: #f9fafb;
}
.description-body {
margin-top: 6px;
display: none;
}
.description-body.open {
display: block;
}
.coach-modal-backdrop,
.comment-modal-backdrop,
.share-modal-backdrop {
position:fixed;
inset:0;
background:rgba(15,23,42,0.8);
display:none;
align-items:center;
justify-content:center;
z-index:50;
}
.coach-modal-backdrop.open,
.comment-modal-backdrop.open,
.share-modal-backdrop.open {
display:flex;
}
.coach-modal,
.comment-modal,
.share-modal {
width:100%;
max-width:620px;
background:#020617;
border-radius:14px;
border:1px solid #111827;
box-shadow:0 20px 60px rgba(0,0,0,.8);
padding:14px 16px 16px;
}
.coach-modal-header,
.comment-modal-header,
.share-modal-header {
display:flex;
justify-content:space-between;
align-items:center;
margin-bottom:8px;
}
.coach-modal-header h3,
.comment-modal-header h3,
.share-modal-header h3 {
margin:0;
font-size:0.95rem;
}
.coach-modal-close,
.comment-modal-close,
.share-modal-close {
border:none;
background:transparent;
color:#9ca3af;
cursor:pointer;
font-size:1.2rem;
line-height:1;
}
.coach-panel-hint,
.comment-panel-hint {
font-size:0.78rem;
color:#9ca3af;
margin-bottom:8px;
}
.coach-form-row {
display:grid;
grid-template-columns: 0.9fr 1.1fr;
gap:10px;
align-items:flex-start;
margin-bottom:8px;
}
.coach-emoji-select {
display:flex;
gap:4px;
flex-wrap:wrap;
background:#020314;
border-radius:999px;
padding:3px 6px;
border:1px solid #111827;
}
.coach-emoji-select button {
border:none;
background:transparent;
cursor:pointer;
font-size:1rem;
line-height:1;
}
.coach-time-range {
display:flex;
gap:6px;
align-items:center;
font-size:0.8rem;
color:#9ca3af;
}
.coach-time-range input {
width:70px;
padding:4px 6px;
border-radius:6px;
border:1px solid #111827;
background:#020314;
color:#e5e7eb;
font-size:0.8rem;
}
.coach-comment textarea {
width:100%;
min-height:60px;
resize:vertical;
border-radius:8px;
border:1px solid #111827;
background:#020314;
color:#e5e7eb;
font-size:0.85rem;
padding:6px 8px;
}
.coach-actions,
.comment-modal-actions,
.share-modal-actions {
display:flex;
justify-content:flex-end;
margin-top:6px;
gap:8px;
}
.btn-small {
border:none;
border-radius:999px;
padding:5px 10px;
font-size:0.75rem;
cursor:pointer;
background:#06b6d4;
color:#0f172a;
}
.btn-small:hover { background:#22d3ee; }
.btn-ghost {
border:1px solid #111827;
border-radius:999px;
padding:5px 10px;
font-size:0.75rem;
cursor:pointer;
background:#020314;
color:#9ca3af;
}
.comments-panel {
margin-top:18px;
padding:14px 16px;
border-radius:12px;
border:1px solid #111827;
background:#020314;
}
.comments-panel-header {
display:flex;
justify-content:space-between;
align-items:center;
margin-bottom:8px;
}
.comments-tabs {
display:flex;
gap:6px;
}
.comments-tab {
border:none;
border-radius:999px;
padding:4px 8px;
font-size:0.75rem;
cursor:pointer;
background:transparent;
color:#9ca3af;
border:1px solid transparent;
}
.comments-tab.active {
background:#06b6d4;
color:#0f172a;
border-color:#06b6d4;
}
.comments-list {
border-top:1px solid #111827;
padding-top:8px;
margin-top:4px;
}
.comment-item {
display:flex;
gap:8px;
padding:6px 0;
border-bottom:1px solid #020617;
}
.comment-avatar {
width:28px;
height:28px;
border-radius:999px;
overflow:hidden;
background:#020314;
flex-shrink:0;
}
.comment-avatar img { width:100%; height:100%; object-fit:cover; }
.comment-body { flex:1; }
.comment-header-line {
display:flex;
align-items:center;
gap:6px;
font-size:0.78rem;
color:#9ca3af;
}
.comment-author { font-weight:500; color:#e5e7eb; }
.comment-time-chip {
padding:2px 6px;
border-radius:999px;
border:1px solid #1f2937;
background:#020314;
font-size:0.75rem;
cursor:pointer;
color:#93c5fd;
}
.comment-content { margin-top:2px; font-size:0.85rem; }
.comment-actions {
margin-top:4px;
font-size:0.75rem;
color:#6b7280;
display:flex;
gap:10px;
align-items:center;
}
.comment-actions button {
border:none;
background:transparent;
color:#6b7280;
cursor:pointer;
font-size:0.75rem;
padding:0;
}
.reply-item {
margin-top:4px;
margin-left:24px;
padding-left:8px;
border-left:1px solid #111827;
font-size:0.8rem;
color:#9ca3af;
}
.comment-modal-body {
display:flex;
flex-direction:column;
gap:8px;
}
.comment-row {
display:flex;
gap:8px;
flex-wrap:wrap;
align-items:center;
}
.comment-timestamp-type {
display:flex;
gap:6px;
font-size:0.78rem;
color:#9ca3af;
}
.comment-timestamp-type button {
border:none;
border-radius:999px;
padding:3px 8px;
background:#020314;
border:1px solid #111827;
color:#9ca3af;
cursor:pointer;
font-size:0.75rem;
}
.comment-timestamp-type button.active {
background:#06b6d4;
color:#0f172a;
border-color:#06b6d4;
}
.comment-time-inputs {
display:flex;
gap:6px;
align-items:center;
font-size:0.8rem;
color:#9ca3af;
}
.comment-time-inputs input {
width:70px;
padding:4px 6px;
border-radius:6px;
border:1px solid #111827;
background:#020314;
color:#e5e7eb;
font-size:0.8rem;
}
.comment-textarea {
width:100%;
min-height:60px;
resize:vertical;
border-radius:8px;
border:1px solid #111827;
background:#020314;
color:#e5e7eb;
font-size:0.85rem;
padding:6px 8px;
}
.comment-like-toggle {
display:flex;
align-items:center;
gap:4px;
font-size:0.8rem;
color:#9ca3af;
}
.share-options {
display:flex;
flex-wrap:wrap;
gap:8px;
margin-bottom:10px;
}
.share-pill {
border:none;
border-radius:999px;
padding:6px 10px;
font-size:0.8rem;
cursor:pointer;
background:#020314;
border:1px solid #111827;
color:#d1d5db;
display:flex;
align-items:center;
gap:6px;
}
.share-link-wrapper {
display:flex;
gap:6px;
align-items:center;
font-size:0.8rem;
color:#9ca3af;
}
.share-link-wrapper input {
flex:1;
padding:4px 6px;
border-radius:6px;
border:1px solid #111827;
background:#020314;
color:#e5e7eb;
font-size:0.8rem;
}
.events-sidebar {
position: fixed;
top: 0;
right: 0;
width: 340px;
max-width: 80vw;
height: 100vh;
background: #020617;
border-left: 1px solid #111827;
box-shadow: -12px 0 40px rgba(0,0,0,.6);
transform: translateX(100%);
transition: transform 0.3s ease-out;
display: flex;
flex-direction: column;
z-index: 40;
}
.events-sidebar.open { transform: translateX(0); }
.events-sidebar-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 14px;
border-bottom: 1px solid #111827;
}
.events-sidebar-header h3 { margin: 0; font-size: 0.95rem; }
.close-btn {
border: none; background: transparent; color: #9ca3af;
cursor: pointer; font-size: 1rem;
}
.tab-header {
display: flex; gap: 6px;
margin: 10px 12px 6px;
border-bottom: 1px solid #111827;
padding-bottom: 4px;
}
.tab-button {
flex: 1; text-align: center; padding: 6px 0;
font-size: 0.85rem; color: #9ca3af; cursor: pointer;
border-radius: 999px; background: transparent; border: none;
position: relative;
}
.tab-button.active {
background: #020314; color: #e5e7eb; font-weight: 500;
}
.tab-button.active::after {
content: ""; position: absolute; left: 8px; right: 8px; bottom: -4px;
height: 4px; background: #020617;
}
.tab-panels { flex: 1; overflow-y: auto; padding: 0 10px 12px; min-height: 0; }
.tab-panel { display: none; }
.tab-panel.active { display: block; }
.event-list { margin-top: 6px; border-top: 1px solid #111827; padding-top: 6px; }
.event-item {
display: grid; grid-template-columns: auto 1fr;
gap: 6px 10px; padding: 6px 4px;
border-radius: 6px; cursor: pointer;
}
.event-item:hover { background: #020314; }
.event-time {
font-size: 0.8rem;
color: #93c5fd;
min-width: 80px;
text-align: center;
}
.event-label { font-size: 0.9rem; }
.event-meta { font-size: 0.75rem; color: #6b7280; }
.pill { display:inline-block; padding:2px 6px; border-radius:999px; font-size:0.7rem; margin-left:4px; }
.pill-blue { background:rgba(59,130,246,.18); color:#bfdbfe; }
.pill-red { background:rgba(248,113,113,.16); color:#fecaca; }
.section-label { text-transform:uppercase; font-size:0.75rem; letter-spacing:.08em; color:#6b7280; margin:4px 0 2px; }
/* Round marker between points */
.round-marker {
display:flex;
align-items:center;
justify-content:center;
padding:4px 8px;
border-radius:999px;
background:#facc15;
color:#000;
font-size:0.8rem;
font-weight:700;
margin:4px 0;
}
.events-controller {
position: absolute;
top: 28px;
right: 28px;
display:flex;
gap:8px;
z-index:20;
}
.events-controller button {
border:none; border-radius:999px; padding:6px 10px;
font-size:0.75rem; cursor:pointer;
background:rgba(15,23,42,0.9); color:#d1d5db; border:1px solid #111827;
}
.events-controller button:hover { background:#020314; }
@media (max-width: 900px) {
.fighters-row { grid-template-columns: 1fr; }
.match-center { order: -1; }
.event-header { flex-direction:column; align-items:flex-start; }
.event-header-actions { align-self:flex-end; }
.coach-form-row { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="page">
<div class="video-shell">
<div class="events-controller">
<button data-open-sidebar="both">Bookmarks</button>
</div>
<div class="video-wrapper">
<video id="sportsVideo" src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"></video>
<div class="controls">
<div class="controls-top">
<button class="play-btn" id="playPauseBtn"></button>
<div class="time-labels">
<span id="currentTimeLabel">0:00</span>
<span>/</span>
<span id="durationLabel">0:00</span>
</div>
</div>
<div class="progress-wrapper" id="progressWrapper">
<div class="progress-bar" id="progressBar">
<div class="progress-fill" id="progressFill"></div>
<div class="progress-handle" id="progressHandle"></div>
</div>
</div>
</div>
</div>
<div class="event-header">
<div class="event-header-left">
<div class="event-logo">
<img src="https://picsum.photos/seed/event-logo/200/200" alt="Event logo">
</div>
<div class="event-text">
<h1 class="title">Taekwondo Finals Blue vs Red (U18)</h1>
<div class="meta">Championship 2026 • Court 2 • Best of 3 rounds</div>
</div>
</div>
<div class="event-header-actions">
<button class="btn-icon" type="button" id="shareVideoBtn">
<span>⤴️</span>
<span>Share</span>
</button>
</div>
</div>
<!-- Collapsible card + description (YouTube style) -->
<section class="description-panel">
<button class="description-toggle" type="button" id="toggleDescription">
<span id="descriptionToggleLabel">Show description</span>
<span id="descriptionToggleIcon"></span>
</button>
<div class="description-body" id="descriptionBody">
<!-- Match card inside collapsible body -->
<section class="match-card">
<div class="match-header">
<div class="match-label">Final • Male -63kg division</div>
</div>
<div class="fighters-row">
<article class="fighter-card">
<div class="fighter-top">
<div class="fighter-photo">
<img src="https://picsum.photos/seed/blue-competitor/200/260" alt="Blue fighter">
</div>
<div style="display:flex; flex-direction:column; align-items:center; gap:8px;">
<div class="fighter-logo">
<img src="https://picsum.photos/seed/blue-logo/160/160" alt="Blue team logo">
</div>
<span class="fighter-badge blue">Blue</span>
</div>
</div>
<div class="fighter-info">
<div class="fighter-name">Ali Mohammed</div>
<div class="fighter-team">Blue Dragons Club</div>
<div class="fighter-country">
<span class="fighter-country-flag">🇧🇭</span>
<span>Bahrain</span>
</div>
</div>
</article>
<div class="match-center">
<div class="score-pill">
<span class="score-number">7</span>
<span class="score-label">Final score</span>
<span class="score-number">5</span>
</div>
<div class="referee-block">
<div class="ref-photo">
<img src="https://picsum.photos/seed/referee/160/160" alt="Referee">
</div>
<div class="ref-name">M. AlKhalifa</div>
<div class="ref-label">Center Referee</div>
</div>
</div>
<article class="fighter-card">
<div class="fighter-top">
<div style="display:flex; flex-direction:column; align-items:center; gap:8px;">
<div class="fighter-logo">
<img src="https://picsum.photos/seed/red-logo/160/160" alt="Red team logo">
</div>
<span class="fighter-badge red">Red</span>
</div>
<div class="fighter-photo">
<img src="https://picsum.photos/seed/red-competitor/200/260" alt="Red fighter">
</div>
</div>
<div class="fighter-info">
<div class="fighter-name">Omar AlKhaled</div>
<div class="fighter-team">Red Tigers TKD</div>
<div class="fighter-country">
<span class="fighter-country-flag">🇸🇦</span>
<span>Saudi Arabia</span>
</div>
</div>
</article>
</div>
<div class="match-footer">
Manama Sports Hall • Electronic scoring system (PSS & headgear) • Video replay available for head kicks and gam-jeom appeals
</div>
</section>
<section class="markdown-body">
<div style="font-size:0.8rem; color:#9ca3af; margin-bottom:4px;">
3 x 2:00 rounds • Golden point if tied
</div>
<h2>Match overview</h2>
<p>
This final features two explosive male U18 -63kg fighters: Blue builds pressure with strong body kicks and ring control, while Red
waits to counter with head shots and angle changes. Use this replay to analyze how each fighter manages distance after exchanges,
how quickly they reset their guard, and where hesitation after conceding points changes the momentum of the round.
</p>
<p>
Coaches can also focus on corner instructions between rounds, the timing of tactical time-outs, and how often each athlete follows
the game plan under fatigue in the closing 30 seconds of every round.
</p>
</section>
</div>
</section>
<!-- Comments always visible -->
<section class="comments-panel">
<div class="comments-panel-header">
<h3 style="margin:0; font-size:0.95rem;">Comments & replies</h3>
<div style="display:flex; align-items:center; gap:6px;">
<div class="comments-tabs">
<button class="comments-tab active" type="button">All</button>
<button class="comments-tab" type="button">Highlights</button>
</div>
<button class="btn-icon" type="button" id="openCommentModal">
💬
<span>Comment</span>
</button>
</div>
</div>
<div class="comments-list">
<div class="comment-item">
<div class="comment-avatar">
<img src="https://picsum.photos/seed/user1/80/80" alt="User avatar">
</div>
<div class="comment-body">
<div class="comment-header-line">
<span class="comment-author">Viewer_21</span>
<span></span>
<span>2 min ago</span>
<span></span>
<span class="comment-time-chip">@00:3200:50</span>
</div>
<div class="comment-content">
Love how Blue keeps pressure here, but you can see the guard dropping right after scoring.
</div>
<div class="comment-actions">
<button type="button">Reply</button>
<span>12 likes</span>
</div>
<div class="reply-item">
<strong>Coach Ahmed:</strong> Exactly. This is the clip we use in training when we talk about “score and cover”.
</div>
</div>
</div>
<div class="comment-item">
<div class="comment-avatar">
<img src="https://picsum.photos/seed/user2/80/80" alt="User avatar">
</div>
<div class="comment-body">
<div class="comment-header-line">
<span class="comment-author">TKDfan</span>
<span></span>
<span>10 min ago</span>
<span></span>
<span class="comment-time-chip">@full video</span>
</div>
<div class="comment-content">
Great match overall, both fighters stayed active until the last seconds. Respect to both teams.
</div>
<div class="comment-actions">
<button type="button">Reply</button>
<span>5 likes</span>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
<!-- Comment modal -->
<div class="comment-modal-backdrop" id="commentModal">
<div class="comment-modal" role="dialog" aria-modal="true">
<div class="comment-modal-header">
<h3>Add comment</h3>
<button class="comment-modal-close" id="closeCommentModal" aria-label="Close comment">&times;</button>
</div>
<div class="comment-panel-hint">
Choose how you want to link this comment: whole video, a single time stamp, or a time range for a specific exchange.
</div>
<div class="comment-modal-body">
<div class="comment-row">
<div class="comment-timestamp-type">
<span style="font-size:0.78rem;">Link type:</span>
<button type="button" class="active">Video</button>
<button type="button">Time stamp</button>
<button type="button">Time range</button>
</div>
<div class="comment-time-inputs">
<span>From</span>
<input type="text" placeholder="00:45">
<span>To</span>
<input type="text" placeholder="01:10">
</div>
</div>
<textarea class="comment-textarea" placeholder="Share your thoughts about this match or this moment..."></textarea>
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:4px;">
<label class="comment-like-toggle">
<input type="checkbox" style="accent-color:#22c55e; margin:0;">
<span>Like this video</span>
</label>
</div>
</div>
<div class="comment-modal-actions">
<button class="btn-ghost" type="button" id="cancelCommentModal">Cancel</button>
<button class="btn-small" type="button">Post comment</button>
</div>
</div>
</div>
<!-- Share modal -->
<div class="share-modal-backdrop" id="shareModal">
<div class="share-modal" role="dialog" aria-modal="true">
<div class="share-modal-header">
<h3>Share this match</h3>
<button class="share-modal-close" id="closeShareModal" aria-label="Close share">&times;</button>
</div>
<p style="font-size:0.8rem; color:#9ca3af; margin:4px 0 8px;">
Copy a link or share directly to your favorite apps.
</p>
<div class="share-options">
<button class="share-pill" type="button">
📨 <span>Copy link</span>
</button>
<button class="share-pill" type="button">
💬 <span>WhatsApp</span>
</button>
<button class="share-pill" type="button">
🐦 <span>Twitter / X</span>
</button>
<button class="share-pill" type="button">
📘 <span>Facebook</span>
</button>
</div>
<div class="share-link-wrapper">
<span>Link</span>
<input type="text" value="https://example.com/video/taekwondo-finals" readonly>
</div>
<div class="share-modal-actions">
<button class="btn-ghost" type="button" id="cancelShareModal">Close</button>
</div>
</div>
</div>
<!-- Points / Foul modal -->
<div class="coach-modal-backdrop" id="pointsModal">
<div class="coach-modal" role="dialog" aria-modal="true">
<div class="coach-modal-header">
<h3>Register point / foul</h3>
<button class="coach-modal-close" id="closePointsModal" aria-label="Close points modal">&times;</button>
</div>
<div class="coach-panel-hint">
Select the round, fighter, and whether this is a point or a foul, then set the time and impact on the score.
</div>
<div class="coach-form-row">
<div>
<div style="font-size:0.75rem; color:#9ca3af; margin-bottom:4px;">Type</div>
<div class="coach-emoji-select">
<button type="button" data-type="point">🥋</button>
<button type="button" data-type="foul">⚠️</button>
</div>
</div>
<div>
<div style="font-size:0.75rem; color:#9ca3af; margin-bottom:4px;">Round / fighter</div>
<div style="display:flex; gap:6px; flex-wrap:wrap; font-size:0.8rem;">
<select style="flex:1; min-width:80px; padding:4px 6px; border-radius:6px; border:1px solid #111827; background:#020314; color:#e5e7eb;">
<option>Round 1</option>
<option>Round 2</option>
<option>Round 3</option>
</select>
<select style="flex:1; min-width:80px; padding:4px 6px; border-radius:6px; border:1px solid #111827; background:#020314; color:#e5e7eb;">
<option>Blue</option>
<option>Red</option>
</select>
</div>
</div>
</div>
<div class="coach-form-row">
<div>
<div style="font-size:0.75rem; color:#9ca3af; margin-bottom:4px;">Time</div>
<div class="coach-time-range">
<span>At</span>
<input type="text" placeholder="01:12">
</div>
</div>
<div>
<div style="font-size:0.75rem; color:#9ca3af; margin-bottom:4px;">Impact on score</div>
<div style="display:flex; gap:6px; align-items:center; font-size:0.8rem; color:#9ca3af;">
<span>Δ score</span>
<input type="number" placeholder="+1 / -1" style="width:80px; padding:4px 6px; border-radius:6px; border:1px solid #111827; background:#020314; color:#e5e7eb;">
</div>
</div>
</div>
<div class="coach-comment">
<div style="font-size:0.75rem; color:#9ca3af; margin-bottom:4px;">Note (optional)</div>
<textarea placeholder="E.g. body kick scored, gam-jeom for pushing, etc."></textarea>
</div>
<div class="coach-actions">
<button class="btn-ghost" type="button" id="cancelPointsModal">Cancel</button>
<button class="btn-small" type="button">Add event</button>
</div>
</div>
</div>
<aside class="events-sidebar" id="eventsSidebar">
<div class="events-sidebar-header">
<h3>Match events</h3>
<button class="close-btn" id="closeSidebar">&times;</button>
</div>
<div class="tab-header">
<button class="tab-button active" data-tab="official">Points</button>
<button class="tab-button" data-tab="review">Coach review</button>
</div>
<div class="tab-panels">
<div class="tab-panel active" id="tab-official">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:4px;">
<div>
<div class="section-label">Rounds & points</div>
</div>
<button class="btn-icon" type="button" id="openPointsModal">
<!--<span>Add point</span>-->
</button>
</div>
<div class="event-list" id="officialEvents">
<!-- Round marker for Round 1 -->
<div class="round-marker">ROUND 1</div>
<!-- Round 1 points -->
<div class="event-item" data-time-start="20">
<div class="event-time">@00:20</div>
<div>
<div class="event-label">
Blue body kick (1 pt)
<span class="pill pill-blue">Blue</span>
</div>
<div class="event-meta">Round 1 • Score 1 0 • Clean contact.</div>
</div>
</div>
<div class="event-item" data-time-start="45">
<div class="event-time">@00:45</div>
<div>
<div class="event-label">
Blue scores body kick
<span class="pill pill-blue">Blue</span>
</div>
<div class="event-meta">Round 1 • Score 2 0 • Judge: Central.</div>
</div>
</div>
<!-- Round marker for Round 2 -->
<div class="round-marker">ROUND 2</div>
<!-- Round 2 points -->
<div class="event-item" data-time-start="90">
<div class="event-time">@01:30</div>
<div>
<div class="event-label">
Red head kick (3 pts)
<span class="pill pill-red">Red</span>
</div>
<div class="event-meta">Round 2 • Score 2 3 • Video replay requested.</div>
</div>
</div>
<!-- You can add more Round markers like this:
<div class="round-marker">ROUND 3</div>
followed by that round's events.
-->
</div>
</div>
<div class="tab-panel" id="tab-review">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:4px;">
<div class="section-label">Private notes</div>
<button class="btn-icon" type="button" id="openCoachModalFromSidebar">
<!--<span>Coach note</span>-->
</button>
</div>
<div class="event-list" id="reviewEvents">
<div class="event-item" data-time-start="32" data-time-end="50">
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center;">
<div style="font-size:1.2rem; margin-bottom:2px;">🔥</div>
<div class="event-time">@00:3200:50</div>
</div>
<div>
<div class="event-label">Good pressure, but guard too low after first kick</div>
<div class="event-meta">
Coach Ahmed • Hands drop after scoring, drill guard recovery immediately.
</div>
</div>
</div>
<div class="event-item" data-time-start="125" data-time-end="140">
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center;">
<div style="font-size:1.2rem; margin-bottom:2px;">🤔</div>
<div class="event-time">@02:0502:20</div>
</div>
<div>
<div class="event-label">Missed counter opportunity</div>
<div class="event-meta">
Coach Sara • Great angle, but no follow up. Use this clip to discuss risk vs reward.
</div>
</div>
</div>
<div class="event-item" data-time-start="205">
<div style="display:flex; flex-direction:column; align-items:center; justify-content:center;">
<div style="font-size:1.2rem; margin-bottom:2px;">😄</div>
<div class="event-time">@03:25</div>
</div>
<div>
<div class="event-label">Excellent angle change and follow-up</div>
<div class="event-meta">
Coach Ahmed • Save as positive highlight, ideal example of exit and re-entry after scoring.
</div>
</div>
</div>
</div>
</div>
</div>
</aside>
<script>
const video = document.getElementById('sportsVideo');
const playBtn = document.getElementById('playPauseBtn');
const progressBar = document.getElementById('progressBar');
const progressFill = document.getElementById('progressFill');
const progressHandle = document.getElementById('progressHandle');
const currentTimeLabel = document.getElementById('currentTimeLabel');
const durationLabel = document.getElementById('durationLabel');
function formatTime(t) {
if (!isFinite(t)) return '0:00';
const m = Math.floor(t / 60);
const s = Math.floor(t % 60).toString().padStart(2, '0');
return `${m}:${s}`;
}
function updateTimeUI() {
currentTimeLabel.textContent = formatTime(video.currentTime);
durationLabel.textContent = formatTime(video.duration);
const ratio = video.duration ? video.currentTime / video.duration : 0;
const pct = Math.max(0, Math.min(1, ratio)) * 100;
progressFill.style.width = pct + '%';
progressHandle.style.left = pct + '%';
}
video.addEventListener('timeupdate', updateTimeUI);
video.addEventListener('loadedmetadata', updateTimeUI);
playBtn.addEventListener('click', () => {
if (video.paused) {
video.play();
playBtn.textContent = '❚❚';
} else {
video.pause();
playBtn.textContent = '►';
}
});
video.addEventListener('play', () => { playBtn.textContent = '❚❚'; });
video.addEventListener('pause', () => { playBtn.textContent = '►'; });
function seekToRatio(ratio) {
if (!video.duration) return;
const clamped = Math.max(0, Math.min(1, ratio));
video.currentTime = clamped * video.duration;
}
progressBar.addEventListener('click', (e) => {
const rect = progressBar.getBoundingClientRect();
const ratio = (e.clientX - rect.left) / rect.width;
seekToRatio(ratio);
});
function seekWithOptionalSegment(start, end) {
video.currentTime = start;
video.play();
if (!isNaN(end) && end > start) {
const handler = () => {
if (video.currentTime >= end) {
video.pause();
video.removeEventListener('timeupdate', handler);
}
};
video.addEventListener('timeupdate', handler);
}
}
function attachEvents(containerId) {
const container = document.getElementById(containerId);
if (!container || !video) return;
container.addEventListener('click', (e) => {
const item = e.target.closest('.event-item');
if (!item) return;
const start = parseFloat(item.dataset.timeStart || '0');
const end = parseFloat(item.dataset.timeEnd || '0');
seekWithOptionalSegment(start, end);
});
}
const sidebar = document.getElementById('eventsSidebar');
const controllerButtons = document.querySelectorAll('[data-open-sidebar]');
const closeSidebarBtn = document.getElementById('closeSidebar');
let sidebarHover = false;
let sidebarRequested = false;
function openSidebar(mode) {
sidebar.classList.add('open');
sidebarRequested = true;
if (mode === 'official') switchTab('official');
else if (mode === 'review') switchTab('review');
else if (mode === 'both') switchTab('official');
}
function closeSidebar() {
sidebar.classList.remove('open');
sidebarRequested = false;
}
controllerButtons.forEach(btn => {
btn.addEventListener('click', () => {
const mode = btn.dataset.openSidebar;
openSidebar(mode);
});
});
closeSidebarBtn.addEventListener('click', () => { closeSidebar(); });
sidebar.addEventListener('mouseenter', () => { sidebarHover = true; });
sidebar.addEventListener('mouseleave', () => {
sidebarHover = false;
setTimeout(() => {
if (!sidebarHover && sidebarRequested) {
sidebar.classList.remove('open');
sidebarRequested = false;
}
}, 150);
});
const tabButtons = document.querySelectorAll('.tab-button');
const tabPanels = {
official: document.getElementById('tab-official'),
review: document.getElementById('tab-review'),
};
function switchTab(tab) {
tabButtons.forEach(b => {
b.classList.toggle('active', b.dataset.tab === tab);
});
Object.keys(tabPanels).forEach(key => {
tabPanels[key].classList.toggle('active', key === tab);
});
}
tabButtons.forEach(btn => {
btn.addEventListener('click', () => {
switchTab(btn.dataset.tab);
});
});
attachEvents('officialEvents');
attachEvents('reviewEvents');
// Comment modal
const commentModal = document.getElementById('commentModal');
const openCommentModalBtn = document.getElementById('openCommentModal');
const closeCommentModalBtn = document.getElementById('closeCommentModal');
const cancelCommentModalBtn = document.getElementById('cancelCommentModal');
function openCommentModal() {
commentModal.classList.add('open');
}
function closeCommentModal() {
commentModal.classList.remove('open');
}
openCommentModalBtn.addEventListener('click', openCommentModal);
closeCommentModalBtn.addEventListener('click', closeCommentModal);
cancelCommentModalBtn.addEventListener('click', closeCommentModal);
commentModal.addEventListener('click', (e) => {
if (e.target === commentModal) closeCommentModal();
});
// Share modal
const shareModal = document.getElementById('shareModal');
const shareVideoBtn = document.getElementById('shareVideoBtn');
const closeShareModalBtn = document.getElementById('closeShareModal');
const cancelShareModalBtn = document.getElementById('cancelShareModal');
function openShareModal() {
shareModal.classList.add('open');
}
function closeShareModal() {
shareModal.classList.remove('open');
}
shareVideoBtn.addEventListener('click', openShareModal);
closeShareModalBtn.addEventListener('click', closeShareModal);
cancelShareModalBtn.addEventListener('click', closeShareModal);
shareModal.addEventListener('click', (e) => {
if (e.target === shareModal) closeShareModal();
});
// Points modal
const pointsModal = document.getElementById('pointsModal');
const openPointsModalBtn = document.getElementById('openPointsModal');
const closePointsModalBtn = document.getElementById('closePointsModal');
const cancelPointsModalBtn = document.getElementById('cancelPointsModal');
function openPointsModal() {
pointsModal.classList.add('open');
}
function closePointsModal() {
pointsModal.classList.remove('open');
}
openPointsModalBtn.addEventListener('click', openPointsModal);
closePointsModalBtn.addEventListener('click', closePointsModal);
cancelPointsModalBtn.addEventListener('click', closePointsModal);
pointsModal.addEventListener('click', (e) => {
if (e.target === pointsModal) closePointsModal();
});
// Collapsible description
const descriptionBody = document.getElementById('descriptionBody');
const descriptionToggle = document.getElementById('toggleDescription');
const descriptionToggleLabel = document.getElementById('descriptionToggleLabel');
const descriptionToggleIcon = document.getElementById('descriptionToggleIcon');
if (descriptionToggle && descriptionBody) {
descriptionToggle.addEventListener('click', () => {
const isOpen = descriptionBody.classList.toggle('open');
descriptionToggleLabel.textContent = isOpen ? 'Hide description' : 'Show description';
descriptionToggleIcon.textContent = isOpen ? '▲' : '▼';
});
}
</script>
</body>
</html>