PageSourceSearch

https://flagid.org/game?utm_source=flagid&utm_medium=homepage-card&utm_campaign=announce-game

html flagid.org collected 2026-10-02 12:11:42 UTC 118,147 bytes, 1,863 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="utf-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
6    <meta name="csrf-token" content="Z7r6rq22hAzmUgxWTdlp9T3pWZBNyrLm8LK2ikb7">
7
8    
9    
9<script src="https://cmp.setupcmp.com/cmp/cmp/cmp-stub.js" data-prop-id="6317"></script>
9
10        
10<script src="https://cmp.setupcmp.com/cmp/cmp/cmp-v1.js" data-prop-stpd-cmp-id="6317" async></script>
vendor: 78 bytes, lines 10-13
10
11    
12    
13    <script async src="https://www.googletagmanager.com/gtag/js?id=
13G-WRBE5ZZGBE
vendor: 16 bytes, lines 13-14
13"></script>
14    
14<script>
15        
vendor: 152 bytes, lines 15-19
15window.dataLayer = window.dataLayer || [];
16        function gtag(){dataLayer.push(arguments);}
17
18        gtag('js', new Date());
19        gtag('config', '
19G-WRBE5ZZGBE
vendor: 54 bytes, lines 19-22
19', {
20            'anonymize_ip': true
21        });
22    
22</script>
22
23
24    
25                        
25<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6114758564581825" crossorigin="anonymous"></script>
25
26            
27            
27<script>
28                window.adsbygoogle = window.adsbygoogle || [];
29                window.adBreak = window.adConfig = function (o) { window.adsbygoogle.push(o); };
30            </script>
30
31            
32    <title>Flagid Game — match flags to their countries and colors</title>
33
34    
35    <meta property="og:type" content="website">
36<meta property="og:url" content="https://flagid.org/game">
37<meta property="og:title" content="Flagid Game — match flags to their countries and colors">
38<meta property="og:description" content="Match flags to their countries, then match a flag to its exact colours. Built on flagid.org&#039;s vexillology database — national, regional, historical and organisational flags.">
39<meta property="og:image" content="https://flagid.org/images/og-game.png">
40<meta property="og:image:width" content="1200">
41<meta property="og:image:height" content="630">
42<meta property="og:site_name" content="Flagid">
43<meta property="og:locale" content="en_US">
44
45
46<meta name="twitter:card" content="summary_large_image">
47<meta name="twitter:url" content="https://flagid.org/game">
48<meta name="twitter:title" content="Flagid Game — match flags to their countries and colors">
49<meta name="twitter:description" content="Match flags to their countries, then match a flag to its exact colours. Built on flagid.org&#039;s vexillology database — national, regional, historical and organisational flags.">
50<meta name="twitter:image" content="https://flagid.org/images/og-game.png">
51
52
53<meta name="description" content="Match flags to their countries, then match a flag to its exact colours. Built on flagid.org&#039;s vexillology database — national, regional, historical and organisational flags.">
54
55    
56    <link rel="manifest" href="/game-manifest.json">
57    <meta name="theme-color" content="#1c1a15">
58    <meta name="mobile-web-app-capable" content="yes">
59    <meta name="apple-mobile-web-app-capable" content="yes">
60    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
61    <meta name="apple-mobile-web-app-title" content="Flagid Game">
62    <link rel="icon" type="image/png" href="/favicons/game/favicon-96x96.png" sizes="96x96" />
63    <link rel="icon" type="image/svg+xml" href="/favicons/game/favicon.svg" />
64    <link rel="shortcut icon" href="/favicons/game/favicon.ico" />
65    <link rel="apple-touch-icon" sizes="180x180" href="/favicons/game/apple-touch-icon.png" />
66    <meta name="apple-mobile-web-app-title" content="Flagid Game" />
67    <link rel="preconnect" href="https://fonts.googleapis.com">
68    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
69    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
70    <link rel="preload" as="style" href="https://flagid.org/build/assets/game-BGr2ay6U.css" /><link rel="modulepreload" href="https://flagid.org/build/assets/game-PyxF0sPz.js" /><link rel="modulepreload" href="https://flagid.org/build/assets/module.esm-BK6W-XiJ.js" /><link rel="stylesheet" href="https://flagid.org/build/assets/game-BGr2ay6U.css" data-navigate-track="reload" />
70<script type="module" src="https://flagid.org/build/assets/game-PyxF0sPz.js" data-navigate-track="reload"></script>
70</head>
71<body class="game-body" x-data x-cloak
72    :data-game-theme="($store.game.settingsOpen && $store.game.settingsView === 'daily_highscores') || ($store.game.state === 'daily' && !($store.game.settingsOpen && $store.game.settingsView === 'highscores')) ? 'daily' : 'journey'">
73    <header
74        class="game-brand-header"
75        x-show="['menu', 'level-intro', 'game-over'].includes($store.game.state)"
76        x-cloak
77    >
78        
79        <a href="https://flagid.org/game" class="game-brand-header__link"
80            :class="{ 'game-brand-header__link--inert': $store.game.state === 'level-intro' }"
81            :aria-disabled="$store.game.state === 'level-intro'"
82            @click.prevent="if ($store.game.state !== 'level-intro') { $store.game.hamburgerOpen = false; $store.game.goToMenu(); }"
83            aria-label="Flagid Game — start screen">
84            <div class="game-logo-lockup" role="img" aria-label="Flagid Game">
85    <svg class="flagid-logo flagid-logo--game game-logo-lockup__type" role="img" aria-label="Flagid Game" aria-hidden="true"
86     xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1166.1 138">
87    <g>
88	<g>
89		<path class="flagid-logo-color-2" d="M42.5,73.2c-1.3,16,9.3,12.5,19.6,11.4c3.1-0.4,6,2,6.5,5.1c0,0.4,0,0.7,0,1.1l-0.4,7.1
90			c-0.2,3.6-3.1,6.5-6.7,6.7l-11.8,0.9c-0.2,0-0.4,0-0.4,0.2c-4.2,1.6-6,4.9-5.8,10c0.4,5.6,0.7,10,0.7,13.8c0,3.1-2,6-5.1,6.7
91			c-7.6,2-14.9,2-22,0.4c-12.9-3.1-8.7-49.2-7.8-59.7c0-0.7-0.2-1.3-0.9-1.8c-5.8-4.7-7.8-14.5-8-22C0,44-0.5,31.5,1.5,22.2
92			C3.6,10.9,13.1,7.3,24.7,6.4C45,4.8,61.6,4.8,74.6,6.8c7.3,1.1,11.8,5.6,13.1,13.8c1.3,8,3.3,38.3-4.9,43.4
93			C75,68.9,67,66.2,54.3,64.7C47,63.8,43.2,66.5,42.5,73.2z"/>
94		<path class="flagid-logo-color-2" d="M119.5,5.3c8.2,0,13.8,0.2,16.7,0.9c13.6,3.3,10.5,26.7,8.9,36.9c-2.9,18.5-5.6,35.2-5.3,53.9
95			c0.4,18.7,21.1,5.3,32.9,7.3c5.3,0.9,5.3,6.9,5.8,11.8c1.1,13.8-6.9,19.6-20,20.9c-12.2,1.1-25.6,1.1-40.1-0.4
96			c-4-0.4-8-2-11.8-4.9c-4.9-3.6-4.5-12.7-4-18.3c0.9-13.4,2.2-25.4,4-36.3c0.2-0.9-0.4-1.6-1.1-1.8c-6.7-1.6-10.5-6-11.6-13.8
97			c-2-15.1-1.6-28.9,1.1-41.2c1.1-4.9,4.2-8.9,9.6-12.2C107.9,6.4,112.8,5.5,119.5,5.3z"/>
98		<path class="flagid-logo-color-2" d="M191.4,77.4c0.2-0.9-0.2-2-0.9-2.7c-3.6-3.6-5.6-8-5.6-13.6c-0.4-15.8,0.2-32.5,8-45.2
99			c1.3-2.2,4.5-4.7,9.1-7.3c1.1-0.7,2.2-1.1,3.6-1.3c14.5-2.4,27.4-2.7,38.5-0.9c12.2,2,19.6,9.8,21.6,23.6c4,26.9,7.6,55.4,10.7,85
100			c0.7,6.7,1.1,14.9-4,19.6c-3.8,3.6-13.1,3.1-19.8,2.9c-10-0.4-11.8-4.5-12.7-14c-0.4-4.5-1.3-9.3-2.7-14.9
101			c-0.4-1.8-1.8-3.1-3.6-3.6c-8.2-2.2-10.7,0.9-11.6,9.3c-0.7,6.5-0.4,15.1-5.8,20.7c-0.7,0.7-1.3,1.1-2.2,1.1
102			c-11.1,2.2-26.3,3.6-26.7-11.1C186.7,110.6,188.3,94.8,191.4,77.4z M236.2,70.5c0-3.3-2.9-6.2-6.2-6.2h-2c-3.3,0-6.2,2.9-6.2,6.2
103			l0,0l0.2,13.1c0,3.3,2.9,6.2,6.2,6.2h2c3.3,0,6.2-2.9,6.2-6.2l0,0L236.2,70.5z"/>
104		<path class="flagid-logo-color-2" d="M334.8,105.2c2.2-3.3,2.4-6.5,0.4-9.6c-0.4-0.7-1.3-1.3-2-1.6c-2.9-1.1-4.7-2.2-5.1-3.3
105			c-2.9-5.6-2-9.8,2.7-12.9c3.6-2.2,10-2,15.6-2c12.5,0,19.1,7.3,19.8,21.6c0.7,13.8,0.9,26-9.3,33.6c-8.9,6.5-21.6,6.5-32.7,6.5
106			c-43.8,0.2-46.3-67.9-44.1-97c0.4-4.7,4.2-16.5,8.2-20.9c5.3-6,11.4-9.8,17.8-11.4c17.1-4.2,33.6-4.7,49-1.3
107			c4.7,0.9,8.9,3.8,12.7,8.2c7.1,8.2,6.7,23.8,5.1,34.7c-0.9,6-2,10.2-3.3,12.7c-6.5,11.1-28.7,4.7-38.7,2.2
108			c-12.9-3.1-14.2,1.3-14.5,12.2c-0.2,8,0.4,15.1,2,21.1c1.8,7.6,6.7,10.5,14.7,8.2C333.4,106.6,334.1,105.9,334.8,105.2z"/>
109		<path class="flagid-logo-color-2" d="M403.3,136.4c-7.1-4.9-7.1-14-7.3-23.8c-0.4-12-0.2-23.8,0.7-36.1c0-0.4-0.4-1.1-0.9-1.1
110			c-7.1-1.3-11.4-5.6-12.5-12.7c-3.1-16.7-3.1-32.1-0.2-45.6c1.3-6.5,5.8-10,12.9-10.9s26.9-2.7,31.8,3.6c7.1,9.1,4.9,18.5,5.1,30.7
111			c0,8.5-2.4,18-2.4,26.5c0,23.6,0.7,43.2,1.6,58.8c0.4,6.9-2.7,10.7-8.9,11.4c-5.8,0.7-11.8,0.7-17.6,0
112			C404.9,137.1,404,136.8,403.3,136.4z"/>
113		<path class="flagid-logo-color-2" d="M493.7,137.1c-8,0.4-21.6,2.2-28.3-1.3c-8.9-4.7-12.7-14.7-13.1-24c-0.9-14.9-1.1-26.7-0.9-34.9
114			c0-0.9-0.4-1.8-1.1-2.2l-2.7-1.6l-0.2-0.2c-1.6-1.8-2.4-4-2.9-7.1c-2.9-17.6-2.7-33.8,0.9-48.5c0.2-0.7,0.4-1.1,0.7-1.8
115			c2.9-4.5,7.1-7.3,12.7-8c19.4-2.9,37.4-2.9,54.8-0.4c4.2,0.7,9.1,2.7,14.5,6.2c11.8,7.6,13.4,22.3,12.9,35.2
116			c-1.6,34.7-4.7,76.3-45,88.4C495,136.8,494.3,137.1,493.7,137.1z M481.4,110.6c0.9,2.2,3.6,3.1,5.8,2.2c0.4-0.2,0.9-0.4,1.3-0.9
117			c8.2-7.1,10.2-24,11.1-36.5c0.2-5.1-3.1-9.8-8-11.1l-0.9-0.2c-4.2-1.1-8.7,1.6-9.8,5.8c-0.2,0.7-0.2,1.1-0.2,1.8
118			c-0.4,13.6-0.2,25.4,0.4,35.2C481.2,109,481.2,110.1,481.4,110.6z"/>
119		<path class="flagid-logo-color-2" d="M780.5,106.8c0.9-0.2,1.6-0.7,2-1.3c2.2-3.3,2.4-6.5,0.2-9.6c-0.4-0.7-1.3-1.3-2-1.6
120			c-2.9-1.1-4.7-2.2-5.1-3.3c-2.9-5.6-2-9.8,2.7-12.9c3.6-2.2,10-2,15.6-2c12.5,0,19.1,7.3,19.8,21.8c0.7,13.8,0.9,26-9.3,33.6
121			c-8.9,6.5-21.6,6.5-32.7,6.5c-43.8,0-46.1-68.1-43.8-97.3c0.4-4.7,4.2-16.5,8.2-20.9c5.3-6,11.4-9.8,17.8-11.1
122			c17.1-4.2,33.6-4.7,49-1.3c4.7,0.9,8.9,3.8,12.7,8.2c7.1,8.2,6.7,23.8,5.1,34.7c-0.9,6-2,10.2-3.3,12.7
123			c-6.5,11.1-28.7,4.7-38.7,2.2c-12.9-3.1-14.2,1.3-14.5,12.2c-0.2,8,0.4,15.1,2,21.1C767.8,105.9,772.7,108.8,780.5,106.8z"/>
124		<path class="flagid-logo-color-2" d="M835,74.7c-3.6-3.6-5.6-8-5.6-13.6c-0.4-15.8,0.2-32.5,8-45.2c1.3-2.2,4.5-4.7,9.1-7.3
125			c1.1-0.7,2.2-1.1,3.6-1.3c14.5-2.4,27.4-2.7,38.5-0.9c12.2,2,19.6,10,21.6,23.6c4,26.9,7.3,55.4,10.5,85
126			c0.7,6.7,1.1,14.9-4.2,19.6c-3.8,3.6-13.1,3.1-19.8,2.9c-10-0.4-12-4.5-12.7-14c-0.4-4.5-1.3-9.3-2.7-14.9
127			c-0.4-1.8-1.8-3.1-3.6-3.6c-8.2-2.2-10.7,0.9-11.6,9.3c-0.7,6.5-0.4,15.1-5.8,20.7c-0.7,0.7-1.3,1.1-2.2,1.1
128			c-11.1,2.2-26.3,3.6-26.7-11.1c-0.4-14.5,1.1-30.5,4.2-47.9C836.1,76.3,835.7,75.4,835,74.7z M880.4,70.3c0-3.3-2.7-5.8-6-5.8l0,0
129			H872c-3.3,0-5.8,2.7-5.8,6l0.2,13.6c0,3.3,2.7,5.8,6,5.8l0,0h2.4c3.3,0,5.8-2.7,5.8-6L880.4,70.3z"/>
130		<path class="flagid-logo-color-2" d="M1004.4,29.3c2-5.1,4-9.3,5.8-12.5c6-9.8,13.8-10.9,25.6-11.6c12-0.7,22,2.2,24.5,15.1
131			c1.8,8.5,2.4,18.7,2.4,30.5c0,17.8-0.4,36.7-1.8,56.8c-0.4,6.2-1.3,12.7-2.9,18.9c-3.1,12.9-13.4,12.2-24.9,9.6
132			c-0.9-0.2-1.6-0.7-2.2-1.3c-3.1-3.8-4.7-7.6-4-11.8c2-16.7,3.6-28,4.2-34.5c0.7-5.3,0.7-11.1-0.2-17.4c-0.9-7.8-9.1-10-14.2-4.5
133			c-0.4,0.4-0.7,1.1-0.9,1.8c-2.7,14.5-2,29.2,2.2,43.8c2.9,10,4,24.5-10.2,25.2c-6.9,0.4-15.8,0.7-19.8-4.7
134			c-4.2-5.6-4.2-10.9-2.2-17.8c2.2-8.7,5.3-17.1,5.6-25.6c0.2-7.3-0.2-13.8-1.3-19.8c-0.4-2.4-1.8-4-4-4.9
135			c-19.4-8.2-9.8,46.1-8.2,56.8c0.7,4.5-0.4,8.5-3.1,11.8c-3.6,4.5-11.6,4.5-16.9,4.2c-20.3-1.3-15.1-48.3-13.8-60.8
136			c0-0.9-0.4-1.6-1.3-1.6l0,0c-18.5-1.1-15.1-37.4-14.2-48.3c1.3-13.8,8.9-20.9,23.1-21.4c10-0.2,18.9,0,26.7,0.9
137			c15.3,2,18.6,11.1,24.2,23.4c0.2,0.2,0.4,0.4,0.9,0.4C1004.1,29.6,1004.4,29.6,1004.4,29.3z"/>
138		<path class="flagid-logo-color-2" d="M1121.2,103.5c4.2,9.6,20.7-2.2,30.9,1.8c0.9,0.2,1.6,0.9,2,1.8c4.7,10.5,4.9,24-7.3,28.7
139			c-2.4,0.9-7.1,1.6-14.2,1.8c-11.8,0.4-22.5,0.2-32.1-1.1c-6-0.9-10.9-4-14.7-9.8c-0.4-0.7-0.7-1.1-0.9-1.8
140			c-4-15.4-2.9-31.4-1.8-47.9c0-1.1-0.4-2-1.6-2.4l-1.3-0.4c-0.7-0.2-1.1-0.7-1.3-1.1c-8.7-12-6.9-28.5-5.8-43.8
141			c1.4-19.3,14.7-23.3,32.8-24c12.7-0.4,24.7-0.4,36.1,0c4.2,0.2,7.8,0.9,10.7,1.8c13.6,4.9,13.4,17.1,13.4,30
142			c0,7.3-0.4,12.7-1.3,15.8c-4.5,17.8-22,13.4-36.5,10.9c-3.1-0.7-6.2,1.1-7.3,3.8c-0.7,1.3-0.4,3.6,0.7,6.7
143			c0.2,1.1,1.3,1.8,2.2,1.8l17.8,1.3c3.3,0.2,6,3.3,5.8,6.7l0,0l-0.2,2.7c-0.2,3.1-2.9,5.6-6,5.8c-8.2,0-17.4-0.7-19.6,7.3
144			C1120.8,101.5,1120.8,102.3,1121.2,103.5z"/>
145	</g>
146	<g>
147		<path id="disc_2_" fill="#c6a43b" d="M635.8,0c-38.1,0-69,30.9-69,69c0,22.7,11,42.8,27.9,55.4c1.8,1.3,3.8,2.6,5.7,3.8
148			c10.3,6.2,22.5,9.7,35.4,9.7c38.1,0,69-30.9,69-69S673.9,0,635.8,0z"/>
149		<path class="flagid-logo-color-3" d="M600.2,43.1L600.2,43.1L600.2,43.1v-0.3c4.3-1.4,7.2-6,6-10.9c-0.9-3.2-3.4-5.7-6.7-6.5
150			c-4.9-1.2-9.9,1.7-11.2,6.6c-0.2,0.8-0.3,1.4-0.3,2.2c0,4,2.6,7.3,6.3,8.6V125c1.8,1.3,3.8,2.6,5.8,3.8V91.4h85.8V43.2L600.2,43.1
151			L600.2,43.1z M641.7,87.4h-21.2V46.9h21.2V87.4z M682.2,87.4H661V46.9h21.2V87.4z"/>
152		<rect x="620.5" y="46.9" class="flagid-logo-color-2" width="21.2" height="40.5"/>
153		<rect x="661" y="46.9" class="flagid-logo-color-2" width="21.2" height="40.5"/>
154	</g>
155</g>
156</svg>
157</div>
158        </a>
159    </header>
160
161    
162    <button
163        class="game-hamburger-btn"
164        x-show="$store.game.state !== 'playing' && !$store.daily.isPlaying"
165        @click="$store.game.hamburgerOpen = true"
166        aria-label="Menu"
167    >
168        <svg viewBox="0 0 24 24" fill="currentColor" width="22" height="22"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
169    </button>
170
171    
172    <div
173        x-show="$store.game.hamburgerOpen"
174        x-transition:enter="game-panel-enter"
175        x-transition:enter-start="game-panel-enter-start"
176        x-transition:enter-end="game-panel-enter-end"
177        x-transition:leave="game-panel-leave"
178        x-transition:leave-start="game-panel-leave-start"
179        x-transition:leave-end="game-panel-leave-end"
180        class="game-panel"
181        @keydown.escape.window="$store.game.hamburgerOpen = false"
182        x-cloak
183    >
184        <div class="game-panel__header">
185            <h2>Menu</h2>
186            <button @click="$store.game.hamburgerOpen = false" class="game-panel__close" aria-label="Close">
187                <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24">
187<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
188            </button>
189        </div>
190        <div class="game-panel__body">
191            <button @click="$store.game.openProfile()" class="game-panel__item game-menu-profile"
192                :aria-label="$store.game.isGuest ? 'Log in' : 'View your profile'">
193                <span class="game-menu-profile__avatar">
194                    <img x-show="!$store.game.isGuest && $store.game.avatar" :src="$store.game.avatar"
195                        class="game-account-btn__avatar" referrerpolicy="no-referrer" alt="">
196                    <svg x-show="$store.game.isGuest || !$store.game.avatar" class="game-account-btn__avatar game-account-btn__avatar--placeholder"
197                        aria-hidden="true" viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>
198                    <img x-show="!$store.game.isGuest && $store.game.countryFlag" :src="$store.game.countryFlag"
199                        class="game-flag-badge" alt="" aria-hidden="true" x-cloak>
200                </span>
201                <span class="game-menu-profile__text">
202                    <strong x-text="$store.game.isGuest ? 'Log in' : ($store.game.playerName || 'Your profile')"></strong>
203                    <small x-show="!$store.game.isGuest">View profile</small>
204                </span>
205            </button>
206            
207            <button @click="$store.game.openHighscores()" class="game-panel__item game-panel__item--board" data-game-theme="journey">
208                <svg viewBox="0 0 24 24" fill="currentColor" width="20" height="20"><path d="M7 4V2H17V4H20C20.55 4 21 4.45 21 5V11C21 12.1 20.1 13 19 13H16.83C16.42 14.17 15.31 15 14 15H13V17H16V19H13V22H11V19H8V17H11V15H10C8.69 15 7.58 14.17 7.17 13H5C3.9 13 3 12.1 3 11V5C3 4.45 3.45 4 4 4H7ZM5 6V11H7V6H5ZM17 6V11H19V6H17Z"/></svg>
209                <span>Flag Journey Hall of Fame</span>
210            </button>
211            <button @click="$store.game.openDailyHighscores()" class="game-panel__item game-panel__item--board" data-game-theme="daily">
212                <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="20" height="20"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M7 2v6m10-6v6M3 11h18m-13 5 3 3 5-5"/></svg>
213                <span>Daily Challenge Scores</span>
214            </button>
215            
216            <button
217                x-show="$store.game.installPromptEvent"
218                x-cloak
219                @click="$store.game.installApp()"
220                class="game-panel__item"
221            >
222                <svg viewBox="0 0 24 24" fill="currentColor" width="20" height="20"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
223                <span>Install App</span>
224            </button>
225            <button
226                class="game-panel__item"
227                @click="$store.game.toggleSound()"
228                :aria-label="$store.game.soundsMuted ? 'Turn sound on' : 'Turn sound off'"
229            >
230                <svg x-show="!$store.game.soundsMuted" viewBox="0 0 24 24" fill="currentColor" width="20" height="20"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3A4.5 4.5 0 0014 8.03v7.94c1.48-.74 2.5-2.27 2.5-3.97zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></svg>
231                <svg x-show="$store.game.soundsMuted" x-cloak viewBox="0 0 24 24" fill="currentColor" width="20" height="20"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.21.05-.42.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51A8.796 8.796 0 0021 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06a8.99 8.99 0 003.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/></svg>
232                <span x-text="$store.game.soundsMuted ? 'Sound Off' : 'Sound On'"></span>
233            </button>
234
235            
236            <button
237                x-show="$store.game.credits.length"
238                @click="$store.game.openCredits()"
239                class="game-panel__link"
240            >Credits</button>
241
242            
243            <form
244                method="POST"
245                action="https://flagid.org/logout"
246                class="game-panel__logout"
247                x-show="!$store.game.isGuest"
248                x-cloak
249            >
250                <input type="hidden" name="_token" value="Z7r6rq22hAzmUgxWTdlp9T3pWZBNyrLm8LK2ikb7">
251                <input type="hidden" name="redirect" value="/game">
252                <button type="submit" class="game-panel__item game-panel__item--danger">
253                    <svg viewBox="0 0 24 24" fill="currentColor" width="20" height="20"><path d="M17 7l-1.41 1.41L18.17 11H8v2h10.17l-2.58 2.58L17 17l5-5-5-5zM4 5h8V3H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8v-2H4V5z"/></svg>
254                    <span>Log out</span>
255                </button>
256            </form>
257
258
259        </div>
260    </div>
261
262    
263    <div
264        x-show="$store.game.flashEvent"
265        x-transition:enter="game-flash-enter"
266        x-transition:enter-start="game-flash-enter-start"
267        x-transition:enter-end="game-flash-enter-end"
268        x-transition:leave="game-flash-leave"
269        x-transition:leave-start="game-flash-leave-start"
270        x-transition:leave-end="game-flash-leave-end"
271        class="game-flash"
272        :class="$store.game.flashEvent ? 'game-flash--' + $store.game.flashEvent : ''"
273        x-cloak
274        aria-hidden="true"
275    >
276        <template x-if="$store.game.flashEvent === 'correct'">
277            <span class="game-flash__mark game-flash__mark--icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
278    <path d="m4 12 5 5L20 6"/>
279</svg></span>
280        </template>
281        <template x-if="$store.game.flashEvent === 'wrong'">
282            <span class="game-flash__mark game-flash__mark--icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
283    <path d="m6 6 12 12M18 6 6 18"/>
284</svg></span>
285        </template>
286        
287        <template x-if="$store.game.flashEvent === 'extra-life'">
288            <span class="game-flash__mark game-flash__mark--message">Extra life! <svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
289    <path d="M4 22V3m0 1c5-4 9 4 15 0v9c-6 4-10-4-15 0m10 6h8m-4-4v8"/>
290</svg></span>
291        </template>
292        <template x-if="$store.game.flashEvent === 'times-up'">
293            <span class="game-flash__mark game-flash__mark--icon">
294                <svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96">
295    <style type="text/css">
296        .times-up-icon-0{fill:none;stroke:currentColor;stroke-width:8;}
297        .times-up-icon-1{fill:none;stroke:currentColor;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;}
298        .times-up-icon-2{fill:none;stroke:currentColor;stroke-width:3.6838;stroke-miterlimit:10;}
299        .times-up-icon-3{fill:none;stroke:currentColor;stroke-width:4.3095;stroke-linecap:round;stroke-miterlimit:10;}
300    </style>
301    <g>
302        <circle class="times-up-icon-0" cx="43.2" cy="54.2" r="30"/>
303        <path class="times-up-icon-1" d="M43.2,35.2v21l14,8"/>
304    </g>
305    <g>
306        <path class="times-up-icon-2" d="M74.9,7.1L61,30.9c-0.7,1.1,0.2,2.6,1.5,2.6h27.8c1.3,0,2.1-1.4,1.5-2.6L77.9,7.1C77.2,5.9,75.6,5.9,74.9,7.1z"/>
307        <line class="times-up-icon-3" x1="76.4" y1="15.3" x2="76.4" y2="22.8"/>
308        <line class="times-up-icon-3" x1="76.4" y1="27.7" x2="76.4" y2="28"/>
309    </g>
310</svg>            </span>
311        </template>
312    </div>
313
314
315    
316    <div x-show="$store.game.state === 'menu'" class="game-screen game-menu">
317        <div class="game-menu__inner">
318            <h1 class="game-menu__title">Flagid<br>Game</h1>
319
320            <div class="game-menu__player">
321                <button type="button"
322                    class="game-profile__avatar-wrap game-menu__avatar"
323                    @click="$store.game.openProfile()"
324                    :aria-label="$store.game.isGuest ? 'Log in' : 'View your profile'">
325                    <img x-show="!$store.game.isGuest && $store.game.avatar"
326                        :src="$store.game.avatar"
327                        class="game-profile__avatar" referrerpolicy="no-referrer" alt="">
328                    <svg x-show="$store.game.isGuest || !$store.game.avatar"
329                        class="game-profile__avatar game-profile__avatar--placeholder"
330                        aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
331                        <path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/>
332                    </svg>
333                    <img x-show="!$store.game.isGuest && $store.game.countryFlag"
334                        :src="$store.game.countryFlag"
335                        class="game-flag-badge game-flag-badge--lg" alt="" aria-hidden="true" x-cloak>
336                </button>
337                <p class="game-menu__name" x-show="$store.game.playerName"
338                    x-text="$store.game.playerName" x-cloak></p>
339                <a x-show="$store.game.isGuest" href="https://flagid.org/game/login"
340                    class="game-menu__login" x-cloak>Log in</a>
341            </div>
342
343            <div class="daily-menu-card" data-game-theme="journey">
344                <button @click="$store.game.startGame()" class="game-btn game-btn--primary" :disabled="$store.game.loading">
345                    <span>Flag Journey</span>
346                    <span x-show="$store.game.loading" x-cloak class="game-spinner"></span>
347                </button>
348                <p>Endure the levels. Outlast the flags.</p>
349                <button type="button" class="daily-menu-card__board" @click="$store.game.openHighscores()">
350                    <svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M7 4V2H17V4H20C20.55 4 21 4.45 21 5V11C21 12.1 20.1 13 19 13H16.83C16.42 14.17 15.31 15 14 15H13V17H16V19H13V22H11V19H8V17H11V15H10C8.69 15 7.58 14.17 7.17 13H5C3.9 13 3 12.1 3 11V5C3 4.45 3.45 4 4 4H7ZM5 6V11H7V6H5ZM17 6V11H19V6H17Z"/></svg>
351                    <span>Hall of Fame</span>
352                </button>
353            </div>
354            <div class="daily-menu-card" data-game-theme="daily">
355                <button @click="$store.daily.open()" class="game-btn game-btn--primary">
356                    <span>Daily Challenge</span>
357                </button> 
358                <p>Match the flags. Match the colors.</p>
359                <button type="button" class="daily-menu-card__board" @click="$store.game.openDailyHighscores()">
360                    <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="M4 20V10m6 10V4m6 16v-7m4 7H2"/></svg>
361                    <span>Scores</span>
362                </button>
363            </div>
364
365            
366            <template x-if="$store.game.testNote">
367                <p class="game-menu__test-note"
368                   :class="{ 'game-menu__test-note--error': $store.game.testFlagError }"
369                   x-text="$store.game.testNote"></p>
370            </template>
371
372        </div>
373    </div>
374
375    <section
376    x-show="$store.game.state === 'daily' && !$store.daily.isPlaying"
377    x-transition:enter="game-panel-enter"
378    x-transition:enter-start="game-panel-enter-start"
379    x-transition:enter-end="game-panel-enter-end"
380    x-transition:leave="game-panel-leave"
381    x-transition:leave-start="game-panel-leave-start"
382    x-transition:leave-end="game-panel-leave-end"
383    class="game-panel daily-screen"
384    
385    @keydown.escape.window="$store.game.settingsOpen || ($store.game.state = 'menu')"
386    x-cloak
387>
388    <button class="game-panel__close daily-screen__close" @click="$store.game.state = 'menu'" aria-label="Close">
389        <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
390    </button>
391    <header class="daily-header">
392        <p class="daily-eyebrow">ONE DAY. TWO CHALLENGES.</p>
393        <h1>Flagid Daily <span x-show="$store.daily.data" x-text="'#' + $store.daily.data?.number"></span></h1>
394        <p x-show="$store.daily.data" x-text="$store.daily.data?.date + ' · Resets at midnight UTC'"></p>
395    </header>
396
397    <div x-show="$store.daily.error" class="daily-notice" role="alert">
398        <p x-text="$store.daily.error"></p>
399        <button class="daily-link" :disabled="$store.daily.busy" @click="$store.daily.pending ? $store.daily.sendPending() : $store.daily.load()">Try again</button>
400    </div>
401    <p x-show="$store.daily.busy" role="status">Saving your place…</p>
402    <template x-if="$store.daily.data">
403        <div>
404            <div x-show="$store.daily.expired" class="daily-notice">
405                <p>A new daily challenge is ready.</p>
406                <button class="game-btn game-btn--primary" @click="$store.daily.load()">Open Today’s Challenge</button>
407            </div>
408
409            <div x-show="$store.daily.phase === 'intro'" class="daily-intro">
410                <button class="game-btn game-btn--primary" :disabled="$store.daily.busy || $store.daily.expired" @click="$store.daily.start()">Play Today</button>
411            </div>
412
413            <div x-show="$store.daily.phase === 'result'" class="daily-result">
414                <p class="daily-eyebrow" x-text="$store.daily.data.score === $store.daily.data.max_score ? 'PERFECT DAY!' : 'DAILY COMPLETE'"></p>
415                <h2><span x-text="$store.daily.data.score"></span><small x-text="'/' + $store.daily.data.max_score"></small></h2>
416                <p>🏁 Match: <strong x-text="$store.daily.data.match_mistakes"></strong> <span x-text="$store.daily.data.match_mistakes === 1 ? 'mistake' : 'mistakes'"></span></p>
417                <p>🎨 Colors: <strong x-text="$store.daily.data.color_mistakes"></strong> <span x-text="$store.daily.data.color_mistakes === 1 ? 'mistake' : 'mistakes'"></span></p>
418                <p>Next challenge in <strong x-text="$store.daily.countdown"></strong></p>
419                <button class="game-btn game-btn--primary" @click="$store.daily.share()">Share result</button>
420                <p aria-live="polite" x-text="$store.daily.feedback"></p>
421                <textarea x-show="$store.daily.shareFallback" :value="$store.daily.data.share_text" readonly @focus="$el.select()" aria-label="Copy your result" rows="7"></textarea>
422                
423                <button class="game-panel__item game-panel__item--board" data-game-theme="daily" @click="$store.game.openDailyHighscores()">
424                    <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="20" height="20"><rect x="3" y="5" width="18" height="16" rx="2"/>
424<path d="M7 2v6m10-6v6M3 11h18m-13 5 3 3 5-5"/></svg>
425                    <span>Daily Challenge Scores</span>
426                </button>
427            </div>
428
429            
430            <div class="daily-reminder" x-show="$store.reminder.status !== 'unsupported'">
431                <template x-if="$store.reminder.status === 'off'">
432                    <div class="daily-reminder__row">
433                        <button class="game-btn" :disabled="$store.reminder.busy" @click="$store.reminder.enable()">🔔 Remind me every day</button>
434                        <label class="daily-reminder__time">at
435                            <select :value="$store.reminder.hour" @change="$store.reminder.setHour($event.target.value)">
436                                <template x-for="opt in $store.reminder.hourOptions" :key="opt.value">
437                                    <option :value="opt.value" x-text="opt.label" :selected="opt.value === $store.reminder.hour"></option>
438                                </template>
439                            </select>
440                        </label>
441                    </div>
442                </template>
443                <template x-if="$store.reminder.status === 'on'">
444                    <div class="daily-reminder__row">
445                        <span>🔔 Reminder on, every day at</span>
446                        <select aria-label="Reminder time" :value="$store.reminder.hour" @change="$store.reminder.setHour($event.target.value)">
447                            <template x-for="opt in $store.reminder.hourOptions" :key="opt.value">
448                                <option :value="opt.value" x-text="opt.label" :selected="opt.value === $store.reminder.hour"></option>
449                            </template>
450                        </select>
451                        <button class="daily-link" :disabled="$store.reminder.busy" @click="$store.reminder.disable()">Turn off</button>
452                    </div>
453                </template>
454                <p x-show="$store.reminder.status === 'denied'" class="daily-reminder__note">Notifications are blocked for this site. Allow them in your browser settings to get a daily reminder.</p>
455                <p x-show="$store.reminder.status === 'ios-install'" class="daily-reminder__note">Want a daily reminder? Tap <strong>Share → Add to Home Screen</strong>, then open Flagid Game from your home screen.</p>
456                <p x-show="$store.reminder.error" class="daily-reminder__note" role="alert" x-text="$store.reminder.error"></p>
457            </div>
458        </div>
459    </template>
460</section>
461
462<template x-if="$store.daily.isPlaying">
463    <div class="game-screen game-board" data-daily-board>
464        <header class="game-header">
465            <div class="game-header__level">
466                <div class="game-header__level-num" x-text="$store.daily.phase === 'match' ? 1 : 2"></div>
467                <div class="game-header__level-text">
468                    <div class="game-header__level-category" x-text="'Flagid Daily #' + $store.daily.data.number"></div>
469                    <div class="game-header__level-name" x-text="$store.daily.phase === 'match' ? 'Match the flags' : 'Match the colors'"></div>
470                </div>
471            </div>
472            <div class="game-header__score" aria-live="polite" :aria-label="$store.daily.data.score + ' points'" x-text="$store.daily.data.score"></div>
473        </header>
474
475        <div class="game-grid" x-data="{ get boardGame() { return $store.daily; } }" x-show="boardGame.mode === 'name'">
476            
477            <div class="game-col game-col--flags">
478                <template x-for="(pair, idx) in boardGame.flagOrder" :key="'f'+pair.id">
479                    <button
480                        class="game-box game-box--flag"
481                        :class="{
482                            'game-box--selected': boardGame.selectedFlag === idx,
483                            'game-box--correct': pair.flagStatus === 'correct',
484                            'game-box--wrong': pair.flash === 'wrong',
485                            'game-box--blocked': boardGame.flagIsBlocked(pair.id),
486                            'game-box--faded': pair.faded,
487                        }"
488                        :disabled="boardGame.inputLocked || pair.flagStatus !== 'active' || boardGame.flagIsBlocked(pair.id)"
489                        @click="boardGame.selectBox('flag', idx)"
490                    >
491                        <template x-if="pair.image_url">
492                            <img :src="pair.image_url" alt="Flag" class="game-flag-img" loading="eager">
493                        </template>
494                        <template x-if="pair.image_svg">
495                            <div class="game-flag-svg" x-html="pair.image_svg"></div>
496                        </template>
497                        <span x-show="pair.flagStatus === 'correct'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
498    <path d="m4 12 5 5L20 6"/>
499</svg></span>
500                        <span x-show="pair.flash === 'wrong'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
501    <path d="m6 6 12 12M18 6 6 18"/>
502</svg></span>
503                    </button>
504                </template>
505            </div>
506
507            
508            <div class="game-col game-col--names">
509                <template x-for="(pair, idx) in boardGame.nameOrder" :key="'n'+pair.id">
510                    <button
511                        class="game-box game-box--name"
512                        :class="{
513                            'game-box--selected': boardGame.selectedName === idx,
514                            'game-box--correct': pair.nameStatus === 'correct',
515                            'game-box--wrong': pair.flash === 'wrong',
516                            'game-box--blocked': boardGame.nameIsBlocked(pair.id),
517                            'game-box--faded': pair.faded,
518                        }"
519                        :disabled="boardGame.inputLocked || pair.nameStatus !== 'active' || boardGame.nameIsBlocked(pair.id)"
520                        @click="boardGame.selectBox('name', idx)"
521                    >
522                        <span class="game-box__name" x-text="pair.name"></span>
523                        <template x-if="pair.subtitle_parts && pair.subtitle_parts.length">
524                            <span class="game-box__subtitle">
525                                <template x-for="(part, pIdx) in pair.subtitle_parts" :key="pIdx">
526                                    <span :class="'subtitle-' + part.source" x-text="part.text"></span>
527                                </template>
528                            </span>
529                        </template>
530                        <span x-show="pair.nameStatus === 'correct'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
531    <path d="m4 12 5 5L20 6"/>
532</svg></span>
533                        <span x-show="pair.flash === 'wrong'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
534    <path d="m6 6 12 12M18 6 6 18"/>
535</svg></span>
536                    </button>
537                </template>
538            </div>
539        </div>
540
541        <template x-if="$store.daily.phase === 'colors'">
542            <div
543            class="game-color" x-data="{ get boardGame() { return $store.daily; } }" x-init="boardGame.paintRegions()"
544            :class="boardGame.hoistSide === 'right' ? 'game-color--hoist-right' : ''"
545            x-show="boardGame.mode === 'colour'"
546            x-cloak
547        >
548            <div class="game-color__meta">
549                <span
550                    class="game-color__progress"
551                    x-show="boardGame.flagCount > 1"
552                    x-text="'Flag ' + boardGame.boardIndex + '/' + boardGame.flagCount"
553                ></span>
554                <span class="game-color__title">
555                    <span class="game-color__name" x-text="boardGame.board?.name"></span>
556                    <template x-if="boardGame.board?.subtitle_parts?.length">
557                        <span class="game-color__subtitle">
558                            <template x-for="(part, pIdx) in boardGame.board.subtitle_parts" :key="pIdx">
559                                <span :class="'subtitle-' + part.source" x-text="part.text"></span>
560                            </template>
561                        </span>
562                    </template>
563                </span>
564            </div>
565
566            
567            <div class="game-color__board">
568                <button
569                    class="game-color__hoist"
570                    type="button"
571                    x-bind:disabled="!boardGame.isAdmin"
572                    :aria-label="boardGame.isAdmin ? ('Move the hoist to the ' + (boardGame.hoistSide === 'right' ? 'left' : 'right')) : null"
573                    @click="boardGame.toggleHoistSide()"
574                ></button>
575                <div class="game-color__stack">
576                    <div
577                        class="game-color-svg"
578                        @click="boardGame.onSvgClick($event)"
579                        x-html="boardGame.board?.image_svg || ''"
580                    ></div>
581
582                    
583                    <div
584                        class="game-color__slots"
585                        :class="boardGame.regionOrder.length > 8 ? 'game-color__slots--dense' : ''"
586                    >
587                        <template x-for="slot in boardGame.regionOrder" :key="slot">
588                            <button
589                                class="game-slot"
590                                :class="[
591                                    boardGame.regionTones[slot] ? 'gc-tone-' + boardGame.regionTones[slot] : '',
592                                    boardGame.selectedRegion === slot ? 'game-slot--selected' : '',
593                                    ['solved', 'revealed'].includes(boardGame.regionStates[slot]) ? 'game-slot--solved' : '',
594                                    boardGame.regionStates[slot] === 'given' ? 'game-slot--given' : '',
595                                    boardGame.slotIsBlocked(slot) ? 'game-slot--blocked' : '',
596                                ]"
597                                :style="boardGame.regionFills[slot] ? 'background-color: ' + boardGame.regionFills[slot] : ''"
598                                :disabled="boardGame.inputLocked || boardGame.regionStates[slot] !== 'active' || boardGame.slotIsBlocked(slot)"
599                                @click="boardGame.selectRegion(slot)"
600                            >
601                                
602                                <span
603                                    x-show="['solved', 'revealed'].includes(boardGame.regionStates[slot])"
604                                    class="game-box__icon"
605                                    :style="{ color: boardGame.tickInk(slot) }"
606                                ><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
607    <path d="m4 12 5 5L20 6"/>
608</svg></span>
609                                
610                                <span
611                                    x-show="boardGame.regionStates[slot] === 'given'"
612                                    class="game-box__icon"
613                                    :style="{ color: boardGame.tickInk(slot) }"
614                                    :title="(boardGame.board?.given?.[slot]?.name || '') + ' — given'"
615                                >&bull;</span>
616                                
617                                <svg class="game-slot__ants" viewBox="0 0 72 48" preserveAspectRatio="none" aria-hidden="true">
618                                    <rect x="1.5" y="1.5" width="69" height="45" rx="4"/>
619                                </svg>
620                            </button>
621                        </template>
622                    </div>
623
624                    <div
625                        class="game-color__swatches"
626                        :class="boardGame.swatches.length > 8 ? 'game-color__swatches--dense' : ''"
627                    >
628                        <template x-for="sw in boardGame.swatches" :key="sw.id">
629                            <button
630                                class="game-swatch"
631                                :class="{
632                                    'game-swatch--selected': boardGame.selectedSwatch === sw.id,
633                                    'game-swatch--used': sw.status === 'used',
634                                    'game-swatch--blocked': sw.status === 'active' && boardGame.swatchIsBlocked(sw.id
634),
635                                }"
636                                
637                                :style="sw.status === 'used'
638                                    ? { backgroundColor: sw.hex, color: boardGame.inkOn(sw.hex) }
639                                    : { backgroundColor: '', color: '' }"
640                                :disabled="boardGame.inputLocked || sw.status !== 'active' || boardGame.swatchIsBlocked(sw.id)"
641                                @click="boardGame.selectSwatch(sw.id)"
642                            >
643                                <span class="game-swatch__chip" :style="{ backgroundColor: sw.hex }"></span>
644                                <span class="game-swatch__label" x-text="sw.name"></span>
645                                <span x-show="sw.status === 'used'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
646    <path d="m4 12 5 5L20 6"/>
647</svg></span>
648                                <span x-show="sw.status === 'active' && boardGame.swatchIsBlocked(sw.id)" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
649    <path d="m6 6 12 12M18 6 6 18"/>
650</svg></span>
651                            </button>
652                        </template>
653                    </div>
654                </div>
655            </div>
656        </div>
657        </template>
658
659        <footer class="game-footer daily-game-footer">
660            <button type="button" class="daily-link" @click="$store.daily.leave()">Menu</button>
661            <span class="daily-game-feedback" aria-live="polite" x-text="$store.daily.feedback || 'Correct +1 · Incorrect −1'"></span>
662            <span class="daily-tries" aria-live="polite"><strong x-text="$store.daily.tries"></strong> <span x-text="$store.daily.tries === 1 ? 'try' : 'tries'"></span></span>
663        </footer>
664
665        <div x-show="$store.daily.error || $store.daily.expired" class="daily-board-notice daily-notice" role="alert">
666            <p x-text="$store.daily.expired ? 'A new daily challenge is ready.' : $store.daily.error"></p>
667            <button class="daily-link" :disabled="$store.daily.busy" @click="$store.daily.pending && !$store.daily.expired ? $store.daily.sendPending() : $store.daily.load()" x-text="$store.daily.expired ? 'Open Today’s Challenge' : 'Try again'"></button>
668        </div>
669        <span x-show="$store.daily.busy" class="sr-only" role="status">Saving your attempt…</span>
670    </div>
671</template>
672
673    
674    <div
675        x-show="$store.game.settingsOpen"
676        x-transition:enter="game-panel-enter"
677        x-transition:enter-start="game-panel-enter-start"
678        x-transition:enter-end="game-panel-enter-end"
679        x-transition:leave="game-panel-leave"
680        x-transition:leave-start="game-panel-leave-start"
681        x-transition:leave-end="game-panel-leave-end"
682        class="game-panel"
683        
684        @keydown.escape.window="$store.game.playerCardOpen || $store.game.closeSettings()"
685    >
686        <div class="game-panel__header">
687            <button @click="$store.game.backToNavigationMenu()" class="game-panel__back" aria-label="Back to menu">
688                <svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor" width="22" height="22"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
689            </button>
690            <h2 x-text="({ highscores: 'Flag Journey Hall of Fame', daily_highscores: 'Daily Challenge Scores', profile: 'Profile', credits: 'Credits' })[$store.game.settingsView]"></h2>
691            <button @click="$store.game.closeSettings()" class="game-panel__close" aria-label="Close">
692                <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
693            </button>
694        </div>
695
696        <div class="game-panel__body">
697            
698            
699            <div class="game-panel__highscores" x-show="$store.game.settingsView === 'daily_highscores'">
700                <div x-show="$store.game.loading" class="game-panel__loading">
701                    <span class="game-spinner"></span>
702                </div>
703                <div class="game-panel__highscores-content" x-show="!$store.game.loading">
704                    <p class="game-profile__footnote">Lifetime points and streaks across every Flagid Daily. Ranked players are signed in only.</p>
705                    <div class="game-tabs">
706    <button class="game-tab" :class="{ 'game-tab--active': $store.game.activeDailyTab === 'all_time' }" @click="$store.game.activeDailyTab = 'all_time'">Players</button>
707    <button class="game-tab" :class="{ 'game-tab--active': $store.game.activeDailyTab === 'stats' }" @click="$store.game.activeDailyTab = 'stats'">Challenges</button>
708</div>
709                    <div x-show="$store.game.activeDailyTab === 'all_time'">
710    <div class="game-highscores__scroll">
711        <table class="game-highscores__table">
712            <colgroup>
713                <col class="game-highscores__col--rank">
714                <col class="game-highscores__col--avatar">
715                <col class="game-highscores__col--name">
716                <col class="game-highscores__col--score">
717                <col class="game-highscores__col--levels">
718                <col class="game-highscores__col--levels">
719            </colgroup>
720            <thead>
721                <tr>
722                    <th>#</th>
723                    <th colspan="2">Name</th>
724                    <th>Points</th>
725                    <th>Streak</th>
726                    <th>Days</th>
727                </tr>
728            </thead>
729            <tbody>
730                <template x-for="(entry, idx) in $store.game.dailyBoardList" :key="entry.id">
731                    <tr :class="{ 'game-highscores__row--mine': entry.is_mine }">
732                        <td class="game-highscores__rank" x-text="idx + 1"></td>
733                        <td class="game-highscores__avatar-cell">
734                            <img x-show="entry.avatar" :src="entry.avatar" class="game-highscores__avatar" referrerpolicy="no-referrer" alt="">
735                            <svg x-show="!entry.avatar" class="game-highscores__avatar game-highscores__avatar--placeholder" viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>
736                            <img x-show="entry.country_flag" :src="entry.country_flag" class="game-flag-badge game-flag-badge--sm" alt="" aria-hidden="true" x-cloak>
737                        </td>
738                        <td class="game-highscores__name" x-text="entry.player_name"></td>
739                        <td class="game-highscores__score" x-text="entry.score"></td>
740                        <td class="game-highscores__levels" x-text="entry.streak"></td>
741                        <td class="game-highscores__levels" x-text="entry.days"></td>
742                    </tr>
743                </template>
744            </tbody>
745        </table>
746    </div>
747    <p x-show="$store.game.dailyBoardList.length === 0" class="game-highscores__empty">No scores yet</p>
748</div>
749
750
751<div x-show="$store.game.activeDailyTab === 'stats'" x-cloak>
752    <div class="game-highscores__scroll">
753        <table class="game-highscores__table">
754            <colgroup>
755                <col class="game-highscores__col--rank">
756                <col class="game-highscores__col--name">
757                <col class="game-highscores__col--levels">
758                <col class="game-highscores__col--levels">
759            </colgroup>
760            <thead>
761                <tr>
762                    <th>#</th>
763                    <th>Date</th>
764                    <th>Played</th>
765                    <th>Done</th>
766                </tr>
767            </thead>
768            <tbody>
769                <template x-for="entry in $store.game.dailyStatsList" :key="entry.id">
770                    <tr>
771                        <td class="game-highscores__rank" x-text="entry.number"></td>
772                        <td class="game-highscores__name" x-text="entry.date"></td>
773                        <td class="game-highscores__levels" x-text="entry.played"></td>
774                        <td class="game-highscores__levels" x-text="entry.completed"></td>
775                    </tr>
776                </template>
777            </tbody>
778        </table>
779    </div>
780    <p x-show="$store.game.dailyStatsList.length === 0" class="game-highscores__empty">No challenges yet</p>
781</div>
782                </div>
783            </div>
784
785            <div class="game-panel__highscores" x-show="$store.game.settingsView === 'highscores'">
786                <div x-show="$store.game.loading" class="game-panel__loading">
787                    <span class="game-spinner"></span>
788                </div>
789                <div class="game-panel__highscores-content" x-show="!$store.game.loading">
790                    <p class="game-profile__footnote">The official ranking of Flagid Game players.</p>
791                    <div class="game-tabs">
792    <button class="game-tab" :class="{ 'game-tab--active': $store.game.activeTab === 'all_time' }" @click="$store.game.activeTab = 'all_time'">Hall of Fame</button>
793    <button class="game-tab" :class="{ 'game-tab--active': $store.game.activeTab === 'today' }" @click="$store.game.activeTab = 'today'">Today</button>
794    <button class="game-tab" :class="{ 'game-tab--active': $store.game.activeTab === 'month' }" @click="$store.game.activeTab = 'month'">October 2026</button>
795</div>
796                    <p
797    class="game-highscores__reset"
798    x-show="$store.game.activeTab === 'today'"
799    x-cloak
800    x-effect="$store.game.activeTab === 'today' ? $store.game.startDailyCountdown() : $store.game.stopDailyCountdown()"
801>Resets in <span x-text="$store.game.dailyResetIn"></span> (00:00 UTC)</p>
802<div class="game-highscores__scroll">
803    <table class="game-highscores__table">
804        
805        <colgroup>
806            <col class="game-highscores__col--rank">
807            <col class="game-highscores__col--avatar">
808            <col class="game-highscores__col--name">
809            <col class="game-highscores__col--score">
810            <col class="game-highscores__col--levels">
811            <col class="game-highscores__col--date">
812        </colgroup>
813        <thead>
814            <tr>
815                <th>#</th>
816                <th colspan="2">Name</th>
817                
818                <th>Best score</th>
819                <th>Levels</th>
820                <th class="game-highscores__th--date">Date</th>
821            </tr>
822        </thead>
823        <tbody>
824            <template x-for="(entry, idx) in $store.game.highscoresList" :key="entry.id">
825                <tr
826                    :class="{
827                        'game-highscores__highlight': entry.id === $store.game.sessionId,
828                        'game-highscores__row--mine': entry.is_mine && entry.id !== $store.game.sessionId,
829                    }"
830                    :title="entry.level_name ? 'Reached: ' + entry.level_name : ''"
831                >
832                    <td class="game-highscores__rank" x-text="idx + 1"></td>
833                    <td class="game-highscores__avatar-cell">
834                        <img x-show="entry.avatar" :src="entry.avatar" class="game-highscores__avatar" referrerpolicy="no-referrer" alt="">
835                        <svg x-show="!entry.avatar" class="game-highscores__avatar game-highscores__avatar--placeholder" viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>
836                        <img x-show="entry.country_flag" :src="entry.country_flag" class="game-flag-badge game-flag-badge--sm" alt="" aria-hidden="true" x-cloak>
837                    </td>
838                    
839                    <td class="game-highscores__name">
840                        <button
841                            x-show="entry.is_player && !$store.game.isGuest"
842                            @click="$store.game.openPlayerCard(entry)"
843                            class="game-highscores__name-btn"
844                            :aria-label="`View ${entry.player_name}'s card`"
845                            x-text="entry.player_name"
846                        ></button>
847                        <span
848                            x-show="!(entry.is_player && !$store.game.isGuest)"
849                            x-text="entry.player_name"
850                        ></span>
851                    </td>
852                    <td class="game-highscores__score" x-text="entry.score"></td>
853                    <td class="game-highscores__levels" x-text="entry.levels"></td>
854                    <td class="game-highscores__date" x-text="entry.date"></td>
855                </tr>
856            </template>
857        </tbody>
858        <tfoot x-show="$store.game.showMyRankRow" x-cloak>
859            <tr
860                class="game-highscores__rank-row"
861                :title="$store.game.myEntry?.level_name ? 'Reached: ' + $store.game.myEntry.level_name : ''"
862            >
863                <td class="game-highscores__rank" x-text="$store.game.myRank"></td>
864                <td class="game-highscores__avatar-cell">
865                    <img x-show="$store.game.myEntry?.avatar" :src="$store.game.myEntry?.avatar" class="game-highscores__avatar" referrerpolicy="no-referrer" alt="">
866                    <svg x-show="!$store.game.myEntry?.avatar" class="game-highscores__avatar game-highscores__avatar--placeholder" viewBox="0 0 24 24" fill="currentColor"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>
867                    <img x-show="$store.game.myEntry?.country_flag" :src="$store.game.myEntry?.country_flag" class="game-flag-badge game-flag-badge--sm" alt="" aria-hidden="true" x-cloak>
868                </td>
869                <td class="game-highscores__name" x-text="$store.game.myEntry?.player_name"></td>
870                <td class="game-highscores__score" x-text="$store.game.myEntry?.score"></td>
871                <td class="game-highscores__levels" x-text="$store.game.myEntry?.levels"></td>
872                <td class="game-highscores__date" x-text="$store.game.myEntry?.date"></td>
873            </tr>
874        </tfoot>
875    </table>
876</div>
877
878<p
879    x-show="$store.game.highscoresList.length === 0"
880    class="game-highscores__empty"
881    x-text="$store.game.activeTab === 'today' ? 'No games played today yet' : 'No scores yet'"
882>No scores yet</p>
883                </div>
884            </div>
885
886            
887            <div x-show="$store.game.settingsView === 'profile'" class="game-profile">
888                <div x-show="$store.game.loading" class="game-panel__loading">
889                    <span class="game-spinner"></span>
890                </div>
891
892                <div x-show="!$store.game.loading">
893                    <div class="game-profile__identity">
894                        <div class="game-profile__avatar-wrap">
895                            <img
896                                x-show="$store.game.avatar"
897                                :src="$store.game.avatar"
898                                class="game-profile__avatar"
899                                referrerpolicy="no-referrer"
900                                alt=""
901                            >
902                            <svg
903                                x-show="!$store.game.avatar"
904                                class="game-profile__avatar game-profile__avatar--placeholder"
905                                viewBox="0 0 24 24"
906                                fill="currentColor"
907                            ><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>
908
909                            
910                            <button
911                                type="button"
912                                class="game-avatar-edit"
913                                :disabled="$store.game.avatarUploading"
914                                @click="$refs.avatarInput.click()"
915                                aria-label="Change profile picture"
916                            >
917                                <span x-show="$store.game.avatarUploading" class="game-spinner game-spinner--xs" x-cloak></span>
918                                <svg x-show="!$store.game.avatarUploading" viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M9 2L7.17 4H4a2 2 0 00-2 2v12a2 2 0 002 2h16a2 2 0 002-2V6a2 2 0 00-2-2h-3.17L15 2H9zm3 15a5 5 0 110-10 5 5 0 010 10zm0-2a3 3 0 100-6 3 3 0 000 6z"/></svg>
919                            </button>
920                            <input
921                                type="file"
922                                x-ref="avatarInput"
923                                class="game-visually-hidden"
924                                accept="image/jpeg,image/png,image/webp,image/gif"
925                                @change="$store.game.uploadAvatar($event)"
926                            >
927
928                            
929                            <button
930                                type="button"
931                                class="game-flag-badge-btn"
932                                @click="$store.game.countryEditing = !$store.game.countryEditing"
933                                :aria-expanded="$store.game.countryEditing"
934                                aria-label="Change your flag"
935                            >
936                                <img
937                                    x-show="$store.game.countryFlag"
938                                    :src="$store.game.countryFlag"
939                                    class="game-flag-badge game-flag-badge--lg"
940                                    alt=""
941                                    x-cloak
942                                >
943                                
944                                <span
945                                    x-show="!$store.game.countryFlag"
946                                    class="game-flag-badge game-flag-badge--lg game-flag-badge--empty"
947                                >+</span>
948                            </button>
949
950                            <button
951                                type="button"
952                                class="game-profile__avatar-remove"
953                                x-show="$store.game.avatar && !$store.game.avatarUploading"
954                                @click="$store.game.removeAvatar()"
955                                aria-label="Remove photo"
956                                x-cloak
957                            >
958                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" width="12" height="12"><path d="M5 5l14 14M19 5L5 19"/></svg>
959                            </button>
960                        </div>
961
962                        <p class="game-profile__error" x-show="$store.game.avatarError" x-text="$store.game.avatarError" x-cloak></p>
963
964                        
965                        <div x-show="!$store.game.nicknameEditing" class="game-profile__name-row">
966                            <span class="game-profile__name" x-text="$store.game.playerName"></span>
967                            <button
968                                @click="$store.game.nicknameEditing = true"
969                                class="game-profile__edit"
970                                aria-label="Change nickname"
971                            >
972                                <svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1.003 1.003 0 000-1.42l-2.34-2.34a1.003 1.003 0 00-1.42 0l-1.83 1.83 3.75 3.75 1.84-1.82z"/></svg>
973                            </button>
974                        </div>
975
976                        
977                        <div x-show="$store.game.nicknameEditing" x-cloak class="game-profile__name-edit">
978                            <input
979                                type="text"
980                                x-model="$store.game.nickname"
981                                maxlength="20"
982                                class="game-input"
983                                aria-label="Game nickname"
984                                @keydown.enter="$store.game.saveNickname()"
985                                @keydown.escape.stop="$store.game.nicknameEditing = false"
986                            >
987                            <button @click="$store.game.saveNickname()" class="game-btn game-btn--primary" :disabled="$store.game.nicknameSaving">
988                                <span x-show="!$store.game.nicknameSaving">Save</span>
989                                <span x-show="$store.game.nicknameSaving" x-cloak class="game-spinner"></span>
990                            </button>
991                        </div>
992
993                        
994                        <div class="game-profile__country" x-show="$store.game.countryEditing" x-cloak>
995                            <label class="game-profile__country-label" for="game-country">Your flag</label>
996                            <select
997                                id="game-country"
998                                class="game-input game-profile__country-select"
999                                x-model="$store.game.countryCode"
1000                                :disabled="$store.game.countrySaving"
1001                                @change="$store.game.saveCountry()"
1002                            >
1003                                <option value="">No flag</option>
1004                                <template x-for="opt in ($store.game.profile?.country_options || [])" :key="opt.code">
1005                                    <option :value="opt.code" x-text="opt.name"></option>
1006                                </template>
1007                            </select>
1008                        </div>
1009                    </div>
1010
1011                    <section class="game-profile__mode" data-game-theme="journey">
1012                        <h3 class="game-profile__mode-title">
1013                            <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="18" height="18"><circle cx="12" cy="12" r="9"/><path d="m16 8-2.5 5.5L8 16l2.5-5.5Z"/></svg>
1014                            <span>Flag Journey</span>
1015                        </h3>
1016                        <div class="game-profile__stats">
1017                            <div class="game-profile__stat">
1018                                <span class="game-profile__stat-value" x-text="$store.game.profile?.games_played ?? 0"></span>
1019                                <span class="game-profile__stat-label">Games</span>
1020                            </div>
1021                            <div class="game-profile__stat">
1022                                <span class="game-profile__stat-value" x-text="$store.game.profile?.best_score ?? '—'"></span>
1023                                <span class="game-profile__stat-label">Best score</span>
1024                            </div>
1025                            <div class="game-profile__stat">
1026                                <span class="game-profile__stat-value" x-text="$store.game.profile?.best_rank ? '#' + $store.game.profile.best_rank : '—'"></span>
1027                                <span class="game-profile__stat-label">Best rank</span>
1028                            </div>
1029                        </div>
1030
1031                        
1032                        <section class="game-profile__section">
1033                            <h3 class="game-profile__heading">Best scores</h3>
1034                            <p
1035                                x-show="!$store.game.profile?.best?.length"
1036                                class="game-highscores__empty"
1037                            >No games played yet</p>
1038                            <table x-show="$store.game.profile?.best?.length" class="game-highscores__table">
1039                                <thead>
1040                                    <tr><th>Last level</th><th>Score</th><th>Level</th><th class="game-highscores__th--date">Date</th></tr>
1041                                </thead>
1042                                <tbody>
1043                                    <template x-for="run in ($store.game.profile?.best || [])" :key="run.id">
1044                                        <tr>
1045                                            <td class="game-highscores__name game-highscores__level-name" :title="run.level_name || ''" x-text="run.level_name || '—'"></td>
1046                                            <td>
1047                                                <span x-text="run.score"></span><span x-show="!run.is_ranked" class="game-run-unranked" title="Played signed out — not in the Flag Journey Hall of Fame">*</span>
1048                                            </td>
1049                                            <td x-text="run.levels"></td>
1050                                            <td class="game-highscores__date" x-text="run.date"></td>
1051                                        </tr>
1052                                    </template>
1053                                </tbody>
1054                            </table>
1055                            <p class="game-profile__footnote" x-show="($store.game.profile?.best || []).some(r => !r.is_ranked)">* Played signed out — not in the Flag Journey Hall of Fame.</p>
1056                        </section>
1057
1058                        <section class="game-profile__section">
1059                            <h3 class="game-profile__heading">Recent games</h3>
1060                            <p
1061                                x-show="!$store.game.profile?.recent?.length"
1062                                class="game-highscores__empty"
1063                            >No games played yet</p>
1064                            <table x-show="$store.game.profile?.recent?.length" class="game-highscores__table">
1065                                <thead>
1066                                    <tr><th>Last level</th><th>Score</th><th>Level</th><th class="game-highscores__th--date">Date</th></tr>
1067                                </thead>
1068                                <tbody>
1069                                    <template x-for="run in ($store.game.profile?.recent || [])" :key="run.id">
1070                                        <tr>
1071                                            <td class="game-highscores__name game-highscores__level-name" :title="run.level_name || ''" x-text="run.level_name || '—'"></td>
1072                                            <td>
1073                                                <span x-text="run.score"></span><span x-show="!run.is_ranked" class="game-run-unranked" title="Played signed out — not in the Flag Journey Hall of Fame">*</span>
1074                                            </td>
1075                                            <td x-text="run.levels"></td>
1076                                            <td class="game-highscores__date" x-text="run.date"></td>
1077                                        </tr>
1078                                    </template>
1079                                </tbody>
1080                            </table>
1081                            <p class="game-profile__footnote" x-show="($store.game.profile?.recent || []).some(r => !r.is_ranked)">* Played signed out — not in the Flag Journey Hall of Fame.</p>
1082                        </section>
1083                    </section>
1084
1085                    <section class="game-profile__mode" data-game-theme="daily">
1086    <h3 class="game-profile__mode-title">
1087        <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="18" height="18"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M7 2v6m10-6v6M3 11h18m-13 5 3 3 5-5"/></svg>
1088        <span>Daily Challenge</span>
1089    </h3>
1090    <div class="game-profile__stats game-profile__stats--daily">
1091        <div class="game-profile__stat">
1092            <span class="game-profile__stat-value" x-text="$store.game.profile?.daily?.completed ?? 0"></span>
1093            <span class="game-profile__stat-label">Completed</span>
1094        </div>
1095        <div class="game-profile__stat">
1096            <span class="game-profile__stat-value" x-text="$store.game.profile?.daily?.streak ?? 0"></span>
1097            <span class="game-profile__stat-label">Current streak</span>
1098        </div>
1099        <div class="game-profile__stat">
1100            <span class="game-profile__stat-value" x-text="$store.game.profile?.daily?.best_streak ?? 0"></span>
1101            <span class="game-profile__stat-label">Best streak</span>
1102        </div>
1103        <div class="game-profile__stat">
1104            <span class="game-profile__stat-value" x-text="$store.game.profile?.daily?.perfect_days ?? 0"></span>
1105            <span class="game-profile__stat-label">Perfect days</span>
1106        </div>
1107        <div class="game-profile__stat">
1108            <span class="game-profile__stat-value" x-text="$store.game.profile?.daily?.average_mistakes ?? 0"></span>
1109            <span class="game-profile__stat-label">Avg. mistakes</span>
1110        </div>
1111    </div>
1112</section>
1113                </div>
1114            </div>
1115
1116            
1117            <div x-show="$store.game.settingsView === 'credits'" class="game-credits">
1118                <template x-for="group in $store.game.credits" :key="group.category">
1119                    <section class="game-credits__group">
1120                        <h3 class="game-credits__heading" x-text="group.category"></h3>
1121                        <template x-for="(entry, i) in group.entries" :key="group.category + i">
1122                            <div class="game-credits__entry">
1123                                <p class="game-credits__title">
1124                                    <template x-if="entry.url">
1125                                        <a :href="entry.url" target="_blank" rel="noopener" x-text="entry.title"></a>
1126                                    </template>
1127                                    <template x-if="!entry.url">
1128                                        <span x-text="entry.title"></span>
1129                                    </template>
1130                                </p>
1131                                <p x-show="entry.license_text" class="game-credits__license" x-text="entry.license_text"></p>
1132                                <a
1133                                    x-show="entry.license_url"
1134                                    :href="entry.license_url"
1135                                    target="_blank"
1136                                    rel="noopener"
1137                                    class="game-credits__license-link"
1138                                >Full licence</a>
1139                            </div>
1140                        </template>
1141                    </section>
1142                </template>
1143            </div>
1144        </div>
1145    </div>
1146
1147    
1148    
1149    <div
1150        x-show="$store.game.playerCardOpen"
1151        x-transition:enter="game-panel-enter"
1152        x-transition:enter-start="game-panel-enter-start"
1153        x-transition:enter-end="game-panel-enter-end"
1154        x-transition:leave="game-panel-leave"
1155        x-transition:leave-start="game-panel-leave-start"
1156        x-transition:leave-end="game-panel-leave-end"
1157        class="game-panel game-panel--stacked"
1158        @keydown.escape.window="$store.game.closePlayerCard()"
1159        x-cloak
1160    >
1161        <div class="game-panel__header">
1162            
1163            <button
1164                @click="$store.game.closePlayerCard()"
1165                class="game-panel__back"
1166                aria-label="Back"
1167            >
1168                <svg viewBox="0 0 24 24" fill="currentColor" width="22" height="22"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
1169            </button>
1170            <h2 x-text="$store.game.playerCard?.name || 'Player'"></h2>
1171            <button @click="$store.game.closeSettings()" class="game-panel__close" aria-label="Close">
1172                <svg viewBox="0 0 24 24" fill="currentColor" width="24" height="24">
1172<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
1173            </button>
1174        </div>
1175
1176        <div class="game-panel__body">
1177            <div class="game-profile game-profile--readonly">
1178                <div x-show="$store.game.playerCardLoading" class="game-panel__loading">
1179                    <span class="game-spinner"></span>
1180                </div>
1181
1182                
1183                <p
1184                    x-show="$store.game.playerCardError"
1185                    class="game-highscores__empty"
1186                    x-text="$store.game.playerCardError"
1187                    x-cloak
1188                ></p>
1189
1190                <div x-show="!$store.game.playerCardLoading && $store.game.playerCard" x-cloak>
1191                    <div class="game-profile__identity">
1192                        <div class="game-profile__avatar-wrap">
1193                            <img
1194                                x-show="$store.game.playerCard?.avatar"
1195                                :src="$store.game.playerCard?.avatar"
1196                                class="game-profile__avatar"
1197                                referrerpolicy="no-referrer"
1198                                alt=""
1199                            >
1200                            <svg
1201                                x-show="!$store.game.playerCard?.avatar"
1202                                class="game-profile__avatar game-profile__avatar--placeholder"
1203                                viewBox="0 0 24 24"
1204                                fill="currentColor"
1205                            ><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>
1206
1207                            
1208                            <img
1209                                x-show="$store.game.playerCard?.country_flag"
1210                                :src="$store.game.playerCard?.country_flag"
1211                                class="game-flag-badge game-flag-badge--lg"
1212                                alt=""
1213                                aria-hidden="true"
1214                                x-cloak
1215                            >
1216                        </div>
1217
1218                        <div class="game-profile__name-row">
1219                            <span class="game-profile__name" x-text="$store.game.playerCard?.name"></span>
1220                        </div>
1221                    </div>
1222
1223                    <section class="game-profile__mode" data-game-theme="journey">
1224                        <h3 class="game-profile__mode-title">
1225                            <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="18" height="18"><circle cx="12" cy="12" r="9"/><path d="m16 8-2.5 5.5L8 16l2.5-5.5Z"/></svg>
1226                            <span>Flag Journey</span>
1227                        </h3>
1228                        <div class="game-profile__stats">
1229                            <div class="game-profile__stat">
1230                                <span class="game-profile__stat-value" x-text="$store.game.playerCard?.games_played ?? 0"></span>
1231                                <span class="game-profile__stat-label">Games</span>
1232                            </div>
1233                            <div class="game-profile__stat">
1234                                <span class="game-profile__stat-value" x-text="$store.game.playerCard?.best_score ?? '—'"></span>
1235                                <span class="game-profile__stat-label">Best score</span>
1236                            </div>
1237                            <div class="game-profile__stat">
1238                                <span class="game-profile__stat-value" x-text="$store.game.playerCard?.best_rank ? '#' + $store.game.playerCard.best_rank : '—'"></span>
1239                                <span class="game-profile__stat-label">Best rank</span>
1240                            </div>
1241                        </div>
1242
1243                        <section class="game-profile__section">
1244                            <h3 class="game-profile__heading">Best scores</h3>
1245                            <p
1246                                x-show="!$store.game.playerCard?.best?.length"
1247                                class="game-highscores__empty"
1248                            >No games played yet</p>
1249                            <table x-show="$store.game.playerCard?.best?.length" class="game-highscores__table">
1250                                <thead>
1251                                    <tr><th>Last level</th><th>Score</th><th>Level</th><th class="game-highscores__th--date">Date</th></tr>
1252                                </thead>
1253                                <tbody>
1254                                    <template x-for="run in ($store.game.playerCard?.best || [])" :key="run.id">
1255                                        <tr>
1256                                            <td class="game-highscores__name game-highscores__level-name" :title="run.level_name || ''" x-text="run.level_name || '—'"></td>
1257                                            <td>
1258                                                <span x-text="run.score"></span><span x-show="!run.is_ranked" class="game-run-unranked" title="Played signed out — not in the Flag Journey Hall of Fame">*</span>
1259                                            </td>
1260                                            <td x-text="run.levels"></td>
1261                                            <td class="game-highscores__date" x-text="run.date"></td>
1262                                        </tr>
1263                                    </template>
1264                                </tbody>
1265                            </table>
1266                            <p class="game-profile__footnote" x-show="($store.game.playerCard?.best || []).some(r => !r.is_ranked)">* Played signed out — not in the Flag Journey Hall of Fame.</p>
1267                        </section>
1268
1269                        <section class="game-profile__section">
1270                            <h3 class="game-profile__heading">Recent games</h3>
1271                            <p
1272                                x-show="!$store.game.playerCard?.recent?.length"
1273                                class="game-highscores__empty"
1274                            >No games played yet</p>
1275                            <table x-show="$store.game.playerCard?.recent?.length" class="game-highscores__table">
1276                                <thead>
1277                                    <tr><th>Last level</th><th>Score</th><th>Level</th><th class="game-highscores__th--date">Date</th></tr>
1278                                </thead>
1279                                <tbody>
1280                                    <template x-for="run in ($store.game.playerCard?.recent || [])" :key="run.id">
1281                                        <tr>
1282                                            <td class="game-highscores__name game-highscores__level-name" :title="run.level_name || ''" x-text="run.level_name || '—'"></td>
1283                                            <td>
1284                                                <span x-text="run.score"></span><span x-show="!run.is_ranked" class="game-run-unranked" title="Played signed out — not in the Flag Journey Hall of Fame">*</span>
1285                                            </td>
1286                                            <td x-text="run.levels"></td>
1287                                            <td class="game-highscores__date" x-text="run.date"></td>
1288                                        </tr>
1289                                    </template>
1290                                </tbody>
1291                            </table>
1292                            <p class="game-profile__footnote" x-show="($store.game.playerCard?.recent || []).some(r => !r.is_ranked)">* Played signed out — not in the Flag Journey Hall of Fame.</p>
1293                        </section>
1294                    </section>
1295
1296                    <section class="game-profile__mode" data-game-theme="daily">
1297    <h3 class="game-profile__mode-title">
1298        <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="18" height="18"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M7 2v6m10-6v6M3 11h18m-13 5 3 3 5-5"/></svg>
1299        <span>Daily Challenge</span>
1300    </h3>
1301    <div class="game-profile__stats game-profile__stats--daily">
1302        <div class="game-profile__stat">
1303            <span class="game-profile__stat-value" x-text="$store.game.playerCard?.daily?.completed ?? 0"></span>
1304            <span class="game-profile__stat-label">Completed</span>
1305        </div>
1306        <div class="game-profile__stat">
1307            <span class="game-profile__stat-value" x-text="$store.game.playerCard?.daily?.streak ?? 0"></span>
1308            <span class="game-profile__stat-label">Current streak</span>
1309        </div>
1310        <div class="game-profile__stat">
1311            <span class="game-profile__stat-value" x-text="$store.game.playerCard?.daily?.best_streak ?? 0"></span>
1312            <span class="game-profile__stat-label">Best streak</span>
1313        </div>
1314        <div class="game-profile__stat">
1315            <span class="game-profile__stat-value" x-text="$store.game.playerCard?.daily?.perfect_days ?? 0"></span>
1316            <span class="game-profile__stat-label">Perfect days</span>
1317        </div>
1318        <div class="game-profile__stat">
1319            <span class="game-profile__stat-value" x-text="$store.game.playerCard?.daily?.average_mistakes ?? 0"></span>
1320            <span class="game-profile__stat-label">Avg. mistakes</span>
1321        </div>
1322    </div>
1323</section>
1324                </div>
1325            </div>
1326        </div>
1327    </div>
1328
1329    
1330    
1331    <div x-show="$store.game.state === 'level-intro'" class="game-screen game-intro">
1332        <div class="game-intro__inner">
1333            
1334            <div class="game-intro__badge">
1335                <span x-text="'Level ' + $store.game.levelDisplayNumber"></span>
1336            </div>
1337            <template x-if="$store.game.levelMeta.is_new_level !== false">
1338                <div>
1339                    <div class="game-intro__image" x-show="$store.game.levelMeta.image_url" x-cloak>
1340                        <img :src="$store.game.levelMeta.image_url" :alt="$store.game.levelMeta.name">
1341                    </div>
1342                    <p class="game-intro__category"
1343                       x-show="$store.game.levelMeta.category_name"
1344                       :style="{ backgroundColor: $store.game.levelMeta.category_color, color: $store.game.levelMeta.category_text_color }"
1345                       x-text="$store.game.levelMeta.category_name"
1346                       x-cloak></p>
1347                    <h2 class="game-intro__region" x-text="$store.game.levelMeta.name"></h2>
1348                    <p class="game-intro__type" x-text="$store.game.levelMeta.mode_label"></p>
1349                </div>
1350            </template>
1351            <template x-if="$store.game.levelMeta.is_new_level === false">
1352                <h2 class="game-intro__mode-announce" x-text="$store.game.levelMeta.mode_label"></h2>
1353            </template>
1354            <div class="game-intro__progress-bar">
1355                <div class="game-intro__progress-fill" :style="{ animationDuration: $store.game.introDuration + 'ms' }"></div>
1356            </div>
1357        </div>
1358    </div>
1359
1360    
1361    
1362    <div x-show="$store.game.state === 'level-choice'" class="game-screen game-level-choice" x-cloak>
1363        <div class="game-level-choice__inner">
1364            <h2 class="game-level-choice__title">Level complete</h2>
1365            <p class="game-level-choice__hint">Pick where to go next</p>
1366            <div class="game-level-choice__options">
1367                <template x-for="option in $store.game.choiceOptions" :key="option.id">
1368                    <button type="button"
1369                            class="game-level-choice__card"
1370                            :class="{ 'is-auto-picked': $store.game.choiceAutoPickId === option.id }"
1371                            :disabled="$store.game.loading"
1372                            @click="$store.game.chooseLevel(option.id)">
1373                        <div class="game-level-choice__card-image">
1374                            <img x-show="option.image_url" :src="option.image_url" :alt="option.name">
1375                            <div class="game-level-choice__card-placeholder" x-show="!option.image_url"></div>
1376                        </div>
1377                        <div class="game-level-choice__card-body">
1378                            <p class="game-level-choice__card-desc"
1379                               x-show="option.category_name"
1380                               :style="{ backgroundColor: option.category_color, color: option.category_text_color }"
1381                               x-text="option.category_name"></p>
1382                            <h3 class="game-level-choice__card-name" x-text="option.name"></h3>
1383                        </div>
1384                    </button>
1385                </template>
1386            </div>
1387            
1388            <template x-if="$store.game.state === 'level-choice' && $store.game.choiceTimeout > 0">
1389                <div class="game-level-choice__timer" aria-hidden="true">
1390                    <div class="game-level-choice__timer-fill"
1391                         :class="{ 'is-paused': $store.game.choicePaused }"
1392                         :style="{ animationDuration: $store.game.choiceTimeout + 'ms' }"></div>
1393                </div>
1394            </template>
1395        </div>
1396    </div>
1397
1398    
1399    <div x-show="$store.game.state === 'level-complete'" class="game-screen game-bonus">
1400        <div class="game-bonus__inner">
1401            <p class="game-bonus__label">Time Bonus</p>
1402            <div class="game-bonus__points" x-text="'+' + $store.game.timeBonus"></div>
1403        </div>
1404    </div>
1405
1406    
1407    <div x-show="$store.game.state === 'playing'" class="game-screen game-board" data-classic-board>
1408
1409        
1410        <header class="game-header">
1411            <div class="game-header__level">
1412                
1413                <div class="game-header__level-num" x-text="$store.game.levelDisplayNumber"></div>
1414                <div class="game-header__level-text">
1415                    
1416                    <div class="game-header__level-category"
1417                         x-show="$store.game.levelMeta.category_name"
1418                         :style="{ backgroundColor: $store.game.levelMeta.category_color, color: $store.game.levelMeta.category_text_color }"
1419                         x-text="$store.game.levelMeta.category_name"
1420                         x-cloak></div>
1421                    <div class="game-header__level-name">
1422                        
1423                        <span x-text="$store.game.levelMeta.name" x-effect="$store.game.fitLevelName($el)"></span>
1424                    </div>
1425                </div>
1426            </div>
1427
1428            
1429            <template x-if="$store.game.isFlagTest">
1430                <button
1431                    class="game-header__skip"
1432                    :disabled="$store.game.skippingTestFlag"
1433                    @click="$store.game.skipTestFlag()"
1434                    title="Next flag"
1435                >Skip &rsaquo;&rsaquo;</button>
1436            </template>
1437
1438            
1439            <div
1440                class="game-header__score"
1441                :class="{ 'game-header__score--pulse': $store.game.scorePulsing }"
1442                aria-live="polite"
1443            >
1444                <span x-text="$store.game.score"></span>
1445            </div>
1446        </header>
1447
1448        <div class="game-grid" x-data="{ get boardGame() { return $store.game; } }" x-show="boardGame.mode === 'name'">
1449            
1450            <div class="game-col game-col--flags">
1451                <template x-for="(pair, idx) in boardGame.flagOrder" :key="'f'+pair.id">
1452                    <button
1453                        class="game-box game-box--flag"
1454                        :class="{
1455                            'game-box--selected': boardGame.selectedFlag === idx,
1456                            'game-box--correct': pair.flagStatus === 'correct',
1457                            'game-box--wrong': pair.flash === 'wrong',
1458                            'game-box--blocked': boardGame.flagIsBlocked(pair.id),
1459                            'game-box--faded': pair.faded,
1460                        }"
1461                        :disabled="boardGame.inputLocked || pair.flagStatus !== 'active' || boardGame.flagIsBlocked(pair.id)"
1462                        @click="boardGame.selectBox('flag', idx)"
1463                    >
1464                        <template x-if="pair.image_url">
1465                            <img :src="pair.image_url" alt="Flag" class="game-flag-img" loading="eager">
1466                        </template>
1467                        <template x-if="pair.image_svg">
1468                            <div class="game-flag-svg" x-html="pair.image_svg"></div>
1469                        </template>
1470                        <span x-show="pair.flagStatus === 'correct'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1471    <path d="m4 12 5 5L20 6"/>
1472</svg></span>
1473                        <span x-show="pair.flash === 'wrong'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
1474    <path d="m6 6 12 12M18 6 6 18"/>
1475</svg></span>
1476                    </button>
1477                </template>
1478            </div>
1479
1480            
1481            <div class="game-col game-col--names">
1482                <template x-for="(pair, idx) in boardGame.nameOrder" :key="'n'+pair.id">
1483                    <button
1484                        class="game-box game-box--name"
1485                        :class="{
1486                            'game-box--selected': boardGame.selectedName === idx,
1487                            'game-box--correct': pair.nameStatus === 'correct',
1488                            'game-box--wrong': pair.flash === 'wrong',
1489                            'game-box--blocked': boardGame.nameIsBlocked(pair.id),
1490                            'game-box--faded': pair.faded,
1491                        }"
1492                        :disabled="boardGame.inputLocked || pair.nameStatus !== 'active' || boardGame.nameIsBlocked(pair.id)"
1493                        @click="boardGame.selectBox('name', idx)"
1494                    >
1495                        <span class="game-box__name" x-text="pair.name"></span>
1496                        <template x-if="pair.subtitle_parts && pair.subtitle_parts.length">
1497                            <span class="game-box__subtitle">
1498                                <template x-for="(part, pIdx) in pair.subtitle_parts" :key="pIdx">
1499                                    <span :class="'subtitle-' + part.source" x-text="part.text"></span>
1500                                </template>
1501                            </span>
1502                        </template>
1503                        <span x-show="pair.nameStatus === 'correct'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1504    <path d="m4 12 5 5L20 6"/>
1505</svg></span>
1506                        <span x-show="pair.flash === 'wrong'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
1507    <path d="m6 6 12 12M18 6 6 18"/>
1508</svg></span>
1509                    </button>
1510                </template>
1511            </div>
1512        </div>
1513
1514
1515        <template x-if="$store.game.state === 'playing' && $store.game.mode === 'colour'">
1516            <div
1517            class="game-color" x-data="{ get boardGame() { return $store.game; } }" x-init="boardGame.paintRegions()"
1518            :class="boardGame.hoistSide === 'right' ? 'game-color--hoist-right' : ''"
1519            x-show="boardGame.mode === 'colour'"
1520            x-cloak
1521        >
1522            <div class="game-color__meta">
1523                <span
1524                    class="game-color__progress"
1525                    x-show="boardGame.flagCount > 1"
1526                    x-text="'Flag ' + boardGame.boardIndex + '/' + boardGame.flagCount"
1527                ></span>
1528                <span class="game-color__title">
1529                    <span class="game-color__name" x-text="boardGame.board?.name"></span>
1530                    <template x-if="boardGame.board?.subtitle_parts?.length">
1531                        <span class="game-color__subtitle">
1532                            <template x-for="(part, pIdx) in boardGame.board.subtitle_parts" :key="pIdx">
1533                                <span :class="'subtitle-' + part.source" x-text="part.text"></span>
1534                            </template>
1535                        </span>
1536                    </template>
1537                </span>
1538            </div>
1539
1540            
1541            <div class="game-color__board">
1542                <button
1543                    class="game-color__hoist"
1544                    type="button"
1545                    x-bind:disabled="!boardGame.isAdmin"
1546                    :aria-label="boardGame.isAdmin ? ('Move the hoist to the ' + (boardGame.hoistSide === 'right' ? 'left' : 'right')) : null"
1547                    @click="boardGame.toggleHoistSide()"
1548                ></button>
1549                <div class="game-color__stack">
1550                    <div
1551                        class="game-color-svg"
1552                        @click="boardGame.onSvgClick($event)"
1553                        x-html="boardGame.board?.image_svg || ''"
1554                    ></div>
1555
1556                    
1557                    <div
1558                        class="game-color__slots"
1559                        :class="boardGame.regionOrder.length > 8 ? 'game-color__slots--dense' : ''"
1560                    >
1561                        <template x-for="slot in boardGame.regionOrder" :key="slot">
1562                            <button
1563                                class="game-slot"
1564                                :class="[
1565                                    boardGame.regionTones[slot] ? 'gc-tone-' + boardGame.regionTones[slot] : '',
1566                                    boardGame.selectedRegion === slot ? 'game-slot--selected' : '',
1567                                    ['solved', 'revealed'].includes(boardGame.regionStates[slot]) ? 'game-slot--solved' : '',
1568                                    boardGame.regionStates[slot] === 'given' ? 'game-slot--given' : '',
1569                                    boardGame.slotIsBlocked(slot) ? 'game-slot--blocked' : '',
1570                                ]"
1571                                :style="boardGame.regionFills[slot] ? 'background-color: ' + boardGame.regionFills[slot] : ''"
1572                                :disabled="boardGame.inputLocked || boardGame.regionStates[slot] !== 'active' || boardGame.slotIsBlocked(slot)"
1573                                @click="boardGame.selectRegion(slot)"
1574                            >
1575                                
1576                                <span
1577                                    x-show="['solved', 'revealed'].includes(boardGame.regionStates[slot])"
1578                                    class="game-box__icon"
1579                                    :style="{ color: boardGame.tickInk(slot) }"
1580                                ><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1581    <path d="m4 12 5 5L20 6"/>
1582</svg></span>
1583                                
1584                                <span
1585                                    x-show="boardGame.regionStates[slot] === 'given'"
1586                                    class="game-box__icon"
1587                                    :style="{ color: boardGame.tickInk(slot) }"
1588                                    :title="(boardGame.board?.given?.[slot]?.name || '') + ' — given'"
1589                                >&bull;</span>
1590                                
1591                                <svg class="game-slot__ants" viewBox="0 0 72 48" preserveAspectRatio="none" aria-hidden="true">
1592                                    <rect x="1.5" y="1.5" width="69" height="45" rx="4"/>
1593                                </svg>
1594                            </button>
1595                        </template>
1596                    </div>
1597
1598                    <div
1599                        class="game-color__swatches"
1600                        :class="boardGame.swatches.length > 8 ? 'game-color__swatches--dense' : ''"
1601                    >
1602                        <template x-for="sw in boardGame.swatches" :key="sw.id">
1603                            <button
1604                                class="game-swatch"
1605                                :class="{
1606                                    'game-swatch--selected': boardGame.selectedSwatch === sw.id,
1607                                    'game-swatch--used': sw.status === 'used',
1608                                    'game-swatch--blocked': sw.status === 'active' && boardGame.swatchIsBlocked(sw.id
1608),
1609                                }"
1610                                
1611                                :style="sw.status === 'used'
1612                                    ? { backgroundColor: sw.hex, color: boardGame.inkOn(sw.hex) }
1613                                    : { backgroundColor: '', color: '' }"
1614                                :disabled="boardGame.inputLocked || sw.status !== 'active' || boardGame.swatchIsBlocked(sw.id)"
1615                                @click="boardGame.selectSwatch(sw.id)"
1616                            >
1617                                <span class="game-swatch__chip" :style="{ backgroundColor: sw.hex }"></span>
1618                                <span class="game-swatch__label" x-text="sw.name"></span>
1619                                <span x-show="sw.status === 'used'" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
1620    <path d="m4 12 5 5L20 6"/>
1621</svg></span>
1622                                <span x-show="sw.status === 'active' && boardGame.swatchIsBlocked(sw.id)" class="game-box__icon"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round">
1623    <path d="m6 6 12 12M18 6 6 18"/>
1624</svg></span>
1625                            </button>
1626                        </template>
1627                    </div>
1628                </div>
1629            </div>
1630        </div>
1631        </template>
1632
1633        
1634        <footer class="game-footer">
1635            <div class="game-footer__lives">
1636                
1637                <template x-for="i in $store.game.lifeSlots" :key="i">
1638                    <span
1639                        class="game-life"
1640                        :style="{ '--life-flag-phase': (-((i - 1) % 8) * 100) + 'ms' }"
1641                        :class="{
1642                            'game-life--lost': i > $store.game.lives,
1643                            'game-life--extra': i > $store.game.startingLives,
1644                        }"
1645                    ><!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
1646<svg aria-hidden="true" class="game-event-icon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
1647	 viewBox="0 0 24 24" fill="currentColor" style="enable-background:new 0 0 24 24;" xml:space="preserve">
1648<style>
1649    .life-flag-frame {
1650        opacity: 0;
1651        animation: life-flag-wave 800ms steps(1, end) infinite;
1652        animation-delay: calc(var(--life-flag-frame-offset, 0ms) + var(--life-flag-phase, 0ms));
1653    }
1654    .game-life--lost .life-flag-frame { animation-play-state: paused; }
1655    @keyframes life-flag-wave {
1656        0% { opacity: 1; }
1657        12.5%, 100% { opacity: 0; }
1658    }
1659    @media (prefers-reduced-motion: reduce) {
1660        .life-flag-frame { animation: none; opacity: 0; }
1661        .life-flag-frame--first { opacity: 1; }
1662    }
1663</style>
1664<g id="hoist">
1665	<rect x="4.5" y="2.5" width="1" height="21.5"/>
1666	<circle cx="5" cy="1.5" r="0.8"/>
1667</g>
1668<g id="f2" class="life-flag-frame" style="--life-flag-frame-offset: -700ms">
1669	<path d="M5.1,3.8c5-4,10.3,0.6,15-1v10c-5.2,6.7-10-4-15,0V3.8z"/>
1670</g>
1671<g id="f4" class="life-flag-frame" style="--life-flag-frame-offset: -500ms">
1672	<path d="M5.1,3.3c6.9-3.7,5.6,5.1,14.1,0.8l0.2,9.4c-4.7,2.2-9.2-2.6-14.4-0.6V3.3z"/>
1673</g>
1674<g id="f1" class="life-flag-frame life-flag-frame--first">
1675	<path d="M5,4c5-4,9,4,15,0v9c-6,4-10-4-15,0V4z"/>
1676</g>
1677<g id="f5" class="life-flag-frame" style="--life-flag-frame-offset: -400ms">
1678	<path d="M5.1,3.3C18.5,3.2,15.9,8,19.3,4.1l-0.4,9.2c-2.5,3.2-3.1-1.2-13.8-0.4V3.3z"/>
1679</g>
1680<g id="f3" class="life-flag-frame" style="--life-flag-frame-offset: -600ms">
1681	<path d="M5.1,3.3C13.3,0,16.5,9.7,20.4,4.1l-0.3,8.3c-3.5,4.8-9.8-1.5-15,0.5V3.3z"/>
1682</g>
1683<g id="f6" class="life-flag-frame" style="--life-flag-frame-offset: -300ms">
1684	<path d="M5.1,3.3C7.4,4.8,12.8,2,18.5,2.6c0.5,0,1.2,0.8,1.2,1.3l-0.8,9.6c-0.4-2.7-11.7-1.6-13.8-0.6V3.3z"/>
1685</g>
1686<g id="f7" class="life-flag-frame" style="--life-flag-frame-offset: -200ms">
1687	<path d="M5.1,3.3c13.4-0.1,3.8,3.5,14.1,0.8l0.2,8.8C5.8,15.7,15.8,12,5.1,12.8V3.3z"/>
1688</g>
1689<g id="f8" class="life-flag-frame" style="--life-flag-frame-offset: -100ms">
1690	<path d="M5.1,3.3c6.5-3.9,10.8,3.6,15,1.3l-0.7,8.7c-9.7,1.2-6.7-4.5-14.2-0.4V3.3z"/>
1691</g>
1692</svg></span>
1693                </template>
1694            </div>
1695
1696            <div
1697                class="game-timer"
1698                :class="{
1699                    'game-timer--warning': $store.game.timerPercent < 50 && $store.game.timerPercent >= 25,
1700                    'game-timer--danger': $store.game.timerPercent < 25,
1701                }"
1702            >
1703                <svg class="game-timer__svg" viewBox="0 0 36 36" aria-hidden="true">
1704                    <circle class="game-timer__track" cx="18" cy="18" r="15.915"></circle>
1705                    <circle
1706                        class="game-timer__progress"
1707                        cx="18"
1708                        cy="18"
1709                        r="15.915"
1710                        :style="{ strokeDashoffset: 100 - $store.game.timerPercent }"
1711                    ></circle>
1712                </svg>
1713                
1714                <div class="game-timer__bonus" x-text="'+' + $store.game.potentialBonus"></div>
1715            </div>
1716        </footer>
1717    </div>
1718
1719    
1720    <div x-show="$store.game.state === 'game-over'" class="game-screen game-over">
1721        <div class="game-over__inner" :class="{ 'game-over__inner--visible': $store.game.gameOverVisible }">
1722            
1723            <div class="game-menu__identity game-over__identity">
1724                <div class="game-over__label"><svg aria-hidden="true" class="game-event-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1725    <path d="M5 22V3M5 4h15v11H5"/>
1726    <path d="M5 4h5v5H5zm10 0h5v5h-5zm-5 5h5v6h-5z" fill="currentColor" stroke="none"/>
1727</svg> Game Over</div>
1728                <div
1729                    class="game-over__score"
1730                    :class="{
1731                        'game-over__score--visible': $store.game.scoreVisible,
1732                        'game-over__score--glow-gold': $store.game.newHighscores.all_time,
1733                        'game-over__score--glow-silver': !$store.game.newHighscores.all_time && $store.game.newHighscores.month,
1734                        'game-over__score--glow-bronze': !$store.game.newHighscores.all_time && !$store.game.newHighscores.month && $store.game.newHighscores.today,
1735                        'game-over__score--glow-personal': !$store.game.newHighscores.all_time && !$store.game.newHighscores.month && !$store.game.newHighscores.today && $store.game.newHighscores.personal_best,
1736                    }"
1737                    x-text="$store.game.score"
1738                ></div>
1739                <div class="game-over__hs-badges">
1740                    <span x-show="$store.game.newHighscores.all_time" x-cloak class="game-over__hs-badge game-over__hs-badge--gold">&#9733; All-Time Best</span>
1741                    <span x-show="$store.game.newHighscores.month" x-cloak class="game-over__hs-badge game-over__hs-badge--silver">&#9733; Best This Month</span>
1742                    <span x-show="$store.game.newHighscores.today" x-cloak class="game-over__hs-badge game-over__hs-badge--bronze">&#9733; Best Today</span>
1743                    <span x-show="$store.game.newHighscores.personal_best" x-cloak class="game-over__hs-badge game-over__hs-badge--personal">&#9733; Personal Best</span>
1744                </div>
1745                
1746                
1747                <p class="game-over__meta">
1748                    Level <span x-text="$store.game.levelDisplayNumber"></span>
1749                    <template x-if="$store.game.myRank && !$store.game.isGuest">
1750                        <span>
1751                            &middot; <span class="game-over__rank" x-text="'#' + $store.game.myRank"></span>
1752                            of <span x-text="$store.game.playersTotal.toLocaleString()"></span>
1753                        </span>
1754                    </template>
1755                </p>
1756
1757                
1758                <div class="game-over__name" x-show="$store.game.actionsVisible" x-cloak>
1759                    <div x-show="!$store.game.nameEditing" class="game-over__name-row">
1760                        <span class="game-over__name-value" x-text="$store.game.editableName"></span>
1761                        <button
1762                            @click="$store.game.nameEditing = true"
1763                            class="game-profile__edit"
1764                            aria-label="Change your name on the leaderboard"
1765                        >
1766                            <svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1.003 1.003 0 000-1.42l-2.34-2.34a1.003 1.003 0 00-1.42 0l-1.83 1.83 3.75 3.75 1.84-1.82z"/></svg>
1767                        </button>
1768                    </div>
1769
1770                    <div x-show="$store.game.nameEditing" x-cloak class="game-over__name-edit">
1771                        <input
1772                            type="text"
1773                            x-model="$store.game.editableName"
1774                            maxlength="20"
1775                            class="game-input"
1776                            aria-label="Your name on the leaderboard"
1777                            @keydown.enter="$store.game.saveName()"
1778                            @keydown.escape.stop="$store.game.nameEditing = false"
1779                        >
1780                        <button @click="$store.game.saveName()" class="game-btn game-btn--primary" :disabled="$store.game.nameSaving">
1781                            <span x-show="!$store.game.nameSaving">Save</span>
1782                            <span x-show="$store.game.nameSaving" x-cloak class="game-spinner"></span>
1783                        </button>
1784                    </div>
1785                </div>
1786            </div>
1787
1788            
1789            <div class="game-over__actions" :class="{ 'game-over__actions--visible': $store.game.actionsVisible }">
1790                <button @click="$store.game.startGame()" class="game-btn game-btn--primary" :disabled="$store.game.loading">
1791                    <span x-show="!$store.game.loading">Play Again</span>
1792                    <span x-show="$store.game.loading" x-cloak class="game-spinner"></span>
1793                </button>
1794
1795                
1796                <button @click="$store.game.openHighscores()" class="game-btn game-btn--secondary">
1797                    <svg viewBox="0 0 24 24" fill="currentColor" width="20" height="20" style="margin-right:0.4rem"><path d="M7 4V2H17V4H20C20.55 4 21 4.45 21 5V11C21 12.1 20.1 13 19 13H16.83C16.42 14.17 15.31 15 14 15H13V17H16V19H13V22H11V19H8V17H11V15H10C8.69 15 7.58 14.17 7.17 13H5C3.9 13 3 12.1 3 11V5C3 4.45 3.45 4 4 4H7ZM5 6V11H7V6H5ZM17 6V11H19V6H17Z"/></svg>
1798                    Flag Journey Hall of Fame
1799                </button>
1800
1801                <button @click="$store.game.shareScore()" class="game-btn game-over__share-btn">
1802                    <span class="flex" x-show="!$store.game.shareSuccess">
1803                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
1804                        <span>Share Score</span>
1805                    </span>
1806                    <span x-show="$store.game.shareSuccess" x-cloak>Copied!</span>
1807                </button>
1808
1809                
1810                <button @click="$store.game.goToMenu()" class="game-btn game-btn--secondary">Menu</button>
1811
1812                
1813                <div
1814                    x-show="$store.game.isGuest"
1815                    x-cloak
1816                    class="game-over__claim"
1817                    :class="{ 'game-over__claim--visible': $store.game.actionsVisible }"
1818                >
1819                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
1820                    <span>
1821                        <template x-if="$store.game.myRank && $store.game.playersTotal">
1822                            <span>This would place <strong x-text="'#' + $store.game.myRank"></strong> of
1823                                <span x-text="$store.game.playersTotal.toLocaleString()"></span> &mdash;
1824                            </span>
1825                        </template>
1826                        guest runs aren&rsquo;t recorded in the Flag Journey Hall of Fame.
1827                        <a href="https://flagid.org/game/login" @click="$store.game.rememberClaim()">Sign in to claim it</a>
1828                    </span>
1829                </div>
1830            </div>
1831        </div>
1832    </div>
1833
1834    
1835    <div
1836        class="game-ad-anchor"
1837        x-show="$store.game.showAdAnchor"
1838        x-cloak
1839        x-init="$watch(() => $store.game.showAdAnchor, (visible) => { if (visible) $store.game.requestAnchorAd(); })"
1840    >
1841        <button
1842            type="button"
1843            class="game-ad-anchor__close"
1844            @click="$store.game.adAnchorClosed = true"
1845            aria-label="Close ad"
1846        >&times;</button>
1847        <ins class="adsbygoogle"
1848             style="display:block"
1849             data-ad-client="ca-pub-6114758564581825"
1850             data-ad-slot="7051401143"
1851             data-ad-format="auto"
1852             data-full-width-responsive="true"></ins>
1853    </div>
1854
1855    
1856    
1856<script>
1857        window.gameConfig = {"isGuest":true,"isAdmin":false,"testLevelId":null,"testFlagId":null,"testFlagLabel":null,"testFlagError":null,"testRandomFlag":false,"testRandomFlagReset":false,"testRandomFlagCount":0,"playerName":"","avatar":null,"countryFlag":"\/vendor\/flag-icons\/us.svg","levelTime":18,"correctGuessTimeGain":2,"wrongGuessTimeGain":-1,"flagsPerLevel":6,"startingLives":5,"extraLifeScore":100,"totalLevels":60,"levelIntroDuration":2500,"levelChoiceTimeout":10,"globalSounds":{"correct_answer":"https:\/\/flagid.org\/storage\/game-sounds\/blipSelect.wav","extra_life":"https:\/\/flagid.org\/storage\/game-sounds\/extra-life.mp3","game_over":"https:\/\/flagid.org\/storage\/game-sounds\/gameover.mp3","level_complete":"https:\/\/flagid.org\/storage\/game-sounds\/levelup.mp3","level_intro":"https:\/\/flagid.org\/storage\/game-sounds\/intro.mp3","select":"https:\/\/flagid.org\/storage\/game-sounds\/select.mp3","tick":"https:\/\/flagid.org\/storage\/game-sounds\/tick.mp3","times_up":"https:\/\/flagid.org\/storage\/game-sounds\/timesup.mp3","wrong_answer":"https:\/\/flagid.org\/storage\/game-sounds\/wrong.mp3"},"vapidPublicKey":"BDEWaML_BylWUXODu4LjxXg2F41gAIQoYzwJ2P-gC6eb8jdauLNLtRDrjMurCZo7-K04O6fbhCjq7xfxnmMB5tA","credits":[{"category":"Level images","entries":[{"title":"Doha\u0027s skyline flags","license_text":null,"url":"https:\/\/www.pexels.com\/@sajjad-naqvi-1348573","license_url":null},{"title":"Dorint Park Hotel in Bremen","license_text":null,"url":"https:\/\/www.pexels.com\/@nikolai-kolosov\/","license_url":null},{"title":"Motorboat","license_text":null,"url":"https:\/\/www.pexels.com\/@derwin-edwards-163348797\/","license_url":null},{"title":"Rice fields ","license_text":null,"url":"https:\/\/www.pexels.com\/@quang-nguyen-vinh-222549\/","license_url":null},{"title":"Swiss Federal Assembly","license_text":"The Swiss Parliament allows reuse of its images of the Federal Palace (interior and exterior) without restriction, provided that the source of the image, http:\/\/www.parlament.ch, is properly attributed. Redistribution, derivative works, commercial use, and all other uses are permitted.\n","url":"https:\/\/fr.wikipedia.org\/wiki\/Fichier:Federalpalace-dome.jpg","license_url":null}]},{"category":"Fonts","entries":[{"title":"Luckiest Guy - Astigmatic","license_text":"Luckiest Guy is licensed under the Apache License, Version 2.0.","url":"https:\/\/fonts.google.com\/specimen\/Luckiest+Guy?preview.script=Latn","license_url":"http:\/\/www.apache.org\/licenses\/LICENSE-2.0"}]}],"gameUrl":"https:\/\/flagid.org\/game","loginUrl":"https:\/\/flagid.org\/game\/login","adsEnabled":true,"adInterstitialCadence":3};
1858        window.gameCsrfToken = 'Z7r6rq22hAzmUgxWTdlp9T3pWZBNyrLm8LK2ikb7';
1859    </script>
1859
1860
1861<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a4439c6f3e9a32fd',t:'MTc5MDk0MzEwMQ=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
1861<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"49a450f3589e4a3db6d61f5dfc4ca54b","r":1,"spa":2}' crossorigin="anonymous"></script>
1861
1862</body>
1863</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.