/* GENERATED by bit-alpine/publish.sh -- do not edit.
   Source: ~/Developer/bit-alpine/index.html <style> block. */
/* Press Start 2P, inlined. Same face BCB uses, so the two front doors are
   the same product. It is INLINE rather than a file because Chrome blocks
   font fetches from file:// origins, and `open index.html` has to keep
   working — 12.5KB of woff2, 16.7KB base64. The site's CSP therefore
   needs `font-src 'self' data:`; fonts cannot execute, so that is a safe
   allowance and it is the same one img-src already makes. */
@font-face{font-family:'PixelDisplay';font-style:normal;font-weight:400;
  font-display:block;src:url(data:font/woff2;base64,d09GMgABAAAAADDgABAAAAAAo5QAADB/AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhYcgzwGYACEbAiBYgmaFhEICoKJUIHrZAuDRAABNgIkA4Z0BCAFhEoHhF4MgTEbyJFVB2LEHeDgkiZSjEQIGweAQH3FQFVvB3IcbeUK+A9wihJYG6OnUAshhGYwU8sJisSmGdGEOziHGsMYsqVz0we/TuoFtPqyNKPSs/LvM7A+RxU8I/hz29u6bf1GpfgMuypbQre8/NnueIYU2tGu8t/PwLaRP8nJC8/De9afm7QdQBnYK2GwylrveWn/ASjxj7d7G/DGv8iSwOPpzHIv//91ZvdJXyacUYBky5JBMrHs/PG3HQAyBmEBQ9xUe3rPQp9yi3a7av1PW0owvQNqnua7upM2RBvSkRGkoGRzFcCizKirnjbA5n/TqkoSmFHg2/2YkDYfj+6lQ6YnR/z/X6Pd9/58sTHZv5Y2LxYaPojNOQzifyuRUIiNVPGQKIWMnc2HqKbl9OQNku7+HRIDKi7EDAAwpLbQVvnRG1Km9RPNmZBlUBu6DF1G4sxB6CTBVaJOVAlANO6XalL/2qGBBkDOyK6z0dkk1dSsziok10KhipXPIfpR8AnCaTaJJa369XQGzB8w8v9nqlVaVQAIUOPINS6yfEvt7vkgkT1nMv9yE10G/l9dxa5CN8SGEwCBOgKiHCjKYKQ11OqhuhtUE9I80j+uc1jjOLrzkZYacbzRGWczb7K7LJrJzqXJJUlyOsb0DbRPSUh27Zdfhec7NNGQVhEQW0REQc2k9n+ytWtu+C8tYPf5ySPPistc5oIc2a14jGl1uk42W8spJBZUUMrQFJIvt0cAW75+9YSbKKioCGCtjqUoJXedJiTtjhX9sMcTKb72GtYwmzGgYMQSKxC4zzZggQHKPx2omLBeq+8AGlDt/3KDr0Kt73T37N6Rkmb/zn3IQ6eFxNSY8rMJJt6zkUFqyWGPARAsEfxRcMWaYKANhbnECQTeUkGjNeFafxmRob3p4Qq2mBgxMrH9cAqNSbRBdiKGgruqB5uFymLGoWCPiZmgnkHrMYpfM5qxmGYqhLCmAlIap10RDRoRR2OoeeNKBAH8tlDCVFOBUTszU0NT4Sa38ifSmEF9KrMxgjJVaQFq063STlKOIl5WvrIFN1j8NCrFYQga6lMA9alUFRYBKK/bBFoN/TpXVEQbFP7qptAw4ArYiZdpJLMkpnHbr5xU7ir3VdFcNW/NXwsqszo1rPWBp54T+AYNsxm4t9dIkGVxstGborlonprvrtqtYv4E1He8ew/Gb9/fbr+Nvw2/bsLjefIXZeDjAY8rH9d4bP9o06OMP/1bjQCQAOq4DjKbr5xMJoHk/21A5R8W8B97OM15FrKSVczmIH+xlv9ZzJ8s4hhHOMo8zmHAFjsOOOGOB5544U8AGkGChYoVL0GiJMkyZMqSLddy5rCCGyzhAXnKlKuptgYaaqSxllppra12Ouihl9766Ke/CpWqVBtmKddYxgl28i+72Mdu9nOdi9znErr1nGQdl3nIVY4zlWnc4RQXmMtdpjDSBmYyg1nMxxIjJqxZYMUGe9xwxgVX/PDGB18cCREpTLhoEQ4RJV2KVGlyxOmrSL4CJQoVK1VDfXXUVU8LTTXTXC3tddFRJ910dpiuBhtgoEGG6GmoGN2tYTVb2MpmKv8xvvNdGWg+Oj3V2van6O01OtSnvxn9EQzkSUujRPiFUf4xXcEGccb3ArD0C6ETS3SdeuJZU6tMiMfIZzwlI/32wIP5geyrhCYuEEK6DQgiOkuyqcVjS8nGIfjtOJn5pMkM+0TvoEfXyGvKRth86rVo9fE8eHz93M+DUlhrqhUCCtdEOmQmWWDax0qqxEG+nYJj5I/THvHZ0VAai/IBrEEavwMmIQS1IisEIY77oxAsZRs9kBnpEFTEuqeiO7p0pxI6kCaWzBYtGodFmTkUgDyjkAC1n2zSJijn9NDPjEDW8oqsUho3yMwNH9fV9GTwEnQA+ZYnWWqKFo50OV+x6RbtBpLBiGvUnR67gNBdojQ7Js1JEyo5S7eNMZ/uFwe/GGajI3uFx0BysRvfncdu3H6InmtpGxCvaZOMT1qZLLGvR2ZE9LKecGg2DztMe5KaWnFj3Y6yIak71OX4xYwxNU0RmJAATOyRNn6fPPJa6Tq0tGXQLpI04sL9xSxDNmmCSkAsihnpHNddYBCkJ2mw1TJsg5G5eSv8YphnPc2/WkTkyWhokMjVIvbSti9s0Q1zXweW+ufRqHFowy9tfY+pRIvFh8fsgrDY2SQcFqTpgGHLdc+gZLgSeKDBzUiqDsrGui+zuI8sV/NHbfhyTst3AWUUG5FGJBanBgbEgME4YvosWZiFvN8CxPUuSRD9hoh+fwfE7aFNSKNtz7Du0KNfd/TpZBOHSJr+E40SQhi4PCkxl8UPlkrulmt2QdyyXLcL0URlEtnCZLKVMbKNKWQ7c5EdzE12Mg/ZxbzjWSPm35SuydK2F1SkKxslXaO5Tkk1/mhHK2nGH/+g3m0PrYKWnnQP3U01oEmCSSTJZKIzRlJMIQZzEZO5SZp5SIZ5G7ZBvV5J/vTI6AQd6YNLqLQFle2yb1UwzLeZb9FrigYYBFuzLum2BMbwjEoZgZSsr2uTuiq2ikLrI385TFSXDRSuW6NicAO3XfUvQ6PBaiRrFAHt9wn1bwDA8IHcLpXh9Ul+v9QMagxGvp8Q/JfIsm6qybFs9JkgiYNvb900RYJqoKIKoW+Powv54z4RxxP8vgqw6dd7bRrDtL6Ws2wZQl1F4hgzrtj96vSK9lEuCFDn1ugu2nlUMveRGcBRASfe4z75hv8qaaOa+ksyR7dfcB616RHIOtcVSj+SiX2polfj58dVJBEPhbJIhzzSHUuqqOjRfHkfVRKAzJR+uq10ekSfknFHZctGJBnxnaPsgMX45IqRqEivkJmaaWM0KSNyn9mm8nCw7JjDhllQTLJf6tZIspujh220H2FwsKLrsOCkLEPfHU77CrVotZIa14HKUoy5DHXOwinPFzFwfVsWU+Libu8OVhCFilcB36mLZd7fN+IHY6blPUeEX1cng0cdqlIYXrNcO+/9ppvq+KW5jNCcn/aGYas98KkDw3Y7ayu42Qpzq89pZKJiYZKIHFQXpaZYyem6r8bu3JZ+ytAUDzOWNYX6/Z9i4L6gDfiqj6/ltko4SkEHrGQ0jlbbHPZYTa8FLamlkZw83ZdZ3+hegz09GrdTtdae7D96wBRQd2xVLxMHDZt3cmgrqCNBhX7Wk8G8w2Ytj/FQ77QjpgGGRI8yIse2EehxRuTEIDCiJxmRU9sI9DSj08+YrwA2QM/GiJy7iUDPx4hceBFA9GKMyKWbCPRyjNQV1VSwqxCRa9sIdMKITAeBMZ0xIvNtBLpgpJf46IBdx5jcuIlAb8ZI3yJA6O0YkTs3EejdGJ28Z6CzkPo+OMZ+jT+ge9XD2ceI8slHBrGSxwmKPUkQeVpCVzp9Fu/S7+Jd/T3BG/3BupEfE0R+ShD5uQTnRn+JO/TXuEN/izv0d4uQ5wkiLxJEXpbQI/RVvEdfx3v0TbxH31qEvEsQeZ+gcz7YX71MurRu4dr0LFdyav3zefxzbosIYjbjAMATADkK8hOcKuDyHTABEahzYJ5TVPg/YDlGUaFMc0K05lhDImGLnquSqEpuky1LuBs5s6oyagy8jIokJoIKKAV6f/Vx5bQfe3fRrnUDxx0EIHWXvJJGpqCaUGEqs0F0cGip9cQdvWKqA9RdCYSGa0iDqM+jNth2sGl40HhKpvI9s3rvafbkL8thm2nbycxCzh/cMTk9/+h7m6ZZO/8YEcQQqGfavcz2/unjYAf9k8G2syiLyw8e/DczsH0w2geCGALknv0gA6tKGaDYr+vw7Whp7p7nA2Rj/kD/kKPfMyxsyI2W3pnbYNOTFFDfDjaU8O1NB/LvPW0a8smTbT9NNk19P6U0eKV/MNXTmBOHROTsiYUgM/Swe4tMZJK/ykyWG6amfU9SAGgRIQhFTv734EnGonHkJHm7fhh66xHBAqCC6j3rTZ094JL4cP5kCRECFkyGn+F50/rnZYmCS9DZBYOFQJgzoUWnw1cnjiVvuAZrDNqZqii2Oi5DOQtyTV8G/UgW8BKWvqoqJn38jsH5ibcGqzFlOJ4TPSeu4HwmjXWDDU58OyQdWuOmtZzueF6kSTUPIFGjoIzocsCxwn2gzmucT71M85uG+BVw3AyEuppHVtJqT/yvwbfJDiMKiQbDZw/B8rar2G4lybDuddDA0U7OtwrnO6EmIhrWGlK7+3CWcBNSGr0rayU6NxgxRIXsehw3KNUzIC2DTBIRFrq1QRS9lhGrEToT1YU5VAsLa6/FQuftxLwJK0o/1wVYgAvQovEdaRtE6IvoBOQwOrUkMkDGNEveQVThTJG0s81xU5GgvxQjCSY8pfwGtuj7B5yV5cA5Vz0mxBDmoM3si79gKmXaZwZ6CaTaOlITCgLcyvvoAMNUTqgTfHBKptQrYG6219OCQ9YY2Np9xm/g5FwUS2hWIVI80s4CA9rRNjvEwt5L53pggCd6GRfnrAQ9TcfEDl8Lj+06arGFErZhPWTYvyqhr47FbRIOxt06JEY0RG1hUWWumhX77cEFDUIrG0ru4JnCtcFiTrr2vsDFHcvWPrBPiJKEhqcdCFDFvaMNi6ayUWXAo78nRsulVANJDyfEJIGullDYOjPG3ijsqI5o/rCc4vmC1zWL0b+HHOfmT1r6Vr8zj6oWp9znvqFoBkO0mFyDIemR3AJUwbfgzVmY9JKCZwm1NrLLsADjoFPmJZWoCEHibb8iTkZz4yWDd6bCG8DAM6it/GTVCdoFoAoWaEcsS4GcNMCuWdaeC9HObBLDKupuwiaRnudkM+p1/KhVB6lG1YLzNTehfohjZsC1Pko52yZqf6aHeRNw8S4KSbLGBbeclZhQxFyLSLpCARYExZ25lDU63AFjmn/KWopYMsnTwBy4A/PKlZi7w0owxNjSNslLrb1GWOv2sy1KrsnUHhWvDC9RUO1KRZjIKcd4ZHdvZEh8ZYn4AmGsMpBKEosBsXayurhaTLpSWEYjzYUiFvJhuMqO57EAb6zpqPMm0oZzLeEIqBsGZrW/8ECLTvtAVocDiVgi0z5a8hIsiC+DzmlzKgQkOIQSvMbcdfzGuEd3z3FF5T38ahGAAvM1s/w/Lx9jo6i1TiyK7MPw0sICwKiosWGGa3bnoMjIWnmGQ13O4TZ1ysDyuRQb4ZKBIwLdT1q7d9rBT/Ya7IUZaZsKVVHvIKoVOk6ouT0IodQV1bpiZ4kzHJpWrOjBLdgit3eI0zlE7rB8+ESxyxxTvoycsym4Bbd1357UpCSVSVW5y198yhad+/rFH2NWYPwNGFba7eDVYZ2Be7MyRu0F3FN+S9fQsnOpLPbEbIxv2VciCR7g0g8QDofzSlw9cfTorAuf9cmyHguuA6sKPQYtiaTllpOtAgCXkuQ18ECXzTBwm+hCL4wYDO0XTCct22/k4BXb8EDHHX5aHuOBhzx4H8wCjeatJvICA8oufImp5Qv7nmDgC7Mg87GV+XSA8DeaFv8A5+3A7oJaBgYKxA5Af7yVb2htSItS8biWZE9sxch9mK8yaiF07+IW5bsMjN5T3dgJlwjCjXCIeuudNtQ6aefQFXjkuBgIEsKa2wLH12RdnWspBrgL6DrypG/VoS3ATlca8CwkT/FYQ6/9RYUQ023PefxUnS2uwfXlHwKiFRL+tMsm+jcacqTxmuf8DnPOb/ZFnQYS5wNtcIpTWATNT7ay4fLk1Gsfa2f8+gWcdBGlle5AEhRIbkojSZCkSRAgkuRDs66QHB369a8M4UOC8gn264/6kuh4mF83ulYokuJ8jsQc4JW/bDX478uuw8a+Z1oBNeSH+nCSkoiIKLweD45LzfxpgKZRUt1LcbeIr7C0FKLteodgB486NNDJgtI5PcVTpsq3qyaBlhD79vf5uqtYzF7wEFV/LgKN2eyCgwqtH+QLlkJTMmVcZZ/RYVASesV6RO9dUNlloFfOeXQZSlZK55S595WYfXrYBVgyeSSIWgnxjPdYBEDUl51FUCa27BKkOaEtg5lRBzMTyDuCmetRxtTOWTlup8PInC6Ngp6QIs9EUyNXjidK0aZbXkd/RBS15E70ae6S1s4mmN51jqGUC40U/NmJPGC6uTjEcA+SMbD/YRkpSp01MteqZ/WAYYMhco62LJyqDuDRflmsIgLtjmxXT+REi03WOSkFhdeAs5YtkHR9GQuOFylgKPHiwedqrtBNThiAFwVl264Yq6Hrg24EKpfbw4bZymSDYjqx3/S1ECQWhhwMXUs4yROlWJZ3kRym8LYtbc1TmWDjHI9mea/twl5tajYX7kUCthBXfEEqkQfFfNdARKqGi34IkMcbFvvBcPo4C2MahUR97HIrglhybIR53j6mXLIG4xIkss+uL0m0X0v+K9/pWjUA5l6kVVa9lCqRR+21Plkg9QfBQufoz6kB4vB1V8rWiZdjMfbIx7zC+QrZs29CfBKgwr0qCkF2+DHCiqEm8jWjsQ4h4sWLiO8t35o3euNDw8mHzGMWGIHcEpn91/UY2z/HjKumpkOUF6cJCF4p6jDuwhWV2r9lIU2KQ1Fyh6+S8Ib40IBwPTdnVua/px3EAYbGJp9d+M7Eq1sb+1slyOh+JjGHcC8ug8mJjz1SEwS6ptww60SVZpTVFA5hMRO6slqxxiti96pwPykeEAHNma2/A5XNEEtiv63Em99ZPKYQ0pyjC/hJ9soROx3GA4pgc9kAIFycCtIIenoNGzXasryp8NSNfWltUrzuLnv+yZAzms/HZshG701+gfOF6I9FO+xuphQXrZ5vBOISuBFe0YOgUT5sUTvjInolf0uyobCfZfXWqndEjTyouQYuO8E1aSufPGyqjN+VZZBByeB5nu58UDmHyiURAXSuraNs2OdyDgjEczOS0tpJFoU6KgQbvnKSF40xXVgPTuq+eF+uKUmbuf5st4jxfAgjFyawnrSOkZPQQncfCZHzrJYtwCsfiUhrf6bSDioX2pSt/pF1itrnnqFo1FQhEu4Hll4vrr1uRfEqiPY9J/lWBJepKi5DLEODCGuER5j89YR1EEfbHB14u8euFJfOurqrdO/vPwlDM0OFPLzVOuY1KHwxprHv7RGlGRydVB6e6mm5F01IIFAoocqNfuVaf0GEUG1PgJUg+/qsAZ+zF5jVO4a93qB6KZmT1zS2/f2qE1yZuiL8/t/J27Wxw0qXEvEdQezDlfLV/gWPKWAiK6NPfOVOoiGS8y4YoXKFhJDamzE6O6wbYOPIjf76W2joB+/+EUDX7+hjc5dno1rYwV31mqH30N+qj67yHDeAurLnueH88Hxu2XFbN2JmJDHBrcCjRkjaZvia3EFn+CD48twoHEhCSluPyvtR1+qI9HYfgN5mzAXvaO/QZN8NwMI9u9NlFS1/XLQ2RpR8S3H2eGcZz7KH7c1poisHtG6W/Js7Jgt3jIPPopYY43gzQVOLtflCHF268BiXfyBaC96n6xit1//5pLUoVmSve/Njrk1XgOwqHKRwkNRuPkdHnAmqYWN2BmEqpLXCW0CAyNRopRi9AIoZlXRuCRZHv+plLnmLLpGZeKUzwUWXMcj0Uxov6vqwkVsiMqpkqfTIMT50quW1XANteM1Z5ZCT9U1u8TnFPtjSzyMebCycKODBaPQ3wZX/1JkWuo8Kh9l4/9pJMAx5E8l9HFpdyYadxhB1BvTXDqemXjOZvPT6anlzfo6aPisrzTgXjexDR4EkR5SL8SyLbo9z8cr/pjGCxqmxNECE65/nTuMF1X2l4SpIhJUrknN533dEqCW+83vDIW6JKvi0E1g1scyl8GfCnhf6yksy+/DbdlPPhKga+dZygmKEx1V2G8ElX+KdHD0h26sddscLQjRFNL4eHXzci3tY/JJr7Vn5B/bbHeVRVLbxUKbGWTZ3+QvRwQ1zz/vwg3vP3h/aXr32DaR1J842ayq+Hluoy1pZbZcUvXaTW2Kh+YRxz1Fjl3d98IiR09X0v5/28xui+H9UvpLid83/jr/H/39nS0qQv1uH/s9/Pj+LMhQFdAwKonxoJMtpmMEb5Zc1AVzXWWx2kU+6y9GhoDL/YFgVbjC9n1sF/yDBFFas55taL5935hE7ndSbpUOjp9yHC8KrYEBAKejGNq351nC/rtfFZrwzmC/8pLtHpuc9tQnT+7nb9V9MqOqzdph39Ky78+lcvrz7XTMM6LSCjhsrTituCpKIm/BwIsoSw9F14/qyep3aZrfrWgHKHltcysU+6R6R+5idaJ1w4X4myffJQ+vBS/EM61X2viC9n0lbutpxoevSP2xEaTFudhIibO8AL6tzSZtMZ1yk2nG9l86hxfqEtdIbYJe/cCG3KjCenzNfiP+l8iHU1ZNBIOf78tj98MJBrn6wq1uyP8uE8IHkFgO3ZuvdfEje3buToaWDjgSv1MFx2Eb2lltXlY3JeJFIzdi8APgeGex+0RyNZHq9UJ8A5a0COK7DPcSirXysYy9TO+n0oqvox/PkjG7jdM8fINzRGKTk28Qd/y431tU2Ydf1MVkEuwRwwZPufQQ/FqbrDc7fz8zPL+DHFGeXP/vyswZ9eSc84j75+ONvQyrosCD1g8NCbZjIKfJgIpGUSmuLZLbq0mgI1Qmrxw0kq4nqz2Lab5gPAU7EQ6JIKoNBs+hQjs1CaelsW0c6FiEC1UBFfX7stXz6J340I5kSSxqD0ghRQEqohRzUSnJ9yBl9D9H7JT4QfI7ZbzvS9RHyxf3izoTWMTISlFRSuqoX8qz+DlrQfy6FVWVOXeeLAiLnqff5tXnux/E17kIVP46GJi75UKLJD0AT6TDKSIgxRvZO2u5Du6gWgTplntATcZ2AExM8orxjwzmmaI37GpZyOSbUCUaYJZJIKq4667kwZuM4TPoeQmzUgFRdQif02Eqa0NjPnTJPQcaQrltzm0KUZYCGPe1qW+Ea2cekDy9puOcNDWqiJu9LUfatD64Kk87eRZlwqNsbZJ+QTpAJvuBeNWOypipHf8WVSHhOzo5WbN0ZuJ0sewCtoqu1e1MJE0KvPvcotYPDQicZ0wH0Ehs3Ru9Bvs8GKNkvWWYx6QJ2N5KV2amNFogHsDnIuNC2DDc55IyM6qUQjRcVlFoqn1TD+1LY0jWLkP0wUSgUEgHBMmHy5D461z1ArRf/pJsTqkviCT0lxwScMmmTmIVKrW0qfKqutASLXISIb8hNGSJ7MtRiKPEe4yU3LyxAa0ZEdzAt3KNtupvKLMfQvACAmrC7XJ/46nSNj1yFJ8DCWSwQV1a77BfTfQEMm2m2Hhbzg8MnXcJuRkditpUFAHorAKyMVSirH3c/t12tqVPuE6O3QI9XOIm3gl6oj0WdSauyuBvPpGbUwifzXd9Bg2aPe2kTUNa+W3wJTUVP+DsuvLldRnowyAGD7dfylGPFRkF1PDLXBnHlLlQCqaSSvSHz69UOKFNySqODt5Tn+/CAAgViRgfIQlmLUJs1Ivd+esCQYBkOeOoOEIZYvqbOsV2vJhFXq7y6e5E4nyzs9nXT4uyO+zmo0JtKSIQ5rEW4X6bSV00zmyyVikJK9LgzU+JqbFrOmJG2irALK9a7CFMAtXsETxOg3OZqLmgsvEMJfWxeOE8FSoQgHLhYAy2Sc53F5oDvAcMczjH9m/LTgWXSMB3L2tqtWbXab0bZcSPRcKs3u5oXpzpqu1pkhoW+2mzVB0dRtDCMGmDLXVyxV+rR+kiCWlgHT9w6SrF8LIE74vuU+Qfwyeei+NmnY2pyS/L046knOLnzUaFC6IQxSUm2jF/T8G2gJe/n6LGHibi4J92N5r1L7BNQJojju8YjCuVgf4YcGHCp8aCr4+J2YfETFFZVxeJnNiwgalLIZKL7AlguzDTN/4Z4C3AmHxJqSQe6Dbng7osfMguBAmMlq/LxlNYrsVTYzEHOvO3NMuuU8Rvw9KkofvI8NYfR0TGn+5m/+thMYgqeME8qh1RPH8NjpTngUiy0dlQ6vgc6FjSnT6bhkiashd5gfD+3rMP1OMNaIF9c66xWy28aw1p8QiakhgyLUN9AI7CI4qJEs7XavvlDB3cryZpiAoMMOrxs5Zm4TI0fK1MuvieHgV143KrK3T2t8kwrB5RawIWqwhM/IKAZi0NGw4NS9jS40kRcdfO2Ng4baM9tncmKLr74wqs4DzRwxc5e+aPfR4PEWfq3u7GMKtURtdbKs6D9GHJeyMB0FDQIVTEqzLLFEj4SVjf8qa1aH40RJoS3NFFttEZOAmdBOU5bNh5Ofi43PgQBgaLHOuU84WNA6+LeNFZKq5Ko61ax/w5fWZaRfvsJ0PfYm0UQUDQSahinCT1caZmAwb00zNtQ5TU0RRAnHNkipQnlyrhv1YHVid9+RAKf8PH7GRHIOVos8/52gUVSO0R+pyKQKwT5UCe2uUK6Wrs3YWkCTGuxc2BQLpi22fn5PiRVNB1KWJwnNAvnG5ok0w0UoXKDlAgcXFWjwAEWWpQclzlCdXUy4aMoiAnhefLMDYSw2ImayMRZ51AfZ+KhlsqR2hIQhZ0Mh7uk/1qLSJbCJgJVrQ4OabpqazJFNBEt0x3joe6G43BRaEEk33MVyXfSRw2SJxfFF/D6UnS+xtASDp/V4owxHTApyA+brJr3IDlfTHuR1McktExIp4FtggADw5af1MLw5CVNJJqlNgS0mo5tXZWaNk9pVduCK1J4fo/yYw5hJ0/Oxuzt+SYrLPQNZp2YeCCpEnBr4MEAK/WMQWBN1/5IzUmZB7LEFtaLu2lfEOZPOppVbTctiPW+mU7oHMnxdjdFQTPv0RkLssZWungLw1UKnnITmD6XukcUgx5SU7m8SA9mBF5IhqBClZXD1mxHgxsl4vQOpQ54A0GUy8OtKJROa3e+Hn6YNgPkrcBFwvfbq6vH7TZQlQg2dLwSwkqbwijZgBKLhUgkt3VxBX+Fh+k+HaO8WtRNawR4ZuR3cfqPMEx33H1jt1VYuE0PikV0eb8OFiasgqGHcgNeLIV99sV369uN3q8zr5V2QBdydmCG2xwe0ztnd1t1FBSu7wetLnbuLpyoM2WfaP/tbLA1fl+TE0ySyejbVsX5xzEYT3dHXcwukfDq/anxUwmOElwmFhJqes9os+IML7u4m0S+rTzsceYVC1lrfrf0uxc5LJQEuX4MRomt6NZh6y42WWEh2Z1dKrMjeU/wCldWZkskh1xLyijN/1jifQeEVMWc+A07gMXUZSUQuT14LfKcT1ajzWlXJFtAtr8Two2TEgciYzzskL+oKOMSXYfJSiQVJraPSDUoer2QtwZGUjQJrmpOozW+4E+VzrlSwVH2ONJKM8wcSe2PMBrV2KYQcW9qmcd2YP2bj9xKVoSWRjVvg7dFsew5H1hrDGhxpIJ6tWPnz0ue84HW5Xmf+XyWxQTs6atYB68OJrUnllE8HUAkikFRnEsIQnCitYJrgcWaRzlE6mw0oVeRyoTQ2Fjyxp6/RJq/h17zjWOrYTy2cBOIHr1VCqw0MxmRMSRXIAYhDhHxlQuC5SVSaFDLzlXA5srWeRkygI6JmTeF+5PTIxlQgO4cx2JBnNrOa2KWTBDiuZwlQPu/n9c/nAf/bTQVRfbDqEjlMDvVEqtd1Hl3PB6opLtNoU4eE3pSCyaATXvKlwfg4Vks/fQY3P3vafmzMceAoqCxUge8APpGQIiUtpAB3th1T16/SwpJLAPldDO021c47xspyJgIGJBfQhdfLENADCq4anHU6N6FjWW15nrkOByMLEvDEuSJNi5keB7b5ClBrAdvPP1JTuyDK5Aqhk2/aWZ6QxdizayeMH3E0g26h1jDR2S1KeXboq7pNYwbsSCF334alHU3HG6nv9LsWtZ3ozklpbsq3fGEiMpeAtXax16az2uT9yI2pMmvX7vo4Z9CBgv39rp31+O8WZxR5PExwlQQdZ1WEuA8nR12zu2+jZfkTtpE4meYmOsPH9iJFtgSOg143E0/NKHZfwQXdJiDklJeWUnhnKK9zUeJvAYcs4eDoHcy4Ro+n6XOsVCYSq7TNUkRJhr6I/PzGhbZdiWNwA88qAvZC+q2qfXVcxsvOtybxL14fdjjOb/tv19INwDQRw40+KdFuPUdfP/6HyCEG3SeJBGpOUW7CFzMlvQ2XEoWkw2d68dyXxD1kpdKWNf7Biw4O6tPFLF/yEyW7DfKtIu//ps+9UfK41y70YrpBthfP7lPI1rUwZyM+yu6e3e/xtNQoPpXL+FWWw5C9CNPsIqQgBpRv6wU3KSmO5+vQcciFaj0hjom4LSR7cFJpWQFg0Q0BcapoGkVtieQPL7JxEETVKZ6g9TWcLjYN/BmSCicyqCo4PrO1Tfl/hBGN2Xa47tL9wGSva1oE3CoIU0W78HfXddIlsrRUUhVed+UBFtPnKc/7FZlnAqkstY2ofN2/viKIMzoYAiSGBVLBDe8G2Wq0Rpyh/RXpYY9CbIJ6N75502w9rfYQBH8DWQCU6bYOJOHlSpbGyLt+7FTNWWbCFL7kKie6lA4jVQUsUpYIhsLwI1JZ63oBuGTDUWO6+kFFRaFYlmwxQQZ9MFkb6INV5sy02kRWMgTPkKmfIPwSjNz8boBFmre1pcRzALrt65avNa03n1Hj/Fr54niM7rwDDpQ408IN1iovGGCPXgUFE7qw6r9WCiYD+VQ6bFTnhA+5dM15A6q0rrBflO/PvErGqqc5UGJlI/P5HBpDWq625vpJsH7T4xBNub1D/6aAGGu1R/bnRnz71duEwLsJxruLK9TZsG2NErkkoZD7RZQn5AdpWRWHqJ2pDqIo58LmS3M+2PYNH2Kz/SWixAoWBRZCR8c5Fl/hoK4VHqByiHDoabYVDF30qDtmzZP7twPQ799TOOpv9kqQz88mD2NAS6VinHWtnLZzMzM2x+Yj2a/bCCw/QrOplnQw8amCddb+O0f4ymnCU+o6Us0UqOt6vaeqp7KoSovuMU4bNj/TOPrD4lDvG8sgU5xIQ/3uNPye2+ur2QukhCkmDJMmmAVssN6MtGaXNsfiVhR6GPIg/QYu37Mk3QztUvXXvBqmmWD19K8/pFmae4z68Neq1UrDMPdhNBF4hj3uB6XJiELkY2wJQpM2QGvbMq/h22Ij11+cLg2e+5AAiwF58bDofZv14qF8dbkTjxc9I7z0HeJXRtfJEY5MnqXz5s9+76uQ8CXvC88TFCuu7rVQhWsfRNr0mEG3wGIsJ2MvDdB98FfMZFJWUZUAoLgqjDAHyR2viDfd1oRgje7fGMW9wtDuAHnZslNRhLRYvdky/rZ5WvdTsrQUsMlmffCh+k/HFb+LCoZJiGWiTitLq5piEzRdyplalnObNyFA1hQNPyj/Gn4MIJlzdcm4bEHUwtGHSfMIdFH1qslz4MFgJ1dlfEwPPHQHl4qIGqeChc5SluSRiVQ3ilL6eKMrCQwaUChl0J5AtgzbdElU8VHl4t7Gp482doPJ8k/GhLEVXhMdko1a2WfyxbO7dBYI7mBCMyFvM4Li4/jCcXUD1uWHgEsqXpSk/3X5VWSiAQ0yEBklw6rmZNcVPXUNL9AtEb41YqSqfv+CwS+mwpyplJnLBOcEu/w4aW9QFLRIIcFMiwXTUh+7QWlpDlG1RCc3yflAnsJ/rXAej6XUXRy7YNR+o5SZyTCl6JTPFQiUFnAKBXL7Wwf5OnL6JAkOi7DC8nz9K+ETfrrcCcLez4eFEKUo6BnclEfV3glKkxjEw+da9TfJkDMxkbUPSoNyTyhV1QwYXo/TYgeDyd56aPV5YkrbKwO8tUAldyYV+7kjozlkhgYChGxQuUKpNIwzhN6VCgmzO5Nl7LIg+1MRS7v1g4qufy2chyj2rXK7x02Di/ouyrnHEOWauFcCSoovyWgpgm74sflHTYOJd4PXG6VRZTAglFgDkChRXACyGuWnJa6oDHGS/5WI2L6NQkMknpP5QV151YbLFhz0CX0Ce9yj0BJIL9SjiJ2Z/Um/qK0pg1QXylItO83MIjH4b74yYyslFnyMCsPwsKAS1BpF3JDxIn0NT7RGRK5oYu3kJOSMsMJY2+O+7VLjfprC3t49SO5uK6ewz8I83uBL74Wi776Um8Z+FLqLvqwGb/qxlbKarnFLWfiKGwaKVWuUB8oLcq0me7e78OvFHr/68EnsTevAK8YE61krjZUUE6eB+i0eZ1e1oUIbxvmvGut6jjI3OQKgst9OdKnaCuOdIB001DHzBjtUMqO3relgrOX9N5pivxGWUrGb6hcZMG/S7afqtZHD7sT4r83vLfmY+e6TMPM5enM67L+Gh06pXxhs2v0TuEjna4KfKNrZ0ivyETh7PlwjyQ/IO9kGdXdTIM7mLb2Hqv9hOJfYUJtiOXXxKWvdhxXTtuPuWfTbbWR6i8+bCC4xLmKBm4jX8S80mihIACo9hOsu+YJvazUJsxeMHD4WJt6fuhFaPUQKGJlMESM6mgBXhOnXAAhR6PzQLBuWSf0liomdH6ziLc3At3qBbZvcOQueueNywPJjTTQdnWbGuBP1kcSy84M44EsZuwA9Fq/fFWrVKcK7doLdhox+P8QEuyCqwKHFRAmG+5wecXAEuBN9brhCtLb2q3BzZ+3fdWUCrEnPmOjL62viFfc0XoPgYMZD3R+vD+PY+iVH2flbY9VJEX+Q/ri8fFp38bT02V8VMYRAnA9OJ/pbhrv+Hn55E9/DdDfPzwAv9hIUEn6voovHjSvHhN6krtr8Z2ui3LOAWgzUabzIJKdW6QL4WDBK6wm225h0brcVYf2t/YdonATC7uFuj/wAtEN0Op5h0wQ5XiyTqWLySox+/ReXLa45eDI5TDJ4wO/3O3AjaCO98nWUm0lJwaqWu0JLjHx0XPQDdSOcmWHzL0ouvz88yeGqBSd8BCNW6w5AZwwHm8OnJY4DWenui51gBjg5ivWMFmVNIzUXHn7Adx9HxMWY+uMPuACur9PQoAQRkKejNPw7u5r5Wd1lOZFjB+v89M1JJ2XNO6/+HxPp4fzaYgQ2qCxTTnzp1Ps/OLhwZSLRz4lbWZdCJXxhAto3efl05Bc9I/OJT591d+ZP2Nr6/UlnWI9mXt6/jn3/uquf94sPZzTeBkZwP1I3dR3GR7zPG3wmObXPKf5/llYMrnb/+AgkiWWV9nMmq2cNIK4vDtwN/N/feRgvdST59fuxOnUNxV0ztK+nJwNi9JKupjSWm3Y28kpbaCEiZN79dQBUYzYfA131g/Bs0yc3FgONF/YJRqVL3CZ/XlCYGMB8kQWQxhzY/RrsUyAyMPMYhOzZQWH2GTzWDhhIzKnVCWgMKKyIV+GP6yHSkzEn90/paqkAvUvluSv1fr9tlHPs96N2W94kRhbDZekLx4LYOhoORBLL/JUhPeh5V9XUyk710b617RJSrVl/L87Je9Xkk49oRqZwykyqo8xpePU2ugJuVQS9oYgAATw6G9M8Vo455OlKv4B8D0cn6H08arn/rz5AQ3Y/hoNBioEwEClXQgRMSv2HyujMz5/67vUA1guvqrO8TzfdDTVhNX7P4OuMq5ffHPsrR75Xu+cNa6bvDt+76azJ2B6GLZL63wmSzDey9ZNGRqeJXcSGPJSXd8OHf+z1ELy+4C++I5Of6um0+lklwg8IYMtISxQKNDQNGC33UQQwJJuVMRgBe6KNTQk+PJ6SMGex0MqeZYOGYhRNWTEmzZDJiKk2PZ0DHqoEK8ZIEv86YN1NkhP3a7Ig3EG232eP/v9DdJdvPrK1NHAIF0NNlhjFToapEKSBmI10lV3lfq0NpvpapCsa/XXj0ayOAm1tiKqRVrLd6G1c/9Vk61YS42UysZiguHVtxbrb4ChZqh116Odf4ZKWaOJQbuGlsSZWvvrpavORblQZdQ9zAic5QidtdYuhiowzDi0q53BAFyrQqQYGtV6cnOD6MHGtKtyswuNshhUNOvpqC+2yw/KnaDzoIx5hx5Y+d3xBERBQSXEGU7RyQY628hsQoXpItwzInR1mrOcI1KUaDHOc4GLXCJWnPioBrO78YNf5grdXWMOm9hMslcfv3K9dBmuc4Mebn7Sy8wcL8hVoufHuti9uNnXYkp1bS33nBoGmO/3z0A11VJbHbeoUKVapbrqqR8DDTQ0RCNDDTfCMEvQbaGx1zTRVDNTaK6FkUYzhlEfCfPU2njJXto6zBEWsBAXXHH7EBn+ES//p4tRTGLBfj7yic/YyXeMSfjhwDoMLMOEE0GWYsSaP84UaaeDPAVssGUbW3EUS9awloMc4gTb2cFOdnFcrIznABZibQJ/iw32vGU3GoEC+IOOlostlmIXe4JZmcxEpjGV6YyjvacUxkEcxYkZPOQ2Myl2lwfo/Y8d3VleHjt8+Or92N3bO0w+u392+bK7Qyeuxq/d8rjrXR77+73h6eTVq1dudE6nLzN9/PbVpw+vp+EDiOZO/2+VzD36rxNpTqf5h/c5cj3wVdcZOvQL/570hejrBdJf6rD56wL34Pvd7XpuDDnouo9mns/0ZuzMOS/zNHyZM9eJifZEUt6bf/B/y/Poc/9zF8DgBQkX8K2G5OoyhiU1/P6EJ/9yXiULZp7yx/McxNbKfNt3tcPlET6aSZ4DU+WpHW4WyP2i/9+s2JdNyXPmV2UxgWEXAAA=) format('woff2')}
/* ===========================================================================
   BIT ALPINE — B3B canon, "Clean Card" language lifted from Bit Lax.
   Apple-native font stack only: no CDN, so it renders instantly offline and
   inside a Capacitor shell later. Warm off-white ground, white cards,
   near-black ink, one accent, soft layered shadows, pill buttons.
   =========================================================================== */
:root{
  --bg:#f1f3ef; --bg-2:#e7eae4; --surface:#ffffff;
  --ink:#16181c; --ink-2:#5b626a; --hair:#e4e7e1;
  --accent:#0b4f8f;            /* alpine blue — gold is reserved for the mark */
  --on-accent:#ffffff;
  --gold:#ffd700;
  --font-display:'Futura','Avenir Next Condensed','Trebuchet MS',sans-serif;
  --font-body:'Avenir Next','Avenir','Segoe UI',sans-serif;
  /* ---- Tecmo front door. Lifted wholesale from Bit College Basketball's title
     screen so the two games read as one studio: deep navy ground, gold rule,
     sharp corners, 2px border, a hard 3px shadow with NO blur, and the press
     moving the button down onto its own shadow. Hierarchy is weight and size
     only — no glow sweep, no inset ring, no gradient buttons. ---- */
  --font-pixel:'PixelDisplay','Courier New',monospace;
  /* SNOW, not BCB's navy-and-gold. Same canon — pixel face, sharp corners, 2px
     border, hard unblurred shadow, press-onto-the-shadow — recoloured to the
     mountain: white faces, a cold blue-grey shadow instead of near-black, deep
     slate for line and type, alpine blue as the one accent. Gold stays reserved
     for the B3B mark and is never a UI colour. */
  --tec-face:#ffffff; --tec-face-hi:#e9f2fb; --tec-shadow:#9cb3c8;
  --tec-line:#1b2a38; --tec-line-2:#4a6178;
  --tec-accent:#0b4f8f; --tec-accent-hi:#12639f; --tec-accent-sh:#06304f;
  --tec-ink:#16222e; --tec-ink-2:#5f7488;
  --r-sm:10px; --r:16px; --r-lg:22px;
  --shadow:0 1px 2px rgba(18,20,24,.05), 0 12px 30px -14px rgba(18,20,24,.20);
  --shadow-accent:0 10px 22px -10px rgba(11,79,143,.6);
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:36px;
  /* env() with no fallback resolves to NOTHING where it is unsupported, which
     makes every calc() using it invalid — and an invalid `right` silently drops
     the element to its static position, half off the screen. Always give 0px. */
  --safe-t:env(safe-area-inset-top,0px);  --safe-r:env(safe-area-inset-right,0px);
  --safe-b:env(safe-area-inset-bottom,0px); --safe-l:env(safe-area-inset-left,0px);
}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);
  color:var(--ink);font-family:var(--font-body);
  -webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent;
  user-select:none;-webkit-user-select:none;touch-action:none;overscroll-behavior:none}
