Up-in-the-Air – blob

You can use Git to clone the repository via the web URL. Download snapshot (zip)
Add fun new easter egg
[Up-in-the-Air] / index.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <title>Up in the Air</title>
7 <link rel="icon" type="image/png" sizes="32x32" href="textures/icon-32.png">
8 <link rel="icon" type="image/png" sizes="16x16" href="textures/icon-16.png">
9 <!--
10 // SPDX-License-Identifier: GPL-3.0-or-later
11 /**
12  * Up in the Air
13  * – a browser game created for FediJam 2024 –
14  * https://fietkau.media/up_in_the_air
15  *
16  * Copyright (c) Julian Fietkau
17  * See README.txt for details.
18  *
19  *******************************************************************************
20  *
21  * This program is free software: you can redistribute it and/or modify
22  * it under the terms of the GNU General Public License as published by
23  * the Free Software Foundation, either version 3 of the License, or
24  * (at your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
33  *
34  */
35 -->
36 <style>
37   @font-face {
38     font-family: 'Cookie';
39     src: url('fonts/cookie.woff2') format('woff2');
40     font-weight: normal;
41     font-display: block;
42   }
43   @font-face {
44     font-family: 'Nihonium113';
45     src: url('fonts/nihonium113.woff2') format('woff2');
46     font-weight: normal;
47     font-display: block;
48   }
49   @font-face {
50     font-family: 'Atkinson Hyperlegible';
51     src: url('fonts/atkinson-hyperlegible-regular.woff2') format('woff2');
52     font-weight: normal;
53     font-display: block;
54   }
55   @font-face {
56     font-family: 'Atkinson Hyperlegible';
57     src: url('fonts/atkinson-hyperlegible-bold.woff2') format('woff2');
58     font-weight: bold;
59     font-display: block;
60   }
61   @font-face {
62     font-family: 'OpenDyslexic';
63     src: url('fonts/opendyslexic-regular.woff2') format('woff2');
64     font-weight: normal;
65     font-display: block;
66   }
67   @font-face {
68     font-family: 'OpenDyslexic';
69     src: url('fonts/opendyslexic-bold.woff2') format('woff2');
70     font-weight: bold;
71     font-display: block;
72   }
73   body {
74     box-sizing: border-box;
75     min-height: 100svh;
76     margin: 0;
77     padding: 0;
78     background: #eee;
79     display: flex;
80     justify-content: center;
81     align-items: center;
82   }
83   @media (prefers-color-scheme: dark) {
84     body {
85       background: #111;
86     }
87   }
88   .upInTheAirGame {
89     container-type: inline-size;
90     box-sizing: border-box;
91     width: min(100cqw, 100svw);
92     height: min(100cqh, 100svh);
93     padding: var(--game-margin);
94     font-family: sans-serif;
95     line-height: 1;
96     display: flex;
97     justify-content: center;
98     align-items: flex-start;
99     --game-margin: 2rem;
100   }
101   .upInTheAirGame:fullscreen {
102     background: #eee;
103   }
104   @media (prefers-color-scheme: dark) {
105     .upInTheAirGame:fullscreen {
106       background: #111;
107     }
108   }
109   .upInTheAirGame .ui-container {
110     position: relative;
111     width: min(calc(100cqh - 2 * var(--game-margin)), calc(100cqw));
112     aspect-ratio: 1 / 1;
113     background: #fff;
114     image-rendering: pixelated;
115     box-shadow: 1px 1px 3px #000a;
116     overflow: hidden;
117   }
118   .upInTheAirGame .virtual-input-widget {
119     box-sizing: border-box;
120     display: none;
121     width: min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin)));
122     aspect-ratio: 1 / 1;
123     position: absolute;
124     bottom: var(--game-margin);
125     right: var(--game-margin);
126     z-index: 25;
127   }
128   .upInTheAirGame.virtual-input-left .virtual-input-widget {
129     left: var(--game-margin);
130     right: unset;
131   }
132   @media (min-width: 15cm) and (min-height: 15cm) {
133     @container (min-width: calc(100cqh - 4cm - 1rem - 4rem)) {
134       .upInTheAirGame .ui-container.control-touchpad, .upInTheAirGame .ui-container.control-thumbstick {
135         margin: 0 calc(1rem + min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin))));
136         align-self: flex-end;
137       }
138     }
139     @container (min-width: calc(100cqh - 4cm - 1rem - 4rem)) and (max-width: calc(100cqh + 2 * 4cm + 2rem)) {
140       .upInTheAirGame .ui-container.control-touchpad, .upInTheAirGame .ui-container.control-thumbstick {
141         margin: 0 calc(1rem + min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin)))) 0 0;
142         align-self: flex-end;
143       }
144       .upInTheAirGame.virtual-input-left .ui-container.control-touchpad, .upInTheAirGame .ui-container.control-thumbstick {
145         margin: 0 0 0 calc(1rem + min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin))));
146         align-self: flex-end;
147       }
148     }
149   }
150   @media (max-width: 15cm) or (max-height: 15cm) {
151     .upInTheAirGame {
152       --game-margin: 0px;
153     }
154     .upInTheAirGame .virtual-input-widget {
155       bottom: 1rem;
156       right: 1rem;
157     }
158     .upInTheAirGame.virtual-input-left .virtual-input-widget {
159       left: 1rem;
160       right: unset;
161     }
162     @container (min-width: calc(100cqh - 4cm - 2rem)) {
163       .upInTheAirGame .ui-container.control-touchpad, .upInTheAirGame .ui-container.control-thumbstick {
164         margin: 0 calc(2rem + min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin))));
165         align-self: flex-end;
166       }
167     }
168     @container (min-width: calc(100cqh - 4cm - 2rem)) and (max-width: calc(100cqh + 2 * 4cm + 4rem)) {
169       .upInTheAirGame .ui-container.control-touchpad, .upInTheAirGame .ui-container.control-thumbstick {
170         margin: 0 calc(2rem + min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin)))) 0 0;
171         align-self: flex-end;
172       }
173       .upInTheAirGame.virtual-input-left .ui-container.control-touchpad, .upInTheAirGame .ui-container.control-thumbstick {
174         margin: 0 0 0 calc(2rem + min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin))));
175         align-self: flex-end;
176       }
177     }
178   }
179   .upInTheAirGame .ui-container.font-atkinson * {
180     font-family: 'Atkinson Hyperlegible' !important;
181   }
182   .upInTheAirGame .ui-container.font-atkinson > .ui-page {
183     font-size: .9em;
184   }
185   .upInTheAirGame .ui-container.font-opendyslexic * {
186     font-family: 'OpenDyslexic' !important;
187   }
188   .upInTheAirGame .ui-container.font-opendyslexic > .ui-page {
189     font-size: .8em;
190   }
191   .upInTheAirGame .virtual-input-widget.touchpad {
192     display: block;
193     background-color: #585858;
194     background-image: url('data:image/svg+xml,%3Csvg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="m33.5 224a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-96-32a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-96-32a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-96-32a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-96-32a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-96-32a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-96-32a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm160 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-128 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm-32 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5zm64 0a1.5 1.5 0 0 1-1.5 1.5 1.5 1.5 0 0 1-1.5-1.5 1.5 1.5 0 0 1 1.5-1.5 1.5 1.5 0 0 1 1.5 1.5z" fill="none" stroke="%23aaa" opacity=".25"/%3E%3C/svg%3E'), radial-gradient(circle at 25% 25%, #686868, #484848);
195     border-radius: 3%;
196     border: 2px inset #808080;
197     overflow: hidden;
198   }
199   .upInTheAirGame .virtual-input-widget .circle {
200     position: relative;
201     left: 50%;
202     top: 50%;
203     transform: translate(-50%, -50%);
204     display: block;
205     aspect-ratio: 1 / 1;
206     border-radius: 50%;
207     transition-property: left, top;
208     transition-duration: 0ms;
209   }
210   .upInTheAirGame .virtual-input-widget.touchpad .circle {
211     width: 5%;
212     background-color: #fff;
213     opacity: 0.4;
214   }
215   .upInTheAirGame .virtual-input-widget.thumbstick {
216     display: block;
217     background-color: #585858;
218     background-image: radial-gradient(circle, #808080, #484848);
219     border-radius: 50%;
220     border: 2px inset #808080;
221   }
222   .upInTheAirGame .virtual-input-widget.thumbstick .circle {
223     width: 50%;
224     background-color: #ccc;
225     background-image: radial-gradient(#ccc 0%, #ccc 20%, #999 25%, #ccc 30%, #ccc 40%, #999 45%, #ccc 50%, #444 100%);
226     box-shadow: 0 0 .3cm #000;
227   }
228   .upInTheAirGame .ui-page {
229     position: absolute;
230     left: 0;
231     top: 0;
232     bottom: 0;
233     right: 0;
234     box-sizing: border-box;
235     height: 100%;
236     opacity: 0;
237     display: none;
238     transition: opacity 250ms;
239   }
240   .upInTheAirGame .ui-page:not(.gameplay) {
241     z-index: 10;
242   }
243   .upInTheAirGame .ui-page a {
244     color: #c50031;
245     text-decoration: none;
246   }
247   .upInTheAirGame .ui-page a:hover {
248     text-decoration: underline;
249   }
250   .upInTheAirGame .ui-page h2 {
251     margin: 0;
252     padding: 0;
253     font-family: Cookie;
254     font-size: 3em;
255     text-shadow: -.05em -.05em 0 #fff, .05em -.05em 0 #fff, .05em .05em 0 #fff, -.05em .05em 0 #fff, 0 -.07em 0 #fff, .07em 0 0 #fff, 0 .07em 0 #fff, -.07em 0 0 #fff;
256   }
257   .upInTheAirGame .ui-page .area {
258     overflow-y: auto;
259     background: #000d;
260     border-radius: 1em;
261     padding: .7em 1.2em;
262     color: #fff;
263     font-family: 'Nihonium113';
264     font-size: 1.2em;
265   }
266   .upInTheAirGame .ui-page .area h3 {
267     margin: 1ex 0 .4ex 0;
268     padding: 0;
269     font-size: 1.4em;
270     font-weight: bold;
271   }
272   .upInTheAirGame .ui-page .area h3:first-child {
273     margin-top: 0;
274   }
275   .upInTheAirGame .ui-page .area h3.bigskip {
276     margin-top: 1.5em;
277   }
278   .upInTheAirGame .ui-page .area h4 {
279     margin: 1ex 0 .4ex 0;
280     padding: 0;
281     font-size: 1.2em;
282     font-weight: bold;
283   }
284   .upInTheAirGame .ui-page .area a {
285     color: #d53c59;
286   }
287   .upInTheAirGame .ui-page .area p {
288     margin: 0;
289     padding: 0;
290   }
291   .upInTheAirGame .ui-page .area p.seealso {
292     margin-top: 1em;
293     text-align: center;
294   }
295   .upInTheAirGame .ui-page .area.twocol {
296     flex-grow: 1;
297     display: flex;
298     flex-direction: row;
299     gap: 2em;
300   }
301   .upInTheAirGame .ui-page .area.twocol .column {
302     display: flex;
303     flex-direction: column;
304     flex-grow: 1;
305     justify-content: space-between;
306     gap: .1em;
307     overflow-y: scroll;
308   }
309   .upInTheAirGame .ui-page .area.twocol .column:last-child {
310     width: 40%;
311     flex-grow: 0;
312     flex-shrink: 0;
313   }
314   .upInTheAirGame .ui-page.controls {
315     background-color: #fff;
316     color: #444;
317     padding: 1em;
318     display: flex;
319     flex-direction: column;
320     justify-content: center;
321     align-items: center;
322     font-size: 1.5em;
323     text-align: center;
324   }
325   .upInTheAirGame .ui-page.controls p {
326     margin: .15em auto;
327     max-width: 23em;
328     font-size: .8em;
329     line-height: 1.2;
330   }
331   .upInTheAirGame .ui-page.controls p:last-child {
332     font-size: .85;
333   }
334   .upInTheAirGame .ui-page.controls svg {
335     margin: 1em;
336     max-height: 8em;
337   }
338   .upInTheAirGame .ui-page.controls svg path {
339     fill: currentColor;
340   }
341   .upInTheAirGame .ui-page.controls button {
342     margin: 1em;
343     border: 1px solid #444;
344     box-shadow: 0 2px #444;
345     padding: .6em 1em;
346     background: #fff;
347     color: #444;
348     font-family: unset;
349     font-size: 1em;
350   }
351   .upInTheAirGame .ui-page.controls button:hover {
352     background: #eee;
353     border: 1px solid #444;
354   }
355   .upInTheAirGame .ui-page.controls button:active {
356     background: #ddd;
357     border: 1px solid #444;
358   }
359   .upInTheAirGame .ui-page.options .feather {
360     flex-grow: 1;
361     display: flex;
362     flex-direction: column;
363     justify-content: space-evenly;
364     align-items: center;
365   }
366   .upInTheAirGame .ui-page.options .feather input,
367   .upInTheAirGame .ui-page.title .system-buttons input {
368     position: absolute;
369     left: -99999px;
370     width: 1px;
371     height: 1px;
372     opacity: 0;
373   }
374   .upInTheAirGame .ui-page.options .feather img {
375     width: 6em;
376     margin: -2em 0;
377     transition: 150ms transform;
378     transform: scaleY(-1) translateX(-1em);
379   }
380   .upInTheAirGame .ui-page.options .feather input:checked + img {
381     transform: scaleY(-1) translateX(1em);
382   }
383   .upInTheAirGame .ui-page.options .feather label:hover img,
384   .upInTheAirGame .ui-page.options .feather label:focus-within img {
385     filter: 
386         drop-shadow(-.1em -.1em 0 #fff) 
387         drop-shadow(.1em -.1em 0 #fff)
388         drop-shadow(.1em .1em 0 #fff) 
389         drop-shadow(-.1em .1em 0 #fff);
390   }
391   .upInTheAirGame .ui-page.options .warning.storage {
392     display: none;
393   }
394   .upInTheAirGame .ui-page.options .feather label:nth-child(1) { z-index: 50; }
395   .upInTheAirGame .ui-page.options .feather label:nth-child(2) { z-index: 49; }
396   .upInTheAirGame .ui-page.options .feather label:nth-child(3) { z-index: 48; }
397   .upInTheAirGame .ui-page.options .feather label:nth-child(4) { z-index: 47; }
398   .upInTheAirGame .ui-page.options .feather label:nth-child(5) { z-index: 46; }
399   .upInTheAirGame .ui-page.options .feather label:nth-child(6) { z-index: 45; }
400   .upInTheAirGame .ui-page.options .feather label:nth-child(7) { z-index: 44; }
401   .upInTheAirGame .ui-page.options .feather label:nth-child(8) { z-index: 43; }
402   .upInTheAirGame .ui-page.options .feather label:nth-child(9) { z-index: 42; }
403   .upInTheAirGame .ui-page.options .feather label:nth-child(10) { z-index: 41; }
404   .upInTheAirGame .ui-page.options .feather label:nth-child(11) { z-index: 40; }
405   .upInTheAirGame .ui-page.options .feather label:nth-child(12) { z-index: 39; }
406   .upInTheAirGame .ui-page.options .feather label:nth-child(13) { z-index: 38; }
407   .upInTheAirGame .ui-page.options .feather label:nth-child(14) { z-index: 37; }
408   .upInTheAirGame .ui-page.options .feather label:nth-child(15) { z-index: 36; }
409   .upInTheAirGame .ui-page.loading {
410     background-color: #fff;
411     display: flex;
412     flex-direction: column;
413     justify-content: center;
414     align-items: center;
415     gap: 1ex;
416     opacity: 1;
417     font-size: 1.3rem;
418   }
419   .upInTheAirGame .ui-page.loading img {
420     display: block;
421     margin-bottom: 1rem;
422     animation: upInTheAirGame-loading-pinwheel-spin 2s linear infinite;
423   }
424   @keyframes upInTheAirGame-loading-pinwheel-spin {
425     100% {
426       transform:rotate(360deg);
427     }
428   }
429   .upInTheAirGame .ui-page.loading progress {
430     box-sizing: border-box;
431     height: 10px;
432     border-radius: 5px;
433     border: 1px inset #000a;
434     background: #80808030;
435     appearance: none;
436   }
437   .upInTheAirGame .ui-page.loading progress::-webkit-progress-value,
438   .upInTheAirGame .ui-page.loading progress::-moz-progress-bar {
439     background: #f998a6;
440   }
441   .upInTheAirGame .ui-page.title {
442     padding: 3em;
443     display: flex;
444     flex-direction: column;
445     justify-content: flex-start;
446     align-items: end;
447     gap: 2em;
448   }
449   .upInTheAirGame .ui-page.title.end {
450     align-items: start;
451   }
452   .upInTheAirGame .ui-page.title h1 {
453     font-size: 1em;
454     width: 24em;
455     aspect-ratio: 174 / 96;
456     background: url('textures/logo.png');
457     background-size: contain;
458     background-repeat: no-repeat;
459     background-position: center;
460     margin: 0 0 .7em;
461     padding: 0;
462     color: #fff0;
463   }
464   .upInTheAirGame .ui-page.title::before {
465     /* image preloading hack */
466     content: url('textures/button-hover.png') url('textures/button-pressed.png');
467     position: absolute;
468     left: -9999px;
469     top: -99999px;
470     opacity: 0;
471   }
472   .upInTheAirGame .ui-page > button,
473   .upInTheAirGame .ui-page.outro .area button {
474     padding: 0;
475     min-width: 8em;
476     color: #000;
477     font-family: Cookie;
478     font-size: 2.5em;
479     line-height: 1em;
480     appearance: none;
481     background: #f4f09a;
482     border: .4em outset #fffcbf;
483     border-radius: 1em;
484     border-image: url('textures/button-standard.png') 20 / .75em round;
485     border-image-outset: .2em;
486   }
487   .upInTheAirGame .font-opendyslexic .ui-page > button,
488   .upInTheAirGame .font-opendyslexic .ui-page.outro .area button {
489     min-width: 10em;
490   }
491   .upInTheAirGame .ui-page > button:hover,
492   .upInTheAirGame .ui-page.outro .area button:hover {
493     background: #e9ce8a;
494     border-image-source: url('textures/button-hover.png');
495   }
496   .upInTheAirGame .ui-page > button:active,
497   .upInTheAirGame .ui-page.outro .area button:active {
498     background: #f9c8d5;
499     border-image-source: url('textures/button-pressed.png');
500   }
501   .upInTheAirGame .ui-page.title .system-buttons {
502     position: absolute;
503     left: 0;
504     bottom: 0;
505     padding: .7ex;
506     display: flex;
507     flex-direction: column;
508     align-items: start;
509     gap: 1ex;
510   }
511   .upInTheAirGame .ui-page.title.end .system-buttons {
512     left: unset;
513     right: 0;
514     align-items: end;
515   }
516   @media not (hover: hover) {
517     .upInTheAirGame .ui-page.title .system-buttons {
518       font-size: 2em;
519     }
520   }
521   .upInTheAirGame .ui-page.title .system-buttons svg {
522     width: 2em;
523     height: 2em;
524   }
525   .upInTheAirGame .ui-page.title .system-buttons svg:hover {
526     filter: drop-shadow(0 0 1px #000);
527   }
528   .upInTheAirGame .ui-page.title .system-buttons label input:not(:checked) + svg g {
529     display: none;
530   }
531   .upInTheAirGame .ui-page.title .system-buttons button {
532     appearance: none;
533     display: block;
534     margin: 0;
535     padding: 0;
536     border: none;
537     background: none;
538     font-size: 1em;
539   }
540   .upInTheAirGame .ui-page.title .footer {
541     position: absolute;
542     right: 0;
543     bottom: 0;
544     padding: .7ex;
545     display: flex;
546     flex-direction: column;
547     align-items: end;
548     font-family: 'Nihonium113';
549     font-size: 1.4em;
550     text-shadow: -.07em -.07em 0 #fff, .07em -.07em 0 #fff, .07em .07em 0 #fff, -.07em .07em 0 #fff, 0 -.1em 0 #fff, .1em 0 0 #fff, 0 .1em 0 #fff, -.1em 0 0 #fff;
551   }
552   .upInTheAirGame .ui-container:not(.font-atkinson):not(.font-opendyslexic) .ui-page.title .footer {
553     line-height: .9em;
554   }
555   .upInTheAirGame .ui-page.title.end .footer {
556     right: unset;
557     left: 0;
558     align-items: start;
559   }
560   .upInTheAirGame .ui-page.title .footer a.fediverse {
561     background-image: url('textures/fediverse.svg');
562     background-size: contain;
563     background-repeat: no-repeat;
564     background-position: left;
565     padding-left: 1.2em;
566   }
567   .upInTheAirGame .ui-page.gameplay .hud {
568     position: absolute;
569     left: .4em;
570     top: .4em;
571     width: 2em;
572     height: 2em;
573     display: flex;
574     align-items: center;
575     justify-content: center;
576     font-size: 1.6em;
577     font-family: Cookie;
578     text-shadow: -.05em -.05em 0 #fff, .05em -.05em 0 #fff, .05em .05em 0 #fff, -.05em .05em 0 #fff, 0 -.07em 0 #fff, .07em 0 0 #fff, 0 .07em 0 #fff, -.07em 0 0 #fff;
579     opacity: 0;
580     display: none;
581     pointer-events: none;
582   }
583   .upInTheAirGame .ui-page.gameplay .hud svg {
584     position: absolute;
585     left: 0;
586     top: 0;
587   }
588   .upInTheAirGame .ui-page.gameplay p {
589     position: absolute;
590     font-family: 'Cookie';
591     font-size: 3em;
592     text-shadow: -.05em -.05em 0 #fff, .05em -.05em 0 #fff, .05em .05em 0 #fff, -.05em .05em 0 #fff, 0 -.07em 0 #fff, .07em 0 0 #fff, 0 .07em 0 #fff, -.07em 0 0 #fff;
593   }
594   .upInTheAirGame .font-opendyslexic .ui-page.gameplay p {
595     font-size: 2.4em;
596   }
597   .upInTheAirGame .ui-page.credits {
598     padding: 1em;
599     display: flex;
600     flex-direction: column;
601     justify-content: center;
602     align-items: center;
603     gap: 1em;
604   }
605   .upInTheAirGame .ui-page.options {
606     position: relative;
607     padding: 1em;
608     display: flex;
609     flex-direction: column;
610     justify-content: center;
611     align-items: center;
612     gap: 1em;
613   }
614   .upInTheAirGame .ui-page.options .area.accessibility {
615     display: none;
616   }
617   .upInTheAirGame .ui-page.options .areatabs {
618     margin-bottom: -1em;
619     display: flex;
620     align-items: center;
621     gap: 1ex;
622   }
623   .upInTheAirGame .ui-page.options .areatabs button {
624     appearance: none;
625     width: 10em;
626     padding: .5em;
627     border: none;
628     border-radius: 1em 1em 0 0;
629     background: #000d;
630     color: #fff;
631     font-family: 'Nihonium113';
632     font-size: 1.6em;
633   }
634   .upInTheAirGame .ui-page.options .areatabs button.active {
635     padding-bottom: .7em;
636   }
637   .upInTheAirGame .ui-page input[type=range] {
638     font-size: 1em;
639     accent-color: #c50031;
640   }
641   .upInTheAirGame .ui-page input[type=radio],
642   .upInTheAirGame .ui-page input[type=checkbox] {
643     width: 1.3em;
644     height: 1.3em;
645     margin: .2em 0;
646     font-size: 1em;
647     vertical-align: sub;
648     accent-color: #c50031;
649   }
650   .upInTheAirGame .ui-page.options .area button {
651     padding: .3em;
652     width: max-content;
653     font-size: 1em;
654     font-family: 'Nihonium113';
655   }
656   .upInTheAirGame .ui-page.options .controls {
657     position: relative;
658   }
659   .upInTheAirGame .ui-page.options .controls p:last-child {
660     margin-top: 1em;
661     padding-right: 1em;
662     height: 4em;
663   }
664   .upInTheAirGame .ui-page.options .controls p:last-child span:not(:first-child) {
665     display: none;
666   }
667   .upInTheAirGame .ui-page.options .controls .leftside {
668     position: absolute;
669     left: 60%;
670     top: 4em;
671     max-width: 40%;
672   }
673   .upInTheAirGame .ui-page.options .controls .leftside label {
674     display: inline;
675   }
676   .upInTheAirGame .ui-page.options .graphics *:not(.audio) label,
677   .upInTheAirGame .ui-page.options .audiotheme:not(.audio) label {
678     display: inline;
679     margin-left: 1ex;
680   }
681   .upInTheAirGame .font-opendyslexic .ui-page.options .graphics *:not(.audio) label,
682   .upInTheAirGame .font-opendyslexic .ui-page.options .audiotheme:not(.audio) label {
683     margin-left: 0;
684   }
685   .upInTheAirGame .font-opendyslexic .ui-page.options .graphics p {
686     display: flex;
687     align-items: center;
688     gap: 1ex;
689   }
690   .upInTheAirGame .font-opendyslexic .ui-page.options .audiotheme:not(.audio) label {
691     margin-right: 1em;
692   }
693   .upInTheAirGame .ui-page.options p.annotation {
694     margin: 0 0 .7em 1.6em;
695   }
696   .upInTheAirGame .ui-page.options label.standardfont {
697     font-family: 'Nihonium113' !important;
698   }
699   .upInTheAirGame .ui-page.options label.atkinson {
700     font-family: 'Atkinson Hyperlegible' !important;
701   }
702   .upInTheAirGame .ui-page.options label.opendyslexic {
703     font-family: OpenDyslexic !important;
704   }
705   .upInTheAirGame .ui-page.options div.difficulty p:nth-child(4) {
706     margin-top: 1ex;
707   }
708   .upInTheAirGame .ui-page .audio {
709     display: grid;
710     gap: .5ex 1ex;
711   }
712   .upInTheAirGame .ui-page.options .audio {
713     grid-template-columns: auto auto auto;
714   }
715   .upInTheAirGame .ui-page.options .audio h3 {
716     grid-column: 1 / 4;
717   }
718   .upInTheAirGame .ui-page.pause .audio {
719     grid-template-columns: auto auto;
720     color: #fff;
721     font-size: 1.2em;
722     font-family: 'Nihonium113';
723   }
724   .upInTheAirGame .ui-page .audio label,
725   .upInTheAirGame .ui-page .audio span {
726     display: flex;
727     align-items: center;
728     justify-content: end;
729     gap: 1ex;
730   }
731   .upInTheAirGame .ui-page.options *:not(.audio) > label {
732     display: flex;
733     align-items: center;
734     justify-content: start;
735     gap: 1ex;
736     width: max-content;
737   }
738   .upInTheAirGame .ui-page.options .area.twocol .keyboard {
739     display: flex;
740     flex-direction: column;
741     justify-content: flex-start;
742     gap: 1em;
743   }
744   .upInTheAirGame .ui-page.options .keyboard div:nth-child(2) {
745     width: max-content;
746     margin: 0 auto;
747     display: flex;
748     flex-direction: column;
749     justify-content: flex-start;
750     align-items: flex-end;
751   }
752   .upInTheAirGame .ui-page.options .keyboard label button {
753     box-sizing: border-box;
754     margin: .7ex 0 .7ex .7ex;
755     padding: 0;
756     width: 5em;
757     height: 1.5em;
758     display: flex;
759     justify-content: center;
760     align-items: center;
761     overflow: hidden;
762     white-space: nowrap;
763   }
764   .upInTheAirGame .ui-page.options .keyboard  div > button {
765     align-self: center;
766     margin-top: 1em;
767   }
768   .upInTheAirGame .ui-page.keyboard-modal {
769     z-index: 20;
770     opacity: 1;
771     display: flex;
772     justify-content: center;
773     align-items: center;
774     background: #000c;
775     font-size: 2em;
776     font-family: 'Nihonium113';
777     color: #fff;
778   }
779   .upInTheAirGame .ui-page .audio input[type=range] {
780     width: 8em;
781   }
782   .upInTheAirGame .ui-page .audio span {
783     width: 1.2em;
784     text-align: right;
785   }
786   .upInTheAirGame .ui-page.options select {
787     font-family: 'Nihonium113';
788     font-size: 1em;
789   }
790   .upInTheAirGame .ui-page.outro {
791     padding: 1em;
792     display: flex;
793     flex-direction: column;
794     justify-content: center;
795     align-items: center;
796     gap: 1em;
797   }
798   .upInTheAirGame .ui-page.outro .area {
799     display: flex;
800     flex-direction: column;
801     justify-content: center;
802     align-items: center;
803     font-size: 2em;
804     text-align: center;
805     gap: 1em;
806   }
807   .upInTheAirGame .ui-page.outro .area div.examples {
808     box-sizing: border-box;
809     width: 100%;
810     border-radius: .4em;
811     padding: .6em;
812     background: #ece3d5;
813     display: flex;
814     flex-direction: column;
815     color: #000;
816     font-family: Cookie;
817   }
818   .upInTheAirGame .font-opendyslexic .ui-page.outro .area > p {
819     font-size: 0.9em;
820   }
821   .upInTheAirGame .ui-page.outro .area strong {
822     font-weight: normal;
823     color: #d53c59;
824   }
825   .upInTheAirGame .ui-page.outro .area div.examples strong {
826     font-weight: normal;
827     color: #c50031;
828   }
829   .upInTheAirGame .ui-page.outro .area > p:first-child {
830     display: flex;
831     align-items: center;
832     gap: 1ex;
833   }
834   .upInTheAirGame .ui-page.outro .count {
835     font-size: 2em;
836     color: #d53c59;
837   }
838   .upInTheAirGame .ui-page.outro .area button {
839     width: max-content;
840     min-width: unset;
841     margin: 0;
842     padding: 0 .5em;
843     border-width: .3em;
844     font-size: 1em;
845   }
846   .upInTheAirGame .ui-page.unlock {
847     padding: 1em;
848     display: flex;
849     flex-direction: column;
850     justify-content: center;
851     align-items: center;
852     gap: 1em;
853   }
854   .upInTheAirGame .ui-page.unlock .area {
855     display: flex;
856     flex-direction: column;
857     justify-content: center;
858     align-items: center;
859     font-size: 2em;
860     text-align: center;
861     gap: 1em;
862   }
863   .upInTheAirGame .ui-page.unlock .area img {
864     margin-top: 1em;
865     transform: scale(2, -2);
866   }
867   .upInTheAirGame .ui-page.pause {
868     background: #000d;
869     padding: 1em;
870     display: flex;
871     flex-direction: column;
872     justify-content: center;
873     align-items: center;
874     gap: 1em;
875   }
876   .upInTheAirGame .ui-page.pause h2 {
877     color: #fff;
878     text-shadow: unset;
879   }
880   .upInTheAirGame .ui-page.pause button {
881     margin: .6em;
882   }
883   .upInTheAirGame .ui-page.pause button.small {
884     width: 5em;
885     margin: 0;
886     padding: 0;
887     border-image-width: 1em;
888     font-size: 1.6em;
889   }
890   .upInTheAirGame .ui-container.control-mouse .ui-page.gameplay,
891   .upInTheAirGame .ui-container.control-mouse .ui-page.openingcutscene,
892   .upInTheAirGame .ui-container.control-mouse .ui-page.endingcutscene {
893     cursor: none;
894   }
895   .upInTheAirGame canvas {
896     box-sizing: border-box;
897     display: block;
898     width: 100% !important;
899     height: 100% !important;
900     margin: 0 auto;
901   }
902 </style>
903 <script type="importmap">
904   {
905     "imports": {
906       "three": "/three/three.module.js"
907     }
908   }
909 </script>
910 </head>
911 <body>
912 <div class="upInTheAirGame">
913 <div class="ui-container">
914 <div class="ui-page loading">
915 <img src="textures/pinwheel.png" alt="Spinning red pinwheel loading animation">
916 <progress value="0" max="100"></progress>
917 <div><span>0</span> %</div>
918 </div>
919 <div class="ui-page controls">
920 <p class="mouse">You appear to be using a device with a <strong>mouse or touchpad</strong> and an on-screen cursor.</p>
921 <p class="touchpad">You appear to be using a device with a <strong>touch screen</strong>.</p>
922 <svg version="1.1" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg">
923 <path class="mouse" d="m64 0c-35.3 0-64 28.7-64 64v288c0 35.3 28.7 64 64 64h176l-10.7 32h-69.3c-17.7 0-32 14.3-32 32s14.3 32 32 32h256c17.7 0 32-14.3 32-32s-14.3-32-32-32h-69.3l-10.7-32h176c35.3 0 64-28.7 64-64v-288c0-35.3-28.7-64-64-64h-448zm0 64h448v224h-448v-224zm191.5 67.49c-2.962 0-5.367 2.405-5.367 5.367v85.8c0 2.823 2.29 5.092 5.09 5.092 1.458 0 2.87-0.6256 3.842-1.736l19.11-21.87 13.44 26.91c1.828 3.656 6.272 5.137 9.928 3.309 3.656-1.828 5.137-6.27 3.309-9.926l-13.12-26.31h27.33c2.823 0 5.113-2.29 5.113-5.113 0-1.458-0.6234-2.846-1.711-3.818l-63.4-56.34c-0.995-0.8793-2.246-1.365-3.564-1.365z"/>
924 <path class="touchpad" d="m112 64c0-35.3 28.7-64 64-64h224c35.3 0 64 28.7 64 64v384c0 35.3-28.7 64-64 64h-224c-35.3 0-64-28.7-64-64zm128 384c0 8.8 7.2 16 16 16h64c8.8 0 16-7.2 16-16s-7.2-16-16-16h-64c-8.8 0-16 7.2-16 16zm160-384h-224v320h224z"/>
925 </svg>
926 <p>Setting gameplay controls to: <strong><span class="mouse">Mouse movement</span><span class="touchpad">Virtual touchpad</span></strong></p>
927 <p>If this is incorrect or you have other preferences, different game control settings are available in the options menu.</p>
928 <button class="goto title">Continue</button>
929 <p>This message will only be shown on first launch.</p>
930 </div>
931 <div class="ui-page title">
932 <h1>Up in the Air</h1>
933 <button class="goto openingcutscene">Start Game</button>
934 <button class="goto options">Options</button>
935 <button class="goto credits">Credits</button>
936 <div class="system-buttons">
937 <label>
938 <input type="checkbox" name="mute">
939 <svg version="1.1" viewBox="0 0 34 34" xmlns="http://www.w3.org/2000/svg" aria-label="Mute audio">
940 <path d="m14 4v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-5v1h-1v1h-1v8h1v1h1v1h5v1h1v1h1v1h1v1h1v1h1v1h1v1h4v-1h1v-6h1v1h1v1h3v2h1v1h4v-1h1v-2h1v-2h1v-4h1v-4h-1v-5h-1v-1h-1v-2h-1v-1h-4v1h-1v2h-3v1h-1v1h-1v-6h-1v-1h-3z" fill="#fff"/>
941 <path d="m15 6v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-5v1h-1v6h1v1h5v1h1v1h1v1h1v1h1v1h1v1h1v1h2v-22h-1zm11 2v3h1v2h1v8h-1v2h-1v3h2v-2h1v-2h1v-4h1v-2h-1v-5h-1v-1h-1v-2h-1zm-4 3v1h1v2h1v6h-1v2h-1v1h3v-1h1v-4h1v-2h-1v-4h-1v-1h-2zm-2 2v1h-1v1h1v4h-1v1h1v1h1v-1h1v-6h-1v-1z" fill="#000"/>
942 <g>
943 <path d="m27 0v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v4h1v1h1v1h1v1h4v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-4h-1v-1h-1v-1h-1v-1h-3z" fill="#fff"/>
944 <path d="m28 2v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v1h-1v2h1v1h1v1h2v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-1h1v-2h-1v-1h-1v-1h-1z" fill="#000"/>
945 </g>
946 </svg>
947 </label>
948 <button>
949 <svg version="1.1" viewBox="0 0 34 34" xmlns="http://www.w3.org/2000/svg">
950 <path d="m0 0v11h7v-4h4v-7h-11zm23 0v7h4v4h7v-11h-11zm-23 23v11h11v-7h-4v-4h-7zm27 0v4h-4v7h11v-11h-7z" fill="#fff"/>
951 <path d="m2 2v7h3v-4h4v-3h-7zm23 0v3h4v4h3v-7h-7zm-23 23v7h7v-3h-4v-4h-3zm27 0v4h-4v3h7v-7h-3z" fill="#000"/>
952 </svg>
953 </button>
954 </div>
955 <div class="footer">
956 <span>Version: 0.9.1</span>
957 <span>A game for <a href="https://itch.io/jam/fedi-jam" target="_blank" class="fediverse">FediJam 2024</a></span>
958 <span>Website: <a href="https://fietkau.media/up_in_the_air" target="_blank">fietkau.media/up_in_the_air</a></span>
959 </div>
960 </div>
961 <div class="ui-page options">
962 <h2>Options</h2>
963 <div class="areatabs">
964 <button class="general active">General</button>
965 <button class="accessibility">Accessibility</button>
966 </div>
967 <div class="area twocol general">
968 <div class="column">
969 <div class="controls">
970 <h3>Controls</h3>
971 <div class="leftside"><label><input type="checkbox">&nbsp;&nbsp;Left side</label></div>
972 <p><label><input type="radio" name="upInTheAirGame-controls" value="mouse"> Mouse movement</label></p>
973 <p><label><input type="radio" name="upInTheAirGame-controls" value="touchpad"> Virtual touchpad</label></p>
974 <p><label><input type="radio" name="upInTheAirGame-controls" value="thumbstick"> Virtual thumbstick</label></p>
975 <p><label><input type="radio" name="upInTheAirGame-controls" value="keyboard"> Keyboard</label></p>
976 <p><label><input type="radio" name="upInTheAirGame-controls" value="gamepad"> Gamepad</label></p>
977 <p>
978 <span class="mouse">The game is controlled by moving the mouse cursor around inside the play area.</span>
979 <span class="touchpad">The game is controlled through touch movements on an on-screen touchpad. Movements correspond directly to the play area.</span>
980 <span class="thumbstick">The game is controlled through touch movements on an on-screen thumbstick. Directional movements steer the cursor.</span>
981 <span class="keyboard">The game is controlled through arrow or WASD key presses. Key rebinding and additional accessibility options are available.</span>
982 <span class="gamepad">The game is controlled using the thumbstick of an attached gamepad accessory.</span>
983 </p>
984 </div>
985 <div class="graphics">
986 <h3>Graphics</h3>
987 <p>Quality:
988 <label><input type="radio" name="upInTheAirGame-graphics" value="1"> Full</label>
989 <label><input type="radio" name="upInTheAirGame-graphics" value="2"> Reduced</label>
990 <label><input type="radio" name="upInTheAirGame-graphics" value="3"> Minimal</label>
991 </p>
992 </div>
993 <div class="hud">
994 <label><input type="checkbox" name="upInTheAirGame-hud"> Enable HUD</label>
995 <p class="annotation">Shows the number of collected words and the progress through the course in the top left. Only recommended for repeat players and high score chasers.</p>
996 </div>
997 <div class="audio">
998 <h3>Audio</h3>
999 <label>Music:
1000 <input type="range" min="0" max="100" value="50" step="1" class="music"></label>
1001 <span>50</span>
1002 <button class="music">Test</button>
1003 <label>Sound effects:
1004 <input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
1005 <span>50</span>
1006 <button class="sounds">Test</button>
1007 </div>
1008 <div class="audiotheme">
1009 <template><label><input type="radio" name="upInTheAirGame-audiotheme" value="default"> Default</label></template>
1010 <span>Audio theme:</span>
1011 </div>
1012 </div>
1014 <div class="column">
1015 <h3>Feather Customization</h3>
1016 <p>You can change the feather’s visual appearance. This is an aesthetic choice with no impact on the game mechanics.</p>
1017 <div class="feather">
1018 <label><input type="radio" name="upInTheAirGame-feather" value="blue"><img src="textures/feather-blue.png" alt="Blue feather"></label>
1019 <label><input type="radio" name="upInTheAirGame-feather" value="red"><img src="textures/feather-red.png" alt="Red feather"></label>
1020 <label><input type="radio" name="upInTheAirGame-feather" value="green"><img src="textures/feather-green.png" alt="Green feather"></label>
1021 <label><input type="radio" name="upInTheAirGame-feather" value="black"><img src="textures/feather-black.png" alt="Black feather"></label>
1022 <label><input type="radio" name="upInTheAirGame-feather" value="brown"><img src="textures/feather-brown.png" alt="Brown feather"></label>
1023 <label><input type="radio" name="upInTheAirGame-feather" value="orange"><img src="textures/feather-orange.png" alt="Orange feather"></label>
1024 <label><input type="radio" name="upInTheAirGame-feather" value="purple"><img src="textures/feather-purple.png" alt="Purple feather"></label>
1025 </div>
1026 </div>
1027 </div>
1030 <div class="area twocol accessibility">
1031 <div class="column">
1032 <div>
1033 <h3>Visuals</h3>
1034 <label><input type="checkbox" value="highcontrast"> High contrast mode</label>
1035 <p class="annotation">Render collectibles as bright green dots, replace clouds with dark background.</p>
1036 </div>
1037 <div class="font">
1038 <h3>Font</h3>
1039 <p><label class="standardfont"><input type="radio" name="upInTheAirGame-font" value="standard"> Standard</label></p>
1040 <p><label class="atkinson"><input type="radio" name="upInTheAirGame-font" value="atkinson"> Atkinson Hyperlegible</label></p>
1041 <p><label class="opendyslexic"><input type="radio" name="upInTheAirGame-font" value="opendyslexic"> OpenDyslexic</label></p>
1042 </div>
1043 <div class="difficulty">
1044 <h3>Difficulty</h3>
1045 <p><label>Collecting radius:&nbsp;&nbsp;&nbsp;<select class="collectingradius">
1046 <option value="1">Standard</option>
1047 <option value="2">Generous</option>
1048 <option value="3">Eager</option>
1049 </select></label></p>
1050 <p class="annotation">This setting adjusts how close you need to get to a collectible in order to pick it up.</p>
1051 <p><label>Gameplay speed:&nbsp;&nbsp;&nbsp;<select class="speed">
1052 <option value="100">100 %</option>
1053 <option value="50">50 %</option>
1054 <option value="25">25 %</option>
1055 <option value="10">10 %</option>
1056 </select></label></p>
1057 <p class="annotation">This setting adjusts the speed of the gameplay clock, slowing down all in-game movement and giving you more time to react.</p>
1058 </div>
1059 </div>
1061 <div class="column keyboard">
1062 <div>
1063 <h3>Keyboard Settings</h3>
1064 <p>These settings only have an effect if keyboard controls are enabled.</p>
1065 </div>
1066 <div>
1067 <label>Up: <button class="up" value="ArrowUp|w">🠕 or W</button></label>
1068 <label>Right: <button class="right" value="ArrowRight|d">🠖 or D</button></label>
1069 <label>Down: <button class="down" value="ArrowDown|s">🠗 or S</button></label>
1070 <label>Left: <button class="left" value="ArrowLeft|a">🠔 or A</button></label>
1071 <button value="reset">Reset to default</button>
1072 </div>
1073 <div>
1074 <label><input type="checkbox" value="tapmode"> Tap mode</label>
1075 <p class="annotation">With this setting enabled, movement gets triggered by tapping the keys instead of holding them. Tap a direction multiple times to accelerate, tap the opposite direction to stop.</p>
1076 </div>
1077 </div>
1078 </div>
1080 <div class="area warning storage"><strong>Unable to store data:</strong> Your browser is preventing the game from using the local data storage, possibly due to strict privacy settings. Your in-game data will not be saved between visits.</div>
1082 <button class="goto title">Back</button>
1083 </div>
1084 <div class="ui-page credits">
1085 <h2>Credits</h2>
1086 <div class="area">
1087 <h3>Production / Direction / Programming</h3>
1088 <div class="person julian">
1089 <p>Julian Fietkau</p>
1090 <p><a href="https://fietkau.social/@julian" target="_blank">@julian@fietkau.social</a></p>
1091 <p><a href="https://fietkau.me/" target="_blank">https://fietkau.me</a></p>
1092 </div>
1093 <h3>Artwork</h3>
1094 <div class="person nina">
1095 <p>Nina</p>
1096 <p><a href="https://mastodon.art/@misnina" target="_blank">@misnina@mastodon.art</a></p>
1097 <p><a href="https://misnina.com/" target="_blank">https://misnina.com</a></p>
1098 </div>
1099 <h3 class="bigskip">External Resources</h3>
1100 <h4>Music</h4>
1101 <p>“<a href="https://incompetech.com/music/royalty-free/index.html?isrc=USUAN1100301" target="_blank">Canon in D Major</a>” composed by Johann Pachelbel, arranged by <a href="https://incompetech.com/" target="_blank">Kevin MacLeod</a>
1102 <h4>Sound Effects</h4>
1103 <p>“<a href="https://freesound.org/people/cabled_mess/packs/19827/" target="_blank">Glockenspiel</a>” by <a href="https://computingsound.wixsite.com/cabledmess" target="_blank">Cabled Mess</a> (via <a href="https://freesound.org/" target="_blank">Freesound.org</a>)</p>
1104 <h4>Fonts</h4>
1105 <p>“<a href="https://fonts.google.com/specimen/Cookie" target="_blank">Cookie</a>” by Ania Kruk</p>
1106 <p>“<a href="https://www.1001fonts.com/nihonium113-font.html" target="_blank">Nihonium113</a>” by <a href="https://www.behance.net/japanyoshi" target="_blank">Haley Wakamatsu / UkiyoMoji Fonts</a></p>
1107 <p>“<a href="https://www.brailleinstitute.org/freefont/" target="_blank">Atkinson Hyperlegible</a>” by <a href="https://www.brailleinstitute.org/" target="_blank">Braille Institute of America, Inc.</a></p>
1108 <p>“<a href="https://opendyslexic.org/" target="_blank">OpenDyslexic</a>” by <a href="https://abbiegonzalez.com/" target="_blank">Abbie Gonzalez</a> (<a href="https://hackers.town/@antijingoist" target="_blank">@antijingoist@hackers.town</a>)</p>
1109 <p>Logo: “<a href="https://www.fontspace.com/precious-font-f7252" target="_blank">Precious</a>” by Bolt Cutter Design</p>
1110 <h4>Icons</h4>
1111 <p><a href="https://github.com/FortAwesome/Font-Awesome/blob/6.x/svgs/solid/desktop.svg" target="_blank">Desktop</a>, <a href="https://github.com/FortAwesome/Font-Awesome/blob/6.x/svgs/solid/arrow-pointer.svg" target="_blank">Arrow Pointer</a>, and <a href="https://github.com/FortAwesome/Font-Awesome/blob/6.x/svgs/solid/mobile-screen.svg" target="_blank">Mobile with Screen</a> by Fonticons, Inc. (<a href="https://fontawesome.com/" target="_blank">Font Awesome</a>)</p>
1112 <h4>Engine</h4>
1113 <p><a href="https://threejs.org/" target="_blank">three.js</a> v169 by mrdoob and contributors</p>
1114 <h4>Inspiration</h4>
1115 <p>Game concept inspired by: “<a href="https://www.ferryhalim.com/orisinal/g3/high.htm" target="_blank">High Delivery</a>” by <a href="https://www.ferryhalim.com/" target="_blank">Ferry Halim</a></p>
1116 <p class="seealso">See <a href="README.txt" target="_blank">README.txt</a> for detailed licensing information.</p>
1117 </div>
1118 <button class="goto title">Back</button>
1119 </div>
1120 <div class="ui-page openingcutscene"></div>
1121 <div class="ui-page endingcutscene"></div>
1122 <div class="ui-page outro">
1123 <div class="area outro">
1124 <p>You collected <span class="count">0</span> <span class="optionalPlural">words.</span></p>
1125 <p class="rating"></p>
1126 <p class="examples">Here are a few sentences using some of them:</p>
1127 <div class="examples">
1128 </div>
1129 <button class="examples">More</button>
1130 <p>Can you think of anyone to whom you might need to write something along those lines? When was the last time your feelings were left <strong>up in the air</strong>?</p>
1131 </div>
1132 <button class="goto title">Return to Title Screen</button>
1133 </div>
1134 <div class="ui-page unlock">
1135 <div class="area">
1136 <p>You just unlocked a new feather:</p>
1137 <img src="textures/feather-blue.png" alt="Blue feather">
1138 <p class="name">Blue feather</p>
1139 </div>
1140 <button class="goto title">Return to Title Screen</button>
1141 </div>
1142 <div class="ui-page pause">
1143 <h2>Game Paused</h2>
1144 <div class="audio">
1145 <label>Music:
1146 <input type="range" min="0" max="100" value="50" step="1" class="music"></label>
1147 <span>50</span>
1148 <label>Sound effects:
1149 <input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
1150 <span>50</span>
1151 </div>
1152 <button class="goto previous">Continue</button>
1153 <button class="goto title small">Exit</button>
1154 </div>
1155 <div class="ui-page gameplay">
1156 <div class="hud">
1157 <svg viewBox="0 0 1 1" version="1.1" xmlns="http://www.w3.org/2000/svg">
1158 <path fill="#c50031" d="M0,0"/>
1159 <path fill="#00000040" d="M0,0"/>
1160 </svg>
1161 <span>0</span>
1162 </div>
1163 <canvas width="800" height="800"></canvas>
1164 </div>
1165 </div>
1166 <div class="virtual-input-widget">
1167 <div class="circle"></div>
1168 </div>
1169 </div>
1170 <script type="module" src="main.js"></script>
1171 <script>
1172 function start() {
1173   // Wait until game script has finished loading
1174   if(window.startUpInTheAirGame) {
1175     window['game'] = {};
1176     startUpInTheAirGame(window['game']);
1177   } else {
1178     setTimeout(start, 50);
1179   }
1182 if(!['https:', 'http:'].includes(window.location.protocol)) {
1183   document.querySelectorAll('.upInTheAirGame .ui-page:not(.loading)').forEach(page => page.remove());
1184   document.querySelector('.upInTheAirGame .loading div').innerText = 'This game cannot run without a web server.';
1185 } else {
1186   start();
1188 </script>
1189 </body>
1190 </html>