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">
10 // SPDX-License-Identifier: GPL-3.0-or-later
13 * – a browser game created for FediJam 2024 –
14 * https://fietkau.media/up_in_the_air
16 * Copyright (c) Julian Fietkau
17 * See README.txt for details.
19 *******************************************************************************
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.
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.
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/>.
38 font-family: 'Cookie';
39 src: url('fonts/cookie.woff2') format('woff2');
44 font-family: 'Nihonium113';
45 src: url('fonts/nihonium113.woff2') format('woff2');
50 font-family: 'Atkinson Hyperlegible';
51 src: url('fonts/atkinson-hyperlegible-regular.woff2') format('woff2');
56 font-family: 'Atkinson Hyperlegible';
57 src: url('fonts/atkinson-hyperlegible-bold.woff2') format('woff2');
62 font-family: 'OpenDyslexic';
63 src: url('fonts/opendyslexic-regular.woff2') format('woff2');
68 font-family: 'OpenDyslexic';
69 src: url('fonts/opendyslexic-bold.woff2') format('woff2');
74 box-sizing: border-box;
80 justify-content: center;
83 @media (prefers-color-scheme: dark) {
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;
97 justify-content: center;
98 align-items: flex-start;
101 .game-upintheair:fullscreen {
104 @media (prefers-color-scheme: dark) {
105 .game-upintheair:fullscreen {
109 .game-upintheair .ui-container {
111 width: min(calc(100cqh - 2 * var(--game-margin)), calc(100cqw));
114 image-rendering: pixelated;
115 box-shadow: 1px 1px 3px #000a;
118 .virtual-input-widget {
119 box-sizing: border-box;
121 width: min(4cm, 100cqw, calc(100cqh - 2 * var(--game-margin)));
124 bottom: var(--game-margin);
125 right: var(--game-margin);
128 .virtual-input-left .virtual-input-widget {
129 left: var(--game-margin);
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;
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;
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;
150 @media (max-width: 15cm) or (max-height: 15cm) {
154 .virtual-input-widget {
158 .virtual-input-left .virtual-input-widget {
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;
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;
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;
179 .game-upintheair .ui-container.font-atkinson * {
180 font-family: 'Atkinson Hyperlegible' !important;
182 .game-upintheair .ui-container.font-atkinson > .ui-page {
185 .game-upintheair .ui-container.font-opendyslexic * {
186 font-family: 'OpenDyslexic' !important;
188 .game-upintheair .ui-container.font-opendyslexic > .ui-page {
191 .virtual-input-widget.touchpad {
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);
196 border: 2px inset #808080;
199 .virtual-input-widget .circle {
203 transform: translate(-50%, -50%);
207 transition-property: left, top;
208 transition-duration: 0ms;
210 .virtual-input-widget.touchpad .circle {
212 background-color: #fff;
215 .virtual-input-widget.thumbstick {
217 background-color: #585858;
218 background-image: radial-gradient(circle, #808080, #484848);
220 border: 2px inset #808080;
222 .virtual-input-widget.thumbstick .circle {
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;
234 box-sizing: border-box;
238 transition: opacity 250ms;
240 .ui-page:not(.gameplay) {
245 text-decoration: none;
248 text-decoration: underline;
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;
263 font-family: 'Nihonium113';
267 margin: 1ex 0 .4ex 0;
272 .ui-page .area h3:first-child {
275 .ui-page .area h3.bigskip {
279 margin: 1ex 0 .4ex 0;
291 .ui-page .area p.seealso {
295 .ui-page .area.twocol {
301 .ui-page .area.twocol .column {
303 flex-direction: column;
305 justify-content: space-between;
309 .ui-page .area.twocol .column:last-child {
315 background-color: #fff;
319 flex-direction: column;
320 justify-content: center;
325 .ui-page.controls p {
331 .ui-page.controls p:last-child {
334 .ui-page.controls svg {
338 .ui-page.controls svg path {
341 .ui-page.controls button {
343 border: 1px solid #444;
344 box-shadow: 0 2px #444;
351 .ui-page.controls button:hover {
353 border: 1px solid #444;
355 .ui-page.controls button:active {
357 border: 1px solid #444;
359 .ui-page.options .feather {
362 flex-direction: column;
363 justify-content: space-evenly;
366 .ui-page.options .feather input, .ui-page.title .system-buttons input {
373 .ui-page.options .feather img {
376 transition: 150ms transform;
377 transform: scaleY(-1) translateX(-1em);
379 .ui-page.options .feather input:checked + img {
380 transform: scaleY(-1) translateX(1em);
382 .ui-page.options .feather label:hover img, .ui-page.options .feather label:focus-within img {
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);
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; }
405 background-color: #fff;
407 flex-direction: column;
408 justify-content: center;
414 .ui-page.loading img {
417 animation: loading-pinwheel-spin 2s linear infinite;
419 @keyframes loading-pinwheel-spin {
421 transform:rotate(360deg);
424 .ui-page.loading progress {
425 box-sizing: border-box;
428 border: 1px inset #000a;
429 background: #80808030;
432 .ui-page.loading progress::-webkit-progress-value, .ui-page.loading progress::-moz-progress-bar {
438 flex-direction: column;
439 justify-content: flex-start;
449 aspect-ratio: 174 / 96;
450 background: url('textures/logo.png');
451 background-size: contain;
452 background-repeat: no-repeat;
453 background-position: center;
458 .ui-page.title::before {
459 /* image preloading hack */
460 content: url('textures/button-hover.png') url('textures/button-pressed.png');
466 .ui-page > button, .ui-page.outro .area button {
475 border: .4em outset #fffcbf;
477 border-image: url('textures/button-standard.png') 20 / .75em round;
478 border-image-outset: .2em;
480 .font-opendyslexic .ui-page > button, .font-opendyslexic .ui-page.outro .area button {
483 .ui-page > button:hover, .ui-page.outro .area button:hover {
485 border-image-source: url('textures/button-hover.png');
487 .ui-page > button:active, .ui-page.outro .area button:active {
489 border-image-source: url('textures/button-pressed.png');
491 .ui-page.title .system-buttons {
497 flex-direction: column;
501 .ui-page.title.end .system-buttons {
506 @media not (hover: hover) {
507 .ui-page.title .system-buttons {
511 .ui-page.title .system-buttons svg {
515 .ui-page.title .system-buttons svg:hover {
516 filter: drop-shadow(0 0 1px #000);
518 .ui-page.title .system-buttons label input:not(:checked) + svg g {
521 .ui-page.title .system-buttons button {
530 .ui-page.title .footer {
536 flex-direction: column;
538 font-family: 'Nihonium113';
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;
542 .ui-container:not(.font-atkinson):not(.font-opendyslexic) .ui-page.title .footer {
545 .ui-page.title.end .footer {
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;
557 .ui-page.gameplay p {
559 font-family: 'Cookie';
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;
563 .font-opendyslexic .ui-page.gameplay p {
569 flex-direction: column;
570 justify-content: center;
577 flex-direction: column;
578 justify-content: center;
582 .ui-page.options .area.accessibility {
585 .ui-page.options .areatabs {
591 .ui-page.options .areatabs button {
596 border-radius: 1em 1em 0 0;
599 font-family: 'Nihonium113';
602 .ui-page.options .areatabs button.active {
603 padding-bottom: .7em;
605 .ui-page input[type=range] {
607 accent-color: #c50031;
609 .ui-page input[type=radio], .ui-page input[type=checkbox] {
615 accent-color: #c50031;
617 .ui-page.options .area button {
621 font-family: 'Nihonium113';
623 .ui-page.options .controls {
626 .ui-page.options .controls p:last-child {
631 .ui-page.options .controls p:last-child span:not(:first-child) {
634 .ui-page.options .controls .leftside {
640 .ui-page.options .controls .leftside label {
643 .ui-page.options .graphics *:not(.audio) label, .ui-page.options .audiotheme:not(.audio) label {
647 .game-upintheair.font-opendyslexic .ui-page.options .graphics *:not(.audio) label,
648 .game-upintheair.font-opendyslexic .ui-page.options .audiotheme:not(.audio) label {
651 .game-upintheair.font-opendyslexic .ui-page.options .graphics p {
656 .game-upintheair.font-opendyslexic .ui-page.options .audiotheme:not(.audio) label {
659 .ui-page.options p.annotation {
660 margin: 0 0 .7em 1.6em;
662 .ui-page.options label.standardfont {
663 font-family: 'Nihonium113' !important;
665 .ui-page.options label.atkinson {
666 font-family: 'Atkinson Hyperlegible' !important;
668 .ui-page.options label.opendyslexic {
669 font-family: OpenDyslexic !important;
671 .ui-page.options div.difficulty p:nth-child(4) {
678 .ui-page.options .audio {
679 grid-template-columns: auto auto auto;
681 .ui-page.options .audio h3 {
684 .ui-page.pause .audio {
685 grid-template-columns: auto auto;
688 font-family: 'Nihonium113';
690 .ui-page .audio label, .ui-page .audio span {
693 justify-content: end;
696 .ui-page.options *:not(.audio) > label {
699 justify-content: start;
703 .ui-page.options .area.twocol .keyboard {
705 flex-direction: column;
706 justify-content: flex-start;
709 .ui-page.options .keyboard div:nth-child(2) {
713 flex-direction: column;
714 justify-content: flex-start;
715 align-items: flex-end;
717 .ui-page.options .keyboard label button {
718 box-sizing: border-box;
719 margin: .7ex 0 .7ex .7ex;
724 justify-content: center;
729 .ui-page.options .keyboard div > button {
733 .ui-page.keyboard-modal {
737 justify-content: center;
741 font-family: 'Nihonium113';
744 .ui-page .audio input[type=range] {
747 .ui-page .audio span {
751 .ui-page.options select {
752 font-family: 'Nihonium113';
758 flex-direction: column;
759 justify-content: center;
763 .ui-page.outro .area {
765 flex-direction: column;
766 justify-content: center;
772 .ui-page.outro .area div.examples {
773 box-sizing: border-box;
779 flex-direction: column;
783 .font-opendyslexic .ui-page.outro .area > p {
786 .ui-page.outro .area strong {
790 .ui-page.outro .area div.examples strong {
794 .ui-page.outro .area > p:first-child {
799 .ui-page.outro .count {
803 .ui-page.outro .area button {
814 flex-direction: column;
815 justify-content: center;
819 .ui-page.unlock .area {
821 flex-direction: column;
822 justify-content: center;
828 .ui-page.unlock .area img {
830 transform: scale(2, -2);
836 flex-direction: column;
837 justify-content: center;
845 .ui-page.pause button {
848 .ui-page.pause button.small {
852 border-image-width: 1em;
855 .ui-container.control-mouse .ui-page.gameplay, .ui-container.control-mouse .ui-page.openingcutscene, .ui-container.control-mouse .ui-page.endingcutscene {
859 box-sizing: border-box;
861 width: 100% !important;
862 height: 100% !important;
870 <script type="importmap">
873 "three": "./three.module.js",
874 "three/addons/": "./addons/"
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>
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"/>
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>
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">
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"/>
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"/>
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"/>
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>
929 <div class="ui-page options">
931 <div class="areatabs">
932 <button class="general active">General</button>
933 <button class="accessibility">Accessibility</button>
935 <div class="area twocol general">
937 <div class="controls">
939 <div class="leftside"><label><input type="checkbox"> 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>
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>
953 <div class="graphics">
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>
963 <input type="range" min="0" max="100" value="50" step="1" class="music"></label>
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>
969 <button class="sounds">Test</button>
971 <div class="audiotheme">
972 <template><label><input type="radio" name="upInTheAirGame-audiotheme" value="default"> Default</label></template>
973 <span>Audio theme:</span>
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>
993 <div class="area twocol accessibility">
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>
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>
1006 <div class="difficulty">
1008 <p><label>Collecting radius: <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: <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>
1024 <div class="column keyboard">
1026 <h3>Keyboard Settings</h3>
1027 <p>These settings only have an effect if keyboard controls are enabled.</p>
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>
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>
1044 <button class="goto title">Back</button>
1046 <div class="ui-page credits">
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>
1056 <div class="person nina">
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>
1061 <h3 class="bigskip">External Resources</h3>
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>
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>
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>
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>
1080 <button class="goto title">Back</button>
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">
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>
1094 <button class="goto title">Return to Title Screen</button>
1096 <div class="ui-page unlock">
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>
1102 <button class="goto title">Return to Title Screen</button>
1104 <div class="ui-page pause">
1105 <h2>Game Paused</h2>
1108 <input type="range" min="0" max="100" value="50" step="1" class="music"></label>
1110 <label>Sound effects:
1111 <input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
1114 <button class="goto previous">Continue</button>
1115 <button class="goto title small">Exit</button>
1117 <div class="ui-page gameplay">
1118 <canvas width="800" height="800"></canvas>
1121 <div class="virtual-input-widget">
1122 <div class="circle"></div>
1125 <script type="module" src="main.js"></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.';