#gl{position:fixed;inset:0;width:100%;height:100%;display:block}
/* DOUBLE-TAP ZOOM — reported by real players, who had to reload to escape.
   `touch-action` is NOT INHERITED, and that is the whole story. Three passes at
   this each NAMED a list of elements and each missed some, because every child
   of a named container still defaults to `auto`: the canvas, then the panel
   children, then the title-card text. Enumerating cannot work.
   So: refuse it EVERYWHERE, and opt scrolling back in where it is needed.
   Smoke walks the entire DOM and fails if any element computes to `auto`. */
*{touch-action:none}
/* The panels can outgrow a phone and still have to scroll. `pan-y` keeps the
   scroll and still refuses both the double tap and the pinch. */
.card,.card *,#rider,#mapCard,#riderCard,#setCard{touch-action:pan-y}
/* ...except the map canvas, which runs its own orbit and pinch from pointer
   events and wants the browser to keep its hands off entirely. */
#mapCv{touch-action:none}

/* The way out, if it ever happens anyway — an OS zoom, an accessibility
   setting, a WebKit build that ignores all of the above. Nobody should be
   reloading a game to undo a stray tap. */
/* Positioned from visualViewport in JS, NOT with a plain fixed/centre. When
   iOS zooms, `position:fixed` anchors to the LAYOUT viewport — so the one bar
   whose entire job is to appear when you are zoomed went off-screen exactly
   when it was needed, which is why there was "no easy way out". */
