Up-in-the-Air – blob

You can use Git to clone the repository via the web URL. Download snapshot (zip)
Add proper license information for the open source release
[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   .game-upintheair {
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   .game-upintheair:fullscreen {
102     background: #eee;
103   }
104   @media (prefers-color-scheme: dark) {
105     .game-upintheair:fullscreen {
106       background: #111;
107     }
108   }
109   .game-upintheair .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   .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   .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       .game-upintheair .ui-container.control-touchpad, .game-upintheair .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       .game-upintheair .ui-container.control-touchpad, .game-upintheair .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       .game-upintheair.virtual-input-left .ui-container.control-touchpad, .game-upintheair .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     .game-upintheair {
152       --game-margin: 0px;
153     }
154     .virtual-input-widget {
155       bottom: 1rem;
156       right: 1rem;
157     }
158     .virtual-input-left .virtual-input-widget {
159       left: 1rem;
160       right: unset;
161     }
162     @container (min-width: calc(100cqh - 4cm - 2rem)) {
163       .game-upintheair .ui-container.control-touchpad, .game-upintheair .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       .game-upintheair .ui-container.control-touchpad, .game-upintheair .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       .game-upintheair.virtual-input-left .ui-container.control-touchpad, .game-upintheair .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   .game-upintheair .ui-container.font-atkinson * {
180     font-family: 'Atkinson Hyperlegible' !important;
181   }
182   .game-upintheair .ui-container.font-atkinson > .ui-page {
183     font-size: .9em;
184   }
185   .game-upintheair .ui-container.font-opendyslexic * {
186     font-family: 'OpenDyslexic' !important;
187   }
188   .game-upintheair .ui-container.font-opendyslexic > .ui-page {
189     font-size: .8em;
190   }
191   .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   .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   .virtual-input-widget.touchpad .circle {
211     width: 5%;
212     background-color: #fff;
213     opacity: 0.4;
214   }
215   .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   .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   .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   .ui-page:not(.gameplay) {
241     z-index: 10;
242   }
243   .ui-page a {
244     color: #c50031;
245     text-decoration: none;
246   }
247   .ui-page a:hover {
248     text-decoration: underline;
249   }
250   .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   .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   .ui-page .area h3 {
267     margin: 1ex 0 .4ex 0;
268     padding: 0;
269     font-size: 1.4em;
270     font-weight: bold;
271   }
272   .ui-page .area h3:first-child {
273     margin-top: 0;
274   }
275   .ui-page .area h3.bigskip {
276     margin-top: 1.5em;
277   }
278   .ui-page .area h4 {
279     margin: 1ex 0 .4ex 0;
280     padding: 0;
281     font-size: 1.2em;
282     font-weight: bold;
283   }
284   .ui-page .area a {
285     color: #d53c59;
286   }
287   .ui-page .area p {
288     margin: 0;
289     padding: 0;
290   }
291   .ui-page .area p.seealso {
292     margin-top: 1em;
293     text-align: center;
294   }
295   .ui-page .area.twocol {
296     flex-grow: 1;
297     display: flex;
298     flex-direction: row;
299     gap: 2em;
300   }
301   .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   .ui-page .area.twocol .column:last-child {
310     width: 40%;
311     flex-grow: 0;
312     flex-shrink: 0;
313   }
314   .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   .ui-page.controls p {
326     margin: .15em auto;
327     max-width: 23em;
328     font-size: .8em;
329     line-height: 1.2;
330   }
331   .ui-page.controls p:last-child {
332     font-size: .85;
333   }
334   .ui-page.controls svg {
335     margin: 1em;
336     max-height: 8em;
337   }
338   .ui-page.controls svg path {
339     fill: currentColor;
340   }
341   .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   .ui-page.controls button:hover {
352     background: #eee;
353     border: 1px solid #444;
354   }
355   .ui-page.controls button:active {
356     background: #ddd;
357     border: 1px solid #444;
358   }
359   .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   .ui-page.options .feather input, .ui-page.title .system-buttons input {
367     position: absolute;
368     left: -99999px;
369     width: 1px;
370     height: 1px;
371     opacity: 0;
372   }
373   .ui-page.options .feather img {
374     width: 6em;
375     margin: -2em 0;
376     transition: 150ms transform;
377     transform: scaleY(-1) translateX(-1em);
378   }
379   .ui-page.options .feather input:checked + img {
380     transform: scaleY(-1) translateX(1em);
381   }
382   .ui-page.options .feather label:hover img, .ui-page.options .feather label:focus-within img {
383     filter: 
384         drop-shadow(-.1em -.1em 0 #fff) 
385         drop-shadow(.1em -.1em 0 #fff)
386         drop-shadow(.1em .1em 0 #fff) 
387         drop-shadow(-.1em .1em 0 #fff);
388   }
389   .ui-page.options .feather label:nth-child(1) { z-index: 50; }
390   .ui-page.options .feather label:nth-child(2) { z-index: 49; }
391   .ui-page.options .feather label:nth-child(3) { z-index: 48; }
392   .ui-page.options .feather label:nth-child(4) { z-index: 47; }
393   .ui-page.options .feather label:nth-child(5) { z-index: 46; }
394   .ui-page.options .feather label:nth-child(6) { z-index: 45; }
395   .ui-page.options .feather label:nth-child(7) { z-index: 44; }
396   .ui-page.options .feather label:nth-child(8) { z-index: 43; }
397   .ui-page.options .feather label:nth-child(9) { z-index: 42; }
398   .ui-page.options .feather label:nth-child(10) { z-index: 41; }
399   .ui-page.options .feather label:nth-child(11) { z-index: 40; }
400   .ui-page.options .feather label:nth-child(12) { z-index: 39; }
401   .ui-page.options .feather label:nth-child(13) { z-index: 38; }
402   .ui-page.options .feather label:nth-child(14) { z-index: 37; }
403   .ui-page.options .feather label:nth-child(15) { z-index: 36; }
404   .ui-page.loading {
405     background-color: #fff;
406     display: flex;
407     flex-direction: column;
408     justify-content: center;
409     align-items: center;
410     gap: 1ex;
411     opacity: 1;
412     font-size: 1.3rem;
413   }
414   .ui-page.loading img {
415     display: block;
416     margin-bottom: 1rem;
417     animation: loading-pinwheel-spin 2s linear infinite;
418   }
419   @keyframes loading-pinwheel-spin {
420     100% {
421       transform:rotate(360deg);
422     }
423   }
424   .ui-page.loading progress {
425     box-sizing: border-box;
426     height: 10px;
427     border-radius: 5px;
428     border: 1px inset #000a;
429     background: #80808030;
430     appearance: none;
431   }
432   .ui-page.loading progress::-webkit-progress-value, .ui-page.loading progress::-moz-progress-bar {
433     background: #f998a6;
434   }
435   .ui-page.title {
436     padding: 3em;
437     display: flex;
438     flex-direction: column;
439     justify-content: flex-start;
440     align-items: end;
441     gap: 2em;
442   }
443   .ui-page.title.end {
444     align-items: start;
445   }
446   .ui-page.title h1 {
447     font-size: 1em;
448     width: 24em;
449     aspect-ratio: 174 / 96;
450     background: url('textures/logo.png');
451     background-size: contain;
452     background-repeat: no-repeat;
453     background-position: center;
454     margin: 0 0 .7em;
455     padding: 0;
456     color: #fff0;
457   }
458   .ui-page.title::before {
459     /* image preloading hack */
460     content: url('textures/button-hover.png') url('textures/button-pressed.png');
461     position: absolute;
462     left: -9999px;
463     top: -99999px;
464     opacity: 0;
465   }
466   .ui-page > button, .ui-page.outro .area button {
467     padding: 0;
468     min-width: 8em;
469     color: #000;
470     font-family: Cookie;
471     font-size: 2.5em;
472     line-height: 1em;
473     appearance: none;
474     background: #f4f09a;
475     border: .4em outset #fffcbf;
476     border-radius: 1em;
477     border-image: url('textures/button-standard.png') 20 / .75em round;
478     border-image-outset: .2em;
479   }
480   .font-opendyslexic .ui-page > button, .font-opendyslexic .ui-page.outro .area button {
481     min-width: 10em;
482   }
483   .ui-page > button:hover, .ui-page.outro .area button:hover {
484     background: #e9ce8a;
485     border-image-source: url('textures/button-hover.png');
486   }
487   .ui-page > button:active, .ui-page.outro .area button:active {
488     background: #f9c8d5;
489     border-image-source: url('textures/button-pressed.png');
490   }
491   .ui-page.title .system-buttons {
492     position: absolute;
493     left: 0;
494     bottom: 0;
495     padding: .7ex;
496     display: flex;
497     flex-direction: column;
498     align-items: start;
499     gap: 1ex;
500   }
501   .ui-page.title.end .system-buttons {
502     left: unset;
503     right: 0;
504     align-items: end;
505   }
506   @media not (hover: hover) {
507     .ui-page.title .system-buttons {
508       font-size: 2em;
509     }
510   }
511   .ui-page.title .system-buttons svg {
512     width: 2em;
513     height: 2em;
514   }
515   .ui-page.title .system-buttons svg:hover {
516     filter: drop-shadow(0 0 1px #000);
517   }
518   .ui-page.title .system-buttons label input:not(:checked) + svg g {
519     display: none;
520   }
521   .ui-page.title .system-buttons button {
522     appearance: none;
523     display: block;
524     margin: 0;
525     padding: 0;
526     border: none;
527     background: none;
528     font-size: 1em;
529   }
530   .ui-page.title .footer {
531     position: absolute;
532     right: 0;
533     bottom: 0;
534     padding: .7ex;
535     display: flex;
536     flex-direction: column;
537     align-items: end;
538     font-family: 'Nihonium113';
539     font-size: 1.4em;
540     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;
541   }
542   .ui-container:not(.font-atkinson):not(.font-opendyslexic) .ui-page.title .footer {
543     line-height: .9em;
544   }
545   .ui-page.title.end .footer {
546     right: unset;
547     left: 0;
548     align-items: start;
549   }
550   .ui-page.title .footer a.fediverse {
551     background-image: url('textures/fediverse.svg');
552     background-size: contain;
553     background-repeat: no-repeat;
554     background-position: left;
555     padding-left: 1.2em;
556   }
557   .ui-page.gameplay p {
558     position: absolute;
559     font-family: 'Cookie';
560     font-size: 3em;
561     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;
562   }
563   .font-opendyslexic .ui-page.gameplay p {
564     font-size: 2.4em;
565   }
566   .ui-page.credits {
567     padding: 1em;
568     display: flex;
569     flex-direction: column;
570     justify-content: center;
571     align-items: center;
572     gap: 1em;
573   }
574   .ui-page.options {
575     padding: 1em;
576     display: flex;
577     flex-direction: column;
578     justify-content: center;
579     align-items: center;
580     gap: 1em;
581   }
582   .ui-page.options .area.accessibility {
583     display: none;
584   }
585   .ui-page.options .areatabs {
586     margin-bottom: -1em;
587     display: flex;
588     align-items: center;
589     gap: 1ex;
590   }
591   .ui-page.options .areatabs button {
592     appearance: none;
593     width: 10em;
594     padding: .5em;
595     border: none;
596     border-radius: 1em 1em 0 0;
597     background: #000d;
598     color: #fff;
599     font-family: 'Nihonium113';
600     font-size: 1.6em;
601   }
602   .ui-page.options .areatabs button.active {
603     padding-bottom: .7em;
604   }
605   .ui-page input[type=range] {
606     font-size: 1em;
607     accent-color: #c50031;
608   }
609   .ui-page input[type=radio], .ui-page input[type=checkbox] {
610     width: 1.3em;
611     height: 1.3em;
612     margin: .2em 0;
613     font-size: 1em;
614     vertical-align: sub;
615     accent-color: #c50031;
616   }
617   .ui-page.options .area button {
618     padding: .3em;
619     width: max-content;
620     font-size: 1em;
621     font-family: 'Nihonium113';
622   }
623   .ui-page.options .controls {
624     position: relative;
625   }
626   .ui-page.options .controls p:last-child {
627     margin-top: 1em;
628     padding-right: 1em;
629     height: 4em;
630   }
631   .ui-page.options .controls p:last-child span:not(:first-child) {
632     display: none;
633   }
634   .ui-page.options .controls .leftside {
635     position: absolute;
636     left: 60%;
637     top: 4em;
638     max-width: 40%;
639   }
640   .ui-page.options .controls .leftside label {
641     display: inline;
642   }
643   .ui-page.options .graphics *:not(.audio) label, .ui-page.options .audiotheme:not(.audio) label {
644     display: inline;
645     margin-left: 1ex;
646   }
647   .game-upintheair.font-opendyslexic .ui-page.options .graphics *:not(.audio) label,
648   .game-upintheair.font-opendyslexic .ui-page.options .audiotheme:not(.audio) label {
649     margin-left: 0;
650   }
651   .game-upintheair.font-opendyslexic .ui-page.options .graphics p {
652     display: flex;
653     align-items: center;
654     gap: 1ex;
655   }
656   .game-upintheair.font-opendyslexic .ui-page.options .audiotheme:not(.audio) label {
657     margin-right: 1em;
658   }
659   .ui-page.options p.annotation {
660     margin: 0 0 .7em 1.6em;
661   }
662   .ui-page.options label.standardfont {
663     font-family: 'Nihonium113' !important;
664   }
665   .ui-page.options label.atkinson {
666     font-family: 'Atkinson Hyperlegible' !important;
667   }
668   .ui-page.options label.opendyslexic {
669     font-family: OpenDyslexic !important;
670   }
671   .ui-page.options div.difficulty p:nth-child(4) {
672     margin-top: 1ex;
673   }
674   .ui-page .audio {
675     display: grid;
676     gap: .5ex 1ex;
677   }
678   .ui-page.options .audio {
679     grid-template-columns: auto auto auto;
680   }
681   .ui-page.options .audio h3 {
682     grid-column: 1 / 4;
683   }
684   .ui-page.pause .audio {
685     grid-template-columns: auto auto;
686     color: #fff;
687     font-size: 1.2em;
688     font-family: 'Nihonium113';
689   }
690   .ui-page .audio label, .ui-page .audio span {
691     display: flex;
692     align-items: center;
693     justify-content: end;
694     gap: 1ex;
695   }
696   .ui-page.options *:not(.audio) > label {
697     display: flex;
698     align-items: center;
699     justify-content: start;
700     gap: 1ex;
701     width: max-content;
702   }
703   .ui-page.options .area.twocol .keyboard {
704     display: flex;
705     flex-direction: column;
706     justify-content: flex-start;
707     gap: 1em;
708   }
709   .ui-page.options .keyboard div:nth-child(2) {
710     width: max-content;
711     margin: 0 auto;
712     display: flex;
713     flex-direction: column;
714     justify-content: flex-start;
715     align-items: flex-end;
716   }
717   .ui-page.options .keyboard label button {
718     box-sizing: border-box;
719     margin: .7ex 0 .7ex .7ex;
720     padding: 0;
721     width: 5em;
722     height: 1.5em;
723     display: flex;
724     justify-content: center;
725     align-items: center;
726     overflow: hidden;
727     white-space: nowrap;
728   }
729   .ui-page.options .keyboard  div > button {
730     align-self: center;
731     margin-top: 1em;
732   }
733   .ui-page.keyboard-modal {
734     z-index: 20;
735     opacity: 1;
736     display: flex;
737     justify-content: center;
738     align-items: center;
739     background: #000c;
740     font-size: 2em;
741     font-family: 'Nihonium113';
742     color: #fff;
743   }
744   .ui-page .audio input[type=range] {
745     width: 8em;
746   }
747   .ui-page .audio span {
748     width: 1.2em;
749     text-align: right;
750   }
751   .ui-page.options select {
752     font-family: 'Nihonium113';
753     font-size: 1em;
754   }
755   .ui-page.outro {
756     padding: 1em;
757     display: flex;
758     flex-direction: column;
759     justify-content: center;
760     align-items: center;
761     gap: 1em;
762   }
763   .ui-page.outro .area {
764     display: flex;
765     flex-direction: column;
766     justify-content: center;
767     align-items: center;
768     font-size: 2em;
769     text-align: center;
770     gap: 1em;
771   }
772   .ui-page.outro .area div.examples {
773     box-sizing: border-box;
774     width: 100%;
775     border-radius: .4em;
776     padding: .6em;
777     background: #ece3d5;
778     display: flex;
779     flex-direction: column;
780     color: #000;
781     font-family: Cookie;
782   }
783   .font-opendyslexic .ui-page.outro .area > p {
784     font-size: 0.9em;
785   }
786   .ui-page.outro .area strong {
787     font-weight: normal;
788     color: #d53c59;
789   }
790   .ui-page.outro .area div.examples strong {
791     font-weight: normal;
792     color: #c50031;
793   }
794   .ui-page.outro .area > p:first-child {
795     display: flex;
796     align-items: center;
797     gap: 1ex;
798   }
799   .ui-page.outro .count {
800     font-size: 2em;
801     color: #d53c59;
802   }
803   .ui-page.outro .area button {
804     width: max-content;
805     min-width: unset;
806     margin: 0;
807     padding: 0 .5em;
808     border-width: .3em;
809     font-size: 1em;
810   }
811   .ui-page.unlock {
812     padding: 1em;
813     display: flex;
814     flex-direction: column;
815     justify-content: center;
816     align-items: center;
817     gap: 1em;
818   }
819   .ui-page.unlock .area {
820     display: flex;
821     flex-direction: column;
822     justify-content: center;
823     align-items: center;
824     font-size: 2em;
825     text-align: center;
826     gap: 1em;
827   }
828   .ui-page.unlock .area img {
829     margin-top: 1em;
830     transform: scale(2, -2);
831   }
832   .ui-page.pause {
833     background: #000d;
834     padding: 1em;
835     display: flex;
836     flex-direction: column;
837     justify-content: center;
838     align-items: center;
839     gap: 1em;
840   }
841   .ui-page.pause h2 {
842     color: #fff;
843     text-shadow: unset;
844   }
845   .ui-page.pause button {
846     margin: .6em;
847   }
848   .ui-page.pause button.small {
849     width: 5em;
850     margin: 0;
851     padding: 0;
852     border-image-width: 1em;
853     font-size: 1.6em;
854   }
855   .ui-container.control-mouse .ui-page.gameplay, .ui-container.control-mouse .ui-page.openingcutscene, .ui-container.control-mouse .ui-page.endingcutscene {
856     cursor: none;
857   }
858   canvas {
859     box-sizing: border-box;
860     display: block;
861     width: 100% !important;
862     height: 100% !important;
863     margin: 0 auto;
864   }
865   .options {
866     position: relative;
867     padding: .3em;
868   }
869 </style>
870 <script type="importmap">
871   {
872     "imports": {
873       "three": "./three.module.js",
874       "three/addons/": "./addons/"
875     }
876   }
877 </script>
878 </head>
879 <body>
880 <div class="game-upintheair">
881 <div class="ui-container">
882 <div class="ui-page loading">
883 <img src="textures/pinwheel.png" alt="Spinning red pinwheel loading animation">
884 <progress value="0" max="100"></progress>
885 <div><span>0</span> %</div>
886 </div>
887 <div class="ui-page controls">
888 <p class="mouse">You appear to be using a device with a <strong>mouse or touchpad</strong> and an on-screen cursor.</p>
889 <p class="touchpad">You appear to be using a device with a <strong>touch screen</strong>.</p>
890 <svg version="1.1" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg">
891 <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"/>
892 <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"/>
893 </svg>
894 <p>Setting gameplay controls to: <strong><span class="mouse">Mouse movement</span><span class="touchpad">Virtual touchpad</span></strong></p>
895 <p>If this is incorrect or you have other preferences, different game control settings are available in the options menu.</p>
896 <button class="goto title">Continue</button>
897 <p>This message will only be shown on first launch.</p>
898 </div>
899 <div class="ui-page title">
900 <h1>Up in the Air</h1>
901 <button class="goto openingcutscene">Start Game</button>
902 <button class="goto options">Options</button>
903 <button class="goto credits">Credits</button>
904 <div class="system-buttons">
905 <label>
906 <input type="checkbox" name="mute">
907 <svg version="1.1" viewBox="0 0 34 34" xmlns="http://www.w3.org/2000/svg" aria-label="Mute audio">
908 <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"/>
909 <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"/>
910 <g>
911 <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"/>
912 <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"/>
913 </g>
914 </svg>
915 </label>
916 <button>
917 <svg version="1.1" viewBox="0 0 34 34" xmlns="http://www.w3.org/2000/svg">
918 <path d="m0 0v11h7v-4h4v-7h-11zm23 0v7h4v4h7v-11h-11zm-23 23v11h11v-7h-4v-4h-7zm27 0v4h-4v7h11v-11h-7z" fill="#fff"/>
919 <path d="m2 2v7h3v-4h4v-3h-7zm23 0v3h4v4h3v-7h-7zm-23 23v7h7v-3h-4v-4h-3zm27 0v4h-4v3h7v-7h-3z" fill="#000"/>
920 </svg>
921 </button>
922 </div>
923 <div class="footer">
924 <span>Version: 0.9-jam</span>
925 <span>A game for <a href="https://itch.io/jam/fedi-jam" target="_blank" class="fediverse">FediJam 2024</a></span>
926 <span>Website: <a href="https://fietkau.media/up_in_the_air" target="_blank">fietkau.media/up_in_the_air</a></span>
927 </div>
928 </div>
929 <div class="ui-page options">
930 <h2>Options</h2>
931 <div class="areatabs">
932 <button class="general active">General</button>
933 <button class="accessibility">Accessibility</button>
934 </div>
935 <div class="area twocol general">
936 <div class="column">
937 <div class="controls">
938 <h3>Controls</h3>
939 <div class="leftside"><label><input type="checkbox">&nbsp;&nbsp;Left side</label></div>
940 <p><label><input type="radio" name="upInTheAirGame-controls" value="mouse"> Mouse movement</label></p>
941 <p><label><input type="radio" name="upInTheAirGame-controls" value="touchpad"> Virtual touchpad</label></p>
942 <p><label><input type="radio" name="upInTheAirGame-controls" value="thumbstick"> Virtual thumbstick</label></p>
943 <p><label><input type="radio" name="upInTheAirGame-controls" value="keyboard"> Keyboard</label></p>
944 <p><label><input type="radio" name="upInTheAirGame-controls" value="gamepad"> Gamepad</label></p>
945 <p>
946 <span class="mouse">The game is controlled by moving the mouse cursor around inside the play area.</span>
947 <span class="touchpad">The game is controlled through touch movements on an on-screen touchpad. Movements correspond directly to the play area.</span>
948 <span class="thumbstick">The game is controlled through touch movements on an on-screen thumbstick. Directional movements steer the cursor.</span>
949 <span class="keyboard">The game is controlled through arrow or WASD key presses. Key rebinding and additional accessibility options are available.</span>
950 <span class="gamepad">The game is controlled using the thumbstick of an attached gamepad accessory.</span>
951 </p>
952 </div>
953 <div class="graphics">
954 <h3>Graphics</h3>
955 <p>Quality:
956 <label><input type="radio" name="upInTheAirGame-graphics" value="1"> Full</label>
957 <label><input type="radio" name="upInTheAirGame-graphics" value="2"> Reduced</label>
958 <label><input type="radio" name="upInTheAirGame-graphics" value="3"> Minimal</label>
959 </div>
960 <div class="audio">
961 <h3>Audio</h3>
962 <label>Music:
963 <input type="range" min="0" max="100" value="50" step="1" class="music"></label>
964 <span>50</span>
965 <button class="music">Test</button>
966 <label>Sound effects:
967 <input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
968 <span>50</span>
969 <button class="sounds">Test</button>
970 </div>
971 <div class="audiotheme">
972 <template><label><input type="radio" name="upInTheAirGame-audiotheme" value="default"> Default</label></template>
973 <span>Audio theme:</span>
974 </div>
975 </div>
977 <div class="column">
978 <h3>Feather Customization</h3>
979 <p>You can change the feather’s visual appearance. This is an aesthetic choice with no impact on the game mechanics.</p>
980 <div class="feather">
981 <label><input type="radio" name="upInTheAirGame-feather" value="blue"><img src="textures/feather-blue.png" alt="Blue feather"></label>
982 <label><input type="radio" name="upInTheAirGame-feather" value="red"><img src="textures/feather-red.png" alt="Red feather"></label>
983 <label><input type="radio" name="upInTheAirGame-feather" value="green"><img src="textures/feather-green.png" alt="Green feather"></label>
984 <label><input type="radio" name="upInTheAirGame-feather" value="black"><img src="textures/feather-black.png" alt="Black feather"></label>
985 <label><input type="radio" name="upInTheAirGame-feather" value="brown"><img src="textures/feather-brown.png" alt="Brown feather"></label>
986 <label><input type="radio" name="upInTheAirGame-feather" value="orange"><img src="textures/feather-orange.png" alt="Orange feather"></label>
987 <label><input type="radio" name="upInTheAirGame-feather" value="purple"><img src="textures/feather-purple.png" alt="Purple feather"></label>
988 </div>
989 </div>
990 </div>
993 <div class="area twocol accessibility">
994 <div class="column">
995 <div>
996 <h3>Visuals</h3>
997 <label><input type="checkbox" value="highcontrast"> High contrast mode</label>
998 <p class="annotation">Render collectibles as bright green dots, replace clouds with dark background.</p>
999 </div>
1000 <div class="font">
1001 <h3>Font</h3>
1002 <p><label class="standardfont"><input type="radio" name="upInTheAirGame-font" value="standard"> Standard</label></p>
1003 <p><label class="atkinson"><input type="radio" name="upInTheAirGame-font" value="atkinson"> Atkinson Hyperlegible</label></p>
1004 <p><label class="opendyslexic"><input type="radio" name="upInTheAirGame-font" value="opendyslexic"> OpenDyslexic</label></p>
1005 </div>
1006 <div class="difficulty">
1007 <h3>Difficulty</h3>
1008 <p><label>Collecting radius:&nbsp;&nbsp;&nbsp;<select class="collectingradius">
1009 <option value="1">Standard</option>
1010 <option value="2">Generous</option>
1011 <option value="3">Eager</option>
1012 </select></label></p>
1013 <p class="annotation">This setting adjusts how close you need to get to a collectible in order to pick it up.</p>
1014 <p><label>Gameplay speed:&nbsp;&nbsp;&nbsp;<select class="speed">
1015 <option value="100">100 %</option>
1016 <option value="50">50 %</option>
1017 <option value="25">25 %</option>
1018 <option value="10">10 %</option>
1019 </select></label></p>
1020 <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>
1021 </div>
1022 </div>
1024 <div class="column keyboard">
1025 <div>
1026 <h3>Keyboard Settings</h3>
1027 <p>These settings only have an effect if keyboard controls are enabled.</p>
1028 </div>
1029 <div>
1030 <label>Up: <button class="up" value="ArrowUp|w">🠕 or W</button></label>
1031 <label>Right: <button class="right" value="ArrowRight|d">🠖 or D</button></label>
1032 <label>Down: <button class="down" value="ArrowDown|s">🠗 or S</button></label>
1033 <label>Left: <button class="left" value="ArrowLeft|a">🠔 or A</button></label>
1034 <button value="reset">Reset to default</button>
1035 </div>
1036 <div>
1037 <label><input type="checkbox" value="tapmode"> Tap mode</label>
1038 <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>
1039 </div>
1040 </div>
1041 </div>
1044 <button class="goto title">Back</button>
1045 </div>
1046 <div class="ui-page credits">
1047 <h2>Credits</h2>
1048 <div class="area">
1049 <h3>Production / Direction / Programming</h3>
1050 <div class="person julian">
1051 <p>Julian Fietkau</p>
1052 <p><a href="https://fietkau.social/@julian" target="_blank">@julian@fietkau.social</a></p>
1053 <p><a href="https://fietkau.me/" target="_blank">https://fietkau.me</a></p>
1054 </div>
1055 <h3>Artwork</h3>
1056 <div class="person nina">
1057 <p>Nina</p>
1058 <p><a href="https://mastodon.art/@misnina" target="_blank">@misnina@mastodon.art</a></p>
1059 <p><a href="https://misnina.com/" target="_blank">https://misnina.com</a></p>
1060 </div>
1061 <h3 class="bigskip">External Resources</h3>
1062 <h4>Music</h4>
1063 <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>
1064 <h4>Sound Effects</h4>
1065 <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>
1066 <h4>Fonts</h4>
1067 <p>“<a href="https://fonts.google.com/specimen/Cookie" target="_blank">Cookie</a>” by Ania Kruk</p>
1068 <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>
1069 <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>
1070 <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>
1071 <p>Logo: “<a href="https://www.fontspace.com/precious-font-f7252" target="_blank">Precious</a>” by Bolt Cutter Design</p>
1072 <h4>Icons</h4>
1073 <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>
1074 <h4>Engine</h4>
1075 <p><a href="https://threejs.org/" target="_blank">three.js</a> v169 by mrdoob and contributors</p>
1076 <h4>Inspiration</h4>
1077 <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>
1078 <p class="seealso">See <a href="README.txt" target="_blank">README.txt</a> for detailed licensing information.</p>
1079 </div>
1080 <button class="goto title">Back</button>
1081 </div>
1082 <div class="ui-page openingcutscene"></div>
1083 <div class="ui-page endingcutscene"></div>
1084 <div class="ui-page outro">
1085 <div class="area outro">
1086 <p>You collected <span class="count">0</span> <span class="optionalPlural">words.</span></p>
1087 <p class="rating"></p>
1088 <p class="examples">Here are a few sentences using some of them:</p>
1089 <div class="examples">
1090 </div>
1091 <button class="examples">More</button>
1092 <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>
1093 </div>
1094 <button class="goto title">Return to Title Screen</button>
1095 </div>
1096 <div class="ui-page unlock">
1097 <div class="area">
1098 <p>You just unlocked a new feather:</p>
1099 <img src="textures/feather-blue.png" alt="Blue feather">
1100 <p class="name">Blue feather</p>
1101 </div>
1102 <button class="goto title">Return to Title Screen</button>
1103 </div>
1104 <div class="ui-page pause">
1105 <h2>Game Paused</h2>
1106 <div class="audio">
1107 <label>Music:
1108 <input type="range" min="0" max="100" value="50" step="1" class="music"></label>
1109 <span>50</span>
1110 <label>Sound effects:
1111 <input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
1112 <span>50</span>
1113 </div>
1114 <button class="goto previous">Continue</button>
1115 <button class="goto title small">Exit</button>
1116 </div>
1117 <div class="ui-page gameplay">
1118 <canvas width="800" height="800"></canvas>
1119 </div>
1120 </div>
1121 <div class="virtual-input-widget">
1122 <div class="circle"></div>
1123 </div>
1124 </div>
1125 <script type="module" src="main.js"></script>
1126 <script>
1127 if(!['https:', 'http:'].includes(window.location.protocol)) {
1128   document.querySelectorAll('.game-upintheair .ui-page:not(.loading)').forEach(page => page.remove());
1129   document.querySelector('.game-upintheair .loading div').innerText = 'This game cannot run without a web server.';
1131 </script>
1132 </body>
1133 </html>