|
354 | 354 | color: #c8102e; |
355 | 355 | } |
356 | 356 |
|
| 357 | + /* Double Elimination Styles */ |
| 358 | + .double-elim-container { |
| 359 | + display: flex; |
| 360 | + flex-direction: column; |
| 361 | + gap: 4rem; |
| 362 | + margin-top: 2rem; |
| 363 | + position: relative; |
| 364 | + } |
| 365 | + |
| 366 | + .bracket-section { |
| 367 | + position: relative; |
| 368 | + background: #0d1117; |
| 369 | + border: 2px solid #30363d; |
| 370 | + border-radius: 8px; |
| 371 | + padding: 2rem; |
| 372 | + overflow-x: auto; |
| 373 | + overflow-y: visible; |
| 374 | + } |
| 375 | + |
| 376 | + .bracket-title { |
| 377 | + color: #ffffff; |
| 378 | + font-size: 1.5rem; |
| 379 | + font-weight: 800; |
| 380 | + text-transform: uppercase; |
| 381 | + letter-spacing: 1px; |
| 382 | + margin-bottom: 1.5rem; |
| 383 | + padding-bottom: 0.75rem; |
| 384 | + border-bottom: 3px solid #c8102e; |
| 385 | + display: inline-block; |
| 386 | + width: 100%; |
| 387 | + } |
| 388 | + |
| 389 | + .winners-bracket { |
| 390 | + border-color: #2ea043; |
| 391 | + box-shadow: 0 0 20px rgba(46, 160, 67, 0.1); |
| 392 | + } |
| 393 | + |
| 394 | + .winners-bracket .bracket-title { |
| 395 | + border-bottom-color: #2ea043; |
| 396 | + } |
| 397 | + |
| 398 | + .losers-bracket { |
| 399 | + border-color: #f85149; |
| 400 | + box-shadow: 0 0 20px rgba(248, 81, 73, 0.1); |
| 401 | + } |
| 402 | + |
| 403 | + .losers-bracket .bracket-title { |
| 404 | + border-bottom-color: #f85149; |
| 405 | + } |
| 406 | + |
| 407 | + .grand-finals { |
| 408 | + max-width: 900px; |
| 409 | + margin: 0 auto; |
| 410 | + background: linear-gradient(180deg, #1a1d29 0%, #0d1117 100%); |
| 411 | + border-color: #ffd700; |
| 412 | + border-width: 3px; |
| 413 | + box-shadow: 0 0 40px rgba(255, 215, 0, 0.3), inset 0 0 60px rgba(255, 215, 0, 0.05); |
| 414 | + } |
| 415 | + |
| 416 | + .grand-finals .bracket-title { |
| 417 | + border-bottom-color: #ffd700; |
| 418 | + text-align: center; |
| 419 | + font-size: 1.8rem; |
| 420 | + } |
| 421 | + |
| 422 | + .bracket-wrapper-inner { |
| 423 | + background: transparent; |
| 424 | + border-radius: 6px; |
| 425 | + padding: 1rem; |
| 426 | + min-height: 400px; |
| 427 | + position: relative; |
| 428 | + } |
| 429 | + |
| 430 | + /* Visual connectors between brackets */ |
| 431 | + .bracket-section::before, |
| 432 | + .bracket-section::after { |
| 433 | + content: ''; |
| 434 | + position: absolute; |
| 435 | + width: 3px; |
| 436 | + z-index: 5; |
| 437 | + pointer-events: none; |
| 438 | + } |
| 439 | + |
| 440 | + .winners-bracket::after { |
| 441 | + bottom: -4rem; |
| 442 | + left: 50%; |
| 443 | + height: 4rem; |
| 444 | + transform: translateX(-50%); |
| 445 | + background: linear-gradient(180deg, #2ea043 0%, rgba(46, 160, 67, 0.3) 50%, transparent 100%); |
| 446 | + box-shadow: 0 0 10px rgba(46, 160, 67, 0.4); |
| 447 | + } |
| 448 | + |
| 449 | + .losers-bracket::before { |
| 450 | + top: -4rem; |
| 451 | + left: 50%; |
| 452 | + height: 4rem; |
| 453 | + transform: translateX(-50%); |
| 454 | + background: linear-gradient(180deg, transparent 0%, rgba(248, 81, 73, 0.3) 50%, #f85149 100%); |
| 455 | + box-shadow: 0 0 10px rgba(248, 81, 73, 0.4); |
| 456 | + } |
| 457 | + |
| 458 | + .losers-bracket::after { |
| 459 | + bottom: -4rem; |
| 460 | + left: 50%; |
| 461 | + height: 4rem; |
| 462 | + transform: translateX(-50%); |
| 463 | + background: linear-gradient(180deg, #f85149 0%, rgba(248, 81, 73, 0.3) 50%, transparent 100%); |
| 464 | + box-shadow: 0 0 10px rgba(248, 81, 73, 0.4); |
| 465 | + } |
| 466 | + |
| 467 | + .grand-finals::before { |
| 468 | + top: -4rem; |
| 469 | + left: 50%; |
| 470 | + height: 4rem; |
| 471 | + transform: translateX(-50%); |
| 472 | + background: linear-gradient(180deg, transparent 0%, rgba(255, 215, 0, 0.3) 50%, #ffd700 100%); |
| 473 | + box-shadow: 0 0 15px rgba(255, 215, 0, 0.5); |
| 474 | + } |
| 475 | + |
357 | 476 | @media (max-width: 768px) { |
358 | 477 | h1 { |
359 | 478 | font-size: 2.5rem; |
|
374 | 493 | button { |
375 | 494 | width: 100%; |
376 | 495 | } |
| 496 | + |
| 497 | + .double-elim-container { |
| 498 | + gap: 2rem; |
| 499 | + } |
| 500 | + |
| 501 | + .bracket-section { |
| 502 | + padding: 1.5rem; |
| 503 | + } |
| 504 | + |
| 505 | + .bracket-title { |
| 506 | + font-size: 1.2rem; |
| 507 | + } |
377 | 508 | } |
378 | 509 | </style> |
379 | 510 | </head> |
@@ -517,6 +648,39 @@ <h2>🎯 Complete Interactive Tournament</h2> |
517 | 648 | <div class="log-entry log-info">Click "Start New Tournament" to begin!</div> |
518 | 649 | </div> |
519 | 650 | </div> |
| 651 | + |
| 652 | + <!-- Feature 5: Double Elimination Bracket --> |
| 653 | + <div class="demo-section"> |
| 654 | + <h2>🏆 Double Elimination Bracket</h2> |
| 655 | + <p class="demo-description"> |
| 656 | + A complete double elimination tournament visualization. Teams start in the Winners Bracket (top). |
| 657 | + Losers drop to the Losers Bracket (bottom). The Grand Finals pits the Winners Bracket champion |
| 658 | + against the Losers Bracket champion - the Winners Bracket champion must lose twice to be eliminated. |
| 659 | + </p> |
| 660 | + |
| 661 | + <div class="double-elim-container"> |
| 662 | + <div class="bracket-section winners-bracket"> |
| 663 | + <h3 class="bracket-title">Winners Bracket</h3> |
| 664 | + <div class="bracket-wrapper-inner"> |
| 665 | + <div id="winners-bracket"></div> |
| 666 | + </div> |
| 667 | + </div> |
| 668 | + |
| 669 | + <div class="bracket-section losers-bracket"> |
| 670 | + <h3 class="bracket-title">Losers Bracket</h3> |
| 671 | + <div class="bracket-wrapper-inner"> |
| 672 | + <div id="losers-bracket"></div> |
| 673 | + </div> |
| 674 | + </div> |
| 675 | + |
| 676 | + <div class="bracket-section grand-finals"> |
| 677 | + <h3 class="bracket-title">Grand Finals</h3> |
| 678 | + <div class="bracket-wrapper-inner"> |
| 679 | + <div id="grand-finals-bracket"></div> |
| 680 | + </div> |
| 681 | + </div> |
| 682 | + </div> |
| 683 | + </div> |
520 | 684 | </div> |
521 | 685 |
|
522 | 686 | <footer> |
@@ -985,6 +1149,106 @@ <h2>🎯 Complete Interactive Tournament</h2> |
985 | 1149 |
|
986 | 1150 | addLog('complete-log', '\\n' + report, 'success'); |
987 | 1151 | }); |
| 1152 | + |
| 1153 | + // ======================================================================== |
| 1154 | + // Demo 5: Double Elimination Bracket |
| 1155 | + // ======================================================================== |
| 1156 | + |
| 1157 | + // 8-team double elimination tournament data |
| 1158 | + const doubleElimTeams = [ |
| 1159 | + { name: 'Warriors', id: 'warriors', seed: 1 }, |
| 1160 | + { name: 'Lakers', id: 'lakers', seed: 2 }, |
| 1161 | + { name: 'Celtics', id: 'celtics', seed: 3 }, |
| 1162 | + { name: 'Heat', id: 'heat', seed: 4 }, |
| 1163 | + { name: 'Bucks', id: 'bucks', seed: 5 }, |
| 1164 | + { name: 'Suns', id: 'suns', seed: 6 }, |
| 1165 | + { name: 'Nets', id: 'nets', seed: 7 }, |
| 1166 | + { name: 'Nuggets', id: 'nuggets', seed: 8 } |
| 1167 | + ]; |
| 1168 | + |
| 1169 | + // Winners Bracket (8 teams -> 4 -> 2 -> 1 champion) |
| 1170 | + const winnersBracketData = [ |
| 1171 | + // Round 1: Quarterfinals (4 matches) |
| 1172 | + [ |
| 1173 | + [{ name: 'Warriors', id: 'warriors', seed: 1, score: 105 }, { name: 'Nuggets', id: 'nuggets', seed: 8, score: 92 }], |
| 1174 | + [{ name: 'Lakers', id: 'lakers', seed: 2, score: 98 }, { name: 'Nets', id: 'nets', seed: 7, score: 110 }], |
| 1175 | + [{ name: 'Celtics', id: 'celtics', seed: 3, score: 108 }, { name: 'Suns', id: 'suns', seed: 6, score: 102 }], |
| 1176 | + [{ name: 'Heat', id: 'heat', seed: 4, score: 95 }, { name: 'Bucks', id: 'bucks', seed: 5, score: 112 }] |
| 1177 | + ], |
| 1178 | + // Round 2: Semifinals (2 matches) |
| 1179 | + [ |
| 1180 | + [{ name: 'Warriors', id: 'warriors', seed: 1, score: 118 }, { name: 'Nets', id: 'nets', seed: 7, score: 105 }], |
| 1181 | + [{ name: 'Celtics', id: 'celtics', seed: 3, score: 115 }, { name: 'Bucks', id: 'bucks', seed: 5, score: 108 }] |
| 1182 | + ], |
| 1183 | + // Round 3: Finals (1 match) |
| 1184 | + [ |
| 1185 | + [{ name: 'Warriors', id: 'warriors', seed: 1, score: 120 }, { name: 'Celtics', id: 'celtics', seed: 3, score: 115 }] |
| 1186 | + ], |
| 1187 | + // Round 4: Champion |
| 1188 | + [ |
| 1189 | + [{ name: 'Warriors', id: 'warriors', seed: 1 }] |
| 1190 | + ] |
| 1191 | + ]; |
| 1192 | + |
| 1193 | + // Losers Bracket (losers from winners bracket feed in) |
| 1194 | + // Structure: Round 1 losers play each other, then winners play Round 2 losers, etc. |
| 1195 | + const losersBracketData = [ |
| 1196 | + // Round 1: First round losers (4 teams -> 2) |
| 1197 | + [ |
| 1198 | + [{ name: 'Nuggets', id: 'nuggets', seed: 8, score: 88 }, { name: 'Lakers', id: 'lakers', seed: 2, score: 95 }], |
| 1199 | + [{ name: 'Suns', id: 'suns', seed: 6, score: 102 }, { name: 'Heat', id: 'heat', seed: 4, score: 98 }] |
| 1200 | + ], |
| 1201 | + // Round 2: Losers from Winners Round 2 + Winners from Losers Round 1 (4 teams -> 2) |
| 1202 | + [ |
| 1203 | + [{ name: 'Lakers', id: 'lakers', seed: 2, score: 92 }, { name: 'Nets', id: 'nets', seed: 7, score: 105 }], |
| 1204 | + [{ name: 'Suns', id: 'suns', seed: 6, score: 98 }, { name: 'Bucks', id: 'bucks', seed: 5, score: 110 }] |
| 1205 | + ], |
| 1206 | + // Round 3: Semifinals (2 teams -> 1) |
| 1207 | + [ |
| 1208 | + [{ name: 'Nets', id: 'nets', seed: 7, score: 108 }, { name: 'Bucks', id: 'bucks', seed: 5, score: 112 }] |
| 1209 | + ], |
| 1210 | + // Round 4: Finals (loser plays winner from previous round) |
| 1211 | + [ |
| 1212 | + [{ name: 'Nets', id: 'nets', seed: 7, score: 115 }, { name: 'Celtics', id: 'celtics', seed: 3, score: 118 }] |
| 1213 | + ], |
| 1214 | + // Round 5: Losers Bracket Champion |
| 1215 | + [ |
| 1216 | + [{ name: 'Celtics', id: 'celtics', seed: 3 }] |
| 1217 | + ] |
| 1218 | + ]; |
| 1219 | + |
| 1220 | + // Grand Finals: Winners Bracket Champion vs Losers Bracket Champion |
| 1221 | + const grandFinalsData = [ |
| 1222 | + // Grand Finals Match 1 |
| 1223 | + [ |
| 1224 | + [{ name: 'Warriors', id: 'warriors', seed: 1, score: 125 }, { name: 'Celtics', id: 'celtics', seed: 3, score: 120 }] |
| 1225 | + ], |
| 1226 | + // Grand Finals Match 2 (if needed - Warriors already won, so this is just for display) |
| 1227 | + [ |
| 1228 | + [{ name: 'Warriors', id: 'warriors', seed: 1 }] |
| 1229 | + ] |
| 1230 | + ]; |
| 1231 | + |
| 1232 | + // Initialize Winners Bracket |
| 1233 | + const winnersBracket = new Gracket('#winners-bracket', { |
| 1234 | + src: winnersBracketData, |
| 1235 | + roundLabels: ['Quarterfinals', 'Semifinals', 'Finals', 'Champion'], |
| 1236 | + canvasLineColor: '#2ea043' |
| 1237 | + }); |
| 1238 | + |
| 1239 | + // Initialize Losers Bracket |
| 1240 | + const losersBracket = new Gracket('#losers-bracket', { |
| 1241 | + src: losersBracketData, |
| 1242 | + roundLabels: ['Round 1', 'Round 2', 'Semifinals', 'Finals', 'Champion'], |
| 1243 | + canvasLineColor: '#f85149' |
| 1244 | + }); |
| 1245 | + |
| 1246 | + // Initialize Grand Finals |
| 1247 | + const grandFinalsBracket = new Gracket('#grand-finals-bracket', { |
| 1248 | + src: grandFinalsData, |
| 1249 | + roundLabels: ['Grand Finals', 'Champion'], |
| 1250 | + canvasLineColor: '#ffd700' |
| 1251 | + }); |
988 | 1252 | </script> |
989 | 1253 | </body> |
990 | 1254 | </html> |
0 commit comments