#zoomOut{position:fixed;left:0;top:0;transform-origin:0 0;z-index:60;display:none;
  align-items:center;gap:var(--s3);padding:8px 12px;
  background:var(--tec-face);border:2px solid var(--tec-line);
  box-shadow:0 3px 0 var(--tec-line);font-size:12px;touch-action:none}
body.zoomed #zoomOut{display:flex}
#zoomDbg{position:fixed;left:0;top:0;transform-origin:0 0;z-index:61;
  background:rgba(10,12,16,.86);color:#7CFF9B;font:11px/1.35 monospace;
  padding:6px 8px;white-space:pre-wrap;max-width:92vw;pointer-events:none;
  touch-action:none}

.logo{height:1em;width:auto;display:block}
/* One panel body for every menu — map, kit, results. Sharp corners and a hard
   unblurred drop are the canon; a rounded card with a soft blur is the website
   tell that started all this. */
.card{background:var(--tec-face);border:2px solid var(--tec-line);
      border-radius:0;box-shadow:0 4px 0 var(--tec-shadow)}
/* EVERY card heading is the pixel face. This used to be written per-card and
   `#setCard h2` simply never got one, so "Settings" rendered in the body font
   while "Run Complete" next to it rendered in canon — the one heading in the
   file that missed the rule. Style the FAMILY, not each member; the per-card
   rules below now only override size and colour. */
