🇶🇦 QATvs 🇨🇭 SUI20:00 BST / 3:00pm ET • San Francisco
🇧🇷 BRAvs 🇲🇦 MAR23:00 BST / 6:00pm ET • New York/NJ
🇭🇹 HAIvs SCO SCO02:00† BST / 9:00pm ET • Boston
🇦🇺 AUSvs 🇹🇷 TUR05:00† BST / 12:00am ET • Vancouver
🔓Owner mode active
🔒 Setup is owner-only.
👤 Players
Add everyone taking part. You need at least 2 players to run the draw.
Nina
Aarav
Suhani
Pooja
Maya
Paarth_siuu
Radhi
Aryan
D K Kotecha
Chandulal Batuk
Anit
CR7
🅾 Pin Top-12 Teams
Optionally assign one top-12 team to a specific player. Pinned teams are locked in before the draw runs — max one pin per player.
Nina
Aarav
Suhani
Pooja
Maya
Paarth_siuu
Radhi
Aryan
D K Kotecha
Chandulal Batuk
Anit
CR7
💰 Pot (optional)
€
12 players × €5 = €60 total pot
📶 Live Results API
Enter your football-data.org API key to auto-sync results every time you refresh.
Connected ✔
🏆 All 48 Qualified Teams
Draw is seeded — every player gets 1 top-12 ★ + 1 ranked 13–20. Official codes & flags shown.
🇫🇷 FRA #1🇪🇸 ESP #2🇦🇷 ARG #3ENG #4🇵🇹 POR #5🇧🇷 BRA #6🇳🇱 NED #7🇲🇦 MAR #8🇧🇪 BEL #9🇩🇪 GER #10🇭🇷 CRO #11🇨🇴 COL #13🇸🇳 SEN #14🇲🇽 MEX #15🇺🇸 USA #16🇺🇾 URU #17🇯🇵 JPN #18🇨🇭 SUI #19🇰🇷 KOR #22🇦🇹 AUT #25🇦🇺 AUS #26🇪🇨 ECU #28🇹🇷 TUR #29🇩🇿 ALG #30🇳🇴 NOR #31🇸🇪 SWE #33🇮🇷 IRN #35SCO #36🇵🇾 PAR #37🇨🇿 CZE #38🇬🇭 GHA #40🇪🇬 EGY #41🇸🇦 KSA #56🇵🇦 PAN #57🇹🇳 TUN #58🇨🇦 CAN #59🇨🇮 CIV #60🇳🇿 NZL #63🇶🇦 QAT #65🇧🇦 BIH #66🇮🇶 IRQ #68🇯🇴 JOR #70🇨🇩 COD #74🇿🇦 RSA #76🇭🇹 HAI #83🇺🇿 UZB #87🇨🇻 CPV #90🇨🇼 CUW #104
🎲 The Draw
Seeded draw — everyone gets at least 1 top-12 ★ team and 1 ranked 13–20. Hit the button when everyone’s ready!
Draw complete — 12 players, all 48 teams assigned.
N
Nina
0 pts
🇧🇷
BRA
Brazil
★ #6
🇨🇦
CAN
Canada
#59
🇿🇦
RSA
South Africa
#76
🇰🇷
KOR
South Korea
#22
A
Aarav
0 pts
🇩🇪
GER
Germany
★ #10
🇬🇭
GHA
Ghana
#40
🇸🇪
SWE
Sweden
#33
🇨🇭
SUI
Switzerland
#19
S
Suhani
0 pts
🇳🇱
NED
Netherlands
★ #7
🇨🇿
CZE
Czechia
#38
🇸🇦
KSA
Saudi Arabia
#56
🇨🇮
CIV
Ivory Coast
#60
P
Pooja
0 pts
🇧🇪
BEL
Belgium
★ #9
🇮🇶
IRQ
Iraq
#68
🇯🇴
JOR
Jordan
#70
🇹🇳
TUN
Tunisia
#58
M
Maya
0 pts
🇪🇸
ESP
Spain
★ #2
🇺🇸
USA
USA
#16
🇸🇳
SEN
Senegal
#14
🇶🇦
QAT
Qatar
#65
P
Paarth_siuu
0 pts
🇵🇹
POR
Portugal
★ #5
🇦🇹
AUT
Austria
#25
🇵🇦
PAN
Panama
#57
🇨🇼
CUW
Curacao
#104
R
Radhi
0 pts
🇦🇷
ARG
Argentina
★ #3
🇪🇬
EGY
Egypt
#41
🇹🇷
TUR
Turkey
#29
🏁
SCO
Scotland
#36
A
Aryan
0 pts
🏁
ENG
England
★ #4
🇨🇩
COD
DR Congo
#74
🇪🇨
ECU
Ecuador
#28
🇨🇻
CPV
Cape Verde
#90
DK
D K Kotecha
0 pts
🇫🇷
FRA
France
★ #1
🇲🇽
MEX
Mexico
#15
🇧🇦
BIH
Bosnia-Herz
#66
🇵🇾
PAR
Paraguay
#37
CB
Chandulal Batuk
0 pts
🇨🇴
COL
Colombia
#13
🇺🇾
URU
Uruguay
#17
🇭🇹
HAI
Haiti
#83
🇦🇺
AUS
Australia
#26
A
Anit
0 pts
🇲🇦
MAR
Morocco
★ #8
🇳🇿
NZL
New Zealand
#63
🇯🇵
JPN
Japan
#18
🇳🇴
NOR
Norway
#31
C
CR7
0 pts
🇭🇷
CRO
Croatia
#11
🇩🇿
ALG
Algeria
#30
🇺🇿
UZB
Uzbekistan
#87
🇮🇷
IRN
Iran
#35
12
Players
€60
Total pot
48
Teams still in
🏆 Leaderboard
🥇
N
Nina
🇧🇷 BRA🇨🇦 CAN🇿🇦 RSA🇰🇷 KOR
0pts
🥈
A
Aarav
🇩🇪 GER🇬🇭 GHA🇸🇪 SWE🇨🇭 SUI
0pts
🥉
S
Suhani
🇳🇱 NED🇨🇿 CZE🇸🇦 KSA🇨🇮 CIV
0pts
4
P
Pooja
🇧🇪 BEL🇮🇶 IRQ🇯🇴 JOR🇹🇳 TUN
0pts
5
M
Maya
🇪🇸 ESP🇺🇸 USA🇸🇳 SEN🇶🇦 QAT
0pts
6
P
Paarth_siuu
🇵🇹 POR🇦🇹 AUT🇵🇦 PAN🇨🇼 CUW
0pts
7
R
Radhi
🇦🇷 ARG🇪🇬 EGY🇹🇷 TUR SCO
0pts
8
A
Aryan
ENG🇨🇩 COD🇪🇨 ECU🇨🇻 CPV
0pts
9
DK
D K Kotecha
🇫🇷 FRA🇲🇽 MEX🇧🇦 BIH🇵🇾 PAR
0pts
10
CB
Chandulal Batuk
🇨🇴 COL🇺🇾 URU🇭🇹 HAI🇦🇺 AUS
0pts
11
A
Anit
🇲🇦 MAR🇳🇿 NZL🇯🇵 JPN🇳🇴 NOR
0pts
12
C
CR7
🇭🇷 CRO🇩🇿 ALG🇺🇿 UZB🇮🇷 IRN
0pts
💰 PRIZE BREAKDOWN
🥇
Nina
1st place
€35
🥈
Aarav
2nd place
€15
🥉
Suhani
3rd place
€10
🔒 Results editing is owner-only.
⛳ Update Results
If auto-sync is on, this updates automatically. You can also mark results manually. Points: Group=1 • R32=2 • R16=4 • QF=6 • SF=9 • Runner-up=12 • Winner=20
🇫🇷FRAFranceD K Kotecha
🇪🇸ESPSpainMaya
🇦🇷ARGArgentinaRadhi
ENGEnglandAryan
🇵🇹PORPortugalPaarth_siuu
🇧🇷BRABrazilNina
🇳🇱NEDNetherlandsSuhani
🇲🇦MARMoroccoAnit
🇧🇪BELBelgiumPooja
🇩🇪GERGermanyAarav
🇭🇷CROCroatiaCR7
🇨🇴COLColombiaChandulal Batuk
🇸🇳SENSenegalMaya
🇲🇽MEXMexicoD K Kotecha
🇺🇸USAUSAMaya
🇺🇾URUUruguayChandulal Batuk
🇯🇵JPNJapanAnit
🇨🇭SUISwitzerlandAarav
🇰🇷KORSouth KoreaNina
🇦🇹AUTAustriaPaarth_siuu
🇦🇺AUSAustraliaChandulal Batuk
🇪🇨ECUEcuadorAryan
🇹🇷TURTurkeyRadhi
🇩🇿ALGAlgeriaCR7
🇳🇴NORNorwayAnit
🇸🇪SWESwedenAarav
🇮🇷IRNIranCR7
SCOScotlandRadhi
🇵🇾PARParaguayD K Kotecha
🇨🇿CZECzechiaSuhani
🇬🇭GHAGhanaAarav
🇪🇬EGYEgyptRadhi
🇸🇦KSASaudi ArabiaSuhani
🇵🇦PANPanamaPaarth_siuu
🇹🇳TUNTunisiaPooja
🇨🇦CANCanadaNina
🇨🇮CIVIvory CoastSuhani
🇳🇿NZLNew ZealandAnit
🇶🇦QATQatarMaya
🇧🇦BIHBosnia-HerzD K Kotecha
🇮🇶IRQIraqPooja
🇯🇴JORJordanPooja
🇨🇩CODDR CongoAryan
🇿🇦RSASouth AfricaNina
🇭🇹HAIHaitiChandulal Batuk
🇺🇿UZBUzbekistanCR7
🇨🇻CPVCape VerdeAryan
🇨🇼CUWCuracaoPaarth_siuu
📅 Match Schedule
All 104 matches • UK / BST times • 11 Jun – 19 Jul 2026 • ■ = England or Scotland match
Thu 11 JunPlayed
🇲🇽MEXvsRSA🇿🇦
20:00 BSTMexico CityGroup A
🇰🇷KORvsCZE🇨🇿
03:00† BSTGuadalajaraGroup A
Fri 12 JunPlayed
🇨🇦CANvsBIH🇧🇦
20:00 BSTTorontoGroup B
🇺🇸USAvsPAR🇵🇾
02:00† BSTLos AngelesGroup D
Sat 13 JunToday
🇶🇦QATvsSUI🇨🇭
20:00 BSTSan FranciscoGroup B
🇧🇷BRAvsMAR🇲🇦
23:00 BSTNew York/NJGroup C
🇭🇹HAIvsSCO
02:00† BSTBostonGroup C
🇦🇺AUSvsTUR🇹🇷
05:00† BSTVancouverGroup D
Sun 14 JunTomorrow
🇩🇪GERvsCUW🇨🇼
19:00 BSTHoustonGroup E
🇳🇱NEDvsJPN🇯🇵
22:00 BSTDallasGroup F
🇨🇮CIVvsECU🇪🇨
01:00† BSTPhiladelphiaGroup E
🇸🇪SWEvsTUN🇹🇳
04:00† BSTMonterreyGroup F
Mon 15 JunIn 2 days
🇪🇸ESPvsCPV🇨🇻
18:00 BSTAtlantaGroup H
🇧🇪BELvsEGY🇪🇬
21:00 BSTVancouverGroup G
🇸🇦KSAvsURU🇺🇾
00:00† BSTMiamiGroup H
🇮🇷IRNvsNZL🇳🇿
05:00† BSTLos AngelesGroup G
Tue 16 JunIn 3 days
🇫🇷FRAvsSEN🇸🇳
21:00 BSTNew York/NJGroup I
🇮🇶IRQvsNOR🇳🇴
00:00† BSTBostonGroup I
🇦🇷ARGvsALG🇩🇿
03:00† BSTKansas CityGroup J
🇦🇹AUTvsJOR🇯🇴
08:00† BSTSan FranciscoGroup J
Wed 17 JunIn 4 days
🇵🇹PORvsCOD🇨🇩
19:00 BSTHoustonGroup K
ENGvsCRO🇭🇷
22:00 BSTDallasGroup L
🇬🇭GHAvsPAN🇵🇦
01:00† BSTTorontoGroup L
🇺🇿UZBvsCOL🇨🇴
04:00† BSTMexico CityGroup K
Thu 18 JunIn 5 days
🇨🇿CZEvsRSA🇿🇦
18:00 BSTAtlantaGroup A
🇨🇭SUIvsBIH🇧🇦
21:00 BSTLos AngelesGroup B
🇨🇦CANvsQAT🇶🇦
02:00† BSTVancouverGroup B
🇲🇽MEXvsKOR🇰🇷
04:00† BSTGuadalajaraGroup A
Fri 19 JunIn 6 days
🇿🇦RSAvsMAR🇲🇦
21:00 BSTBostonGroup C
🇺🇸USAvsAUS🇦🇺
22:00 BSTSeattleGroup D
🇧🇷BRAvsHAI🇭🇹
02:00† BSTPhiladelphiaGroup C
🇹🇷TURvsPAR🇵🇾
04:00† BSTSan FranciscoGroup D
Sat 20 JunIn 7 days
🇳🇱NEDvsSWE🇸🇪
19:00 BSTHoustonGroup F
🇩🇪GERvsCIV🇨🇮
22:00 BSTTorontoGroup E
🇪🇨ECUvsCUW🇨🇼
02:00† BSTKansas CityGroup E
🇹🇳TUNvsJPN🇯🇵
06:00† BSTMonterreyGroup F
Sun 21 Jun
🇪🇸ESPvsKSA🇸🇦
18:00 BSTAtlantaGroup H
🇧🇪BELvsIRN🇮🇷
21:00 BSTLos AngelesGroup G
🇺🇾URUvsCPV🇨🇻
00:00† BSTMiamiGroup H
🇳🇿NZLvsEGY🇪🇬
05:00† BSTVancouverGroup G
Mon 22 Jun
🇦🇷ARGvsAUT🇦🇹
19:00 BSTDallasGroup J
🇫🇷FRAvsIRQ🇮🇶
23:00 BSTPhiladelphiaGroup I
🇳🇴NORvsSEN🇸🇳
02:00† BSTNew York/NJGroup I
🇯🇴JORvsALG🇩🇿
07:00† BSTSan FranciscoGroup J
Tue 23 Jun
🇵🇹PORvsUZB🇺🇿
19:00 BSTHoustonGroup K
ENGvsGHA🇬🇭
22:00 BSTSeattleGroup L
🇭🇷CROvsPAN🇵🇦
01:00† BSTTorontoGroup L
🇨🇴COLvsCOD🇨🇩
05:00† BSTKansas CityGroup K
Wed 24 Jun
🇲🇽MEXvsCZE🇨🇿
20:00 BSTMexico CityGroup A
🇰🇷KORvsRSA🇿🇦
20:00 BSTGuadalajaraGroup A
🇧🇦BIHvsQAT🇶🇦
23:00 BSTTorontoGroup B
🇨🇭SUIvsCAN🇨🇦
23:00 BSTVancouverGroup B
Thu 25 Jun
SCOvsBRA🇧🇷
20:00 BSTPhiladelphiaGroup C
🇲🇦MARvsHAI🇭🇹
20:00 BSTNew York/NJGroup C
🇵🇾PARvsAUS🇦🇺
23:00 BSTLos AngelesGroup D
🇹🇷TURvsUSA🇺🇸
23:00 BSTSeattleGroup D
Fri 26 Jun
🇨🇼CUWvsGER🇩🇪
20:00 BSTKansas CityGroup E
🇪🇨ECUvsCIV🇨🇮
20:00 BSTPhiladelphiaGroup E
🇯🇵JPNvsNED🇳🇱
23:00 BSTDallasGroup F
🇹🇳TUNvsSWE🇸🇪
23:00 BSTMonterreyGroup F
Sat 27 Jun
🇪🇬EGYvsBEL🇧🇪
20:00 BSTVancouverGroup G
🇳🇿NZLvsIRN🇮🇷
20:00 BSTLos AngelesGroup G
🇨🇻CPVvsESP🇪🇸
23:00 BSTMiamiGroup H
🇺🇾URUvsKSA🇸🇦
23:00 BSTAtlantaGroup H
Sun 28 Jun
🇸🇳SENvsFRA🇫🇷
20:00 BSTNew York/NJGroup I
🇳🇴NORvsIRQ🇮🇶
20:00 BSTBostonGroup I
🇩🇿ALGvsARG🇦🇷
23:00 BSTKansas CityGroup J
🇯🇴JORvsAUT🇦🇹
23:00 BSTSan FranciscoGroup J
Mon 29 Jun
🇨🇩CODvsPOR🇵🇹
20:00 BSTHoustonGroup K
🇨🇴COLvsUZB🇺🇿
20:00 BSTMexico CityGroup K
🇵🇦PANvsENG
23:00 BSTTorontoGroup L
🇬🇭GHAvsCRO🇭🇷
23:00 BSTDallasGroup L
Fri 3 Jul – Mon 7 Jul
Round of 32 (8 matches)
KNOCKOUT
Sat 5 Jul – Tue 8 Jul
Round of 16 (8 matches)
KNOCKOUT
Fri 10 Jul – Sun 12 Jul
Quarter-finals (4 matches)
KNOCKOUT
Wed 15 – Thu 16 Jul
Semi-finals
KNOCKOUT
Sun 18 Jul
3rd place play-off — Miami
23:00 BSTKNOCKOUT
Sun 19 Jul
🏆 FINAL — New York / New Jersey
20:00 BSTKNOCKOUT
💬 Share to WhatsApp
⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━⚽ FIFA WORLD CUP 2026 SWEEPSTAKE ⚽
━
🏆 LEADERBOARD
🥇 Nina — 0pts
🇧🇷 BRA, 🇨🇦 CAN, 🇿🇦 RSA, 🇰🇷 KOR
🥈 Aarav — 0pts
🇩🇪 GER, 🇬🇭 GHA, 🇸🇪 SWE, 🇨🇭 SUI
🥉 Suhani — 0pts
🇳🇱 NED, 🇨🇿 CZE, 🇸🇦 KSA, 🇨🇮 CIV
4. Pooja — 0pts
🇧🇪 BEL, 🇮🇶 IRQ, 🇯🇴 JOR, 🇹🇳 TUN
5. Maya — 0pts
🇪🇸 ESP, 🇺🇸 USA, 🇸🇳 SEN, 🇶🇦 QAT
6. Paarth_siuu — 0pts
🇵🇹 POR, 🇦🇹 AUT, 🇵🇦 PAN, 🇨🇼 CUW
7. Radhi — 0pts
🇦🇷 ARG, 🇪🇬 EGY, 🇹🇷 TUR, SCO
8. Aryan — 0pts
ENG, 🇨🇩 COD, 🇪🇨 ECU, 🇨🇻 CPV
9. D K Kotecha — 0pts
🇫🇷 FRA, 🇲🇽 MEX, 🇧🇦 BIH, 🇵🇾 PAR
10. Chandulal Batuk — 0pts
🇨🇴 COL, 🇺🇾 URU, 🇭🇹 HAI, 🇦🇺 AUS
11. Anit — 0pts
🇲🇦 MAR, 🇳🇿 NZL, 🇯🇵 JPN, 🇳🇴 NOR
12. CR7 — 0pts
🇭🇷 CRO, 🇩🇿 ALG, 🇺🇿 UZB, 🇮🇷 IRN
💰 Prize pot: €60
━
━
━
━
━
━
━
━
━
━
━
━
━
━
━
━
Good luck everyone! 🎉
💾 Download
Save the app as a single HTML file. Share it with family — they open it in any browser.
🗣 Banter Board Live
Family chat — trash talk welcome. Messages are shared live across all devices.
1
111 Jun 12:47
test
1
111 Jun 12:31
hello
1
1211 Jun 12:02
hello
1
1210 Jun 23:35
hello
1
1210 Jun 18:27
13
1
1210 Jun 16:12
1-2-3
N
Nina10 Jun 14:48
testing
1
1210 Jun 14:46
hello
N
Nina10 Jun 14:44
test
TU
Test User10 Jun 12:54
Hello from console
TU
Test User10 Jun 12:48
Hello from console
TU
Test User10 Jun 12:48
Hello from console
1
110 Jun 12:36
test
1
110 Jun 12:36
test
1
110 Jun 12:35
test
1
110 Jun 12:32
hi
1
110 Jun 12:31
hi
1
110 Jun 12:31
hi
N
Nina10 Jun 12:09
test
N
Nina10 Jun 10:36
test
N
Nina10 Jun 10:16
test
🏆 Route to the Final
Predict the knockout bracket — in R32 use the dropdowns to pick which team from each group advances, then tap a team to pick the match winner. They advance automatically all the way to the final.
Round of 32
🇲🇽
🇨🇦
🇧🇷
🇺🇸
🇩🇪
🇳🇱
🇧🇪
🇪🇸
🇫🇷
🇦🇷
🇵🇹
🇨🇦
🇲🇽
🇺🇸
🇧🇷
🇳🇱
🇩🇪
🇪🇸
🇧🇪
🇦🇷
🇫🇷
🇵🇹
🇲🇽
🇧🇷
🇩🇪
🇧🇪
🇫🇷
🇵🇹
🇲🇽
🇨🇦
Round of 16
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
Quarter-finals
TBD
TBD
TBD
TBD
TBD
TBD
TBD
TBD
Semi-finals
TBD
TBD
TBD
TBD
Final
TBD
TBD
🏆 Predicted Champion
Pick team for player
🔓 Owner Access
Enter your owner password to unlock admin features.
⚽ WC 2026 Sweepstake
Add to your home screen for quick access
Install on iPhone
1
Tap the Share button at the bottom of Safari (box with up-arrow)
2
Scroll down and tap Add to Home Screen
3
Tap Add in the top right - done!
',stateInject+'');
var blob=new Blob([html],{type:'text/html'});
var a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='wc2026-sweepstake.html';a.click();
}
/* -- BOOT -- */
/* -- TODAY'S MATCHES BAR -- */
/* -- TIME HELPERS -- */
function bstToET(bstStr){
// bstStr like "20:00" or "02:00" (dagger already stripped by caller)
var parts=bstStr.split(':');
if(parts.length<2)return '';
var h=parseInt(parts[0],10);
var m=parts[1];
// NJ/NY is EDT = UTC-4, BST = UTC+1, so ET = BST - 5
var eth=((h-5)+24)%24;
var ampm=eth<12?'am':'pm';
var h12=eth%12||12;
return h12+':'+m+ampm+' ET';
}
function renderTodayBar(){
var bar=document.getElementById('today-bar');
var label=document.getElementById('today-bar-label');
var feed=document.getElementById('today-matches');
if(!bar||!feed)return;
var now=new Date();
var days=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var todayStr=days[now.getDay()]+' '+now.getDate()+' '+months[now.getMonth()];
var myTeamCodes=[];
if(state.drawn){
Object.values(state.assignments).forEach(function(teams){
teams.forEach(function(tn){
var t=TEAMS.find(function(x){return x.name===tn});
if(t)myTeamCodes.push(t.code);
});
});
}
// Find today's matches involving drawn teams
var todayMatches=SCHEDULE.filter(function(m){
return m.d===todayStr&&m.t.length===2&&myTeamCodes.length&&m.t.some(function(c){return myTeamCodes.indexOf(c)>=0});
});
// Find next 2 upcoming matches (any) if no matches today for my teams
var nextMatches=[];
if(!todayMatches.length){
// walk schedule to find first 2 future group matches
var found=0;
for(var i=0;i=0;
var mine2=myTeamCodes.indexOf(m.t[1])>=0;
var f1=flagCache[m.t[0]]?'':(t1.emoji||m.t[0]);
var f2=flagCache[m.t[1]]?'':(t2.emoji||m.t[1]);
var bstClean=m.uk.replace('\u2020','');
var etStr=bstToET(bstClean);
return '
';
}).join('');
} else {
// Show "no matches today, next up"
if(label)label.innerHTML='📅 NEXT UPCOMING MATCHES';
bar.style.background='linear-gradient(135deg,rgba(42,57,141,.15),rgba(2,15,42,.3))';
bar.style.borderBottomColor='rgba(42,57,141,.4)';
feed.innerHTML=nextMatches.map(function(m){
var t1=TEAMS.find(function(x){return x.code===m.t[0]})||{emoji:'',code:m.t[0]};
var t2=TEAMS.find(function(x){return x.code===m.t[1]})||{emoji:'',code:m.t[1]};
var f1=flagCache[m.t[0]]?'':(t1.emoji||m.t[0]);
var f2=flagCache[m.t[1]]?'':(t2.emoji||m.t[1]);
var bstClean=m.uk.replace('\u2020','');
var etStr=bstToET(bstClean);
return '
';
}).join('');
}
}
/* -- TEAM MODAL -- */
function openTeamModal(teamName){
var t=TEAMS.find(function(x){return x.name===teamName});
if(!t)return;
var modal=document.getElementById('team-modal');
var inner=document.getElementById('team-modal-content');
if(!modal||!inner)return;
// Find next matches for this team
var upcoming=SCHEDULE.filter(function(m){
return m.t.indexOf(t.code)>=0&&m.uk;
}).slice(0,3);
var stage=state.teamStages[teamName]||'tbd';
var stageInfo=STAGES[stage]||{label:'Not played yet',pts:0};
// Find who owns this team
var owner=Object.entries(state.assignments).find(function(e){return e[1].indexOf(teamName)>=0});
var flagHtml=flagCache[t.code]
?''
:(t.emoji?''+t.emoji+'':'');
var matchRows=upcoming.length
?upcoming.map(function(m){
var opp=m.t[0]===t.code?m.t[1]:m.t[0];
var oppT=TEAMS.find(function(x){return x.code===opp})||{emoji:'',code:opp};
var oppFlag=flagCache[opp]?'':(oppT.emoji||opp);
return '
FIFA Rank #'+t.rank+(t.rank<=10?' • ★ Top 10':t.rank<=20?' • Top 20':'')+'
'
+(owner?'
Drawn by '+owner[0]+'
':'')
+'
'
+'
'
+'
'
+'Current stage'
+''+stageInfo.label+''
+'
'
+'
UPCOMING FIXTURES
'
+matchRows;
modal.style.display='flex';
}
function closeTeamModal(){
var modal=document.getElementById('team-modal');
if(modal)modal.style.display='none';
}
/* -- LIVE MATCH INDICATOR -- */
function getLiveTeams(){
var now=new Date();
var days=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var todayStr=days[now.getDay()]+' '+now.getDate()+' '+months[now.getMonth()];
var liveSet={};
SCHEDULE.forEach(function(m){
if(m.d!==todayStr||!m.uk||!m.t.length)return;
var timeStr=m.uk.replace('\u2020','');
var parts=timeStr.split(':');
if(parts.length<2)return;
var h=parseInt(parts[0],10),mi=parseInt(parts[1],10);
var kickoff=new Date(now);
kickoff.setUTCHours(h-1,mi,0,0);
var diff=(now-kickoff)/60000;
if(diff>=0&&diff<=105)m.t.forEach(function(c){liveSet[c]=true;});
});
return liveSet;
}
/* -- BANTER BOARD (Firebase realtime) -- */
var replyToId=null;
var _fbApp=null;
var _fbDb=null;
var _fbRef=null;
var _fbMessages=[];
function initFirebase(){
if(_fbApp)return;
// Dynamically load Firebase SDKs then connect
function loadScript(src,cb){
var s=document.createElement('script');
s.src=src;
s.onload=cb;
s.onerror=function(){
document.getElementById('banter-status').textContent='Offline (CDN blocked)';
document.getElementById('banter-status').style.color='var(--gray)';
};
document.head.appendChild(s);
}
var appUrl='https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js';
var dbUrl='https://www.gstatic.com/firebasejs/9.23.0/firebase-database-compat.js';
loadScript(appUrl,function(){
loadScript(dbUrl,function(){
try{
var firebaseConfig={
apiKey:'AIzaSyBU6vWqHUbHSnIPdjcGpC3BlwzlwhL24jg',
authDomain:'wc2026-sweepstake-dbd56.firebaseapp.com',
databaseURL:'https://wc2026-sweepstake-dbd56-default-rtdb.europe-west1.firebasedatabase.app',
projectId:'wc2026-sweepstake-dbd56',
storageBucket:'wc2026-sweepstake-dbd56.firebasestorage.app',
messagingSenderId:'11571340466',
appId:'1:11571340466:web:ebfbf6f935ce22ea98d5ab'
};
_fbApp=firebase.initializeApp(firebaseConfig);
_fbDb=firebase.database();
_fbRef=_fbDb.ref('banter');
_fbRef.on('value',function(snapshot){
var data=snapshot.val();
_fbMessages=[];
if(data){
Object.keys(data).forEach(function(k){_fbMessages.push(data[k]);});
_fbMessages.sort(function(a,b){return a.id-b.id;});
}
renderBanter();
updateBanterDot();
});
document.getElementById('banter-status').textContent='Live';
document.getElementById('banter-status').style.color='var(--wc-green)';
}catch(e){
console.warn('Firebase init failed:',e);
document.getElementById('banter-status').textContent='Offline';
document.getElementById('banter-status').style.color='var(--gray)';
}
});
});
}
function updateBanterDot(){
var lastSeen=parseInt(localStorage.getItem('banter-last-seen')||'0',10);
var hasNew=_fbMessages.some(function(m){return m.id>lastSeen;});
var dot=document.getElementById('banter-dot');
if(dot)dot.style.display=hasNew?'inline-block':'none';
}
function setReply(id){
var msg=_fbMessages.find(function(m){return m.id===id;});
if(!msg)return;
replyToId=id;
var preview=document.getElementById('banter-reply-preview');
var previewText=document.getElementById('banter-reply-text');
if(preview&&previewText){
previewText.innerHTML=''+msg.name+': '+msg.text.slice(0,60)+(msg.text.length>60?'...':'');
preview.style.display='flex';
}
var ta=document.getElementById('banter-msg');
if(ta)ta.focus();
}
function clearReply(){
replyToId=null;
var preview=document.getElementById('banter-reply-preview');
if(preview)preview.style.display='none';
}
function renderBanter(){
var sel=document.getElementById('banter-name');
if(sel){
var cur=sel.value;
sel.innerHTML=state.players.length
?state.players.map(function(p){return '';}).join('')
:'';
}
var lastSeen=parseInt(localStorage.getItem('banter-last-seen')||'0',10);
var msgs=_fbMessages;
var feed=document.getElementById('banter-feed');
if(!feed)return;
if(!msgs.length){
feed.innerHTML='
No messages yet. Start the banter! 🗣
';
return;
}
feed.innerHTML=msgs.slice().reverse().map(function(m,i){
var pi=state.players.indexOf(m.name);
var col=pi>=0?pc(pi):{bg:'#444'};
var initials=m.name.split(' ').map(function(w){return w[0];}).join('').toUpperCase().slice(0,2);
var ts=new Date(m.ts).toLocaleTimeString('en-GB',{hour:'2-digit',minute:'2-digit'});
var dateStr=new Date(m.ts).toLocaleDateString('en-GB',{day:'numeric',month:'short'});
var isNew=m.id>lastSeen;
var replyHtml='';
if(m.replyTo){
var orig=_fbMessages.find(function(x){return x.id===m.replyTo;});
if(orig){
var origPi=state.players.indexOf(orig.name);
var origCol=origPi>=0?pc(origPi):{bg:'#444'};
replyHtml='
';
}).join('');
}
function scrollToBanter(id){
var el=document.getElementById('banter-msg-'+id);
if(el){el.scrollIntoView({behavior:'smooth',block:'center'});el.style.background='rgba(240,180,41,.1)';setTimeout(function(){el.style.background='';},1200);}
}
function markBanterRead(){
if(!_fbMessages.length)return;
var maxId=Math.max.apply(null,_fbMessages.map(function(m){return m.id;}));
localStorage.setItem('banter-last-seen',maxId);
var dot=document.getElementById('banter-dot');
if(dot)dot.style.display='none';
}
function postBanter(){
var name=document.getElementById('banter-name').value;
var msg=document.getElementById('banter-msg').value.trim();
if(!name||!msg)return;
if(!_fbRef){alert('Not connected to Firebase yet. Please wait a moment and try again.');return;}
var entry={id:Date.now(),name:name,text:msg,ts:new Date().toISOString()};
if(replyToId)entry.replyTo=replyToId;
_fbRef.push(entry);
document.getElementById('banter-msg').value='';
clearReply();
markBanterRead();
}
function deleteBanter(id){
if(!_fbRef)return;
// Find the Firebase key for this message
_fbRef.once('value',function(snapshot){
snapshot.forEach(function(child){
if(child.val().id===id){
child.ref.remove();
}
});
});
}
/* -- BRACKET PREDICTOR -- */
/*
Bracket structure: 32 teams -> R32 (16 matches) -> R16 (8) -> QF (4) -> SF (2) -> Final (1)
state.bracket = {
rounds: [ [matchObj,...], ... ] // 5 rounds: r32, r16, qf, sf, final
}
matchObj = { t: [teamNameOrNull, teamNameOrNull], winner: teamNameOrNull }
*/
var BRACKET_ROUND_NAMES=['Round of 32','Round of 16','Quarter-finals','Semi-finals','Final'];
function initBracket(){
if(!state.drawn)return;
// WC 2026 official R32 matchup slots by group position
// Format: [slot description, group codes for team options]
// Each match: {label, groups} where groups are the pool of teams to pick from
// Based on official FIFA WC2026 bracket: 12 group winners + 12 runners-up + 8 best 3rds
// We simplify: show all teams from the relevant groups as options, user taps to pick
var R32_SLOTS=[
// Match 1-16 based on official WC2026 bracket structure
// Group winners vs best 3rds / runners-up
{a:['A'],b:['B']}, // 1A v 2B
{a:['C'],b:['D']}, // 1C v 2D
{a:['E'],b:['F']}, // 1E v 2F
{a:['G'],b:['H']}, // 1G v 2H
{a:['I'],b:['J']}, // 1I v 2J
{a:['K'],b:['L']}, // 1K v 2L
{a:['B'],b:['A']}, // 1B v 2A
{a:['D'],b:['C']}, // 1D v 2C
{a:['F'],b:['E']}, // 1F v 2E
{a:['H'],b:['G']}, // 1H v 2G
{a:['J'],b:['I']}, // 1J v 2I
{a:['L'],b:['K']}, // 1L v 2K
// Last 4 matches involve 3rd-place qualifiers - use cross-group pools
{a:['A','B'],b:['C','D']},
{a:['E','F'],b:['G','H']},
{a:['I','J'],b:['K','L']},
{a:['A','C','E'],b:['B','D','F']}
];
// Build a lookup: group letter -> drawn teams in that group
var groupMap={};
var SCHEDULE_GROUPS={
A:['MEX','RSA','KOR','CZE'],B:['CAN','BIH','QAT','SUI'],
C:['BRA','MAR','HAI','SCO'],D:['USA','PAR','AUS','TUR'],
E:['GER','CUW','CIV','ECU'],F:['NED','JPN','SWE','TUN'],
G:['BEL','EGY','IRN','NZL'],H:['ESP','CPV','KSA','URU'],
I:['FRA','SEN','IRQ','NOR'],J:['ARG','ALG','AUT','JOR'],
K:['POR','COD','UZB','COL'],L:['ENG','CRO','GHA','PAN']
};
var drawnCodes={};
Object.values(state.assignments).forEach(function(ts){
ts.forEach(function(tn){
var t=TEAMS.find(function(x){return x.name===tn;});
if(t)drawnCodes[t.code]=tn;
});
});
Object.keys(SCHEDULE_GROUPS).forEach(function(g){
groupMap[g]=SCHEDULE_GROUPS[g].filter(function(c){return drawnCodes[c];}).map(function(c){return drawnCodes[c];});
});
var matches=R32_SLOTS.map(function(slot){
// pool for side a: all drawn teams from those groups
var poolA=[],poolB=[];
slot.a.forEach(function(g){poolA=poolA.concat(groupMap[g]||[]);});
slot.b.forEach(function(g){poolB=poolB.concat(groupMap[g]||[]);});
// pick first from each pool as default slot (user can change by tapping)
return {t:[poolA[0]||null,poolB[0]||null],poolA:poolA,poolB:poolB,winner:null};
});
var rounds=[matches];
for(var r=0;r<4;r++){
var prev=rounds[r];
var next=[];
for(var j=0;j=4)return;
var m=state.bracket.rounds[round][match];
if(!m)return;
// if the old team (being replaced) was the winner, clear their downstream too
var oldTeam=m.t[slot];
if(oldTeam&&m.winner===oldTeam){
m.winner=null;
var nextMatch=Math.floor(match/2);
var nextSlot=match%2;
clearDownstream(round+1,nextMatch,oldTeam,nextSlot);
if(state.bracket.rounds[round+1][nextMatch]){
state.bracket.rounds[round+1][nextMatch].t[nextSlot]=null;
}
}
}
function resetBracket(){
if(!confirm('Reset bracket prediction?'))return;
state.bracket=null;
save();
renderBracket();
}
function renderBracket(){
var el=document.getElementById('bracket-content');
var champCard=document.getElementById('bracket-champion-card');
if(!el)return;
if(!state.drawn){el.innerHTML='
Do the draw first to unlock the bracket predictor.
';
if(champCard)champCard.style.display='none';
return;
}
var rounds=state.bracket.rounds;
var html='
';
for(var r=0;r';
html+='
'+BRACKET_ROUND_NAMES[r]+'
';
html+='
';
for(var m=0;m
';
}
html+='
';
el.innerHTML=html;
// champion display
var finalMatch=rounds[4][0];
var champ=finalMatch&&finalMatch.winner;
if(champ&&champCard){
champCard.style.display='block';
var ct=TEAMS.find(function(x){return x.name===champ;})||{code:'???',emoji:'',rank:99};
var owner=Object.entries(state.assignments).find(function(e){return e[1].indexOf(champ)>=0;});
var flagHtml=flagCache[ct.code]?'':(ct.emoji?''+ct.emoji+'':'');
document.getElementById('bracket-champion-display').innerHTML=
'
'
+'
\uD83C\uDFC6
'
+'
'+flagHtml+'
'
+'
'+champ+'
'
+(owner?'
Drawn by '+owner[0]+'
':'')
+'
';
} else if(champCard){
champCard.style.display='none';
}
}
function renderBracketMatch(round,matchIdx,m){
var t0=m.t[0];
var t1=m.t[1];
var w=m.winner;
function teamHtml(tn,slot){
var pool=slot===0?(m.poolA||[]):(m.poolB||[]);
if(!tn&&!pool.length){
return '
TBD
';
}
// If round 0 and pool has multiple options, show a mini-select
if(round===0&&pool.length>1){
var selOpts=pool.map(function(ptn){
var pt=TEAMS.find(function(x){return x.name===ptn;})||{code:'???'};
return '';
}).join('');
var curT=tn?TEAMS.find(function(x){return x.name===tn;})||{code:'???',emoji:'',rank:99}:{code:'?',emoji:'',rank:99};
var flagHtml=tn&&flagCache[curT.code]?'': (tn&&curT.emoji?''+curT.emoji+'':'');
return '
';
}
var t=TEAMS.find(function(x){return x.name===tn;})||{code:'???',emoji:'',rank:99};
var isW=w===tn;
var isL=w&&w!==tn;
var flagHtml2=flagCache[t.code]?'':(t.emoji?''+t.emoji+'':'');
var owner=Object.entries(state.assignments).find(function(e){return e[1].indexOf(tn)>=0;});
var ownerInitials=owner?owner[0].split(' ').map(function(w2){return w2[0];}).join('').toUpperCase().slice(0,2):'';
var pi=owner?state.players.indexOf(owner[0]):-1;
var ownerCol=pi>=0?pc(pi).bg:'#666';
return '
';
}
function swapBracketSlot(round,match,slot,teamName){
if(!state.bracket)return;
var m=state.bracket.rounds[round][match];
if(!m)return;
m.t[slot]=teamName;
if(m.winner&&m.winner!==m.t[0]&&m.winner!==m.t[1])m.winner=null;
save();renderBracket();
}
function shareBracket(){
if(!state.bracket)return;
var rounds=state.bracket.rounds;
var rnames=['R32','R16','QF','SF','Final'];
var txt='\u26BD WC 2026 BRACKET PREDICTION \u26BD\n';
for(var r=0;rfetchResults());
} else {
setSyncStatus('','No API key set \u2014 add one in Setup for live results');
}