laravel-project/templates/match-latets.html

5339 lines
159 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: #0f0f0f;
color: #f1f1f1;
} /* [page:1] */
.page {
max-width: 1280px;
margin: 0 auto;
padding: 24px 16px 64px;
}
.video-shell {
background: #0f0f0f;
border-radius: 16px;
padding: 16px;
/* box-shadow: 0 18px 60px rgba(0, 0, 0, 0.75); */
position: relative;
overflow: hidden;
border: 1px solid #303030;
}
.video-wrapper {
position: relative;
}
/* Overlay controls on top of video */
.video-wrapper .controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0,0,0,0.8));
padding: 20px 16px 12px;
border-radius: 0 0 12px 12px;
margin-top: 0;
}
video {
width: 100%;
border-radius: 12px;
background: #000;
}
.controls {
margin-top: 8px;
display: flex;
flex-direction: column;
gap: 6px;
}
.controls-top {
display: flex;
align-items: center;
gap: 10px;
}
.controls-right {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
}
.volume-control {
display: flex;
align-items: center;
gap: 6px;
}
.volume-btn {
width: 26px;
height: 26px;
border-radius: 999px;
border: 1px solid #303030;
background: #1e1e1e;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #f1f1f1;
font-size: 14px;
}
.volume-slider {
width: 60px;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: #303030;
border-radius: 999px;
cursor: pointer;
}
.volume-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
border-radius: 999px;
background: #f1f1f1;
cursor: pointer;
}
.volume-slider::-moz-range-thumb {
width: 10px;
height: 10px;
border-radius: 999px;
background: #f1f1f1;
cursor: pointer;
border: none;
}
.fullscreen-btn {
width: 26px;
height: 26px;
border-radius: 999px;
border: 1px solid #303030;
background: #1e1e1e;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #f1f1f1;
font-size: 12px;
}
.play-btn {
width: 26px;
height: 26px;
border-radius: 999px;
border: 1px solid #303030;
background: #1e1e1e;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #f1f1f1;
font-size: 14px;
}
.time-labels {
font-size: 0.8rem;
color: #aaaaaa;
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: #1e1e1e;
border: 1px solid #303030;
overflow: hidden;
}
.progress-fill {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0%;
background: linear-gradient(90deg, #e61e1e, #ff4757);
}
.progress-handle {
position: absolute;
top: 50%;
width: 10px;
height: 10px;
border-radius: 999px;
background: #f1f1f1;
box-shadow: 0 0 0 2px #0f0f0f;
transform: translate(-50%, -50%);
pointer-events: none;
}
/* Bookmark markers on progress bar */
.bookmark-marker {
position: absolute;
top: 50%;
width: 8px;
height: 8px;
border-radius: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
z-index: 10;
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.bookmark-marker:hover {
transform: translate(-50%, -50%) scale(1.4);
box-shadow: 0 0 8px rgba(230, 30, 30, 0.6);
}
.bookmark-marker.blue {
background: #2563eb;
border: 2px solid #93c5fd;
}
.bookmark-marker.red {
background: #ef4444;
border: 2px solid #fecaca;
}
.bookmark-marker.yellow {
background: #facc15;
border: 2px solid #fef08a;
}
.bookmark-marker.coach {
background: #22c55e;
border: 2px solid #86efac;
}
.bookmark-marker.white {
background: #ffffff;
border: 2px solid #e5e5e5;
}
.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: #1e1e1e;
border: 1px solid #303030;
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: #aaaaaa;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.meta-link {
font-size: 0.85rem;
color: #aaaaaa;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-decoration: none;
cursor: pointer;
transition: color 0.2s ease;
}
.meta-link:hover {
color: #e61e1e;
}
.event-header-actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.action-btn {
border: none;
border-radius: 8px;
padding: 8px 14px;
font-size: 0.82rem;
font-weight: 500;
cursor: pointer;
background: #1e1e1e;
border: 1px solid #303030;
color: #f1f1f1;
display: flex;
align-items: center;
gap: 6px;
transition: all 0.2s ease;
}
.action-btn:hover {
background: #303030;
border-color: #404040;
transform: translateY(-1px);
}
.action-btn:active {
transform: translateY(0);
}
.action-btn svg {
flex-shrink: 0;
}
.action-btn.liked {
color: #22c55e;
background: rgba(34, 197, 94, 0.15);
border-color: #22c55e;
}
.action-btn.disliked {
color: #ef4444;
background: rgba(239, 68, 68, 0.15);
border-color: #ef4444;
}
.action-btn.saved {
color: #f59e0b;
background: rgba(245, 158, 11, 0.15);
border-color: #f59e0b;
}
.match-card {
margin-top: 16px;
padding: 16px 18px;
border-radius: 14px;
border: 1px solid #303030;
background: radial-gradient(
circle at top,
#1e1e1e 0,
#0f0f0f 45%,
#0f0f0f 100%
);
}
.match-header {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 12px;
}
.match-label {
font-size: 1.2rem;
text-transform: uppercase;
letter-spacing: 0.16em;
color: #f1f1f1;
text-align: center;
font-weight: 600;
}
.fighters-row {
display: grid;
grid-template-columns: 1.1fr 0.8fr 1.1fr;
align-items: stretch;
gap: 16px;
}
.fighter-card {
border-radius: 14px;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.fighter-top {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
width: 100%;
}
.referee-photo {
width: 80px;
height: 115px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 0 0 1px #0f0f0f;
flex-shrink: 0;
}
.fighter-photo {
width: 110px;
height: 145px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 0 0 1px #0f0f0f;
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: #0f0f0f;
}
.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 #404040;
color: #f1f1f1;
}
.fighter-badge.blue {
background: rgba(37, 99, 235, 0.15);
border-color: #1d4ed8;
}
.fighter-badge.red {
background: rgba(239, 68, 68, 0.14);
border-color: #b91c1c;
}
.fighter-badge.yellow {
background: #facc15;
color: #000;
font-weight: bold;
border-color: #eab308;
}
.fighter-name.blue-corner {
color: #2563eb;
font-weight: bold;
}
.fighter-name.red-corner {
color: #ef4444;
font-weight: bold;
}
.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: #aaaaaa;
}
.fighter-country {
display: inline-flex;
justify-content: center;
align-items: center;
gap: 4px;
color: #aaaaaa;
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: #1e1e1e;
border: 1px solid #303030;
}
.score-number {
font-size: 2rem;
font-weight: 700;
}
.score-label {
font-size: 0.75rem;
color: #aaaaaa;
}
.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 #1e1e1e;
box-shadow: 0 0 0 1px #0f0f0f;
}
.ref-photo img {
width: 100%;
height: 100%;
object-fit: cover;
}
.ref-name {
font-size: 0.75rem;
color: #f1f1f1;
}
.ref-label {
font-size: 0.7rem;
color: #aaaaaa;
}
.match-footer {
margin-top: 12px;
font-size: 0.8rem;
color: #666666;
text-align: center;
}
.hall-link {
color: #e61e1e;
font-weight: 600;
text-decoration: none;
cursor: pointer;
transition: color 0.2s ease;
}
.hall-link:hover {
color: #ff4757;
text-decoration: underline;
}
.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 #303030;
background: #1e1e1e;
padding: 8px 10px 10px;
}
.description-toggle {
width: 100%;
border: none;
background: transparent;
color: #f1f1f1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 0.85rem;
cursor: pointer;
padding: 4px 0;
}
.description-toggle:hover {
color: #ffffff;
}
.description-body {
margin-top: 6px;
display: none;
}
.description-body.open {
display: block;
}
/* ====== IMPROVED MODAL STYLES ====== */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.75);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
display: none;
align-items: center;
justify-content: center;
z-index: 100;
opacity: 0;
transition: opacity 0.3s ease;
}
.modal-backdrop.open {
display: flex;
opacity: 1;
}
.modal {
width: 100%;
max-width: 620px;
background: linear-gradient(145deg, #1a1a1a 0%, #0f0f0f 100%);
border-radius: 20px;
border: 1px solid rgba(230, 30, 30, 0.2);
box-shadow:
0 25px 80px rgba(0, 0, 0, 0.9),
0 0 40px rgba(230, 30, 30, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
padding: 20px 24px 24px;
transform: scale(0.9) translateY(20px);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
position: relative;
overflow: hidden;
}
.modal-backdrop.open .modal {
transform: scale(1) translateY(0);
}
.modal::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, #e61e1e, #ff4757, #e61e1e);
background-size: 200% 100%;
animation: shimmer 3s infinite linear;
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
padding-bottom: 12px;
border-bottom: 1px solid rgba(48, 48, 48, 0.6);
}
.modal-header h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
color: #f1f1f1;
display: flex;
align-items: center;
gap: 10px;
}
.modal-header h3::before {
content: "";
width: 4px;
height: 20px;
background: linear-gradient(180deg, #e61e1e, #ff4757);
border-radius: 2px;
}
.modal-close {
width: 32px;
height: 32px;
border: none;
background: rgba(255, 255, 255, 0.05);
color: #888888;
cursor: pointer;
font-size: 1.2rem;
line-height: 1;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.modal-close:hover {
background: rgba(230, 30, 30, 0.2);
color: #e61e1e;
transform: rotate(90deg);
}
.modal-hint {
font-size: 0.82rem;
color: #888888;
margin-bottom: 16px;
line-height: 1.5;
padding: 12px 14px;
background: rgba(230, 30, 30, 0.08);
border-radius: 10px;
border-left: 3px solid rgba(230, 30, 30, 0.4);
}
.form-row {
display: grid;
grid-template-columns: 0.9fr 1.1fr;
gap: 12px;
align-items: flex-start;
margin-bottom: 12px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.form-label {
font-size: 0.75rem;
color: #888888;
text-transform: uppercase;
letter-spacing: 0.08em;
font-weight: 500;
}
.emoji-select {
display: flex;
gap: 4px;
flex-wrap: wrap;
background: #1a1a1a;
border-radius: 12px;
padding: 4px 8px;
border: 1px solid rgba(48, 48, 48, 0.8);
}
.emoji-select button {
border: none;
background: transparent;
cursor: pointer;
font-size: 1.2rem;
line-height: 1;
padding: 6px 8px;
border-radius: 8px;
transition: all 0.2s ease;
}
.emoji-select button:hover {
background: rgba(230, 30, 30, 0.15);
transform: scale(1.1);
}
.emoji-select button.active {
background: rgba(230, 30, 30, 0.25);
box-shadow: 0 0 12px rgba(230, 30, 30, 0.3);
}
.time-range {
display: flex;
gap: 8px;
align-items: center;
font-size: 0.8rem;
color: #888888;
}
.time-range input,
.modal input,
.modal select,
.modal textarea {
width: 100%;
padding: 10px 12px;
border-radius: 10px;
border: 1px solid rgba(48, 48, 48, 0.8);
background: #1a1a1a;
color: #f1f1f1;
font-size: 0.85rem;
transition: all 0.2s ease;
font-family: inherit;
}
.time-range input {
width: 70px;
}
.modal input:focus,
.modal select:focus,
.modal textarea:focus {
outline: none;
border-color: rgba(230, 30, 30, 0.5);
box-shadow: 0 0 0 3px rgba(230, 30, 30, 0.15);
background: #1e1e1e;
}
.modal input::placeholder,
.modal textarea::placeholder {
color: #555555;
}
.modal select {
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23888888' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 12px center;
padding-right: 36px;
}
.modal textarea {
min-height: 80px;
resize: vertical;
line-height: 1.5;
}
.modal-actions {
display: flex;
justify-content: flex-end;
margin-top: 16px;
gap: 10px;
padding-top: 16px;
border-top: 1px solid rgba(48, 48, 48, 0.4);
}
.btn-primary {
border: none;
border-radius: 12px;
padding: 10px 20px;
font-size: 0.85rem;
font-weight: 600;
cursor: pointer;
background: linear-gradient(135deg, #e61e1e 0%, #ff4757 100%);
color: #ffffff;
box-shadow: 0 4px 15px rgba(230, 30, 30, 0.4);
transition: all 0.25s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 25px rgba(230, 30, 30, 0.5);
background: linear-gradient(135deg, #ff4757 0%, #ff6b7a 100%);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
border: 1px solid rgba(48, 48, 48, 0.8);
border-radius: 12px;
padding: 10px 20px;
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
background: rgba(255, 255, 255, 0.03);
color: #888888;
transition: all 0.2s ease;
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(48, 48, 48, 1);
color: #f1f1f1;
}
/* Share modal specific */
.share-description {
font-size: 0.82rem;
color: #888888;
margin: 0 0 16px;
padding: 10px 12px;
background: rgba(255, 255, 255, 0.02);
border-radius: 8px;
}
.share-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 16px;
}
.share-pill {
border: 1px solid rgba(48, 48, 48, 0.6);
border-radius: 12px;
padding: 10px 16px;
font-size: 0.85rem;
cursor: pointer;
background: rgba(255, 255, 255, 0.03);
color: #d1d5db;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.2s ease;
}
.share-pill:hover {
background: rgba(230, 30, 30, 0.15);
border-color: rgba(230, 30, 30, 0.4);
color: #f1f1f1;
transform: translateY(-2px);
}
.share-link-wrapper {
display: flex;
gap: 10px;
align-items: center;
padding: 12px 14px;
background: #1a1a1a;
border-radius: 12px;
border: 1px solid rgba(48, 48, 48, 0.6);
}
.share-link-wrapper span {
font-size: 0.8rem;
color: #888888;
white-space: nowrap;
}
.share-link-wrapper input {
flex: 1;
padding: 8px 10px;
border-radius: 8px;
border: none;
background: #0f0f0f;
color: #f1f1f1;
font-size: 0.8rem;
}
.share-link-wrapper input:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(230, 30, 30, 0.2);
}
/* Comment modal specific */
.comment-row {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: center;
margin-bottom: 12px;
}
.comment-timestamp-type {
display: flex;
gap: 6px;
font-size: 0.78rem;
color: #888888;
align-items: center;
}
.comment-timestamp-type span {
margin-right: 4px;
}
.comment-timestamp-type button {
border: none;
border-radius: 8px;
padding: 6px 12px;
background: #1a1a1a;
border: 1px solid rgba(48, 48, 48, 0.6);
color: #888888;
cursor: pointer;
font-size: 0.75rem;
transition: all 0.2s ease;
}
.comment-timestamp-type button:hover {
background: rgba(230, 30, 30, 0.1);
border-color: rgba(230, 30, 30, 0.3);
}
.comment-timestamp-type button.active {
background: linear-gradient(135deg, #e61e1e 0%, #ff4757 100%);
color: #ffffff;
border-color: transparent;
box-shadow: 0 2px 10px rgba(230, 30, 30, 0.3);
}
.comment-like-toggle {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.85rem;
color: #888888;
margin-top: 8px;
}
.comment-like-toggle input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: #22c55e;
cursor: pointer;
}
/* Coach modal specific - private note */
.coach-icon {
font-size: 1.2rem;
}
.comments-panel {
margin-top: 18px;
padding: 14px 16px;
border-radius: 12px;
border: 1px solid #303030;
background: #1e1e1e;
}
.comments-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.add-comment-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 18px;
font-size: 0.9rem;
font-weight: 600;
color: #ffffff;
background: linear-gradient(135deg, #e61e1e 0%, #ff4757 100%);
border: none;
border-radius: 12px;
cursor: pointer;
transition: all 0.25s ease;
box-shadow: 0 4px 12px rgba(230, 30, 30, 0.3);
}
.add-comment-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(230, 30, 30, 0.4);
background: linear-gradient(135deg, #ff4757 0%, #ff6b7a 100%);
}
.add-comment-btn:active {
transform: translateY(0);
}
.comments-list {
border-top: 1px solid #303030;
padding-top: 8px;
margin-top: 4px;
}
.comment-item {
display: flex;
gap: 8px;
padding: 6px 0;
border-bottom: 1px solid #0f0f0f;
}
.comment-avatar {
width: 28px;
height: 28px;
border-radius: 999px;
overflow: hidden;
background: #1e1e1e;
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: #aaaaaa;
}
.comment-author {
font-weight: 500;
color: #f1f1f1;
}
.comment-time-chip {
padding: 2px 6px;
border-radius: 999px;
border: 1px solid #404040;
background: #1e1e1e;
font-size: 0.75rem;
cursor: pointer;
color: #e61e1e;
}
.comment-content {
margin-top: 2px;
font-size: 0.85rem;
}
.comment-actions {
margin-top: 4px;
font-size: 0.75rem;
color: #666666;
display: flex;
gap: 10px;
align-items: center;
}
.comment-actions button {
border: none;
background: transparent;
color: #666666;
cursor: pointer;
font-size: 0.75rem;
padding: 0;
}
.reply-item {
margin-top: 4px;
margin-left: 24px;
padding-left: 8px;
border-left: 1px solid #303030;
font-size: 0.8rem;
color: #aaaaaa;
}
.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: #aaaaaa;
}
.comment-timestamp-type button {
border: none;
border-radius: 999px;
padding: 3px 8px;
background: #1e1e1e;
border: 1px solid #303030;
color: #aaaaaa;
cursor: pointer;
font-size: 0.75rem;
}
.comment-timestamp-type button.active {
background: #e61e1e;
color: #ffffff;
border-color: #e61e1e;
}
.comment-time-inputs {
display: flex;
gap: 6px;
align-items: center;
font-size: 0.8rem;
color: #aaaaaa;
}
.comment-time-inputs input {
width: 70px;
padding: 4px 6px;
border-radius: 6px;
border: 1px solid #303030;
background: #1e1e1e;
color: #f1f1f1;
font-size: 0.8rem;
}
.comment-textarea {
width: 100%;
min-height: 60px;
resize: vertical;
border-radius: 8px;
border: 1px solid #303030;
background: #1e1e1e;
color: #f1f1f1;
font-size: 0.85rem;
padding: 6px 8px;
}
.comment-like-toggle {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.8rem;
color: #aaaaaa;
}
.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: #1e1e1e;
border: 1px solid #303030;
color: #d1d5db;
display: flex;
align-items: center;
gap: 6px;
}
.share-link-wrapper {
display: flex;
gap: 6px;
align-items: center;
font-size: 0.8rem;
color: #aaaaaa;
}
.share-link-wrapper input {
flex: 1;
padding: 4px 6px;
border-radius: 6px;
border: 1px solid #303030;
background: #1e1e1e;
color: #f1f1f1;
font-size: 0.8rem;
}
.events-sidebar {
position: fixed;
top: 0;
right: 0;
width: 340px;
max-width: 80vw;
height: 100vh;
background: #0f0f0f;
border-left: 1px solid #303030;
box-shadow: -12px 0 40px rgba(0, 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 #303030;
}
.events-sidebar-header h3 {
margin: 0;
font-size: 0.95rem;
}
.close-btn {
border: none;
background: transparent;
color: #aaaaaa;
cursor: pointer;
font-size: 1rem;
}
.tab-header {
display: flex;
gap: 6px;
margin: 10px 12px 6px;
border-bottom: 1px solid #303030;
padding-bottom: 4px;
}
.tab-button {
flex: 1;
text-align: center;
padding: 6px 0;
font-size: 0.85rem;
color: #aaaaaa;
cursor: pointer;
border-radius: 999px;
background: transparent;
border: none;
position: relative;
}
.tab-button.active {
background: #1e1e1e;
color: #f1f1f1;
font-weight: 500;
}
.tab-button.active::after {
content: "";
position: absolute;
left: 8px;
right: 8px;
bottom: -4px;
height: 4px;
background: #0f0f0f;
}
.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 #303030;
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: #1e1e1e;
}
.event-time {
font-size: 0.8rem;
color: #ffd900;
min-width: 80px;
text-align: center;
}
.event-label {
font-size: 0.9rem;
}
.event-meta {
font-size: 0.75rem;
color: #666666;
}
.pill {
display: inline-block;
padding: 2px 6px;
border-radius: 999px;
font-size: 0.7rem;
margin-left: 4px;
}
.pill-blue {
background: #2563eb;
color: #bfdbfe;
}
.pill-red {
background: #ef4444;
color: #fecaca;
}
.section-label {
text-transform: uppercase;
font-size: 0.75rem;
letter-spacing: 0.08em;
color: #666666;
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: #eab308;
color: #000000;
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, 15, 15, 0.9);
color: #d1d5db;
border: 1px solid #303030;
}
.events-controller button:hover {
background: #1e1e1e;
}
@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-wrapper">
<div class="events-controller">
<button data-open-sidebar="both">Bookmarks</button>
</div>
<video
id="sportsVideo"
src="https://video.innovator.bh/videos/15/stream"
></video>
<!-- Custom Video Controls -->
<div class="controls" id="videoControls">
<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>
<!-- Bookmark markers will be rendered here -->
<div id="bookmarkMarkers"></div>
</div>
</div>
<div class="controls-top">
<button class="play-btn" id="playBtn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>
</button>
<div class="time-labels">
<span id="currentTime">0:00</span>
<span>/</span>
<span id="duration">0:00</span>
</div>
<div class="controls-right">
<div class="volume-control">
<button class="volume-btn" id="volumeBtn" title="Volume">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>
</svg>
</button>
<input type="range" class="volume-slider" id="volumeSlider" min="0" max="1" step="0.1" value="1" title="Volume">
</div>
<button class="fullscreen-btn" id="fullscreenBtn" title="Fullscreen">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path>
</svg>
</button>
</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
<span style="color: #2563eb; font-weight: bold"
>🇧🇭 Ali Mohammed</span
>
vs
<span style="color: #ef4444; font-weight: bold"
>🇸🇦 Omar AlKhaled</span
>
(U18)
</h1>
<a class="meta-link" href="/championship/2026"
>📍 Championship 2026 • Match# 103 • Court 2 •
<span style="color: #ffd900; font-weight: bold"
>M. AlKhalifa</span
></a
>
</div>
</div>
<div class="event-header-actions">
<button class="action-btn" type="button" title="Like">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
></path>
</svg>
<span>1.3k</span>
</button>
<button class="action-btn" type="button" title="Dislike">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
></path>
</svg>
<span>103</span>
</button>
<button
class="action-btn"
type="button"
id="shareVideoBtn"
title="Share"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path>
<polyline points="16 6 12 2 8 6"></polyline>
<line x1="12" y1="2" x2="12" y2="15"></line>
</svg>
<span>Share</span>
</button>
<button class="action-btn" type="button" title="Save">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"
></path>
</svg>
<span>Save</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 blue-corner">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="referee-photo">
<img
src="https://picsum.photos/seed/red-competitor/200/260"
alt="Referee"
/>
</div>
<div style="color: #ffd900; font-weight: bold">
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 red-corner">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">
<a
class="hall-link"
id="hallLink"
title="View venue details"
href="https://maps.google.com/?q=Manama+Sports+Hall+Bahrain"
target="_blank"
rel="noopener noreferrer"
>
📍 Manama Sports Hall
</a>
• Electronic scoring system (PSS & headgear) • Video replay
available for head kicks and gam-jeom appeals
</div>
</section>
<section class="markdown-body">
<h2>Match Overview</h2>
<p>
This Male U18 -63kg final features three 2:00 rounds (with a
golden point tie-breaker) showcasing a classic clash of styles:
Blue drives the action with relentless pressure, body kicks, and
ring control, while Red utilizes angle changes to set up tactical
head-shot counters. When analyzing the replay, coaches and
athletes should focus on distance management and guard resets
immediately following exchanges, specifically noting how conceding
points affects a fighter's momentum and leads to hesitation.
Furthermore, close attention should be paid to the effectiveness
of corner instructions and tactical time-outs, evaluating how
consistently each fighter adheres to the established game plan
during the high-fatigue environment of the final 30 seconds of
every 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>
<button class="add-comment-btn" type="button" id="openCommentModal">
💬 Add Comment
</button>
</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">
<div
class="comment-avatar"
style="
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
"
>
<img
src="https://picsum.photos/seed/coach-ahmed/80/80"
alt="Coach Ahmed"
/>
</div>
<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>
<!-- Comment Modal -->
<div class="modal-backdrop" id="commentModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>💬 Add Comment</h3>
<button class="modal-close" id="closeCommentModal" aria-label="Close">
&times;
</button>
</div>
<div class="modal-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-row">
<div class="comment-timestamp-type">
<span>Link type:</span>
<button type="button" class="active">Video</button>
<button type="button">Time stamp</button>
<button type="button">Time range</button>
</div>
</div>
<div class="comment-row">
<div class="time-range">
<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>
<label class="comment-like-toggle">
<input type="checkbox" />
<span>Like this video</span>
</label>
<div class="modal-actions">
<button class="btn-secondary" type="button" id="cancelCommentModal">
Cancel
</button>
<button class="btn-primary" type="button">Post Comment</button>
</div>
</div>
</div>
<!-- Share Modal -->
<div class="modal-backdrop" id="shareModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>📤 Share this Match</h3>
<button class="modal-close" id="closeShareModal" aria-label="Close">
&times;
</button>
</div>
<p class="share-description">
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="modal-actions">
<button class="btn-secondary" type="button" id="cancelShareModal">
Close
</button>
</div>
</div>
</div>
<!-- Points/Foul Modal -->
<div class="modal-backdrop" id="pointsModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>🥋 Register Point / Foul</h3>
<button class="modal-close" id="closePointsModal" aria-label="Close">
&times;
</button>
</div>
<div class="modal-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="form-row">
<div class="form-group">
<label class="form-label">Type</label>
<div class="emoji-select">
<button type="button" data-type="point" class="active">🥋</button>
<button type="button" data-type="foul">⚠️</button>
</div>
</div>
<div class="form-group">
<label class="form-label">Round / Fighter</label>
<div style="display: flex; gap: 8px">
<select>
<option>Round 1</option>
<option>Round 2</option>
<option>Round 3</option>
</select>
<select>
<option>Blue</option>
<option>Red</option>
</select>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Time</label>
<div class="time-range">
<span>At</span>
<input type="text" placeholder="01:12" />
</div>
</div>
<div class="form-group">
<label class="form-label">Impact on Score</label>
<div class="time-range">
<span>Δ score</span>
<input type="number" placeholder="+1 / -1" />
</div>
</div>
</div>
<div class="form-group">
<label class="form-label">Note (optional)</label>
<textarea
placeholder="E.g. body kick scored, gam-jeom for pushing, etc."
></textarea>
</div>
<div class="modal-actions">
<button class="btn-secondary" type="button" id="cancelPointsModal">
Cancel
</button>
<button class="btn-primary" type="button">Add Event</button>
</div>
</div>
</div>
<!-- Coach Review Modal (Private Note) - Missing Modal -->
<div class="modal-backdrop" id="coachModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>📝 Coach Private Note</h3>
<button class="modal-close" id="closeCoachModal" aria-label="Close">
&times;
</button>
</div>
<div class="modal-hint">
Add a private note for coaching purposes. This will only be visible to
coaches and won't be shared publicly.
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Reaction</label>
<div class="emoji-select">
<button type="button" data-emoji="🔥" class="active">🔥</button>
<button type="button" data-emoji="🤔">🤔</button>
<button type="button" data-emoji="😄">😄</button>
<button type="button" data-emoji="💪">💪</button>
<button type="button" data-emoji="⚠️">⚠️</button>
</div>
</div>
<div class="form-group">
<label class="form-label">Time Range</label>
<div class="time-range">
<span>From</span>
<input type="text" placeholder="00:32" />
<span>To</span>
<input type="text" placeholder="00:50" />
</div>
</div>
</div>
<div class="form-group">
<label class="form-label">Note Title</label>
<input
type="text"
placeholder="E.g. Good pressure, guard dropping..."
/>
</div>
<div class="form-group">
<label class="form-label">Detailed Note</label>
<textarea
placeholder="Describe what happened, what to work on, drills to practice, tactical observations..."
></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Fighter</label>
<select>
<option>Both Fighters</option>
<option>Blue Corner</option>
<option>Red Corner</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Priority</label>
<select>
<option>🔴 High Priority</option>
<option>🟡 Medium</option>
<option>🟢 Low</option>
</select>
</div>
</div>
<div class="modal-actions">
<button class="btn-secondary" type="button" id="cancelCoachModal">
Cancel
</button>
<button class="btn-primary" type="button">Save Note</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">
<div
class="comment-avatar"
style="
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
"
>
<img
src="https://picsum.photos/seed/coach-ahmed/80/80"
alt="Coach Ahmed"
/>
</div>
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">
<div
class="comment-avatar"
style="
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
"
>
<img
src="https://picsum.photos/seed/coach-ahmed/80/80"
alt="Coach Ahmed"
/>
</div>
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");
function seekWithOptionalSegment(start, end) {
// Go 1 second before and play
const seekTime = Math.max(0, start - 1);
video.currentTime = seekTime;
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();
});
// Coach modal (Private Note)
const coachModal = document.getElementById("coachModal");
const openCoachModalFromSidebar = document.getElementById(
"openCoachModalFromSidebar",
);
const closeCoachModalBtn = document.getElementById("closeCoachModal");
const cancelCoachModalBtn = document.getElementById("cancelCoachModal");
function openCoachModal() {
coachModal.classList.add("open");
}
function closeCoachModal() {
coachModal.classList.remove("open");
}
if (openCoachModalFromSidebar) {
openCoachModalFromSidebar.addEventListener("click", openCoachModal);
}
if (closeCoachModalBtn) {
closeCoachModalBtn.addEventListener("click", closeCoachModal);
}
if (cancelCoachModalBtn) {
cancelCoachModalBtn.addEventListener("click", closeCoachModal);
}
if (coachModal) {
coachModal.addEventListener("click", (e) => {
if (e.target === coachModal) closeCoachModal();
});
}
// Emoji select toggle functionality
document.querySelectorAll(".emoji-select button").forEach((btn) => {
btn.addEventListener("click", function () {
const parent = this.closest(".emoji-select");
parent
.querySelectorAll("button")
.forEach((b) => b.classList.remove("active"));
this.classList.add("active");
});
});
// 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 ? "▲" : "▼";
});
}
// Hall/Venue click handler
const hallLink = document.getElementById("hallLink");
if (hallLink) {
hallLink.addEventListener("click", () => {
// Open venue details or navigate to venue page
alert("Manama Sports Hall - View venue details");
});
}
// ==================== Custom Video Controls ====================
const playBtn = document.getElementById("playBtn");
const progressBar = document.getElementById("progressBar");
const progressWrapper = document.getElementById("progressWrapper");
const progressFill = document.getElementById("progressFill");
const progressHandle = document.getElementById("progressHandle");
const currentTimeEl = document.getElementById("currentTime");
const durationEl = document.getElementById("duration");
const bookmarkMarkersContainer = document.getElementById("bookmarkMarkers");
let isPlaying = false;
// Format time (seconds to MM:SS)
function formatTime(seconds) {
if (isNaN(seconds)) return "0:00";
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, "0")}`;
}
// Toggle play/pause
function togglePlay() {
if (video.paused) {
video.play();
} else {
video.pause();
}
}
playBtn.addEventListener("click", togglePlay);
video.addEventListener("click", togglePlay);
// Update play button icon
video.addEventListener("play", () => {
isPlaying = true;
playBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<rect x="6" y="4" width="4" height="16"></rect>
<rect x="14" y="4" width="4" height="16"></rect>
</svg>`;
});
video.addEventListener("pause", () => {
isPlaying = false;
playBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>`;
});
// Update progress bar
video.addEventListener("timeupdate", () => {
if (video.duration) {
const percent = (video.currentTime / video.duration) * 100;
progressFill.style.width = `${percent}%`;
progressHandle.style.left = `${percent}%`;
currentTimeEl.textContent = formatTime(video.currentTime);
}
});
// Set duration when loaded
video.addEventListener("loadedmetadata", () => {
durationEl.textContent = formatTime(video.duration);
// Render bookmarks after video metadata is loaded
renderBookmarkMarkers();
});
// Seek on progress bar click
progressWrapper.addEventListener("click", (e) => {
const rect = progressBar.getBoundingClientRect();
const percent = (e.clientX - rect.left) / rect.width;
video.currentTime = percent * video.duration;
});
// ==================== Volume Control ====================
const volumeBtn = document.getElementById("volumeBtn");
const volumeSlider = document.getElementById("volumeSlider");
// Set initial volume
video.volume = 1;
// Volume button click - toggle mute
volumeBtn.addEventListener("click", () => {
if (video.muted) {
video.muted = false;
video.volume = volumeSlider.value;
volumeBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>
</svg>`;
} else {
video.muted = true;
volumeBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<line x1="23" y1="9" x2="17" y2="15"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</svg>`;
}
});
// Volume slider change
volumeSlider.addEventListener("input", (e) => {
video.volume = e.target.value;
video.muted = false;
volumeBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>
</svg>`;
});
// ==================== Fullscreen Control ====================
const fullscreenBtn = document.getElementById("fullscreenBtn");
const videoWrapper = document.querySelector(".video-wrapper");
fullscreenBtn.addEventListener("click", () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else if (videoWrapper.requestFullscreen) {
videoWrapper.requestFullscreen();
} else if (video.webkitEnterFullscreen) {
// Safari support
video.webkitEnterFullscreen();
}
});
// ==================== Bookmark Markers ====================
// Get all bookmark data from the event lists
function getBookmarks() {
const bookmarks = [];
// Get official events (Points)
const officialEvents = document.querySelectorAll("#officialEvents .event-item");
officialEvents.forEach(item => {
const timeStart = parseFloat(item.dataset.timeStart);
if (!isNaN(timeStart)) {
// Determine color and type based on the event label
const label = item.querySelector(".event-label")?.textContent || "";
let colorClass = "yellow"; // Default for fouls
let bookmarkType = "point";
if (label.includes("Blue")) {
colorClass = "blue";
} else if (label.includes("Red")) {
colorClass = "red";
}
// Check for foul keywords
if (label.toLowerCase().includes("foul") || label.toLowerCase().includes("gam-jeom") || label.toLowerCase().includes("penalty")) {
colorClass = "yellow";
}
bookmarks.push({
time: timeStart,
timeEnd: parseFloat(item.dataset.timeEnd) || null,
color: colorClass,
type: bookmarkType,
label: label
});
}
});
// Get coach review events
const reviewEvents = document.querySelectorAll("#reviewEvents .event-item");
reviewEvents.forEach(item => {
const timeStart = parseFloat(item.dataset.timeStart);
const timeEnd = parseFloat(item.dataset.timeEnd);
if (!isNaN(timeStart)) {
bookmarks.push({
time: timeStart,
timeEnd: isNaN(timeEnd) ? null : timeEnd,
color: "white",
type: "coach"
});
}
});
return bookmarks;
}
// Render bookmark markers on progress bar
function renderBookmarkMarkers() {
if (!bookmarkMarkersContainer || !video.duration) return;
const bookmarks = getBookmarks();
bookmarkMarkersContainer.innerHTML = "";
bookmarks.forEach(bookmark => {
const marker = document.createElement("div");
marker.className = `bookmark-marker ${bookmark.color}`;
const percent = (bookmark.time / video.duration) * 100;
marker.style.left = `${percent}%`;
marker.title = `Jump to ${formatTime(bookmark.time)}`;
// Click on marker based on type
marker.addEventListener("click", (e) => {
e.stopPropagation(); // Prevent seeking to wrong position
if (bookmark.type === "coach" && bookmark.timeEnd && bookmark.timeEnd > bookmark.time) {
// Coach review with time range: play from start to end
video.currentTime = bookmark.time;
video.play();
// Remove any existing timeupdate handler first
video.removeEventListener("timeupdate", window.coachTimeUpdateHandler);
// Create new handler to stop at end time
window.coachTimeUpdateHandler = function() {
if (video.currentTime >= bookmark.timeEnd - 0.1) {
video.pause();
video.currentTime = bookmark.timeEnd; // Ensure we stop exactly at end
video.removeEventListener("timeupdate", window.coachTimeUpdateHandler);
}
};
video.addEventListener("timeupdate", window.coachTimeUpdateHandler);
} else if (bookmark.type === "coach") {
// Coach review without time range: go 1 second before and play
const seekTime = Math.max(0, bookmark.time - 1);
video.currentTime = seekTime;
video.play();
} else {
// Point: play directly from the bookmark timestamp
video.currentTime = bookmark.time;
video.play();
}
});
bookmarkMarkersContainer.appendChild(marker);
});
}
// Re-render bookmarks when video is ready
video.addEventListener("loadeddata", renderBookmarkMarkers);
</script>
</body>
</html><!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: #0f0f0f;
color: #f1f1f1;
} /* [page:1] */
.page {
max-width: 1280px;
margin: 0 auto;
padding: 24px 16px 64px;
}
.video-shell {
background: #0f0f0f;
border-radius: 16px;
padding: 16px;
/* box-shadow: 0 18px 60px rgba(0, 0, 0, 0.75); */
position: relative;
overflow: hidden;
border: 1px solid #303030;
}
.video-wrapper {
position: relative;
}
/* Overlay controls on top of video */
.video-wrapper .controls {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0,0,0,0.8));
padding: 20px 16px 12px;
border-radius: 0 0 12px 12px;
margin-top: 0;
}
video {
width: 100%;
border-radius: 12px;
background: #000;
}
.controls {
margin-top: 8px;
display: flex;
flex-direction: column;
gap: 6px;
}
.controls-top {
display: flex;
align-items: center;
gap: 10px;
}
.controls-right {
display: flex;
align-items: center;
gap: 8px;
margin-left: auto;
}
.volume-control {
display: flex;
align-items: center;
gap: 6px;
}
.volume-btn {
width: 26px;
height: 26px;
border-radius: 999px;
border: 1px solid #303030;
background: #1e1e1e;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #f1f1f1;
font-size: 14px;
}
.volume-slider {
width: 60px;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: #303030;
border-radius: 999px;
cursor: pointer;
}
.volume-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
border-radius: 999px;
background: #f1f1f1;
cursor: pointer;
}
.volume-slider::-moz-range-thumb {
width: 10px;
height: 10px;
border-radius: 999px;
background: #f1f1f1;
cursor: pointer;
border: none;
}
.fullscreen-btn {
width: 26px;
height: 26px;
border-radius: 999px;
border: 1px solid #303030;
background: #1e1e1e;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #f1f1f1;
font-size: 12px;
}
.play-btn {
width: 26px;
height: 26px;
border-radius: 999px;
border: 1px solid #303030;
background: #1e1e1e;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: #f1f1f1;
font-size: 14px;
}
.time-labels {
font-size: 0.8rem;
color: #aaaaaa;
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: #1e1e1e;
border: 1px solid #303030;
overflow: hidden;
}
.progress-fill {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0%;
background: linear-gradient(90deg, #e61e1e, #ff4757);
}
.progress-handle {
position: absolute;
top: 50%;
width: 10px;
height: 10px;
border-radius: 999px;
background: #f1f1f1;
box-shadow: 0 0 0 2px #0f0f0f;
transform: translate(-50%, -50%);
pointer-events: none;
}
/* Bookmark markers on progress bar */
.bookmark-marker {
position: absolute;
top: 50%;
width: 8px;
height: 8px;
border-radius: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
z-index: 10;
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.bookmark-marker:hover {
transform: translate(-50%, -50%) scale(1.4);
box-shadow: 0 0 8px rgba(230, 30, 30, 0.6);
}
.bookmark-marker.blue {
background: #2563eb;
border: 2px solid #93c5fd;
}
.bookmark-marker.red {
background: #ef4444;
border: 2px solid #fecaca;
}
.bookmark-marker.yellow {
background: #facc15;
border: 2px solid #fef08a;
}
.bookmark-marker.coach {
background: #22c55e;
border: 2px solid #86efac;
}
.bookmark-marker.white {
background: #ffffff;
border: 2px solid #e5e5e5;
}
.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: #1e1e1e;
border: 1px solid #303030;
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: #aaaaaa;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.meta-link {
font-size: 0.85rem;
color: #aaaaaa;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-decoration: none;
cursor: pointer;
transition: color 0.2s ease;
}
.meta-link:hover {
color: #e61e1e;
}
.event-header-actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.action-btn {
border: none;
border-radius: 8px;
padding: 8px 14px;
font-size: 0.82rem;
font-weight: 500;
cursor: pointer;
background: #1e1e1e;
border: 1px solid #303030;
color: #f1f1f1;
display: flex;
align-items: center;
gap: 6px;
transition: all 0.2s ease;
}
.action-btn:hover {
background: #303030;
border-color: #404040;
transform: translateY(-1px);
}
.action-btn:active {
transform: translateY(0);
}
.action-btn svg {
flex-shrink: 0;
}
.action-btn.liked {
color: #22c55e;
background: rgba(34, 197, 94, 0.15);
border-color: #22c55e;
}
.action-btn.disliked {
color: #ef4444;
background: rgba(239, 68, 68, 0.15);
border-color: #ef4444;
}
.action-btn.saved {
color: #f59e0b;
background: rgba(245, 158, 11, 0.15);
border-color: #f59e0b;
}
.match-card {
margin-top: 16px;
padding: 16px 18px;
border-radius: 14px;
border: 1px solid #303030;
background: radial-gradient(
circle at top,
#1e1e1e 0,
#0f0f0f 45%,
#0f0f0f 100%
);
}
.match-header {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 12px;
}
.match-label {
font-size: 1.2rem;
text-transform: uppercase;
letter-spacing: 0.16em;
color: #f1f1f1;
text-align: center;
font-weight: 600;
}
.fighters-row {
display: grid;
grid-template-columns: 1.1fr 0.8fr 1.1fr;
align-items: stretch;
gap: 16px;
}
.fighter-card {
border-radius: 14px;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.fighter-top {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
width: 100%;
}
.referee-photo {
width: 80px;
height: 115px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 0 0 1px #0f0f0f;
flex-shrink: 0;
}
.fighter-photo {
width: 110px;
height: 145px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 0 0 1px #0f0f0f;
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: #0f0f0f;
}
.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 #404040;
color: #f1f1f1;
}
.fighter-badge.blue {
background: rgba(37, 99, 235, 0.15);
border-color: #1d4ed8;
}
.fighter-badge.red {
background: rgba(239, 68, 68, 0.14);
border-color: #b91c1c;
}
.fighter-badge.yellow {
background: #facc15;
color: #000;
font-weight: bold;
border-color: #eab308;
}
.fighter-name.blue-corner {
color: #2563eb;
font-weight: bold;
}
.fighter-name.red-corner {
color: #ef4444;
font-weight: bold;
}
.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: #aaaaaa;
}
.fighter-country {
display: inline-flex;
justify-content: center;
align-items: center;
gap: 4px;
color: #aaaaaa;
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: #1e1e1e;
border: 1px solid #303030;
}
.score-number {
font-size: 2rem;
font-weight: 700;
}
.score-label {
font-size: 0.75rem;
color: #aaaaaa;
}
.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 #1e1e1e;
box-shadow: 0 0 0 1px #0f0f0f;
}
.ref-photo img {
width: 100%;
height: 100%;
object-fit: cover;
}
.ref-name {
font-size: 0.75rem;
color: #f1f1f1;
}
.ref-label {
font-size: 0.7rem;
color: #aaaaaa;
}
.match-footer {
margin-top: 12px;
font-size: 0.8rem;
color: #666666;
text-align: center;
}
.hall-link {
color: #e61e1e;
font-weight: 600;
text-decoration: none;
cursor: pointer;
transition: color 0.2s ease;
}
.hall-link:hover {
color: #ff4757;
text-decoration: underline;
}
.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 #303030;
background: #1e1e1e;
padding: 8px 10px 10px;
}
.description-toggle {
width: 100%;
border: none;
background: transparent;
color: #f1f1f1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 0.85rem;
cursor: pointer;
padding: 4px 0;
}
.description-toggle:hover {
color: #ffffff;
}
.description-body {
margin-top: 6px;
display: none;
}
.description-body.open {
display: block;
}
/* ====== IMPROVED MODAL STYLES ====== */
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.75);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
display: none;
align-items: center;
justify-content: center;
z-index: 100;
opacity: 0;
transition: opacity 0.3s ease;
}
.modal-backdrop.open {
display: flex;
opacity: 1;
}
.modal {
width: 100%;
max-width: 620px;
background: linear-gradient(145deg, #1a1a1a 0%, #0f0f0f 100%);
border-radius: 20px;
border: 1px solid rgba(230, 30, 30, 0.2);
box-shadow:
0 25px 80px rgba(0, 0, 0, 0.9),
0 0 40px rgba(230, 30, 30, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
padding: 20px 24px 24px;
transform: scale(0.9) translateY(20px);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
position: relative;
overflow: hidden;
}
.modal-backdrop.open .modal {
transform: scale(1) translateY(0);
}
.modal::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, #e61e1e, #ff4757, #e61e1e);
background-size: 200% 100%;
animation: shimmer 3s infinite linear;
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
padding-bottom: 12px;
border-bottom: 1px solid rgba(48, 48, 48, 0.6);
}
.modal-header h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
color: #f1f1f1;
display: flex;
align-items: center;
gap: 10px;
}
.modal-header h3::before {
content: "";
width: 4px;
height: 20px;
background: linear-gradient(180deg, #e61e1e, #ff4757);
border-radius: 2px;
}
.modal-close {
width: 32px;
height: 32px;
border: none;
background: rgba(255, 255, 255, 0.05);
color: #888888;
cursor: pointer;
font-size: 1.2rem;
line-height: 1;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.modal-close:hover {
background: rgba(230, 30, 30, 0.2);
color: #e61e1e;
transform: rotate(90deg);
}
.modal-hint {
font-size: 0.82rem;
color: #888888;
margin-bottom: 16px;
line-height: 1.5;
padding: 12px 14px;
background: rgba(230, 30, 30, 0.08);
border-radius: 10px;
border-left: 3px solid rgba(230, 30, 30, 0.4);
}
.form-row {
display: grid;
grid-template-columns: 0.9fr 1.1fr;
gap: 12px;
align-items: flex-start;
margin-bottom: 12px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.form-label {
font-size: 0.75rem;
color: #888888;
text-transform: uppercase;
letter-spacing: 0.08em;
font-weight: 500;
}
.emoji-select {
display: flex;
gap: 4px;
flex-wrap: wrap;
background: #1a1a1a;
border-radius: 12px;
padding: 4px 8px;
border: 1px solid rgba(48, 48, 48, 0.8);
}
.emoji-select button {
border: none;
background: transparent;
cursor: pointer;
font-size: 1.2rem;
line-height: 1;
padding: 6px 8px;
border-radius: 8px;
transition: all 0.2s ease;
}
.emoji-select button:hover {
background: rgba(230, 30, 30, 0.15);
transform: scale(1.1);
}
.emoji-select button.active {
background: rgba(230, 30, 30, 0.25);
box-shadow: 0 0 12px rgba(230, 30, 30, 0.3);
}
.time-range {
display: flex;
gap: 8px;
align-items: center;
font-size: 0.8rem;
color: #888888;
}
.time-range input,
.modal input,
.modal select,
.modal textarea {
width: 100%;
padding: 10px 12px;
border-radius: 10px;
border: 1px solid rgba(48, 48, 48, 0.8);
background: #1a1a1a;
color: #f1f1f1;
font-size: 0.85rem;
transition: all 0.2s ease;
font-family: inherit;
}
.time-range input {
width: 70px;
}
.modal input:focus,
.modal select:focus,
.modal textarea:focus {
outline: none;
border-color: rgba(230, 30, 30, 0.5);
box-shadow: 0 0 0 3px rgba(230, 30, 30, 0.15);
background: #1e1e1e;
}
.modal input::placeholder,
.modal textarea::placeholder {
color: #555555;
}
.modal select {
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23888888' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 12px center;
padding-right: 36px;
}
.modal textarea {
min-height: 80px;
resize: vertical;
line-height: 1.5;
}
.modal-actions {
display: flex;
justify-content: flex-end;
margin-top: 16px;
gap: 10px;
padding-top: 16px;
border-top: 1px solid rgba(48, 48, 48, 0.4);
}
.btn-primary {
border: none;
border-radius: 12px;
padding: 10px 20px;
font-size: 0.85rem;
font-weight: 600;
cursor: pointer;
background: linear-gradient(135deg, #e61e1e 0%, #ff4757 100%);
color: #ffffff;
box-shadow: 0 4px 15px rgba(230, 30, 30, 0.4);
transition: all 0.25s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 25px rgba(230, 30, 30, 0.5);
background: linear-gradient(135deg, #ff4757 0%, #ff6b7a 100%);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
border: 1px solid rgba(48, 48, 48, 0.8);
border-radius: 12px;
padding: 10px 20px;
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
background: rgba(255, 255, 255, 0.03);
color: #888888;
transition: all 0.2s ease;
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(48, 48, 48, 1);
color: #f1f1f1;
}
/* Share modal specific */
.share-description {
font-size: 0.82rem;
color: #888888;
margin: 0 0 16px;
padding: 10px 12px;
background: rgba(255, 255, 255, 0.02);
border-radius: 8px;
}
.share-options {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 16px;
}
.share-pill {
border: 1px solid rgba(48, 48, 48, 0.6);
border-radius: 12px;
padding: 10px 16px;
font-size: 0.85rem;
cursor: pointer;
background: rgba(255, 255, 255, 0.03);
color: #d1d5db;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.2s ease;
}
.share-pill:hover {
background: rgba(230, 30, 30, 0.15);
border-color: rgba(230, 30, 30, 0.4);
color: #f1f1f1;
transform: translateY(-2px);
}
.share-link-wrapper {
display: flex;
gap: 10px;
align-items: center;
padding: 12px 14px;
background: #1a1a1a;
border-radius: 12px;
border: 1px solid rgba(48, 48, 48, 0.6);
}
.share-link-wrapper span {
font-size: 0.8rem;
color: #888888;
white-space: nowrap;
}
.share-link-wrapper input {
flex: 1;
padding: 8px 10px;
border-radius: 8px;
border: none;
background: #0f0f0f;
color: #f1f1f1;
font-size: 0.8rem;
}
.share-link-wrapper input:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(230, 30, 30, 0.2);
}
/* Comment modal specific */
.comment-row {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: center;
margin-bottom: 12px;
}
.comment-timestamp-type {
display: flex;
gap: 6px;
font-size: 0.78rem;
color: #888888;
align-items: center;
}
.comment-timestamp-type span {
margin-right: 4px;
}
.comment-timestamp-type button {
border: none;
border-radius: 8px;
padding: 6px 12px;
background: #1a1a1a;
border: 1px solid rgba(48, 48, 48, 0.6);
color: #888888;
cursor: pointer;
font-size: 0.75rem;
transition: all 0.2s ease;
}
.comment-timestamp-type button:hover {
background: rgba(230, 30, 30, 0.1);
border-color: rgba(230, 30, 30, 0.3);
}
.comment-timestamp-type button.active {
background: linear-gradient(135deg, #e61e1e 0%, #ff4757 100%);
color: #ffffff;
border-color: transparent;
box-shadow: 0 2px 10px rgba(230, 30, 30, 0.3);
}
.comment-like-toggle {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.85rem;
color: #888888;
margin-top: 8px;
}
.comment-like-toggle input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: #22c55e;
cursor: pointer;
}
/* Coach modal specific - private note */
.coach-icon {
font-size: 1.2rem;
}
.comments-panel {
margin-top: 18px;
padding: 14px 16px;
border-radius: 12px;
border: 1px solid #303030;
background: #1e1e1e;
}
.comments-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.add-comment-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 18px;
font-size: 0.9rem;
font-weight: 600;
color: #ffffff;
background: linear-gradient(135deg, #e61e1e 0%, #ff4757 100%);
border: none;
border-radius: 12px;
cursor: pointer;
transition: all 0.25s ease;
box-shadow: 0 4px 12px rgba(230, 30, 30, 0.3);
}
.add-comment-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(230, 30, 30, 0.4);
background: linear-gradient(135deg, #ff4757 0%, #ff6b7a 100%);
}
.add-comment-btn:active {
transform: translateY(0);
}
.comments-list {
border-top: 1px solid #303030;
padding-top: 8px;
margin-top: 4px;
}
.comment-item {
display: flex;
gap: 8px;
padding: 6px 0;
border-bottom: 1px solid #0f0f0f;
}
.comment-avatar {
width: 28px;
height: 28px;
border-radius: 999px;
overflow: hidden;
background: #1e1e1e;
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: #aaaaaa;
}
.comment-author {
font-weight: 500;
color: #f1f1f1;
}
.comment-time-chip {
padding: 2px 6px;
border-radius: 999px;
border: 1px solid #404040;
background: #1e1e1e;
font-size: 0.75rem;
cursor: pointer;
color: #e61e1e;
}
.comment-content {
margin-top: 2px;
font-size: 0.85rem;
}
.comment-actions {
margin-top: 4px;
font-size: 0.75rem;
color: #666666;
display: flex;
gap: 10px;
align-items: center;
}
.comment-actions button {
border: none;
background: transparent;
color: #666666;
cursor: pointer;
font-size: 0.75rem;
padding: 0;
}
.reply-item {
margin-top: 4px;
margin-left: 24px;
padding-left: 8px;
border-left: 1px solid #303030;
font-size: 0.8rem;
color: #aaaaaa;
}
.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: #aaaaaa;
}
.comment-timestamp-type button {
border: none;
border-radius: 999px;
padding: 3px 8px;
background: #1e1e1e;
border: 1px solid #303030;
color: #aaaaaa;
cursor: pointer;
font-size: 0.75rem;
}
.comment-timestamp-type button.active {
background: #e61e1e;
color: #ffffff;
border-color: #e61e1e;
}
.comment-time-inputs {
display: flex;
gap: 6px;
align-items: center;
font-size: 0.8rem;
color: #aaaaaa;
}
.comment-time-inputs input {
width: 70px;
padding: 4px 6px;
border-radius: 6px;
border: 1px solid #303030;
background: #1e1e1e;
color: #f1f1f1;
font-size: 0.8rem;
}
.comment-textarea {
width: 100%;
min-height: 60px;
resize: vertical;
border-radius: 8px;
border: 1px solid #303030;
background: #1e1e1e;
color: #f1f1f1;
font-size: 0.85rem;
padding: 6px 8px;
}
.comment-like-toggle {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.8rem;
color: #aaaaaa;
}
.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: #1e1e1e;
border: 1px solid #303030;
color: #d1d5db;
display: flex;
align-items: center;
gap: 6px;
}
.share-link-wrapper {
display: flex;
gap: 6px;
align-items: center;
font-size: 0.8rem;
color: #aaaaaa;
}
.share-link-wrapper input {
flex: 1;
padding: 4px 6px;
border-radius: 6px;
border: 1px solid #303030;
background: #1e1e1e;
color: #f1f1f1;
font-size: 0.8rem;
}
.events-sidebar {
position: fixed;
top: 0;
right: 0;
width: 340px;
max-width: 80vw;
height: 100vh;
background: #0f0f0f;
border-left: 1px solid #303030;
box-shadow: -12px 0 40px rgba(0, 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 #303030;
}
.events-sidebar-header h3 {
margin: 0;
font-size: 0.95rem;
}
.close-btn {
border: none;
background: transparent;
color: #aaaaaa;
cursor: pointer;
font-size: 1rem;
}
.tab-header {
display: flex;
gap: 6px;
margin: 10px 12px 6px;
border-bottom: 1px solid #303030;
padding-bottom: 4px;
}
.tab-button {
flex: 1;
text-align: center;
padding: 6px 0;
font-size: 0.85rem;
color: #aaaaaa;
cursor: pointer;
border-radius: 999px;
background: transparent;
border: none;
position: relative;
}
.tab-button.active {
background: #1e1e1e;
color: #f1f1f1;
font-weight: 500;
}
.tab-button.active::after {
content: "";
position: absolute;
left: 8px;
right: 8px;
bottom: -4px;
height: 4px;
background: #0f0f0f;
}
.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 #303030;
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: #1e1e1e;
}
.event-time {
font-size: 0.8rem;
color: #ffd900;
min-width: 80px;
text-align: center;
}
.event-label {
font-size: 0.9rem;
}
.event-meta {
font-size: 0.75rem;
color: #666666;
}
.pill {
display: inline-block;
padding: 2px 6px;
border-radius: 999px;
font-size: 0.7rem;
margin-left: 4px;
}
.pill-blue {
background: #2563eb;
color: #bfdbfe;
}
.pill-red {
background: #ef4444;
color: #fecaca;
}
.section-label {
text-transform: uppercase;
font-size: 0.75rem;
letter-spacing: 0.08em;
color: #666666;
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: #eab308;
color: #000000;
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, 15, 15, 0.9);
color: #d1d5db;
border: 1px solid #303030;
}
.events-controller button:hover {
background: #1e1e1e;
}
@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-wrapper">
<div class="events-controller">
<button data-open-sidebar="both">Bookmarks</button>
</div>
<video
id="sportsVideo"
src="https://video.innovator.bh/videos/15/stream"
></video>
<!-- Custom Video Controls -->
<div class="controls" id="videoControls">
<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>
<!-- Bookmark markers will be rendered here -->
<div id="bookmarkMarkers"></div>
</div>
</div>
<div class="controls-top">
<button class="play-btn" id="playBtn">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>
</button>
<div class="time-labels">
<span id="currentTime">0:00</span>
<span>/</span>
<span id="duration">0:00</span>
</div>
<div class="controls-right">
<div class="volume-control">
<button class="volume-btn" id="volumeBtn" title="Volume">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>
</svg>
</button>
<input type="range" class="volume-slider" id="volumeSlider" min="0" max="1" step="0.1" value="1" title="Volume">
</div>
<button class="fullscreen-btn" id="fullscreenBtn" title="Fullscreen">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path>
</svg>
</button>
</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
<span style="color: #2563eb; font-weight: bold"
>🇧🇭 Ali Mohammed</span
>
vs
<span style="color: #ef4444; font-weight: bold"
>🇸🇦 Omar AlKhaled</span
>
(U18)
</h1>
<a class="meta-link" href="/championship/2026"
>📍 Championship 2026 • Match# 103 • Court 2 •
<span style="color: #ffd900; font-weight: bold"
>M. AlKhalifa</span
></a
>
</div>
</div>
<div class="event-header-actions">
<button class="action-btn" type="button" title="Like">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
></path>
</svg>
<span>1.3k</span>
</button>
<button class="action-btn" type="button" title="Dislike">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
></path>
</svg>
<span>103</span>
</button>
<button
class="action-btn"
type="button"
id="shareVideoBtn"
title="Share"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"></path>
<polyline points="16 6 12 2 8 6"></polyline>
<line x1="12" y1="2" x2="12" y2="15"></line>
</svg>
<span>Share</span>
</button>
<button class="action-btn" type="button" title="Save">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"
></path>
</svg>
<span>Save</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 blue-corner">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="referee-photo">
<img
src="https://picsum.photos/seed/red-competitor/200/260"
alt="Referee"
/>
</div>
<div style="color: #ffd900; font-weight: bold">
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 red-corner">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">
<a
class="hall-link"
id="hallLink"
title="View venue details"
href="https://maps.google.com/?q=Manama+Sports+Hall+Bahrain"
target="_blank"
rel="noopener noreferrer"
>
📍 Manama Sports Hall
</a>
• Electronic scoring system (PSS & headgear) • Video replay
available for head kicks and gam-jeom appeals
</div>
</section>
<section class="markdown-body">
<h2>Match Overview</h2>
<p>
This Male U18 -63kg final features three 2:00 rounds (with a
golden point tie-breaker) showcasing a classic clash of styles:
Blue drives the action with relentless pressure, body kicks, and
ring control, while Red utilizes angle changes to set up tactical
head-shot counters. When analyzing the replay, coaches and
athletes should focus on distance management and guard resets
immediately following exchanges, specifically noting how conceding
points affects a fighter's momentum and leads to hesitation.
Furthermore, close attention should be paid to the effectiveness
of corner instructions and tactical time-outs, evaluating how
consistently each fighter adheres to the established game plan
during the high-fatigue environment of the final 30 seconds of
every 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>
<button class="add-comment-btn" type="button" id="openCommentModal">
💬 Add Comment
</button>
</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">
<div
class="comment-avatar"
style="
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
"
>
<img
src="https://picsum.photos/seed/coach-ahmed/80/80"
alt="Coach Ahmed"
/>
</div>
<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>
<!-- Comment Modal -->
<div class="modal-backdrop" id="commentModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>💬 Add Comment</h3>
<button class="modal-close" id="closeCommentModal" aria-label="Close">
&times;
</button>
</div>
<div class="modal-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-row">
<div class="comment-timestamp-type">
<span>Link type:</span>
<button type="button" class="active">Video</button>
<button type="button">Time stamp</button>
<button type="button">Time range</button>
</div>
</div>
<div class="comment-row">
<div class="time-range">
<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>
<label class="comment-like-toggle">
<input type="checkbox" />
<span>Like this video</span>
</label>
<div class="modal-actions">
<button class="btn-secondary" type="button" id="cancelCommentModal">
Cancel
</button>
<button class="btn-primary" type="button">Post Comment</button>
</div>
</div>
</div>
<!-- Share Modal -->
<div class="modal-backdrop" id="shareModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>📤 Share this Match</h3>
<button class="modal-close" id="closeShareModal" aria-label="Close">
&times;
</button>
</div>
<p class="share-description">
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="modal-actions">
<button class="btn-secondary" type="button" id="cancelShareModal">
Close
</button>
</div>
</div>
</div>
<!-- Points/Foul Modal -->
<div class="modal-backdrop" id="pointsModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>🥋 Register Point / Foul</h3>
<button class="modal-close" id="closePointsModal" aria-label="Close">
&times;
</button>
</div>
<div class="modal-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="form-row">
<div class="form-group">
<label class="form-label">Type</label>
<div class="emoji-select">
<button type="button" data-type="point" class="active">🥋</button>
<button type="button" data-type="foul">⚠️</button>
</div>
</div>
<div class="form-group">
<label class="form-label">Round / Fighter</label>
<div style="display: flex; gap: 8px">
<select>
<option>Round 1</option>
<option>Round 2</option>
<option>Round 3</option>
</select>
<select>
<option>Blue</option>
<option>Red</option>
</select>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Time</label>
<div class="time-range">
<span>At</span>
<input type="text" placeholder="01:12" />
</div>
</div>
<div class="form-group">
<label class="form-label">Impact on Score</label>
<div class="time-range">
<span>Δ score</span>
<input type="number" placeholder="+1 / -1" />
</div>
</div>
</div>
<div class="form-group">
<label class="form-label">Note (optional)</label>
<textarea
placeholder="E.g. body kick scored, gam-jeom for pushing, etc."
></textarea>
</div>
<div class="modal-actions">
<button class="btn-secondary" type="button" id="cancelPointsModal">
Cancel
</button>
<button class="btn-primary" type="button">Add Event</button>
</div>
</div>
</div>
<!-- Coach Review Modal (Private Note) - Missing Modal -->
<div class="modal-backdrop" id="coachModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-header">
<h3>📝 Coach Private Note</h3>
<button class="modal-close" id="closeCoachModal" aria-label="Close">
&times;
</button>
</div>
<div class="modal-hint">
Add a private note for coaching purposes. This will only be visible to
coaches and won't be shared publicly.
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Reaction</label>
<div class="emoji-select">
<button type="button" data-emoji="🔥" class="active">🔥</button>
<button type="button" data-emoji="🤔">🤔</button>
<button type="button" data-emoji="😄">😄</button>
<button type="button" data-emoji="💪">💪</button>
<button type="button" data-emoji="⚠️">⚠️</button>
</div>
</div>
<div class="form-group">
<label class="form-label">Time Range</label>
<div class="time-range">
<span>From</span>
<input type="text" placeholder="00:32" />
<span>To</span>
<input type="text" placeholder="00:50" />
</div>
</div>
</div>
<div class="form-group">
<label class="form-label">Note Title</label>
<input
type="text"
placeholder="E.g. Good pressure, guard dropping..."
/>
</div>
<div class="form-group">
<label class="form-label">Detailed Note</label>
<textarea
placeholder="Describe what happened, what to work on, drills to practice, tactical observations..."
></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-label">Fighter</label>
<select>
<option>Both Fighters</option>
<option>Blue Corner</option>
<option>Red Corner</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Priority</label>
<select>
<option>🔴 High Priority</option>
<option>🟡 Medium</option>
<option>🟢 Low</option>
</select>
</div>
</div>
<div class="modal-actions">
<button class="btn-secondary" type="button" id="cancelCoachModal">
Cancel
</button>
<button class="btn-primary" type="button">Save Note</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">
<div
class="comment-avatar"
style="
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
"
>
<img
src="https://picsum.photos/seed/coach-ahmed/80/80"
alt="Coach Ahmed"
/>
</div>
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">
<div
class="comment-avatar"
style="
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
margin-right: 4px;
"
>
<img
src="https://picsum.photos/seed/coach-ahmed/80/80"
alt="Coach Ahmed"
/>
</div>
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");
function seekWithOptionalSegment(start, end) {
// Go 1 second before and play
const seekTime = Math.max(0, start - 1);
video.currentTime = seekTime;
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();
});
// Coach modal (Private Note)
const coachModal = document.getElementById("coachModal");
const openCoachModalFromSidebar = document.getElementById(
"openCoachModalFromSidebar",
);
const closeCoachModalBtn = document.getElementById("closeCoachModal");
const cancelCoachModalBtn = document.getElementById("cancelCoachModal");
function openCoachModal() {
coachModal.classList.add("open");
}
function closeCoachModal() {
coachModal.classList.remove("open");
}
if (openCoachModalFromSidebar) {
openCoachModalFromSidebar.addEventListener("click", openCoachModal);
}
if (closeCoachModalBtn) {
closeCoachModalBtn.addEventListener("click", closeCoachModal);
}
if (cancelCoachModalBtn) {
cancelCoachModalBtn.addEventListener("click", closeCoachModal);
}
if (coachModal) {
coachModal.addEventListener("click", (e) => {
if (e.target === coachModal) closeCoachModal();
});
}
// Emoji select toggle functionality
document.querySelectorAll(".emoji-select button").forEach((btn) => {
btn.addEventListener("click", function () {
const parent = this.closest(".emoji-select");
parent
.querySelectorAll("button")
.forEach((b) => b.classList.remove("active"));
this.classList.add("active");
});
});
// 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 ? "▲" : "▼";
});
}
// Hall/Venue click handler
const hallLink = document.getElementById("hallLink");
if (hallLink) {
hallLink.addEventListener("click", () => {
// Open venue details or navigate to venue page
alert("Manama Sports Hall - View venue details");
});
}
// ==================== Custom Video Controls ====================
const playBtn = document.getElementById("playBtn");
const progressBar = document.getElementById("progressBar");
const progressWrapper = document.getElementById("progressWrapper");
const progressFill = document.getElementById("progressFill");
const progressHandle = document.getElementById("progressHandle");
const currentTimeEl = document.getElementById("currentTime");
const durationEl = document.getElementById("duration");
const bookmarkMarkersContainer = document.getElementById("bookmarkMarkers");
let isPlaying = false;
// Format time (seconds to MM:SS)
function formatTime(seconds) {
if (isNaN(seconds)) return "0:00";
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, "0")}`;
}
// Toggle play/pause
function togglePlay() {
if (video.paused) {
video.play();
} else {
video.pause();
}
}
playBtn.addEventListener("click", togglePlay);
video.addEventListener("click", togglePlay);
// Update play button icon
video.addEventListener("play", () => {
isPlaying = true;
playBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<rect x="6" y="4" width="4" height="16"></rect>
<rect x="14" y="4" width="4" height="16"></rect>
</svg>`;
});
video.addEventListener("pause", () => {
isPlaying = false;
playBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>`;
});
// Update progress bar
video.addEventListener("timeupdate", () => {
if (video.duration) {
const percent = (video.currentTime / video.duration) * 100;
progressFill.style.width = `${percent}%`;
progressHandle.style.left = `${percent}%`;
currentTimeEl.textContent = formatTime(video.currentTime);
}
});
// Set duration when loaded
video.addEventListener("loadedmetadata", () => {
durationEl.textContent = formatTime(video.duration);
// Render bookmarks after video metadata is loaded
renderBookmarkMarkers();
});
// Seek on progress bar click
progressWrapper.addEventListener("click", (e) => {
const rect = progressBar.getBoundingClientRect();
const percent = (e.clientX - rect.left) / rect.width;
video.currentTime = percent * video.duration;
});
// ==================== Volume Control ====================
const volumeBtn = document.getElementById("volumeBtn");
const volumeSlider = document.getElementById("volumeSlider");
// Set initial volume
video.volume = 1;
// Volume button click - toggle mute
volumeBtn.addEventListener("click", () => {
if (video.muted) {
video.muted = false;
video.volume = volumeSlider.value;
volumeBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>
</svg>`;
} else {
video.muted = true;
volumeBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<line x1="23" y1="9" x2="17" y2="15"></line>
<line x1="17" y1="9" x2="23" y2="15"></line>
</svg>`;
}
});
// Volume slider change
volumeSlider.addEventListener("input", (e) => {
video.volume = e.target.value;
video.muted = false;
volumeBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>
</svg>`;
});
// ==================== Fullscreen Control ====================
const fullscreenBtn = document.getElementById("fullscreenBtn");
const videoWrapper = document.querySelector(".video-wrapper");
fullscreenBtn.addEventListener("click", () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else if (videoWrapper.requestFullscreen) {
videoWrapper.requestFullscreen();
} else if (video.webkitEnterFullscreen) {
// Safari support
video.webkitEnterFullscreen();
}
});
// ==================== Bookmark Markers ====================
// Get all bookmark data from the event lists
function getBookmarks() {
const bookmarks = [];
// Get official events (Points)
const officialEvents = document.querySelectorAll("#officialEvents .event-item");
officialEvents.forEach(item => {
const timeStart = parseFloat(item.dataset.timeStart);
if (!isNaN(timeStart)) {
// Determine color and type based on the event label
const label = item.querySelector(".event-label")?.textContent || "";
let colorClass = "yellow"; // Default for fouls
let bookmarkType = "point";
if (label.includes("Blue")) {
colorClass = "blue";
} else if (label.includes("Red")) {
colorClass = "red";
}
// Check for foul keywords
if (label.toLowerCase().includes("foul") || label.toLowerCase().includes("gam-jeom") || label.toLowerCase().includes("penalty")) {
colorClass = "yellow";
}
bookmarks.push({
time: timeStart,
timeEnd: parseFloat(item.dataset.timeEnd) || null,
color: colorClass,
type: bookmarkType,
label: label
});
}
});
// Get coach review events
const reviewEvents = document.querySelectorAll("#reviewEvents .event-item");
reviewEvents.forEach(item => {
const timeStart = parseFloat(item.dataset.timeStart);
const timeEnd = parseFloat(item.dataset.timeEnd);
if (!isNaN(timeStart)) {
bookmarks.push({
time: timeStart,
timeEnd: isNaN(timeEnd) ? null : timeEnd,
color: "white",
type: "coach"
});
}
});
return bookmarks;
}
// Render bookmark markers on progress bar
function renderBookmarkMarkers() {
if (!bookmarkMarkersContainer || !video.duration) return;
const bookmarks = getBookmarks();
bookmarkMarkersContainer.innerHTML = "";
bookmarks.forEach(bookmark => {
const marker = document.createElement("div");
marker.className = `bookmark-marker ${bookmark.color}`;
const percent = (bookmark.time / video.duration) * 100;
marker.style.left = `${percent}%`;
marker.title = `Jump to ${formatTime(bookmark.time)}`;
// Click on marker based on type
marker.addEventListener("click", (e) => {
e.stopPropagation(); // Prevent seeking to wrong position
if (bookmark.type === "coach" && bookmark.timeEnd && bookmark.timeEnd > bookmark.time) {
// Coach review with time range: play from start to end
video.currentTime = bookmark.time;
video.play();
// Remove any existing timeupdate handler first
video.removeEventListener("timeupdate", window.coachTimeUpdateHandler);
// Create new handler to stop at end time
window.coachTimeUpdateHandler = function() {
if (video.currentTime >= bookmark.timeEnd - 0.1) {
video.pause();
video.currentTime = bookmark.timeEnd; // Ensure we stop exactly at end
video.removeEventListener("timeupdate", window.coachTimeUpdateHandler);
}
};
video.addEventListener("timeupdate", window.coachTimeUpdateHandler);
} else if (bookmark.type === "coach") {
// Coach review without time range: go 1 second before and play
const seekTime = Math.max(0, bookmark.time - 1);
video.currentTime = seekTime;
video.play();
} else {
// Point: play directly from the bookmark timestamp
video.currentTime = bookmark.time;
video.play();
}
});
bookmarkMarkersContainer.appendChild(marker);
});
}
// Re-render bookmarks when video is ready
video.addEventListener("loadeddata", renderBookmarkMarkers);
</script>
</body>
</html>