.card h2{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
         font-size:clamp(12px,1.8vw,20px);letter-spacing:.10em;color:var(--tec-line)}
.eyebrow{font-family:var(--font-pixel);text-transform:uppercase;letter-spacing:.22em;
         font-weight:400;color:var(--tec-ink-2);font-size:clamp(6px,.8vw,8px)}
/* ONE button family, everywhere — menu, map, kit, results. Sharp corners on
   purpose: a rounded pill is the single strongest "web app" tell, and it is
   what made this read as a website rather than a game. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5em;
     min-height:46px;padding:12px 18px;border:2px solid var(--tec-line);
     border-radius:0;background:var(--tec-face);color:var(--tec-line);
     font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
     letter-spacing:.16em;font-size:clamp(9px,1.05vw,12px);line-height:1;cursor:pointer;
     box-shadow:0 3px 0 var(--tec-shadow);
     transition:transform 70ms ease,background 110ms ease,border-color 110ms ease}
.btn:hover,.btn:focus-visible{background:var(--tec-face-hi);border-color:var(--tec-accent);outline:none}
.btn:active{transform:translateY(3px);box-shadow:0 0 0 var(--tec-shadow)}
.btn--accent{min-height:56px;font-size:clamp(11px,1.35vw,15px);letter-spacing:.24em;
             color:#fff;border-color:var(--tec-accent);
             background:var(--tec-accent);box-shadow:0 3px 0 var(--tec-accent-sh)}
.btn--accent:hover,.btn--accent:focus-visible{background:var(--tec-accent-hi)}
.btn--accent:active{box-shadow:0 0 0 var(--tec-accent-sh)}
.btn--ghost{min-height:42px;font-size:clamp(8px,.95vw,10px);letter-spacing:.12em;
            color:var(--tec-line-2);border-color:var(--tec-shadow)}
/* Selected reads as a filled chip, not a border tint — at pixel sizes a 1px
   colour shift on an outline is invisible. */
