vendor: 6,157 bytes, lines 1-14
1(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2<path d="M7 14H14V12.5H7V14ZM7 11.25H17V9.75H7V11.25ZM7 8.5H17V7H7V8.5ZM4 20V5.5C4 5.08333 4.14583 4.72917 4.4375 4.4375C4.72917 4.14583 5.08333 4 5.5 4H18.5C18.9167 4 19.2708 4.14583 19.5625 4.4375C19.8542 4.72917 20 5.08333 20 5.5V15.5C20 15.9167 19.8542 16.2708 19.5625 16.5625C19.2708 16.8542 18.9167 17 18.5 17H7L4 20ZM6.375 15.5H18.5V5.5H5.5V16.375L6.375 15.5ZM5.5 15.5V5.5V15.5Z" fill="currentColor"/> 3</svg> 4`,t=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 5<path d="M6.5 19C6.08333 19 5.72917 18.8542 5.4375 18.5625C5.14583 18.2708 5 17.9167 5 17.5C5 17.0833 5.14583 16.7292 5.4375 16.4375C5.72917 16.1458 6.08333 16 6.5 16C6.91667 16 7.27083 16.1458 7.5625 16.4375C7.85417 16.7292 8 17.0833 8 17.5C8 17.9167 7.85417 18.2708 7.5625 18.5625C7.27083 18.8542 6.91667 19 6.5 19ZM17 19C17 17.3333 16.6806 15.7778 16.0417 14.3333C15.4167 12.875 14.5625 11.6042 13.4792 10.5208C12.3958 9.4375 11.125 8.58333 9.66667 7.95833C8.22222 7.31944 6.66667 7 5 7V5C6.94444 5 8.75694 5.36806 10.4375 6.10417C12.1319 6.82639 13.6181 7.82639 14.8958 9.10417C16.1736 10.3819 17.1736 11.8681 17.8958 13.5625C18.6319 15.2431 19 17.0556 19 19H17ZM12 19C12 18.0278 11.8194 17.1181 11.4583 16.2708C11.0972 15.4236 10.5972 14.6806 9.95833 14.0417C9.31944 13.4028 8.57639 12.9028 7.72917 12.5417C6.88194 12.1806 5.97222 12 5 12V10C6.26389 10 7.4375 10.2361 8.52083 10.7083C9.60417 11.1667 10.5556 11.8056 11.375 12.625C12.1944 13.4444 12.8333 14.3958 13.2917 15.4792C13.7639 16.5625 14 17.7361 14 19H12Z" fill="currentColor"/> 6</svg> 7`,n=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 8<path d="M15.5 20.2065C14.8056 20.2065 14.2153 19.9635 13.7292 19.4774C13.2431 18.9913 13 18.401 13 17.7065C13 17.5815 13.0278 17.3802 13.0833 17.1024L8.14583 14.0815C7.92361 14.276 7.67361 14.4288 7.39583 14.5399C7.11806 14.651 6.81944 14.7065 6.5 14.7065C5.80556 14.7065 5.21528 14.4635 4.72917 13.9774C4.24306 13.4913 4 12.901 4 12.2065C4 11.5121 4.24306 10.9218 4.72917 10.4357C5.21528 9.9496 5.80556 9.70654 6.5 9.70654C6.81944 9.70654 7.11806 9.7621 7.39583 9.87321C7.67361 9.98432 7.92361 10.1371 8.14583 10.3315L13.0833 7.31071C13.0556 7.21349 13.0347 7.11627 13.0208 7.01904C13.0069 6.92182 13 6.81765 13 6.70654C13 6.0121 13.2431 5.42182 13.7292 4.93571C14.2153 4.4496 14.8056 4.20654 15.5 4.20654C16.1944 4.20654 16.7847 4.4496 17.2708 4.93571C17.7569 5.42182 18 6.0121 18 6.70654C18 7.40099 17.7569 7.99127 17.2708 8.47738C16.7847 8.96349 16.1944 9.20654 15.5 9.20654C15.1806 9.20654 14.8819 9.15099 14.6042 9.03988C14.3264 8.92877 14.0764 8.77599 13.8542 8.58154L8.91667 11.6024C8.94444 11.6996 8.96528 11.7968 8.97917 11.894C8.99306 11.9913 9 12.0954 9 12.2065C9 12.3177 8.99306 12.4218 8.97917 12.519C8.96528 12.6163 8.94444 12.7135 8.91667 12.8107L13.8542 15.8315C14.0764 15.6371 14.3264 15.4843 14.6042 15.3732C14.8819 15.2621 15.1806 15.2065 15.5 15.2065C16.1944 15.2065 16.7847 15.4496 17.2708 15.9357C17.7569 16.4218 18 17.0121 18 17.7065C18 18.401 17.7569 18.9913 17.2708 19.4774C16.7847 19.9635 16.1944 20.2065 15.5 20.2065ZM15.5 18.7065C15.7778 18.7065 16.0139 18.6093 16.2083 18.4149C16.4028 18.2204 16.5 17.9843 16.5 17.7065C16.5 17.4288 16.4028 17.1927 16.2083 16.9982C16.0139 16.8038 15.7778 16.7065 15.5 16.7065C15.2222 16.7065 14.9861 16.8038 14.7917 16.9982C14.5972 17.1927 14.5 17.4288 14.5 17.7065C14.5 17.9843 14.5972 18.2204 14.7917 18.4149C14.9861 18.6093 15.2222 18.7065 15.5 18.7065ZM6.5 13.2065C6.77778 13.2065 7.01389 13.1093 7.20833 12.9149C7.40278 12.7204 7.5 12.4843 7.5 12.2065C7.5 11.9288 7.40278 11.6927 7.20833 11.4982C7.01389 11.3038 6.77778 11.2065 6.5 11.2065C6.22222 11.2065 5.98611 11.3038 5.79167 11.4982C5.59722 11.6927 5.5 11.9288 5.5 12.2065C5.5 12.4843 5.59722 12.7204 5.79167 12.9149C5.98611 13.1093 6.22222 13.2065 6.5 13.2065ZM15.5 7.70654C15.7778 7.70654 16.0139 7.60932 16.2083 7.41488C16.4028 7.22043 16.5 6.98432 16.5 6.70654C16.5 6.42877 16.4028 6.19265 16.2083 5.99821C16.0139 5.80377 15.7778 5.70654 15.5 5.70654C15.2222 5.70654 14.9861 5.80377 14.7917 5.99821C14.5972 6.19265 14.5 6.42877 14.5 6.70654C14.5 6.98432 14.5972 7.22043 14.7917 7.41488C14.9861 7.60932 15.2222 7.70654 15.5 7.70654Z" fill="currentColor"/> 9</svg> 10`,r=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 11<rect width="24" height="24" rx="12" fill="white"/> 12<path d="M9.6 16.5L5.6 12.5L9.6 8.5L10.45 9.35L7.3 12.5L10.45 15.65L9.6 16.5ZM14.4 16.5L13.55 15.65L16.7 12.5L13.55 9.35L14.4 8.5L18.4 12.5L14.4 16.5Z" fill="currentColor"/> 13</svg> 14`,i=`data:image/svg+xml,%3csvg%20width='32'%20height='32'%20viewBox='0%200%2032%2032'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cg%20clip-path='url(%23clip0_1_258)'%3e%3cpath%20d='M26%201H6C3.23858%201%201%203.23858%201%206V26C1%2028.7614%203.23858%2031%206%2031H26C28.7614%2031%2031%2028.7614%2031%2026V6C31%203.23858%2028.7614%201%2026%201Z'%20fill='url(%23pattern0_1_258)'%20stroke='%23242145'%20stroke-width='2'/%3e%3c/g%3e%3cdefs%3e%3cpattern%20id='pattern0_1_258'%20patternContentUnits='objectBoundingBox'%20width='1'%20height='1'%3e%3cuse%20xlink:href='%23image0_1_258'%20transform='scale(0.03125)'/%3e%3c/pattern%3e%3cclipPath%20id='clip0_1_258'%3e%3crect%20width='32'%20height='32'%20fill='white'/%3e%3c/clipPath%3e%3cimage%2
140id='image0_1_258'%20width='32'%20height='32'%20preserveAspectRatio='none'%20xlink:href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAABCNJREFUeAG1V91rXEUU/83szeazNj5YTRVJQWoEg1YqKD6of4KKL2KxD4qPPuiLltpabKlatUIefFFEQQT7KAhFSAVfRKFSQQShXbWUZrMJCdm0m9175/TM1/3YvR9J0x52mLkzc875na+ZHcAREU1yO6KI5rnRbWrnQ6KDSJFwyqcJmOfhNMqIPMe2qcFinhVCNIw4RnapUvmtR6SV76uRdcnBm5Mryhn8dP7yJE9vCB0X/ngUt4y25JVzGgBtT8b2MMjcWVEhnTGTUuh2Q9PrJtKsWwAvsSUi81OK8MHps9j/9EnMPnEcn8z9pBM5DvdWKD8EfjEWmPKpViQE9swexq5dO3mW0Gyu4eKfx7JQDUt1LEo9QBko2WGnG9k9/N3rRYM8pbGgzQHwm3u9EKFWYtxshX564gV4BB+ffD7ZrXOD96soyYvBuCTASkNgmQkX/rqMA699g4iFs1yjZGJiGEGtZmSFoUK73UEgJfjH8xJfff4yHpm9vzIngirlmu69507U6wFqtRyHkVU4uXMsmWKUU1OTsa2UsptSfHqiPATOU2NjdWNlpr6LeqZeFOGOidFYT1pnv+xyAI5jZDiwNS98dts1kTbJR5Lnuhuh8ZjZg/I6CNKAKFaqjDwpLT5ddpGiRJDKyStfdowy5L1SJmqV+87LB5nmt9p0nUu8+fYZ7H3sKO6bOYSvv/sVE+PDzgNkeo2GPPI+C3aMj+DbM79h94Pv4IF9R/DWoe8NiDzKVoEbdrnkHn/mFEZHAqNM5PGKxGg9Zk
14FQukdiqYQGKzgkEX45+wbGR0cs+BQFGR+6oJIWpnTMa1ZgfKWm71fbKQeQZAqM26EMC7FBG2xMPTcZZMYk19frNbx64Ek0F9Zx+f8lzH34ojmMtALhDiPh8Eple0HJUa2T8PSJ53D1ygoWFtt4/ZWnjNy8g7nwINKHjU9CTXv3H+Nat6VllPHSUusaJ2eEu+/aYYSTuSeA1dXr+Pv3d2NepW9LmVOvKClDwcpNwhGZBBoyh5CznIcPz+zGP+cP49KF9/DQzFRGrD4RtVJjiJNVVJCDAHL80dnoYWgoMO7XMpoLbXwx95IpT01f8ri1vB6fCwGHsNMJE4HWPcijQQA5ibKyeg31wGcbIRjqY2HNxmIX5HpQQ3u9k5VZcBrJEr2uKoB//1vG4lKbLV9Ds7XGNx3h+Ec/WPsY0PunfuRkgllb5P8GreU2LjZaiRwq1LCJ27AAILlw+NX+deX+uFSRzKIsIB/GuFHsHX+ymIRN7ckop2IdGsA5WCOKSRSggj8mU4DK+Ae3/CGZ9edc2aXks4pQfd8VE6fNZ8I8SgH9OJmuYkjfvv3z6FsTJd9u3JBC7OEmVvRDkecaqCDa5Foe0L4/Jg2ns28TvxP1U+02Ps/nI6Kj2ute5w08AKp+H2eCQgAAAABJRU5ErkJggg=='/%3e%3c/defs%3e%3c/svg%3e`,a=`data:image/svg+xml,%3csvg%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3crect%20width='24'%20height='24'%20rx='12'%20fill='%23242145'/%3e%3cpath%20d='M6.1321%2016V8.72727H9.00142C9.55066%208.72727%2010.0194%208.82552%2010.4077%209.02202C10.7983%209.21615%2011.0954%209.49195%2011.299%209.84943C11.505%2010.2045%2011.608%2010.6224%2011.608%2011.103C11.608%2011.5859%2011.5038%2012.0014%2011.2955%2012.3494C11.0871%2012.6951%2010.7853%2012.9602%2010.3899%2013.1449C9.99692%2013.3295%209.52107%2013.4219%208.96236%2013.4219H7.04119V12.1861H8.71378C9.00734%2012.1861%209.25118%2012.1458%209.44531%2012.0653C9.63944%2011.9848%209.78385%2011.8641%209.87855%2011.7031C9.97562%2011.5421%2010.0241%2011.3421%2010.0241%2011.103C10.0241%2010.8615%209.97562%2010.6579%209.87855%2010.4922C9.78385%2010.3265%209.63826%2010.201%209.44176%2010.1158C9.24763%2010.0282%209.0026%209.98438%208.70668%209.98438H7.66974V16H6.1321ZM10.0597%2012.6903L11.8672%2016H10.1697L8.40128%2012.6903H10.0597ZM16.1399%2010.8189C16.1115%2010.5324%2015.9896%2010.3099%2015.7741%2010.1513C15.5587%209.99266%2015.2663%209.91335%2014.897%209.91335C14.6461%209.91335%2014.4342%209.94886%2014.2614%2010.0199C14.0885%2010.0885%2013.956%2010.1844%2013.8636%2010.3075C13.7737%2010.4306%2013.7287%2010.5703%2013.7287%2010.7266C13.724%2010.8568%2013.7512%2010.9704%2013.8104%2011.0675C13.8719%2011.1645%2013.956%2011.2486%2014.0625%2011.3196C14.169%2011.3883%2014.2921%2011.4486%2014.4318%2011.5007C14.5715%2011.5504%2014.7206%2011.593%2014.8793%2011.6286L15.5327%2011.7848C15.8499%2011.8558%2016.1411%2011.9505%2016.4062%2012.0689C16.6714%2012.1873%2016.901%2012.3329%2017.0952%2012.5057C17.2893%2012.6785%2017.4396%2012.8821%2017.5462%2013.1165C17.6551%2013.3509%2017.7107%2013.6196%2017.7131%2013.9226C17.7107%2014.3677%2017.5971%2014.7536%2017.3722%2015.0803C17.1496%2015.4046%2016.8277%2015.6567%2016.4062%2015.8366C15.9872%2016.0142%2015.4818%2016.103%2014.8899%2016.103C14.3028%2016.103%2013.7914%2016.013%2013.3558%2015.8331C12.9226%2015.6532%2012.584%2015.3868%2012.3402%2015.0341C12.0987%2014.679%2011.9721%2014.2398%2011.9602%2013.7166H13.4482C13.4647%2013.9605%2013.5346%2014.1641%2013.6577%2014.3274C13.7831%2014.4884%2013.95%2014.6103%2014.1584%2014.6932C14.3691%2014.7737%2014.607%2014.8139%2014.8722%2014.8139C15.1326%2014.8139%2015.3587%2014.776%2015.5504%2014.7003C15.7446%2014.6245%2015.8949%2014.5192%2016.0014%2014.3842C16.108%2014.2493%2016.1612%2014.0942%2016.1612%2013.919C16.1612%2013.7557%2016.1127%2013.6184%2016.0156%2013.5071C15.9209%2013.3958%2015.7813%2013.3011%2015.5966%2013.223C15.4143%2013.1449%2015.1906%2013.0739%2014.9254%2013.0099L14.1335%2012.8111C13.5204%2012.6619%2013.0362%2012.4287%2012.6811%2012.1115C12.326%2011.7943%2012.1496%2011.367%2012.152%2010.8295C12.1496%2010.3892%2012.2668%2010.0045%2012.5036%209.67543C12.7427%209.34635%2013.0705%209.08949%2013.4872%208.90483C13.9039%208.72017%2014.3774%208.62784%2014.9077%208.62784C15.4474%208.62784%2015.9186%208.72017%2016.321%208.90483C16.7259%209.08949%2017.0407%209.34635%2017.2656%209.67543C17.4905%2010.0045%2017.6065%2010.3857%2017.6136%2010.8189H16.1399Z'%20fill='%23FFD02B'/%3e%3c/svg%3e`,o=class{element;constructor(e,t){this.element=document.createElement(e),t&&(this.element.className=t)}destroy(){this.element.remove()}query(e){return this.element.querySelector(e)||void 0}},s=class extends o{constructor(){super(`footer`,`footer`),this.element.innerHTML=` 15 <div class="footer__inner container"> 16 <div class="footer__top"> 17 <div class="footer__brand"> 18 <a href="/" class="footer__logo logo logo--white" data-link> 19 <img src="${i}" alt="" class="logo__img" width="32" height="32">
20 <span class="logo__text">MiniGames</span> 21 </a> 22 <p class="footer__text"> 23 Take a short break and have fun. Hundreds of curated casual mini-games 24 right in your web browser. No download required. 25 </p> 26 </div> 27 28 <nav class="footer__nav"> 29 <div class="footer__group"> 30 <h2 class="footer__title">Explore</h2> 31 <ul class="footer__list list-unstyled"> 32 <li><a href="/" data-link>Home</a></li> 33 <li> 34 <a href="/library" data-link>Library</a> 35 </li> 36 <li> 37 <a href="/" data-link>Categories</a> 38 </li> 39 <li> 40 <a href="/" data-link>Tournaments</a> 41 </li> 42 </ul> 43 </div> 44 45 <div class="footer__group"> 46 <h2 class="footer__title">Company</h2> 47 <ul class="footer__list list-unstyled"> 48 <li> 49 <a href="/" data-link>About Us</a> 50 </li> 51 <li> 52 <a href="/" data-link>Contact</a> 53 </li> 54 <li> 55 <a href="/" data-link>Privacy Policy</a> 56 </li> 57 <li> 58 <a href="/" data-link>Terms of Service</a> 59 </li> 60 </ul> 61 </div> 62 63 <div class="footer__group footer__group--community"> 64 <h2 class="footer__title">Community</h2> 65 <ul class="footer__socials list-unstyled"> 66 <li> 67 <a 68 href="/" 69 class="footer__social-btn" 70 aria-label="Share" 71 target="_blank" 72 rel="noopener noreferrer" 73 data-link 74 >${n}</a 75 > 76 </li> 77 <li> 78 <a 79 href="/" 80 class="footer__social-btn" 81 aria-label="Community Chat" 82 target="_blank" 83 rel="noopener noreferrer" 84 data-link 85 >${e}</a 86 > 87 </li> 88 <li> 89 <a 90 href="/" 91 class="footer__social-btn" 92 aria-label="RSS Feed" 93 target="_blank" 94 rel="noopener noreferrer" 95 data-link 96 >${t}</a 97 > 98 </li> 99 </ul> 100 </div> 101 </nav> 102 </div> 103 104 <div class="footer__bottom">
105 <p class="footer__copyright">© 2026 MiniGames. All rights reserved.</p> 106 107 <a 108 href="https://rs.school/courses/short-track" 109 class="footer__credit" 110 target="_blank" 111 rel="noopener noreferrer" 112 > 113 <img 114 src="${a}" 115 alt="" 116 class="footer__credit-icon" 117 width="24" 118 height="24" 119 > 120 RS School 121 </a> 122 123 <a 124 href="https://github.com/aidardev" 125 class="footer__credit" 126 target="_blank" 127 rel="noopener noreferrer" 128 > 129 ${r} @aidardev 130 </a> 131 132 <p class="footer__attribution">Designed with love</p> 133 </div> 134 </div> 135 `}},c=`<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg"> 136<path d="M1.0625 10L0 8.9375L3.9375 5L0 1.0625L1.0625 -1.19209e-06L5 3.9375L8.9375 -1.19209e-06L10 1.0625L6.0625 5L10 8.9375L8.9375 10L5 6.0625L1.0625 10Z" fill="currentColor"/> 137</svg> 138`,l=`<svg width="16" height="10" viewBox="0 0 16 10" fill="none" xmlns="http://www.w3.org/2000/svg"> 139<line y1="1" x2="16" y2="1" stroke="currentColor" stroke-width="2"/> 140<line y1="5" x2="16" y2="5" stroke="currentColor" stroke-width="2"/> 141<line y1="9" x2="16" y2="9" stroke="currentColor" stroke-width="2"/> 142</svg> 143`,u=class extends o{content;pointerDownOnBackdrop=!1;handlePointerDown=e=>{this.pointerDownOnBackdrop=e.target===this.element};handleClick=e=>{this.pointerDownOnBackdrop&&e.target===this.element&&this.close()};handleClose=async()=>{await Promise.allSettled(this.element.getAnimations({subtree:!0}).map(e=>e.finished)),this.element.open||this.destroy()};constructor({label:e,modifier:t}={}){let n=t?`dialog ${t}`:`dialog`;super(`dialog`,n),e&&this.element.setAttribute(`aria-label`,e),this.content=document.createElement(`div`),this.content.classList.add(`dialog__content`),this.element.append(this.content),this.bindEvents()}bindEvents(){this.element.addEventListener(`pointerdown`,this.handlePointerDown),this.element.addEventListener(`click`,this.handleClick),this.element.addEventListener(`close`,this.handleClose)}setContent(e){typeof e==`string`?this.content.innerHTML=e:this.content.replaceChildren(e)}open(){this.element.open||(this.element.isConnected||document.body.append(this.element),this.element.showModal())}close(e){this.element.close(e)}},d=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M240-80q-33 0-56.5-23.5T160-160v-400q0-33 23.5-56.5T240-640h40v-80q0-83 58.5-141.5T480-920q83 0 141.5 58.5T680-720v80h40q33 0 56.5 23.5T800-560v400q0 33-23.5 56.5T720-80H240Zm0-80h480v-400H240v400Zm296.5-143.5Q560-327 560-360t-23.5-56.5Q513-440 480-440t-56.5 23.5Q400-393 400-360t23.5 56.5Q447-280 480-280t56.5-23.5ZM360-640h240v-80q0-50-35-85t-85-35q-50 0-85 35t-35 85v80ZM240-160v-400 400Z"/></svg>`,f=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm320-280L160-640v400h640v-400L480-440Zm0-80 320-200H160l320 200ZM160-640v-80 480-400Z"/></svg>`,p=`data:image/svg+xml,%3csvg%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M24%2012.2727C24%2011.4218%2023.9221%2010.6036%2023.7774%209.81818H12.2449V14.4655H18.8349C18.5455%2015.96%2017.6772%2017.2255%2016.3748%2018.0764V21.0982H20.3488C22.6642%2019.0036%2024%2015.9273%2024%2012.2727Z'%20fill='%234285F4'/%3e%3cpath%20d='M12.2449%2024C15.551%2024%2018.3228%2022.9309%2020.3488%2021.0982L16.3748%2018.0764C15.2839%2018.7964%2013.8924%2019.2327%2012.2449%2019.2327C9.06122%2019.2327%206.35622%2017.1273%205.38776%2014.2909H1.31354V17.3891C3.32839%2021.3055%207.45826%2024%2012.2449%2024Z'%20fill='%2334A853'/%3e%3cpath%20d='M5.38776%2014.28C5.14286%2013.56%204.99814%2012.7964%204.99814%2012C4.99814%2011.2036%205.14286%2010.44%205.38776%209.72V6.62182H1.31354C0.478664%208.23636%200%2010.0582%200%2012C0%2013.9418%200.478664%2015.7636%201.31354%2017.3782L4.48609%2014.9564L5.38776%2014.28Z'%20fill='%23FBBC05'/%3e%3cpath%20d='M12.2449%204.77818C14.0482%204.77818%2015.6512%205.38909%2016.9314%206.56727L20.4379%203.13091C18.3117%201.18909%2015.551%200%2012.2449%200C7.45826%200%203.32839%202.69455%201.31354%206.62182L5.38776%209.72C6.35622%206.88364%209.06122%204.77818%2012.2449%204.77818Z'%20fill='%23EA4335'/%3e%3c/svg%3e`,m=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="m644-428-58-58q9-47-27-88t-93-32l-58-58q17-8 34.5-12t37.5-4q75 0 127.5 52.5T660-500q0 20-4 37.5T644-428Zm128 126-58-56q38-29 67.5-63.5T832-500q-50-101-143.5-160.5T480-720q-29 0-57 4t-55 12l-62-62q41-17 84-25.5t90-8.5q151 0 269 83.5T920-500q-23 59-60.5 109.5T772-302Zm20 246L624-222q-35 11-70.5 16.5T480-200q-151 0-269-83.5T40-500q21-53 53-98.5t73-81.5L56-792l56-56 736 736-56 56ZM222-624q-29 26-53 57t-41 67q50 101 143.5 160.5T480-280q20 0 39-2.5t39-5.5l-36-38q-11 3-21 4.5t-21 1.5q-75 0-127.5-52.5T300-500q0-11 1.5-21t4.5-21l-84-82Zm319 93Zm-151 75Z"/></svg>`,h=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M607.5-372.5Q660-425 660-500t-52.5-127.5Q555-680 480-680t-127.5 52.5Q300-575 300-500t52.5 127.5Q405-320 480-320t127.5-52.5Zm-204-51Q372-455 372-500t31.5-76.5Q435-608 48
1430-608t76.5 31.5Q588-545 588-500t-31.5 76.5Q525-392 480-392t-76.5-31.5ZM214-281.5Q94-363 40-500q54-137 174-218.5T480-800q146 0 266 81.5T920-500q-54 137-174 218.5T480-200q-146 0-266-81.5ZM480-500Zm207.5 160.5Q782-399 832-500q-50-101-144.5-160.5T480-720q-113 0-207.5 59.5T128-500q50 101 144.5 160.5T480-280q113 0 207.5-59.5Z"/></svg>`;function g(e){let{id:t,name:n,label:r,type:i,placeholder:a,icon:o,autocomplete:s,passwordToggle:c=!1}=e;return` 144 <div class="field${c?` field--has-password-toggle`:``}"> 145 <label class="field__label" for="${t}">${r}</label> 146 <div class="field__control"> 147 <span class="field__icon" aria-hidden="true">${o}</span> 148 <input 149 class="field__input" 150 id="${t}" 151 name="${n}" 152 type="${i}" 153 placeholder="${a}" 154 autocomplete="${s}" 155 > 156 ${c?_():``} 157 </div> 158 </div> 159 `}function _(){return` 160 <button class="field__toggle" type="button" aria-label="Show password" data-password-toggle> 161 <span class="field__toggle-icon field__toggle-icon--show">${h}</span> 162 <span class="field__toggle-icon field__toggle-icon--hide">${m}</span> 163 </button> 164 `}var v=class extends o{handleSubmit=e=>{e.preventDefault()};constructor(){super(`form`,`auth-form`),this.element.noValidate=!0,this.element.innerHTML=` 165 <div class="auth-form__head"> 166 <h2 class="auth-form__title">Welcome Back!</h2> 167 <p class="auth-form__subtitle">Sign in to resume your games and progress.</p> 168 </div> 169 170 <div class="auth-form__fields"> 171 ${g({id:`login-email`,name:`email`,label:`Email Address`,type:`email`,placeholder:`e.g. [email protected]`,icon:f,autocomplete:`email`})} 172 ${g({id:`login-password`,name:`password`,label:`Password`,type:`password`,placeholder:`â¢â¢â¢â¢â¢â¢â¢â¢`,icon:d,autocomplete:`current-password`,passwordToggle:!0})} 173 <button class="auth-form__link auth-form__link--forgot" type="button"> 174 Forgot Password? 175 </button> 176 </div> 177 178 <div class="auth-form__actions"> 179 <button 180 class="auth-form__btn auth-form__btn--submit btn btn--large btn--primary" 181 type="submit" 182 > 183 Login 184 </button> 185 <div class="auth-form__divider" aria-hidden="true"><span>OR</span></div> 186 <button 187 class="auth-form__btn auth-form__btn--google btn btn--medium btn--outline-on-primary" 188 type="button" 189 > 190 <img src="${p}" alt="" width="24" height="24"> 191 Continue with Google 192 </button> 193 </div> 194 195 <p class="auth-form__switch"> 196 Don't have an account? 197 <button class="auth-form__link" type="button" data-auth-tab="register"> 198 Register 199 </button> 200 </p> 201 `,this.element.addEventListener(`submit`,this.handleSubmit)}},y=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M367-527q-47-47-47-113t47-113q47-47 113-47t113 47q47 47 47 113t-47 113q-47 47-113 47t-113-47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Zm80-80h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm296.5-343.5Q560-607 560-640t-23.5-56.5Q513-720 480-720t-56.5 23.5Q400-673 400-640t23.5 56.5Q447-560 480-560t56.5-23.5ZM480-640Zm0 400Z"/></svg>`,b=class extends o{handleSubmit=e=>{e.preventDefault()};constructor(){super(`form`,`auth-form`),this.element.noValidate=!0,this.element.innerHTML=` 202 <div class="auth-form__head"> 203 <h2 class="auth-form__title">Create Account</h2> 204 <p class="auth-form__subtitle">
204Join MiniGames to track your score & streak.</p> 205 </div> 206 207 <div class="auth-form__fields"> 208 ${g({id:`register-username`,name:`username`,label:`Username`,type:`text`,placeholder:`e.g. CozyGamer_99`,icon:y,autocomplete:`username`})} 209 ${g({id:`register-email`,name:`email`,label:`Email Address`,type:`email`,placeholder:`[email protected]`,icon:f,autocomplete:`email`})} 210 ${g({id:`register-password`,name:`password`,label:`Password`,type:`password`,placeholder:`Min. 8 characters`,icon:d,autocomplete:`new-password`})} 211 ${g({id:`register-confirm-password`,name:`confirmPassword`,label:`Confirm Password`,type:`password`,placeholder:`Repeat your password`,icon:d,autocomplete:`new-password`})} 212 </div> 213 214 <div class="auth-form__actions"> 215 <button 216 class="auth-form__btn auth-form__btn--submit btn btn--large btn--primary" 217 type="submit" 218 > 219 Create Account 220 </button> 221 <div class="auth-form__divider" aria-hidden="true"><span>OR</span></div> 222 <button 223 class="auth-form__btn auth-form__btn--google btn btn--medium btn--outline-on-primary" 224 type="button" 225 > 226 <img src="${p}" alt="" width="24" height="24"> 227 Sign up with Google 228 </button> 229 </div> 230 231 <p class="auth-form__switch"> 232 Already have an account? 233 <button class="auth-form__link" type="button" data-auth-tab="login">Login</button> 234 </p> 235 `,this.element.addEventListener(`submit`,this.handleSubmit)}};function x(e){return e===`register`?`register`:`login`}var S=class extends u{handleSwitchClick=e=>{if(!(e.target instanceof Element))return;let t=e.target.closest(`[data-auth-tab]`);t&&this.showTab(x(t.dataset.authTab))};constructor(e=`login`){super({label:`Auth Dialog`,modifier:`dialog--auth`}),this.setContent(` 236 <div class="auth"> 237 <div class="auth__tabs" role="tablist" aria-label="Login or register"> 238 <button 239 class="auth__tab" 240 id="auth-tab-login" 241 type="button" 242 role="tab" 243 aria-controls="auth-panel-login" 244 data-auth-tab="login" 245 > 246 Login 247 </button> 248 <button 249 class="auth__tab" 250 id="auth-tab-register" 251 type="button" 252 role="tab" 253 aria-controls="auth-panel-register" 254 data-auth-tab="register" 255 > 256 Register 257 </button> 258 </div> 259 260 <div 261 class="auth__panel" 262 id="auth-panel-login" 263 role="tabpanel" 264 aria-labelledby="auth-tab-login" 265 data-auth-panel="login" 266 ></div> 267 <div 268 class="auth__panel" 269 id="auth-panel-register" 270 role="tabpanel" 271 aria-labelledby="auth-tab-register" 272 data-auth-panel="register" 273 ></div> 274 </div> 275 `),this.mountForms(),this.showTab(e),this.bindTabEvents()}mountForms(){this.query(`[data-auth-panel="login"]`)?.append(new v().element),this.query(`[data-auth-panel="register"]`)?.append(new b().element)}bindTabEvents(){this.element.addEventListener(`click`,this.handleSwitchClick)}showTab(e){for(let t of this.element.querySelectorAll(`[role="tab"]`))t.setAttribute(`aria-selected`,String(t.dataset.authTab===e));for(let t of this.element.querySelectorAll(`[role="tabpanel"]`))t.hidden=t.dataset.authPanel!==e}},C=class extends o{isMenuOpen=!1;burgerBtn=void 0;closeBtn=void 0;menuContainer=void 0;navLinks=[];handleDocumentClick=e=>{let t=e.target;t instanceof Node&&(this.element.contains(t)||this.closeMenu())};handleEscKey=e=>{e.key===`Escape`&&this.closeMenu()};handleAuthClick=e=>{if(!(e.target instanceof Element))return;let t=e.target.closest(`[data-auth-tab]`);if(!t)return;let n=x(t.dataset.authTab);this.closeMenu(),new S(n).open()};handleLinksClick=e=>{e.target instanceof Element&&e.target.closest(`a`)&&this.closeMenu()};constructor(){super(`header`,`header`),this.element.innerHTML=` 276 <div class="header__inner container"> 277 <a href="/" class="header__logo logo logo--dark" data-link> 278 <img src="${i}" alt="" class="logo__img" width="32" height="32">
279 <span class="logo__text">MiniGames</span> 280 </a> 281 <div class="header__menu" id="mobile-menu"> 282 <div class="header__mobile-topbar"> 283 <a href="/" class="header__logo-mobile logo logo--white" data-link> 284 <img src="${i}" alt="" class="logo__img" width="32" height="32"> 285 <span class="logo__text">MiniGames</span> 286 </a> 287 <button class="header__close btn" type="button" aria-label="Close menu"> 288 ${c} 289 </button> 290 </div> 291 <nav class="header__navbar navbar"> 292 <ul class="navbar__list list-unstyled"> 293 <li><a href="/" data-link data-route="/">Home</a></li> 294 <li><a href="/library" data-link data-route="/library">Library</a></li> 295 <li><a href="/" data-link>Tournaments</a></li> 296 <li><a href="/" data-link>Community</a></li> 297 </ul> 298 </nav> 299 <div class="header__btns"> 300 <button 301 class="header__btn btn btn--medium btn--outline-on-primary" 302 type="button" 303 data-auth-tab="login" 304 > 305 Log In 306 </button> 307 <button 308 class="header__btn btn btn--medium btn--primary" 309 type="button" 310 data-auth-tab="register" 311 > 312 Sign Up 313 </button> 314 </div> 315 </div> 316 <button 317 class="header__btn header__btn--tablet btn btn--small btn--primary" 318 type="button" 319 data-auth-tab="register" 320 > 321 Sign Up 322 </button> 323 <button 324 class="header__hamburger-btn btn btn--icon btn--outline-on-primary" 325 type="button" 326 aria-label="Open menu" 327 aria-expanded="false" 328 aria-controls="mobile-menu" 329 > 330 ${l} 331 </button> 332 </div> 333 `,this.initElements(),this.bindEvents()}initElements(){this.burgerBtn=this.query(`.header__hamburger-btn`),this.closeBtn=this.query(`.header__close`),this.menuContainer=this.query(`.header__menu`),this.navLinks=[...this.element.querySelectorAll(`:scope .navbar__list a[data-route]`)]}bindEvents(){this.burgerBtn?.addEventListener(`click`,()=>this.openMenu()),this.closeBtn?.addEventListener(`click`,()=>this.closeMenu()),this.element.addEventListener(`click`,this.handleAuthClick),this.menuContainer?.addEventListener(`click`,this.handleLinksClick)}setActivePath(e){for(let t of this.navLinks){let n=t.dataset.route===e;t.closest(`li`)?.classList.toggle(`is-active`,n)}}openMenu(){this.isMenuOpen||(this.isMenuOpen=!0,this.menuContainer?.classList.add(`is-open`),this.burgerBtn?.setAttribute(`aria-expanded`,`true`),document.body.classList.add(`is-locked`),document.addEventListener(`click`,this.handleDocumentClick),document.addEventListener(`keydown`,this.handleEscKey))}closeMenu(){this.isMenuOpen&&(this.isMenuOpen=!1,this.menuContainer?.classList.remove(`is-open`),this.burgerBtn?.setAttribute(`aria-expanded`,`false`),document.body.classList.remove(`is-locked`),document.removeEventListener(`click`,this.handleDocumentClick),document.removeEventListener(`keydown`,this.handleEscKey))}};async function w(){let e=await fetch(`/mock-data/leaderboard.json`);if(!e.ok)throw Error(`Failed to load leaderboard: ${e.status}`);return(await e.json()).data}var ee=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 334<path d="M12 3V15M7 8L12 3L17 8M21 15V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V15" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> 335</svg> 336`,te=`/assets/illustration-side-B1_6Masa.png`,ne=class extends o{constructor(){super(`section`,`section section-developer-cta`),this.element.innerHTML=` 337 <div class="developer-cta container"> 338 <img 339 src="${te}" 340 alt="Illustration image" 341 class="developer-cta__img img-responsive" 342 width="680" 343 height="480" 344 loading="lazy" 345 > 346 <div class="developer-cta__card"> 347 <div class="developer-cta__card-content"> 348 <h2 class="developer-cta__title">Are You a Game Developer?</h2> 349 <p class="developer-cta__text"> 350 Want to see your game on MiniGames? We're always looking for fun, 351 engaging mini games to add to our platform. Submit your game 352 and reach thousands of players! 353 </p> 354 <button 355 class="developer-cta__btn btn btn--large btn--primary" 356 type="button" 357 > 358 ${ee} Submit Form 359 </button> 360 <p class="developer-cta__hint"> 361 or contact us at 362 <a href="mailto:[email protected]">[email protected]</a> 363 </p> 364 </div> 365 </div> 366 </div> 367 `}},T=class extends o{constructor(){super(`section`,`section-hero`),this.element.innerHTML=` 368 <div class="hero container"> 369 <div class="hero__card"> 370 <h1 class="hero__title">Take a Short Break & Have Fun</h1> 371 <p class="hero__text hero__text--desktop"> 372 Discover hundreds of curated casual mini-games. Play instantly in your 373 browser â puzzle, match 3, farm, and board classics. 374 </p> 375 <p class="hero__text hero__text--mobile"> 376 Discover hundreds of curated casual mini-games right in y
376our browser. 377 </p> 378 <a href="/library" class="hero__btn btn btn--large btn--primary" data-link> 379 Browse Library 380 </a> 381 </div> 382 </div> 383 `}};function E(e){return e.toLocaleString(`en-US`)}function D(e){return e<1e3?e.toString():e<1e6?`${Math.floor(e/1e3*10)/10}K`:`${Math.floor(e/1e6*10)/10}M`}function O(e){let t=[];for(let n of e)n>=`A`&&n<=`Z`&&t.push(n);return t.length>=2?t[0]+t[1]:e.slice(0,2).toUpperCase()}var k=class extends o{players;constructor(e){super(`section`,`section section-leaderboard`),this.players=e,this.element.innerHTML=` 384 <div class="container"> 385 <div class="section-header"> 386 <h2 class="section-header__title section-title"> 387 Top Players<span class="section-leaderboard__title-extra"> This Week</span> 388 </h2> 389 </div> 390 391 <div class="leaderboard-table-container"> 392 <table class="leaderboard-table"> 393 <thead class="leaderboard-table__head"> 394 <tr> 395 <th 396 scope="col" 397 class="leaderboard-table__col leaderboard-table__col--rank" 398 > 399 Rank 400 </th> 401 <th 402 scope="col" 403 class="leaderboard-table__col leaderboard-table__col--player" 404 > 405 Player 406 </th> 407 <th 408 scope="col" 409 class="leaderboard-table__col leaderboard-table__col--games" 410 > 411 <span class="leaderboard-table__text-full">Games Played</span> 412 <span class="leaderboard-table__text-short">Games</span> 413 </th> 414 <th 415 scope="col" 416 class="leaderboard-table__col leaderboard-table__col--score" 417 > 418 <span class="leaderboard-table__text-full">Total Score</span> 419 <span class="leaderboard-table__text-short">Score</span> 420 </th> 421 <th 422 scope="col" 423 class="leaderboard-table__col leaderboard-table__col--streak" 424 > 425 Streak 426 </th> 427 <th 428 scope="col" 429 class="leaderboard-table__col leaderboard-table__col--favorite" 430 > 431 Favorite Game 432 </th> 433 </tr> 434 </thead> 435 <tbody class="leaderboard-table__body"> 436 ${this.renderRows()} 437 </tbody> 438 </table> 439 </div> 440 </div> 441 `}renderRows(){return this.players.map(e=>{let t=O(e.playerName),n=E(e.totalScore),r=D(e.totalScore);return` 442 <tr class="leaderboard-table__row"> 443 <td class="leaderboard-table__cell leaderboard-table__col--rank"> 444 <span class="leaderboard-table__rank-val">#${e.rank}</span> 445 </td> 446 <td class="leaderboard-table__cell leaderboard-table__col--player"> 447 <div class="leaderboard-table__player-info">
448 <span class="leaderboard-table__avatar avatar">${t}</span> 449 <span class="leaderboard-table__username" 450 >${e.playerName}</span 451 > 452 </div> 453 </td> 454 <td class="leaderboard-table__cell leaderboard-table__col--games"> 455 ${e.gamesPlayed} 456 </td> 457 <td class="leaderboard-table__cell leaderboard-table__col--score"> 458 <span class="leaderboard-table__text-full">${n}</span> 459 <span class="leaderboard-table__text-short">${r}</span> 460 </td> 461 <td class="leaderboard-table__cell leaderboard-table__col--streak"> 462 <span class="leaderboard-table__streak"> 463 ð¥ ${e.streakDays}<span class="leaderboard-table__text-full"> 464 days</span 465 ><span class="leaderboard-table__text-short">d</span> 466 </span> 467 </td> 468 <td class="leaderboard-table__cell leaderboard-table__col--favorite"> 469 <span class="leaderboard-table__badge">${e.favoriteGameName}</span> 470 </td> 471 </tr> 472 `}).join(``)}};async function A(){let e=await fetch(`/mock-data/comments-tukoni-forest-keepers.json`);if(!e.ok)throw Error(`Failed to load comments: ${e.status}`);return(await e.json()).data}async function j(){let e=await fetch(`/mock-data/game-tukoni-forest-keepers.json`);if(!e.ok)throw Error(`Failed to load game details: ${e.status}`);return(await e.json()).data}async function M(){let e=await fetch(`/mock-data/all-games-seed.json`);if(!e.ok)throw Error(`Failed to load games: ${e.status}`);return(await e.json()).data}var N=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>`,P=`<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8z"/></svg>`,F=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 473<path d="M6.4 19L5 17.6L10.6 12L5 6.4L6.4 5L12 10.6L17.6 5L19 6.4L13.4 12L19 17.6L17.6 19L12 13.4L6.4 19Z" fill="currentColor"/> 474</svg> 475`,I=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 476<path d="M12 21L10.55 19.7C8.86667 18.1834 7.475 16.875 6.375 15.775C5.275 14.675 4.4 13.6917 3.75 12.825C3.1 11.9417 2.64167 11.1334 2.375 10.4C2.125 9.66669 2 8.91669 2 8.15002C2 6.58336 2.525 5.27502 3.575 4.22502C4.625 3.17502 5.93333 2.65002 7.5 2.65002C8.36667 2.65002 9.19167 2.83336 9.975 3.20002C10.7583 3.56669 11.4333 4.08336 12 4.75003C12.5667 4.08336 13.2417 3.56669 14.025 3.20002C14.8083 2.83336 15.6333 2.65002 16.5 2.65002C18.0667 2.65002 19.375 3.17502 20.425 4.22502C21.475 5.27502 22 6.58336 22 8.15002C22 8.91669 21.8667 9.66669 21.6 10.4C21.35 11.1334 20.9 11.9417 20.25 12.825C19.6 13.6917 18.725 14.675 17.625 15.775C16.525 16.875 15.1333 18.1834 13.45 19.7L12 21ZM12 18.3C13.6 16.8667 14.9167 15.6417 15.95 14.625C16.9833 13.5917 17.8 12.7 18.4 11.95C19 11.1834 19.4167 10.5084 19.65 9.92503C19.8833 9.32503 20 8.73336 20 8.15002C20 7.15002 19.6667 6.31669 19 5.65003C18.3333 4.98336 17.5 4.65003 16.5 4.65003C15.7167 4.65003 14.9917 4.87503 14.325 5.32503C13.6583 5.75836 13.2 6.31669 12.95 7.00003H11.05C10.8 6.31669 10.3417 5.75836 9.675 5.32503C9.00833 4.87503 8.28333 4.65003 7.5 4.65003C6.5 4.65003 5.66667 4.98336 5 5.
47665003C4.33333 6.31669 4 7.15002 4 8.15002C4 8.73336 4.11667 9.32503 4.35 9.92503C4.58333 10.5084 5 11.1834 5.6 11.95C6.2 12.7 7.01667 13.5917 8.05 14.625C9.08333 15.6417 10.4 16.8667 12 18.3Z" fill="currentColor"/> 477</svg> 478`,L=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 479<path d="M3 20V4L22 12L3 20ZM5 17L16.85 12L5 7V10.5L11 12L5 13.5V17ZM5 17V12V7V10.5V13.5V17Z" fill="currentColor"/> 480</svg> 481`,R=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 482<path d="M8.85 17.825L12 15.925L15.15 17.85L14.325 14.25L17.1 11.85L13.45 11.525L12 8.125L10.55 11.5L6.9 11.825L9.675 14.25L8.85 17.825ZM5.825 22L7.45 14.975L2 10.25L9.2 9.625L12 3L14.8 9.625L22 10.25L16.55 14.975L18.175 22L12 18.275L5.825 22Z" fill="currentColor"/> 483</svg> 484`;function z(e){let t=new Date(e),n=Math.max(0,Date.now()-t.getTime()),r=Math.floor(n/6e4),i=Math.floor(n/36e5),a=Math.floor(n/864e5);if(r<60)return`${Math.max(1,r)} min ago`;if(i<24)return`${i} ${i===1?`hour`:`hours`} ago`;if(a<7)return`${a} ${a===1?`day`:`days`} ago`;let o=Math.floor(a/7);return`${o} ${o===1?`week`:`weeks`} ago`}function B(e,t=16){if(!Number.isFinite(e))throw TypeError(`Value is not a valid number: ${e}`);return`${e/t}rem`}var V=class extends u{game;comments;isFavorite;likedComments=new Set;handleActionClick=e=>{if(!(e.target instanceof Element))return;let t=e.target.closest(`[data-action]`);if(t)switch(t.dataset.action){case`close`:this.close();break;case`favorite`:this.toggleFavorite();break;case`like-comment`:this.toggleCommentLike(t)}};handleSubmit=e=>{let t=e.target;t instanceof HTMLFormElement&&t.matches(`[data-comment-form]`)&&e.preventDefault()};handleInput=e=>{let t=e.target;t instanceof HTMLTextAreaElement&&t.matches(`[data-comment-input]`)&&this.resizeTextarea(t)};constructor({game:e,comments:t}){super({label:`Game Details`,modifier:`dialog--game-details`}),this.game=e,this.comments=t.map(e=>({...e})),this.isFavorite=e.isLikedByCurrentUser;for(let e of this.comments)e.isLikedByCurrentUser&&this.likedComments.add(e.commentId);this.render(),this.updateFavoriteButton(),this.bindGameDetailsEvents()}render(){this.setContent(` 485 <div class="game-details"> 486 ${this.renderHero()} 487 <div class="game-details__body"> 488 ${this.renderInfo()} ${this.renderRecords()} ${this.renderComments()} 489 </div> 490 </div> 491 `)}renderHero(){return` 492 <header class="game-details__hero"> 493 <img 494 class="game-details__hero-img img-responsive" 495 src="${this.game.heroImage}" 496 alt="${this.game.name}" 497 > 498 <button 499 class="game-details__close dialog__close btn btn--icon" 500 type="button" 501 data-action="close" 502 aria-label="Close game details" 503 > 504 ${F} 505 </button> 506 </header> 507 `}renderInfo(){let{specs:e}=this.game;return` 508 <section class="game-details__info"> 509 <header class="game-details__info-header"> 510 <div class="game-details__title-row"> 511 <h2 class="game-details__title">${this.game.name}</h2> 512 <div class="game-details__meta"> 513 <div class="game-details__meta-item meta-item meta-item--rating"> 514 ${R} 515 <span class="meta-item__value">${this.game.rating}</span> 516 </div> 517 <div class="game-details__meta-item meta-item meta-item--likes"> 518 ${I} 519 <span class="meta-item__value" 520 >${D(this.game.likesCount)}</span 521 > 522 </div> 523 </div> 524 </div> 525 <p class="game-details__description">${this.game.fullDescription}</p> 526 </header> 527 528 <dl class="game-details__specs"> 529 ${this.renderSpec(`Genre`,e.genre)} 530 ${this.renderSpec(`Players`,e.players)} 531 ${this.renderSpec(`Duration`,e.duration)} 532 ${this.renderSpec(`Price`,e.price)} 533 </dl> 534 535 <div class="game-details__actions"> 536 <button 537 class="game-details__play btn btn--large btn--primary" 538 type="button" 539 data-action="play" 540 > 541 Play Now 542 </button> 543 <button 544 class="game-details__favorite btn btn--large" 545 type="button" 546 data-action="favorite" 547 aria-pressed="${this.isFavorite}" 548 > 549 ${I}
550 <span data-favorite-label> 551 ${this.isFavorite?`Remove from Favorites`:`Add to Favorites`} 552 </span> 553 </button> 554 </div> 555 </section> 556 `}updateFavoriteButton(){let e=this.query(`[data-action="favorite"]`);if(!e)return;e.setAttribute(`aria-pressed`,String(this.isFavorite)),e.classList.toggle(`is-active`,this.isFavorite);let t=e.querySelector(`[data-favorite-label]`);t&&(t.textContent=this.isFavorite?`Remove from Favorites`:`Add to Favorites`)}renderSpec(e,t){return` 557 <div class="game-details__spec spec"> 558 <dt class="spec__label">${e}</dt> 559 <dd class="spec__value">${t}</dd> 560 </div> 561 `}renderRecords(){return` 562 <section class="game-details__records"> 563 <h3 class="game-details__section-title"> 564 <span aria-hidden="true">ð</span> 565 Top Records 566 </h3> 567 <ol class="game-details__records-list list-unstyled"> 568 ${this.game.topRecords.map(e=>this.renderRecord(e)).join(``)} 569 </ol> 570 </section> 571 `}renderRecord(e){return` 572 <li class="game-details__record record"> 573 <span class="record__position"> 574 <span class="sr-only">Position ${e.position}</span> 575 <span aria-hidden="true">${this.getMedal(e.position)}</span> 576 </span> 577 <span class="record__player">${e.playerName}</span> 578 <strong class="record__score">${e.score.toLocaleString(`en-US`)} pts</strong> 579 <time class="record__date" datetime="${e.achievedAt}"> 580 ${z(e.achievedAt)} 581 </time> 582 </li> 583 `}renderComments(){return` 584 <section class="game-details__comments"> 585 <h3 class="game-details__section-title">Comments (${this.comments.length})</h3> 586 587 <form class="game-details__comment-form comment-form" data-comment-form> 588 <div class="comment-form__avatar avatar" aria-hidden="true">U</div> 589 <label class="comment-form__label sr-only" for="game-details-comment"> 590 Write a comment 591 </label> 592 <textarea 593 id="game-details-comment" 594 class="comment-form__input" 595 name="comment" 596 rows="1" 597 maxlength="1000" 598 placeholder="Write a comment..." 599 data-comment-input 600 ></textarea> 601 <button 602 class="comment-form__submit btn btn--icon btn--on-primary" 603 type="submit" 604 aria-label="Submit comment" 605 > 606 ${L} 607 </button> 608 </form> 609 610 <ul class="game-details__comments-list list-unstyled"> 611 ${this.comments.map(e=>this.renderComment(e)).join(``)} 612 </ul> 613 </section> 614 `}renderComment(e){let t=this.likedComments.has(e.commentId);return` 615 <li class="game-details__comment"> 616 <article class="comment"> 617 <header class="comment__header"> 618 <div class="comment__author"> 619 <span class="comment__avatar avatar" aria-hidden="true"> 620 ${e.authorName.charAt(0).toUpperCase()} 621 </span> 622 623 <h4 class="comment__name">${e.authorName}</h4> 624 </div> 625 <time class="comment__date" datetime="${e.createdAt}"> 626 ${z(e.createdAt)} 627 </time> 628 </header> 629 630 <p class="comment__text">${e.text}</p> 631 632 <button 633 class="comment__like btn" 634 type="button" 635 data-action="like-comment" 636 data-comment-id="${e.commentId}" 637 aria-pressed="${t}"
638 aria-label="${t?`Unlike`:`Like`} comment" 639 > 640 ${I} 641 <span data-comment-like-count> 642 ${e.likesCount+ +!!t} 643 </span> 644 </button> 645 </article> 646 </li> 647 `}bindGameDetailsEvents(){this.element.addEventListener(`click`,this.handleActionClick),this.element.addEventListener(`submit`,this.handleSubmit),this.element.addEventListener(`input`,this.handleInput)}toggleFavorite(){this.isFavorite=!this.isFavorite,this.updateFavoriteButton()}toggleCommentLike(e){let t=e.dataset.commentId;if(!t)return;let n=this.likedComments.has(t);n?this.likedComments.delete(t):this.likedComments.add(t),e.setAttribute(`aria-pressed`,String(!n)),e.setAttribute(`aria-label`,n?`Like comment`:`Unlike comment`),e.classList.toggle(`is-active`,!n);let r=this.comments.find(e=>e.commentId===t);if(!r)return;let i=r.likesCount+ +!n,a=e.querySelector(`[data-comment-like-count]`);a&&(a.textContent=String(i))}resizeTextarea(e){e.style.height=`auto`,e.style.height=B(Math.min(e.scrollHeight,88))}getMedal(e){switch(e){case 1:return`ð¥`;case 2:return`ð¥`;case 3:return`ð¥`;default:return String(e)}}},H=class extends o{game;onClick;handleClick=()=>{this.onClick?.(this.game.slug)};constructor({game:e,onClick:t}){super(`article`,`game-slide`),this.game=e,this.onClick=t,this.element.innerHTML=` 648 <img src="${e.cardImage}" alt="" class="game-slide__img" loading="lazy"> 649 650 <div class="game-slide__overlay"> 651 <h3 class="game-slide__title"> 652 <span class="game-slide__title-text">${e.name}</span> 653 </h3> 654 655 <div class="game-slide__meta"> 656 <div class="game-slide__meta-item meta-item meta-item--rating"> 657 ${R} 658 <span class="meta-item__value">${e.rating}</span> 659 </div> 660 <div class="game-slide__meta-item meta-item meta-item--likes"> 661 ${I} 662 <span class="meta-item__value" 663 >${D(e.likesCount)}</span 664 > 665 </div> 666 </div> 667 </div> 668 `,this.element.addEventListener(`click`,this.handleClick)}destroy(){this.element.removeEventListener(`click`,this.handleClick),super.destroy()}};function U(e,t=300){let n=0,r;return function(...i){let a=Date.now();return a-n>=t&&(n=a,r=e.apply(this,i)),r}}var W=[`is-active`,`is-near`,`is-far`],G=`is-hidden`,K=[...W,G],q=class extends o{track;slideClassName;autoplayInterval;dragThreshold;swipeThreshold;activeIndex=0;autoplayTimer;autoplayStartTime=0;autoplayRemaining=0;isPointerDown=!1;isDragging=!1;pointerStartX=0;handlePointerDown=e=>{this.isPointerDown=!0,this.isDragging=!1,this.pointerStartX=e.clientX,this.stopAutoplay()};handlePointerMove=e=>{this.isPointerDown&&!this.isDragging&&Math.abs(e.clientX-this.pointerStartX)>=this.dragThreshold&&(this.isDragging=!0,this.track.setPointerCapture(e.pointerId))};handlePointerUp=e=>{if(!this.isPointerDown)return;this.isPointerDown=!1;let t=e.clientX-this.pointerStartX;Math.abs(t)>=this.swipeThreshold?t<0?this.next():this.prev():this.resumeAutoplay()};handlePointerCancel=()=>{this.isPointerDown=!1,this.isDragging=!1,this.resumeAutoplay()};handleClickCapture=e=>{this.isDragging&&=(e.preventDefault(),e.stopPropagation(),!1)};goTo=U(e=>{let t=this.getSlideCount();t!==0&&(this.activeIndex=(e%t+t)%t,this.updatePositions())},400);constructor(e={}){super(`div`,`slider`),this.slideClassName=e.slideClassName,this.autoplayInterval=e.autoplayInterval,this.autoplayRemaining=this.autoplayInterval??0,this.dragThreshold=e.dragThreshold??10,this.swipeThreshold=e.swipeThreshold??50,this.applyClassName(e.className),this.track=document.createElement(`ul`),this.track.classList.add(`slider__track`,`list-unstyled`),e.trackClassName&&this.track.classList.add(e.trackClassName),this.element.append(this.track),this.bindPointerEvents()}createSlide(e){let t=document.createElement(`li`);return t.classList.add(`slider__slide`),this.slideClassName&&t.classList.add(this.slideClassName),t.append(e),t}applyClassName(e){e&&this.element.classList.add(...e.split(` `))}updatePositions(){let e=this.getSlides(),t=e.length,n=Math.floor(t/2);for(let[r,i]of e.entries()){let e=r-this.activeIndex;e<-n&&(e+=t),e>n&&(e-=t),i.style.order=String(e),i.classList.remove(...K),i.classList.add(W[Math.abs(e)]??G)}}startAutoplay(e){this.clearTimer(),!(!this.autoplayInterval||this.get
668SlideCount()<=1)&&(this.autoplayStartTime=Date.now(),this.autoplayTimer=setTimeout(()=>{this.isPointerDown||this.next()},e))}clearTimer(){this.autoplayTimer&&=(clearTimeout(this.autoplayTimer),void 0)}stopAutoplay(){this.autoplayTimer&&(this.clearTimer(),this.autoplayRemaining-=Date.now()-this.autoplayStartTime,this.autoplayRemaining<0&&(this.autoplayRemaining=0))}resumeAutoplay(){this.autoplayInterval&&this.startAutoplay(this.autoplayRemaining)}resetAutoplay(){this.autoplayInterval&&(this.autoplayRemaining=this.autoplayInterval,this.startAutoplay(this.autoplayRemaining))}bindPointerEvents(){this.track.addEventListener(`pointerdown`,this.handlePointerDown),this.track.addEventListener(`pointermove`,this.handlePointerMove),this.track.addEventListener(`pointerup`,this.handlePointerUp),this.track.addEventListener(`pointercancel`,this.handlePointerCancel),this.track.addEventListener(`click`,this.handleClickCapture,{capture:!0})}addSlide(e){this.track.append(this.createSlide(e)),this.updatePositions()}addSlides(e){let t=document.createDocumentFragment();for(let n of e)t.append(this.createSlide(n));this.track.append(t),this.activeIndex=0,this.updatePositions(),this.resetAutoplay()}removeAllSlides(){this.stopAutoplay(),this.track.replaceChildren(),this.activeIndex=0}getSlides(){return[...this.track.children].filter(e=>e instanceof HTMLLIElement)}getSlideCount(){return this.track.children.length}getActiveIndex(){return this.activeIndex}next(){this.goTo(this.activeIndex+1),this.resetAutoplay()}prev(){this.goTo(this.activeIndex-1),this.resetAutoplay()}destroy(){this.stopAutoplay(),super.destroy()}},J=4e3,Y=class extends o{slider;constructor(){super(`section`,`section section-new-games`),this.element.innerHTML=` 669 <div class="container"> 670 <div class="section-header"> 671 <h2 class="section-header__title section-title">New Games</h2> 672 <div class="section-header__slider-controls"> 673 <button 674 class="slider__arrow slider__arrow--prev" 675 type="button" 676 aria-label="Previous slide" 677 > 678 ${N} 679 </button> 680 <button 681 class="slider__arrow slider__arrow--next" 682 type="button" 683 aria-label="Next slide" 684 > 685 ${P} 686 </button> 687 </div> 688 </div> 689 </div> 690 `,this.slider=new q({className:`slider-new-games`,trackClassName:`slider-new-games__track`,slideClassName:`slider-new-games__slide`,autoplayInterval:J});let e=this.query(`.container`);e&&(e.append(this.slider.element),this.bindControls(),this.loadGames())}bindControls(){let e=this.query(`.slider__arrow--prev`),t=this.query(`.slider__arrow--next`);e?.addEventListener(`click`,()=>this.slider.prev()),t?.addEventListener(`click`,()=>this.slider.next())}async loadGames(){let e=(await M()).filter(e=>e.featured);this.renderCards(e)}renderCards(e){let t=e.map(e=>new H({game:e,onClick:()=>{this.openGameDetails()}}).element);this.slider.addSlides(t)}async openGameDetails(){let[e,t]=await Promise.all([j(),A()]);new V({game:e,comments:t}).open()}},X=class extends o{developerCta=new ne;constructor(){super(`main`,`home-page`),this.element.append(new T().element,new Y().element,this.developerCta.element),this.loadLeaderboard()}async loadLeaderboard(){let e=new k(await w());this.element.insertBefore(e.element,this.developerCta.element)}};async function Z(){let e=await fetch(`/mock-data/categories.json`);if(!e.ok)throw Error(`Failed to load categories: ${e.status}`);return(await e.json()).data}var re=class extends o{constructor({title:e,subtitle:t}){super(`div`,`page-title container`),this.element.innerHTML=` 691 <h1 class="page-title__title">${e}</h1> 692 ${t?`<p class="page-title__subtitle">${t}</p>`:``} 693 `}},ie=class extends o{activeClass=`chip--active`;activeId;
693onChange;handleClick=e=>{let t=e.target;if(!(t instanceof HTMLElement))return;let n=t.closest(`.chip-group__chip`);if(!n)return;let r=n.dataset.id;r&&r!==this.activeId&&(this.setActive(r),this.onChange?.(r))};constructor({options:e,activeId:t,onChange:n,modifier:r}){super(`div`,`chip-group`),this.activeId=t,this.onChange=n,r&&this.element.classList.add(r),this.element.innerHTML=` 694 ${e.map(e=>` 695 <button 696 type="button" 697 class="chip-group__chip chip ${e.id===this.activeId?this.activeClass:``}" 698 data-id="${e.id}" 699 > 700 ${e.label} 701 </button> 702 `).join(``)} 703 `,this.element.addEventListener(`click`,this.handleClick)}setActive(e){this.activeId=e;for(let t of this.element.querySelectorAll(`.chip-group__chip`))t.classList.toggle(this.activeClass,t.dataset.id===e)}},ae=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 704<path d="M12 15L7 10H17L12 15Z" fill="currentColor"/> 705</svg> 706`,oe=`<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> 707<path d="M11.6664 3.5L5.25036 9.9162L2.33398 6.99975" stroke="currentColor" stroke-width="3" stroke-linecap="round"/> 708</svg> 709`,se=class extends o{options;onChange;activeId;isOpen=!1;triggerEl;listEl;valueEl;handleTriggerClick=()=>{this.isOpen?this.close():this.open()};handleOptionClick=e=>{let t=e.target;if(!(t instanceof HTMLElement))return;let n=t.closest(`.dropdown__option`);if(!n)return;let r=n.dataset.id;if(!r||r===this.activeId){this.close();return}this.activeId=r,this.updateValueLabel(),this.renderOptions(),this.close(),this.onChange?.(r)};handleOutsideClick=e=>{this.isOpen&&(e.target instanceof Node&&this.element.contains(e.target)||this.close())};handleKeydown=e=>{e.key===`Escape`&&this.isOpen&&this.close()};constructor({options:e,activeId:t,label:n=`Sort by`,onChange:r,modifier:i}){super(`div`,`dropdown`),this.options=e,this.activeId=t,this.onChange=r,i&&this.element.classList.add(i),this.element.innerHTML=` 710 <button type="button" class="dropdown__btn" aria-expanded="false"> 711 <span class="dropdown__label">${n}: <span class="dropdown__value"></span></span> 712 ${ae} 713 </button> 714 <ul class="dropdown__list list-unstyled"></ul> 715 `;let a=this.query(`.dropdown__btn`),o=this.query(`.dropdown__list`),s=this.query(`.dropdown__value`);if(!a||!o||!s)throw Error(`Required dropdown elements are missing from the DOM.`);this.triggerEl=a,this.listEl=o,this.valueEl=s,this.renderOptions(),this.updateValueLabel(),this.triggerEl.addEventListener(`click`,this.handleTriggerClick),this.listEl.addEventListener(`click`,this.handleOptionClick),document.addEventListener(`click`,this.handleOutsideClick),document.addEventListener(`keydown`,this.handleKeydown)}renderOptions(){this.listEl.innerHTML=this.options.map(e=>` 716 <li> 717 <button 718 type="button" 719 class="dropdown__option ${e.id===this.activeId?`dropdown__option--active`:``}" 720 data-id="${e.id}" 721 > 722 ${oe} ${e.label} 723 </button> 724 </li> 725 `).join(``)}updateValueLabel(){this.valueEl.textContent=this.options.find(e=>e.id===this.activeId)?.label??``}open(){this.isOpen=!0,this.triggerEl.setAttribute(`aria-expanded`,`true`),this.element.classList.add(`dropdown--open`)}close(){this.isOpen=!1,this.triggerEl.setAttribute(`aria-expanded`,`false`),this.element.classList.remove(`dropdown--open`)}destroy(){document.removeEventListener(`click`,this.handleOutsideClick),document.removeEventListener(`keydown`,this.handleKeydown),super.destroy()}},ce=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 726<path d="M14 18L8 12L14 6L15.4 7.4L10.8 12L15.4 16.6L14 18Z" fill="currentColor"/> 727</svg> 728`,le=`<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 729<path d="M12.6 12L8 7.4L9.4 6L15.4 12L9.4 18L8 16.6L12.6 12Z" fill="currentColor"/> 730</svg> 731`,ue=575.98,de=4,fe=3,pe=class extends o{totalPages;onChange;mediaQuery=matchMedia(`(max-width: ${B(ue)})`);currentPage;handleBreakpointChange=()=>{this.buildStructure(),this.updateState()};handleClick=e=>{let t=e.target;if(!(t instanceof Element))return;let n=t.closest(`button`);if(!n||n.disabled)return;let r=n.dataset.action;if(r===`prev`){this.goTo(this.currentPage-1);return}if(r===`next`){this.goTo(this.currentPage+1);return}let i=Number(n.dataset.page);Number.isSafeInteger(i)&&this.goTo(i)};constructor({totalPages:e,currentPage:t=1,onChange:n}){super(`nav`,`pagination`),this.totalPages=Math.max(1,Math.floor(e)),this.currentPage=this.normalizePage(t),this.onChange=n,this.element.setAttribute(`aria-label`,`Pagination`),this.buildStructure(),this.updateState(),this.element.addEventListener(`click`,this.handleClick),this.mediaQuery.addEventListener(`change`,this.handleBreakpointChange)}buildStructure(){let e=this.getVisiblePagesCount(),t=Array.from({length:e},()=>`<button type="button" class="pagination__page"></button>`).join(``);this.element.innerHTML=` 732 <button 733 type="button" 734 class="pagination__arrow" 735 data-action="prev" 736 aria-label="Previous page" 737 > 738 ${ce} 739 </button> 740 741 <div class="pagination__pages">${t}</div> 742 743 <button 744 type="button" 745 class="pagination__arrow" 746 data-action="next" 747 aria-label="Next page" 748 > 749 ${le} 750 </button> 751 `}updateState(){let e=this.getVisiblePageNumbers(),t=this.element.querySelector(`[data-action="prev"]`),n=this.element.querySelector(`[data-action="next"]`);t&&(t.disabled=this.currentPage===1),n&&(n.disabled=this.currentPage===this.totalPages);let r=this.element.querySelectorAll(`.pagination__page`);for(let[t,n]of r.entries()){let r=e[t];n.textContent=String(r),n.dataset.page=String(r);let i=r===this.currentPage;n.classList.toggle(`pagination__page--active`,i),n.ariaCurrent=i?`page`:void 0}}getVisiblePagesCount(){let e=this.mediaQuery.matches?fe:de;return Math.min(e,this.totalPages)}getVisiblePageNumbers(){let e=this.getVisiblePagesCount(),t=this.totalPages-e+1,n=this.currentPage-Math.floor(e/2);return n=Math.max(1,Math.min(n,t)),Array.from({length:e},(e,t)=>n+t)}goTo(e){let t=this.normalizePage(e);t!==this.currentPage&&(this.currentPage=t,this.updateState(),this.onChange?.(this.currentPage))}normalizePage(e){return Math.min(Math.max(Math.floor(e),1),this.totalPages)}destroy(){this.element.removeEventListener(`click`,this.handleClick),this.mediaQuery.removeEventListener(`change`,this.handleBreakpointChange),super.destroy()}},me=class extends o{constructor(e){super(`article`,`game-card`);let t=e.price===`Free`;this.element.innerHTML=` 752 <div class="game-card__inner"> 753 <img 754 class="game-card__img" 755 src="${e.cardImage}" 756 alt="${e.name}" 757 loading="lazy" 758 > 759 <div class="game-card__body"> 760 <div class="game-card__heading"> 761 <h3 class="game-card__title">${e.name}</h3> 762 <div class="game-card__category">${e.category}</div> 763 <div 764 class="game-card__price game-card__price--desktop${t?` game-card__price--free`:``}" 765 > 766 ${e.price} 767 </div> 768 </div> 769 <p class="game-card__description">
769${e.shortDescription}</p> 770 <div class="game-card__footer"> 771 <div class="game-card__meta"> 772 <div class="game-card__meta-item meta-item meta-item--rating"> 773 ${R} 774 <span class="meta-item__value">${e.rating}</span> 775 </div> 776 <div class="game-card__meta-item meta-item meta-item--likes"> 777 ${I} 778 <span class="meta-item__value" 779 >${D(e.likesCount)}</span 780 > 781 </div> 782 </div> 783 <div 784 class="game-card__price game-card__price--mobile${t?` game-card__price--free`:``}" 785 > 786 ${e.price} 787 </div> 788 <button 789 type="button" 790 class="game-card__details btn btn--medium btn--primary" 791 data-game-slug="${e.slug}" 792 > 793 Details 794 </button> 795 </div> 796 </div> 797 </div> 798 `}},Q=class extends o{onGameDetailsClick;handleClick=e=>{let t=e.target;if(!(t instanceof HTMLElement))return;let n=t.closest(`.game-card__details`);if(!n||!this.element.contains(n))return;let r=n.dataset.gameSlug;r&&this.onGameDetailsClick?.(r)};constructor({games:e,onGameDetailsClick:t}){super(`ul`,`game-grid list-unstyled`),this.onGameDetailsClick=t,this.element.addEventListener(`click`,this.handleClick),this.render(e)}render(e){if(this.element.replaceChildren(),e.length===0){let e=document.createElement(`li`);e.className=`game-grid__item game-grid__item--empty`;let t=document.createElement(`p`);t.className=`game-grid__empty`,t.textContent=`No games found.`,e.append(t),this.element.append(e);return}for(let t of e){let e=document.createElement(`li`);e.className=`game-grid__item`,e.append(new me(t).element),this.element.append(e)}}update(e){this.render(e)}destroy(){this.element.removeEventListener(`click`,this.handleClick),super.destroy()}},$=[{id:`rating-asc`,label:`Rating â`},{id:`rating-desc`,label:`Rating â`},{id:`name-asc`,label:`Name AâZ`},{id:`name-desc`,label:`Name ZâA`}],he=class extends o{constructor(e,t){super(`section`,`section-catalog`),this.element.innerHTML=` 799 <h2 class="sr-only">Game catalog</h2> 800 <div class="catalog container"> 801 <div class="catalog__controls"></div> 802 <div class="catalog__grid"></div> 803 <div class="catalog__pagination"></div> 804 </div> 805 `;let n=t.find(e=>e.isDefault),r=new ie({options:t.map(e=>({id:e.slug,label:e.label})),activeId:n?.slug??t[0]?.slug??``,modifier:`catalog__chip-group`}),i=new se({options:$,activeId:$[0].id,modifier:`catalog__sort`}),a=new pe({totalPages:Math.ceil(e.length/6),currentPage:1}),o=new Q({games:e.slice(0,6),onGameDetailsClick:async()=>{let[e,t]=await Promise.all([j(),A()]);new V({game:e,comments:t}).open()}});this.element.querySelector(`.catalog__controls`)?.append(r.element,i.element),this.element.querySelector(`.catalog__grid`)?.append(o.element),this.element.querySelector(`.catalog__pagination`)?.append(a.element)}},ge=class extends o{constructor(){super(`main`,`library-page`),this.element.append(new re({title:`Game Library`,subtitle:`Browse our collection of casual mini-games`}).element),this.loadLibrary()}async loadLibrary(){let[e,t]=await Promise.all([M(),Z()]);this.element.append(new he(e,t).element)}},_e=class{outlet;routes;current=void 0;listeners=[];constructor(e,t){this.outlet=e,this.routes=t}render(){let e=location.pathname,t=this.routes[e];this.current?.destroy(),this.current=t?new t:void 0,this.current?this.outlet.append(this.current.element):this.outlet.textContent=`404`;for(let t of this.listeners)t(e)}onRouteChange(e){this.listeners.push(e)}start(){addEventListener(`popstate`,()=>this.render()),document.addEventListener(`click`,e=>{let t=e.target;if(!(t instanceof HTMLElement))return;let n=t.closest(`a[data-link]`);n&&(e.preventDefault(),this.navigate(n.getAttribute(`href`)??`/`))}),this.render()}navigate(e){history.pushState(void 0,``,e),this.render(),window.scrollTo(0,0)}};function ve(){let e=document.createElement(`div`);e.className=`app`;let t=new C,n=new s,r=document.createElement(`div`);r.className=`app__outlet`,e.append(t.element,r,n.element),document.body.prepend(e);let i=new _e(r,{"/":X,"/library":ge});i.onRouteChange(e=>t.setActivePath(e)),i.start()}ve();
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.