5339 lines
159 KiB
HTML
5339 lines
159 KiB
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 Al‑Khaled</span
|
||
>
|
||
(U18)
|
||
</h1>
|
||
<a class="meta-link" href="/championship/2026"
|
||
>📍 Championship 2026 • Match# 103 • Court 2 •
|
||
<span style="color: #ffd900; font-weight: bold"
|
||
>M. Al‑Khalifa</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. Al‑Khalifa
|
||
</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 Al‑Khaled</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 & head‑gear) • 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:32–00: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">
|
||
×
|
||
</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">
|
||
×
|
||
</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">
|
||
×
|
||
</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">
|
||
×
|
||
</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">×</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:32–00: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:05–02: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 Al‑Khaled</span
|
||
>
|
||
(U18)
|
||
</h1>
|
||
<a class="meta-link" href="/championship/2026"
|
||
>📍 Championship 2026 • Match# 103 • Court 2 •
|
||
<span style="color: #ffd900; font-weight: bold"
|
||
>M. Al‑Khalifa</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. Al‑Khalifa
|
||
</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 Al‑Khaled</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 & head‑gear) • 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:32–00: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">
|
||
×
|
||
</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">
|
||
×
|
||
</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">
|
||
×
|
||
</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">
|
||
×
|
||
</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">×</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:32–00: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:05–02: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> |