.btn.sel{background:var(--tec-line);color:#fff;border-color:var(--tec-line)}

/* ---------------- HUD ---------------- */
#hud{position:fixed;inset:0;pointer-events:none;opacity:0;transition:opacity .4s ease}
#hud.on{opacity:1}
.hud{position:absolute;padding:10px 14px;
     background:color-mix(in srgb,var(--tec-face) 92%,transparent);
     -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
     border:2px solid var(--tec-line);border-radius:0;
     box-shadow:0 3px 0 var(--tec-shadow)}
.hud .val{font-family:var(--font-pixel);font-weight:400;line-height:1;
          font-variant-numeric:tabular-nums;letter-spacing:.02em;color:var(--tec-ink)}
.hud .val small{font-size:.5em;color:var(--tec-ink-2);margin-left:.5em;letter-spacing:.1em}

#spd{left:calc(var(--s5) + var(--safe-l));bottom:calc(var(--s5) + var(--safe-b))}
#spd .val{font-size:clamp(17px,2.4vw,28px)}
#spdBarWrap{margin-top:9px;width:clamp(110px,13vw,160px);height:6px;
            background:#dfe8f1;border:1px solid var(--tec-line);overflow:hidden}
#spdBar{height:100%;width:0%;background:var(--tec-accent);transition:width .07s linear}
#spdBar.hot{background:#e8590c}

#dist{right:calc(var(--s5) + var(--safe-r));top:calc(var(--s4) + var(--safe-t));text-align:right}
#dist .val{font-size:clamp(13px,1.7vw,19px)}
#best{margin-top:7px;font-family:var(--font-pixel);font-weight:400;
      font-size:clamp(6px,.76vw,8px);letter-spacing:.14em;color:var(--tec-ink-2);
      text-transform:uppercase}
#style{right:calc(var(--s5) + var(--safe-r));top:calc(118px + var(--safe-t));text-align:right}
#style .val{font-size:clamp(13px,1.7vw,19px);color:var(--tec-accent)}
#combo{margin-top:6px;font-family:var(--font-pixel);font-weight:400;
       font-size:clamp(7px,.85vw,9px);letter-spacing:.1em;color:var(--tec-accent);
       opacity:0;transition:opacity .2s}
#combo.on{opacity:1}

#pops{position:absolute;left:50%;top:24%;transform:translateX(-50%);width:92%;text-align:center}
.pop{font-family:var(--font-display);font-weight:700;text-transform:uppercase;
     font-size:clamp(14px,1.7vw,20px);letter-spacing:.1em;line-height:1.7;color:var(--ink);
     text-shadow:0 2px 12px rgba(255,255,255,.85),0 1px 2px rgba(255,255,255,.9);
     animation:pu 1.45s cubic-bezier(.16,.9,.3,1) forwards;white-space:nowrap}
.pop b{color:var(--accent);margin-left:.5em}
@keyframes pu{0%{opacity:0;transform:translateY(12px) scale(.93)}14%{opacity:1;transform:none}
              66%{opacity:1;transform:translateY(-12px)}100%{opacity:0;transform:translateY(-34px)}}
#crashMsg{position:absolute;left:50%;top:42%;transform:translate(-50%,-50%);
          font-family:var(--font-display);font-weight:700;text-transform:uppercase;
          font-size:clamp(20px,2.6vw,32px);letter-spacing:.2em;color:#c8342b;
          text-shadow:0 2px 14px rgba(255,255,255,.9);opacity:0;transition:opacity .15s}
#crashMsg.on{opacity:1}
/* Contextual prompt — the only thing on the hill that asks you to press a key.
   Sits low-centre so it reads without covering the line you're skiing. */
