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'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'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'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 >•</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 ››</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 >•</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">★ All-Time Best</span> 1741 <span x-show="$store.game.newHighscores.month" x-cloak class="game-over__hs-badge game-over__hs-badge--silver">★ Best This Month</span> 1742 <span x-show="$store.game.newHighscores.today" x-cloak class="game-over__hs-badge game-over__hs-badge--bronze">★ Best Today</span> 1743 <span x-show="$store.game.newHighscores.personal_best" x-cloak class="game-over__hs-badge game-over__hs-badge--personal">★ 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 · <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> — 1824 </span> 1825 </template> 1826 guest runs aren’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 >×</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.