#prompt{position:absolute;left:50%;bottom:calc(var(--s5) + 6px + var(--safe-b));
        transform:translate(-50%,8px);display:flex;gap:var(--s3);align-items:center;
        padding:11px 16px;border-radius:0;border:2px solid var(--tec-line);
        background:color-mix(in srgb,var(--tec-face) 94%,transparent);
        box-shadow:0 3px 0 var(--tec-shadow);
        -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
        font-family:var(--font-pixel);font-weight:400;letter-spacing:.12em;
        text-transform:uppercase;font-size:clamp(7px,.85vw,9px);color:var(--tec-line);
        opacity:0;transition:opacity .18s ease,transform .18s ease;pointer-events:none}
#prompt.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
#prompt b{display:grid;place-items:center;min-width:1.9em;height:1.9em;padding:0 .35em;
          border-radius:0;background:var(--tec-line);color:#fff;letter-spacing:0}
#flash{position:fixed;inset:0;background:#fff;opacity:0;pointer-events:none}
#vig{position:fixed;inset:0;pointer-events:none;
     background:radial-gradient(ellipse 82% 72% at 50% 46%,transparent 45%,rgba(24,34,52,.22) 100%)}

/* ---------------- title ---------------- */
/* Scrim stays light — the summit village is behind this and it is the first
   thing anyone sees of the game. The card is opaque, so the text is safe. */
/* The live 3D orbit of the summit village IS the cover art — it is a better
   hero than any painted panel and it can never go out of date. So the job here
   is not to cover it with a card but to GRADE it: darken the edges, sit the
   type in the clear middle, and lay scanlines over the whole thing. */
#title{position:fixed;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;
       transition:opacity .45s ease;
       padding:calc(var(--s4) + var(--safe-t)) calc(var(--s5) + var(--safe-r))
               calc(var(--s4) + var(--safe-b)) calc(var(--s5) + var(--safe-l))}
/* BCB can drop a heavy vignette because its cover is a dark arena. This one is
   bright snow, and the same grade turned the whole mountain to mud. So it is
   inverted: a soft scrim UNDER THE TYPE to buy contrast for gold text, and only
   a light touch at the edges so the hill stays bright and cold. */
#title::before{content:'';position:absolute;inset:0;pointer-events:none;
       background:radial-gradient(ellipse 46% 44% at 50% 44%,rgba(10,22,38,.30) 0%,
                                  rgba(10,22,38,.10) 66%,rgba(10,22,38,0) 100%),
                  linear-gradient(180deg,rgba(10,22,38,.10) 0%,rgba(10,22,38,0) 34%,
                                  rgba(10,22,38,.20) 100%)}
#title::after{content:'';position:absolute;inset:0;pointer-events:none;mix-blend-mode:overlay;
       background:repeating-linear-gradient(0deg,rgba(255,255,255,.035) 0 1px,transparent 1px 3px)}
#title.gone{opacity:0;pointer-events:none}
#titleCard{position:relative;z-index:1;max-width:min(560px,92vw);text-align:center;
           display:flex;flex-direction:column;align-items:center;gap:clamp(12px,2vh,20px);
           background:none;border:0;box-shadow:none;padding:0}
#titleCard .logo{height:clamp(26px,3.2vw,36px);margin-bottom:var(--s1)}
#titleCard h1{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
              font-size:clamp(26px,5.4vw,58px);letter-spacing:.10em;line-height:.95;
              color:var(--tec-line);
              text-shadow:0 4px 0 #ffffff,0 6px 0 var(--tec-shadow),
                          0 10px 26px rgba(20,40,60,.42)}
#mtn{font-family:var(--font-pixel);text-transform:uppercase;
     letter-spacing:.42em;font-size:clamp(7px,.92vw,10px);color:var(--tec-line);
     text-shadow:0 1px 0 #fff,0 -1px 0 #fff,1px 0 0 #fff,-1px 0 0 #fff}
#pick,#units{display:flex;gap:var(--s2);flex-wrap:wrap;justify-content:center}
#runPick{display:flex;gap:var(--s2);align-items:center;justify-content:center}
#pick2{display:flex;gap:var(--s2);align-items:center}
/* Three buttons across a phone leaves ~105px each, which wraps "Drop In" and
   "Trail Map" onto two lines and reads as broken. Stack them: full width, one
   line each, and a proper thumb-sized target instead of a third of a row. */
@media (max-width:430px){
  #pick2{flex-direction:column;align-items:stretch}
  #pick2 .btn{width:100%}
}
.btn--step{padding:0;width:42px;min-width:42px;font-size:14px;line-height:1;letter-spacing:0}
#runNow{display:flex;align-items:center;gap:10px;min-width:clamp(190px,24vw,240px);
        justify-content:center;padding:13px 14px;border:2px solid rgba(255,215,0,.42);
        background:rgba(11,28,48,.86);box-shadow:0 3px 0 var(--tec-shadow)}
#runNow i{width:10px;height:10px;border-radius:0;flex:none}
#runNow b{font-family:var(--font-pixel);font-weight:400;font-size:clamp(8px,.95vw,11px);
          letter-spacing:.08em;color:var(--tec-ink)}
#runNow em{font-style:normal;color:var(--tec-accent);font-family:var(--font-pixel);
           font-size:clamp(7px,.8vw,9px);letter-spacing:.12em;text-transform:uppercase}
#keys{font-family:var(--font-pixel);font-size:clamp(6px,.78vw,8px);color:var(--tec-ink);
      line-height:2.5;letter-spacing:.10em;text-transform:uppercase;
      text-shadow:0 1px 0 #fff,0 -1px 0 #fff,1px 0 0 #fff,-1px 0 0 #fff,0 3px 10px rgba(255,255,255,.9)}
#keys b{color:var(--tec-accent);font-weight:400}

/* ---------------- finish ---------------- */
/* The only chrome that opens the menu, and it is IN THE GAME — the title
   screen is one verb and nothing else. Sits under the altitude/style column so
   it never fights the touch utility row, which is top-centre. */
#setBtn{position:fixed;right:calc(var(--s5) + var(--safe-r));
  top:calc(196px + var(--safe-t));z-index:5;display:none;
  font-family:var(--font-pixel);font-size:9px;letter-spacing:.10em;
  text-transform:uppercase;color:var(--tec-line);
  background:color-mix(in srgb,var(--tec-face) 92%,transparent);
  border:2px solid var(--tec-line);box-shadow:0 3px 0 var(--tec-line);
  padding:10px 12px;cursor:pointer;touch-action:none}
#setBtn:active{transform:translateY(3px);box-shadow:none}
body.playing #setBtn{display:block}
body.mapping #setBtn,body.kitting #setBtn{display:none}

/* THE MAIN MENU IS ONE VERB. It used to show a board picker, a units picker
   and three navigation buttons before you had done anything at all — which is
   a control panel, not a title screen. Everything except "Ski" lives behind
   this door now. */
#settings{position:fixed;inset:0;z-index:8;display:none;align-items:center;
  justify-content:center;
  background:linear-gradient(180deg,rgba(241,243,239,.62),rgba(231,234,228,.88));
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  padding:calc(var(--s4) + var(--safe-t)) calc(var(--s4) + var(--safe-r))
          calc(var(--s4) + var(--safe-b)) calc(var(--s4) + var(--safe-l))}
#settings.on{display:flex}
#setCard{max-width:min(420px,92vw);max-height:100%;overflow:auto;text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:var(--s4);
  padding:clamp(16px,2.4vw,26px)}
.setRow{display:flex;flex-direction:column;gap:var(--s2);align-items:center;width:100%}
.setRow .k{font-family:var(--font-pixel);font-size:8px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--tec-ink);opacity:.75}
#setNav{display:flex;gap:var(--s2)}
/* the legend is over a CARD here, not over the mountain — drop the white halo
   it needs when it floats on snow */
#setCard #keys{text-shadow:none;line-height:2.1;opacity:.85}
/* A KEY legend on a device with no keys is dead weight — and it was 56px of
   the 95px that pushed the Done button clean off a landscape phone. The touch
   build already rewrites the title legend for the same reason. */
body.touch #setCard #keys{display:none}
#finish{position:fixed;inset:0;z-index:6;display:none;align-items:center;justify-content:center;
        background:linear-gradient(180deg,rgba(241,243,239,.6),rgba(231,234,228,.85));
        -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
#finish.on{display:flex}
#finCard{max-width:min(480px,92vw);padding:clamp(22px,3.2vw,36px);text-align:center;
         display:flex;flex-direction:column;align-items:center;gap:var(--s4)}
#finCard h2{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
            font-size:clamp(14px,2vw,22px);letter-spacing:.10em;color:var(--tec-line)}
#finStats{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s3) var(--s5);width:100%}
.stat{text-align:left}
.stat .k{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
         letter-spacing:.16em;font-size:clamp(6px,.76vw,8px);color:var(--tec-ink-2)}
.stat .v{font-family:var(--font-pixel);font-weight:400;font-size:clamp(11px,1.5vw,16px);
         font-variant-numeric:tabular-nums;margin-top:5px;color:var(--tec-line)}

/* ---------------- wipeout ---------------- */
/* Shown once the ragdoll comes to REST, so you always get to watch the whole
   tumble before anything asks you a question. Bottom-anchored and translucent
   so the wreck stays on screen behind it — the crash is the entertainment. */
#wipe{position:fixed;inset:0;z-index:6;display:none;align-items:flex-end;justify-content:center;
      pointer-events:none;
      padding:0 calc(var(--s4) + var(--safe-r)) calc(var(--s6) + var(--safe-b))
                calc(var(--s4) + var(--safe-l))}
#wipe.on{display:flex}
#wipeCard{pointer-events:auto;padding:var(--s4) var(--s5);text-align:center;
          display:flex;flex-direction:column;align-items:center;gap:var(--s3);
          background:color-mix(in srgb,var(--tec-face) 94%,transparent);
          -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
#wipeCard h2{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
             font-size:clamp(12px,1.7vw,18px);letter-spacing:.10em;color:#c8342b}
#wipeBtns{display:flex;gap:var(--s2);flex-wrap:wrap;justify-content:center}
#wipeHint{font-family:var(--font-pixel);font-size:clamp(6px,.76vw,8px);
          letter-spacing:.14em;text-transform:uppercase;color:var(--tec-ink-2)}
#wipeHint b{color:var(--tec-line)}

/* ---------------- trail map ---------------- */
#map{position:fixed;inset:0;z-index:7;display:none;align-items:center;justify-content:center;
     background:linear-gradient(180deg,rgba(241,243,239,.62),rgba(231,234,228,.88));
     -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
     padding:calc(var(--s3) + var(--safe-t)) calc(var(--s4) + var(--safe-r))
             calc(var(--s3) + var(--safe-b)) calc(var(--s4) + var(--safe-l))}
#map.on{display:flex}
#mapCard{display:flex;gap:var(--s5);align-items:stretch;padding:var(--s5);max-height:100%}
#mapCv{border-radius:var(--r-sm);border:1px solid var(--hair);cursor:crosshair;
       height:min(72vh,560px);width:auto;display:block;background:#eef1f4}
#mapSide{display:flex;flex-direction:column;gap:var(--s3);min-width:190px;max-width:262px}
#mapSide h3{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
            font-size:clamp(10px,1.2vw,13px);letter-spacing:.08em;line-height:1.7;
            color:var(--tec-line)}
#mapRegion{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
           letter-spacing:.2em;font-size:clamp(6px,.78vw,8px);color:var(--tec-ink-2)}
.legend{display:flex;flex-direction:column;gap:6px;margin-top:var(--s2)}
.leg{display:flex;align-items:center;gap:9px;font-size:clamp(11px,1.2vw,13px)}
.leg i{width:16px;height:4px;border-radius:2px;flex:none}
/* A run's swatch colour is per-run, so JS sets it via the CSSOM. The lift dash
   is a constant, so it belongs here. Neither may be a style="" attribute — the
   B3B site serves style-src 'self' with no unsafe-inline and drops those. */
.leg i.lift{background:repeating-linear-gradient(90deg,#16181c 0 4px,transparent 4px 7px)}
.leg.gap{margin-top:6px}
.leg span{color:var(--ink-2);margin-left:auto;font-family:var(--font-display);
          font-weight:700;font-size:.82em;letter-spacing:.1em;text-transform:uppercase}
#wayInfo{font-size:clamp(11px,1.2vw,13px);color:var(--ink-2);line-height:1.6}
#wayInfo b{color:var(--ink);font-family:var(--font-display)}
#mapVert{margin-top:auto;display:flex;gap:var(--s3);flex-wrap:wrap}
.vs{font-size:clamp(10px,1.1vw,11px);color:var(--ink-2);text-transform:uppercase;
    letter-spacing:.09em;font-family:var(--font-display);font-weight:700}
.vs b{display:block;font-size:clamp(14px,1.5vw,17px);color:var(--ink);letter-spacing:0}
#mapBtns{display:flex;gap:var(--s2)}
#mapBtns .btn{flex:1;padding-left:0;padding-right:0}
/* The card is a panorama beside a legend column, and it wants ~880px to do
   that. Measured on a 393pt phone it was 865px wide and hung 236px off BOTH
   edges — the trail map, the thing this game is built around having, was
   unreachable on the platform we call first-class. Below that width it stacks
   and the panorama sizes to the WIDTH instead of the height.
   Keyed to the card's real requirement, not to "phone": a 700px desktop window
   has the same problem and gets the same answer. */
@media (max-width:900px){
  #mapCard{flex-direction:column;gap:var(--s3);padding:var(--s4);
           max-width:100%;overflow:auto}
  #mapCv{height:auto;width:100%;max-height:52vh;object-fit:contain}
  #mapSide{min-width:0;max-width:none}
  /* the legend is the first thing worth dropping when height is short */
  #mapVert{margin-top:0}
}
@media (max-width:900px) and (max-height:520px){
  #mapCv{max-height:40vh}
  .legend{display:none}
}

/* ---------------- rider kit ---------------- */
/* Centred, and scrollable if it ever outgrows the viewport. It used to be
   pinned hard left with asymmetric padding, which hung the card off the edge of
   the screen on a narrow window. */
/* Your rider is LIVE behind this. The sim freezes, the camera orbits the real
   figure, and every swatch you touch changes the thing you are looking at — you
   cannot pick a kit from six rows of squares, and a preview that is not the
   actual model is a lie waiting to drift. So the scrim is gone (it was hiding
   the one thing worth showing) and the card sits to the RIGHT, with the camera
   biased so the rider frames up in the space left over. */
#rider{position:fixed;inset:0;z-index:7;display:none;align-items:center;
       justify-content:flex-end;overflow:auto;pointer-events:none;
       padding:calc(var(--s4) + var(--safe-t)) calc(var(--s4) + var(--safe-r))
               calc(var(--s4) + var(--safe-b)) calc(var(--s4) + var(--safe-l))}
#rider.on{display:flex}
#riderCard{width:min(330px,92vw);padding:var(--s5);display:flex;flex-direction:column;
       gap:var(--s3);margin:auto 0;pointer-events:auto;max-height:100%;overflow:auto}
/* Narrow enough that a side-by-side would squeeze the rider out: stack, and let
   the card sit at the bottom with the rider above it. */
@media (max-width:640px){
  #rider{align-items:flex-end;justify-content:center}
  #riderCard{width:min(420px,96vw);margin:0 auto}
}
#riderCard h3{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
              font-size:clamp(11px,1.3vw,15px);letter-spacing:.10em;margin-bottom:var(--s2);
              color:var(--tec-line)}
.kitrow{display:flex;align-items:flex-start;gap:var(--s2)}
.kitrow .k{font-family:var(--font-display);font-weight:700;text-transform:uppercase;
           letter-spacing:.12em;font-size:clamp(8px,.95vw,10px);color:var(--ink-2);
           width:62px;flex:none;padding-top:7px}
/* Wraps. Rows do not all have the same number of colours and must not assume it. */
.sws{display:flex;flex-wrap:wrap;gap:6px;flex:1;min-width:0}
.sw{width:26px;height:26px;border-radius:0;border:2px solid transparent;
    box-shadow:inset 0 0 0 1px rgba(18,20,24,.14);cursor:pointer;flex:none;
    transition:transform .1s ease,border-color .12s ease}
.sw:active{transform:scale(.92)}
.sw.on{border-color:var(--ink);box-shadow:inset 0 0 0 1px rgba(255,255,255,.85)}

/* ---------------- touch controls: TWO POLES ----------------
   Taken literally from how you actually ski. There is no d-pad and no joystick:
   there is a pole under each thumb. Use the LEFT pole and you go left; the right
   pole and you go right. PULL BACK on a pole and it checks — the same brake the
   S key drives. That is the whole vocabulary, and it is why there are only two
   controls on the screen.

   Each pole is one vertical axis of drag:
     push FORWARD  — plant it harder, carve harder (both poles = tuck)
     rest          — a comfortable cruising turn
     pull BACK     — check, and the turn washes out into a skid, as it should
   Flick a pole UP and you pop. Nothing else needs a button.

   LANDSCAPE. Two thumbs at the bottom corners is a landscape hold, and portrait
   gets a rotate prompt instead — see #rotate. Everything wears the Tecmo shell
   (square, 2px line, hard shadow) like the rest of the UI. */
#touch{position:fixed;inset:0;z-index:3;display:none;pointer-events:none}
/* Mounted, but not until the run starts. On the title screen there is nothing
   to steer, and the controls sat straight on top of the cover art — the one
   screen a phone visitor decides on. Same hook as the studio mark:
   `body.playing`, set by begin(). */
body.playing #touch.on{display:block}

/* 56% tall, not more: the hit zone is invisible and it is tempting to make it
   huge, but it has to stay clear of the HUD column or the readouts sit inside
   the control. Wide enough that a thumb never misses, short enough that it
   cannot. */
.pole{position:absolute;bottom:0;width:33%;max-width:190px;height:56%;
      pointer-events:auto;touch-action:none;
      display:flex;align-items:flex-end;justify-content:center}
#poleL{left:0}
#poleR{right:0}
/* The pole itself. transform-origin is the tip, so it pivots where it is
   planted — pushing forward tilts it out, pulling back stands it up toward you,
   which is exactly the shape of a check. Set from JS via .style (CSSOM). */
.pvis{position:relative;width:46px;height:152px;margin-bottom:38px;
      transform-origin:50% 100%;transition:transform .09s ease-out;
      opacity:.5;will-change:transform}
.pole.hot .pvis{opacity:1}
/* A ski pole is mostly SHAFT. A first pass gave the grip a third of the height
   and it read as a thermometer — silhouette is the whole job here, same rule as
   the props on the hill. */
.pshaft{position:absolute;left:50%;top:24px;bottom:0;width:6px;margin-left:-3px;
      background:var(--tec-line)}
.pgrip{position:absolute;left:50%;top:0;width:18px;height:30px;margin-left:-9px;
      background:var(--tec-face);border:2px solid var(--tec-line);
      box-shadow:0 3px 0 var(--tec-shadow)}
/* the strap — two lines of it, and the pole stops being a stick */
.pgrip::after{content:'';position:absolute;left:-9px;top:7px;width:9px;height:12px;
      border:2px solid var(--tec-line);border-right:0;border-radius:6px 0 0 6px}
.pole.hot .pgrip{background:var(--tec-accent);border-color:var(--tec-accent-sh);
      box-shadow:0 0 0 var(--tec-accent-sh)}
/* pulled back far enough to be braking — the grip goes red, because a check is
   a different thing from a turn and you should be able to see which you did */
.pole.chk .pgrip{background:#c8342b;border-color:#7d201a}
.pbasket{position:absolute;left:50%;bottom:15px;width:32px;height:10px;
      margin-left:-16px;border:2px solid var(--tec-line);
      background:var(--tec-face);border-radius:50%}
.plabel{position:absolute;bottom:calc(var(--s3) + var(--safe-b));
      font-family:var(--font-pixel);font-weight:400;font-size:8px;
      letter-spacing:.14em;text-transform:uppercase;color:var(--tec-ink-2);
      opacity:.5;transition:opacity .3s ease;white-space:nowrap}
.pole.hot .plabel{opacity:0}
/* Stalled on a flat: alternating poles IS the skate stride, it just has no
   affordance. Say so, in the place you are already looking. */
#touch.skate .plabel{opacity:1;color:var(--tec-accent)}

/* ---------------- rotate to landscape ----------------
   Two thumbs at the bottom corners is a landscape hold. Orientation cannot be
   LOCKED from a web page on iOS — the Screen Orientation API has no Safari
   support and Android's needs fullscreen — so the honest move is to ask, and to
   make the ask look deliberate rather than broken. */
#rotate{position:fixed;inset:0;z-index:10;display:none;
      place-items:center;text-align:center;padding:var(--s5);
      background:linear-gradient(180deg,#e9f2fb,#c8dbec)}
body.touch.portrait #rotate{display:grid}
#rotate .rot{display:block;width:64px;height:104px;margin:0 auto var(--s5);
      border:3px solid var(--tec-line);border-radius:9px;
      box-shadow:0 4px 0 var(--tec-shadow);animation:tip 2.4s ease-in-out infinite}
@keyframes tip{0%,42%{transform:rotate(0)}62%,100%{transform:rotate(-90deg)}}
#rotate h3{font-family:var(--font-pixel);font-weight:400;text-transform:uppercase;
      font-size:13px;letter-spacing:.1em;color:var(--tec-line);line-height:1.9}
#rotate p{font-family:var(--font-pixel);font-weight:400;font-size:8px;
      letter-spacing:.14em;text-transform:uppercase;color:var(--tec-ink-2);
      margin-top:var(--s3);line-height:2}

/* Utility row, top centre. Both of these were keyboard-only (M and R), which
   meant a phone player could not open the trail map at all and — worse — had no
   way out of a flat spot or a bad line. Top centre because they are deliberate
   taps, not reflexes, and both thumbs live at the bottom. */
#tUtil{position:absolute;left:50%;top:calc(var(--s3) + var(--safe-t));
       transform:translateX(-50%);display:flex;gap:var(--s2);pointer-events:none}
/* 12px vertical (a taller target — these are the only chrome you tap mid-run),
   12px horizontal because the top strip is width-critical: at 375pt the row has
   to fit between the speed card and the altitude card with nothing to spare. */
#tUtil .tu{pointer-events:auto;touch-action:none;padding:12px 12px;border-radius:0;
       background:color-mix(in srgb,var(--tec-face) 92%,transparent);
       -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
       border:2px solid var(--tec-line);box-shadow:0 3px 0 var(--tec-shadow);
       font-family:var(--font-pixel);font-weight:400;font-size:8px;
       letter-spacing:.14em;text-transform:uppercase;color:var(--tec-ink);
       -webkit-user-select:none;user-select:none}
#tUtil .tu:active{background:var(--tec-accent);color:#fff;
       border-color:var(--tec-accent-sh);box-shadow:0 0 0 var(--tec-accent-sh);
       transform:translateY(3px)}

/* On a phone the left thumb sits exactly where the speed readout was. Move it
   up top; it is the one number you actually watch.
   That makes the top edge the busiest strip on the screen — speed, the utility
   row and altitude all want it — so on touch the HUD cards shrink to fit rather
   than stacking on each other. Measured at 393pt: 104 + 127 + 109 + gaps, which
   fits; at full desktop sizing the Map button sat 25px on top of the speed bar. */
body.touch #spd{bottom:auto;left:calc(var(--s4) + var(--safe-l));
                top:calc(var(--s3) + var(--safe-t))}
body.touch #dist{top:calc(var(--s3) + var(--safe-t))}
/* The utility row cannot live in the top strip: speed + row + altitude needs
   ~350pt and a 360pt phone does not have it — measured, the row sat on both
   neighbours. So secondary chrome becomes ONE right-hand column (altitude, then
   the row, then style) and the top centre is left empty. Widths then never
   contend, at any phone size. */
body.touch #tUtil{left:auto;right:calc(var(--s4) + var(--safe-r));
                  top:calc(78px + var(--safe-t));transform:none}
body.touch .hud{padding:8px 11px}
body.touch #spd .val{font-size:17px}
body.touch #spdBarWrap{width:84px;margin-top:6px}
body.touch #dist .val{font-size:14px}
body.touch #best{margin-top:5px}
/* third in the right-hand column */
body.touch #style{top:calc(136px + var(--safe-t))}
/* Landscape phone: only ~375-393pt of height, so the right-hand column and the
   left pole want the same pixels. Style moves under the speed card, and the
   poles are short enough not to reach either. */
@media (max-height:560px){
  body.touch #style{left:calc(var(--s4) + var(--safe-l));right:auto;
                    top:calc(80px + var(--safe-t));text-align:left}
  .pvis{height:126px;margin-bottom:26px}
}
/* Two poles at the bottom corners leave the bottom CENTRE genuinely free for
   the first time — which is where a prompt belongs, and where the board tap
   wants to be. It was fighting a button cluster before. */
body.touch #prompt{bottom:calc(var(--s4) + var(--safe-b));max-width:44vw}

/* corner mark */
/* The studio mark is a TITLE-SCREEN thing. On the hill it is chrome sitting in
   the corner of a game you are trying to be inside of. Hidden the moment the
   title clears; `body.playing` is set by begin(). */
#sig{position:fixed;z-index:4;right:calc(var(--s4) + var(--safe-r));
     bottom:calc(var(--s3) + var(--safe-b));height:clamp(15px,1.8vw,20px);opacity:.72;
     pointer-events:none;transition:opacity .4s ease;
     filter:drop-shadow(0 1px 3px rgba(255,255,255,.9))}
body.playing #sig{opacity:0}
/* Kit view: the rider is the subject, so everything that is not the card gets
   out of the way. */
body.kitting #hud{opacity:0}
body.kitting #touch.on{display:none}
body.kitting #vig{opacity:0}
/* 3D map: the mountain IS the screen, so the scrim goes and the card becomes a
   side panel. Same move as the kit view — the subject is behind the DOM, and a
   full-screen backdrop would be covering the one thing worth looking at. */
body.mapping #hud{opacity:0}
body.mapping #touch.on{display:none}
body.mapping #vig{opacity:0}
body.mapping #map{background:none;-webkit-backdrop-filter:none;backdrop-filter:none;
                  justify-content:flex-start;align-items:flex-start;pointer-events:auto}
body.mapping #mapCard{flex-direction:column;max-width:min(300px,86vw);
                      margin:0;max-height:100%;overflow:auto}
body.mapping #mapCv{display:none}
body.mapping #mapSide{min-width:0;max-width:none}
/* on a phone the panel would eat the model — collapse it to a strip */
@media (max-width:760px){
  body.mapping #mapCard{max-width:min(230px,62vw);padding:var(--s3)}
  body.mapping #mapVert{display:none}
  body.mapping .legend{display:none}
}
/* The Rider button lives on the TITLE, so the title card is the thing most
   likely to be sitting on top of the rider you just asked to look at. */
body.kitting #title{opacity:0;pointer-events:none}
#sig .logo{height:100%}

/* ---------------- perf panel ----------------
   The one instrument that cannot be run from this machine. Every performance
   number the project holds is CPU-side or SwiftShader; this is how a real phone
   GPU gets to state its own case. `?perf=1`. */
#perf{position:fixed;right:calc(var(--s3) + var(--safe-r));
      bottom:calc(var(--s3) + var(--safe-b));z-index:9;width:212px;display:none;
      padding:var(--s3);background:color-mix(in srgb,var(--tec-face) 94%,transparent);
      -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
      border:2px solid var(--tec-line);box-shadow:0 3px 0 var(--tec-shadow);
      font-family:var(--font-pixel);font-weight:400;font-size:8px;
      letter-spacing:.08em;color:var(--tec-ink);line-height:1.9}
#perf.on{display:block}
/* On a phone the bottom-right corner is the button cluster — the instrument
   cannot sit on the controls it is measuring. */
body.touch #perf{left:calc(var(--s4) + var(--safe-l));top:calc(96px + var(--safe-t));
                 right:auto;bottom:auto}
#perfFps{font-size:26px;line-height:1;letter-spacing:0;color:var(--tec-accent)}
#perfFps small{font-size:9px;color:var(--tec-ink-2);margin-left:.5em;letter-spacing:.14em}
#perf .row{display:flex;justify-content:space-between;gap:var(--s2)}
#perf .row b{font-weight:400;color:var(--tec-ink-2)}
#perfGpu{margin-top:6px;color:var(--tec-ink-2);word-break:break-word;
         font-size:7px;line-height:1.6}
#perfQ{display:flex;gap:4px;margin-top:var(--s2)}
#perfQ button{flex:1;font-family:var(--font-pixel);font-weight:400;font-size:7px;
      letter-spacing:.1em;text-transform:uppercase;padding:6px 0;cursor:pointer;
      background:var(--tec-face);color:var(--tec-ink);
      border:2px solid var(--tec-line);box-shadow:0 2px 0 var(--tec-shadow)}
#perfQ button.on{background:var(--tec-accent);color:#fff;
      border-color:var(--tec-accent-sh);box-shadow:0 0 0 var(--tec-accent-sh);
      transform:translateY(2px)}

/* ---------------- pixel-look dev panel (unchanged behaviour) ---------------- */
#px{position:fixed;left:calc(var(--s4) + var(--safe-l));top:calc(var(--s4) + var(--safe-t));
    z-index:8;width:252px;padding:var(--s4);display:none;
    background:color-mix(in srgb,var(--surface) 94%,transparent);
    -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
    border:1px solid var(--hair);border-radius:var(--r);box-shadow:var(--shadow);
    font-size:11px;letter-spacing:.02em}
#px.on{display:block}
.pxh{font-family:var(--font-display);font-weight:700;text-transform:uppercase;
     letter-spacing:.16em;font-size:10px;color:var(--ink-2);margin-bottom:var(--s3)}
.pxh span{float:right;opacity:.65}
.pxh.gap{margin-top:var(--s4)}
/* Shown only if the context fails, so it cannot rely on anything but this rule. */
.nogl{padding:40px;font:16px system-ui;color:#fff}
#px label{display:flex;align-items:center;gap:8px;margin:7px 0;color:var(--ink-2)}
#px label>input[type=range]{flex:1;min-width:0;accent-color:var(--accent);height:3px}
#px select{flex:1;background:var(--surface);color:var(--ink);border:1px solid var(--hair);
           border-radius:6px;padding:4px 5px;font:inherit;font-size:11px}
#px b{width:30px;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;color:var(--accent)}
.pxn{margin-top:var(--s3);font-size:10px;color:var(--ink-2);opacity:.75}
