flight-simulator / dist /index.html
underrate's picture
Initial commit
819bb91 verified
Raw
History Blame Contribute Delete
13 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Flight Simulator</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;700&display=swap"
rel="stylesheet"
/>
<style>
:root {
--hud-ink: #0f2d3f;
--hud-highlight: #2ee5b6;
--hud-warning: #ffc763;
--hud-text: #e9f6ff;
--hud-soft: rgba(233, 246, 255, 0.72);
--hud-muted: rgba(233, 246, 255, 0.32);
--panel-bg: linear-gradient(160deg, rgba(7, 28, 42, 0.86), rgba(10, 44, 63, 0.72));
--panel-border: rgba(46, 229, 182, 0.35);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
overflow: hidden;
font-family: "Space Grotesk", "Segoe UI", sans-serif;
background: #72bbec;
}
#game-container,
canvas {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
}
#game-container {
width: 100vw;
height: 100vh;
background: #87ceeb;
}
#ui-root {
position: fixed;
inset: 0;
padding:
max(clamp(12px, 2vw, 24px), env(safe-area-inset-top))
max(clamp(12px, 2vw, 24px), env(safe-area-inset-right))
max(clamp(12px, 2vw, 24px), env(safe-area-inset-bottom))
max(clamp(12px, 2vw, 24px), env(safe-area-inset-left));
display: grid;
grid-template-columns: minmax(240px, 320px) 1fr minmax(220px, 300px);
grid-template-rows: auto 1fr;
gap: 16px;
pointer-events: none;
z-index: 10;
}
#ui-root::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(140% 90% at 50% 0%, rgba(255, 230, 160, 0.25), transparent 52%),
linear-gradient(180deg, rgba(0, 0, 0, 0.16), transparent 28%);
z-index: -1;
}
.hud-card {
border: 1px solid var(--panel-border);
border-radius: 16px;
background: var(--panel-bg);
box-shadow: 0 14px 30px rgba(3, 12, 20, 0.28);
backdrop-filter: blur(10px);
color: var(--hud-text);
animation: card-in 520ms ease both;
}
.hud-banner {
grid-column: 1 / 4;
padding: 12px 16px;
display: grid;
gap: 2px;
}
.hud-kicker {
margin: 0;
font-family: "Chakra Petch", sans-serif;
letter-spacing: 0.2em;
font-weight: 600;
font-size: 0.72rem;
text-transform: uppercase;
color: var(--hud-soft);
}
.hud-title {
margin: 0;
font-family: "Chakra Petch", sans-serif;
letter-spacing: 0.04em;
font-size: clamp(1rem, 2.2vw, 1.5rem);
}
.hud-status {
margin: 0;
display: flex;
align-items: center;
gap: 8px;
font-size: 0.84rem;
color: var(--hud-soft);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: var(--hud-highlight);
box-shadow: 0 0 10px rgba(46, 229, 182, 0.8);
}
.hud-telemetry {
align-self: end;
padding: 14px;
}
.hud-controls {
align-self: start;
padding: 14px;
animation-delay: 120ms;
}
.hud-heading {
margin: 0 0 12px;
font-family: "Chakra Petch", sans-serif;
font-size: 1rem;
letter-spacing: 0.04em;
}
.meter-wrap {
margin-top: 14px;
display: grid;
gap: 6px;
}
.meter-label {
display: flex;
align-items: center;
justify-content: space-between;
color: var(--hud-soft);
font-size: 0.76rem;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.meter-rail {
height: 9px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.12);
border: 1px solid var(--hud-muted);
overflow: hidden;
}
.meter-fill {
height: 100%;
width: 0;
border-radius: inherit;
background: linear-gradient(90deg, #6dd8ff, var(--hud-highlight));
box-shadow: 0 0 12px rgba(46, 229, 182, 0.55);
transition: width 120ms linear;
}
.telemetry-grid {
margin: 0;
display: grid;
grid-template-columns: auto auto;
gap: 8px 14px;
}
.telemetry-grid dt {
color: var(--hud-soft);
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.telemetry-grid dd {
margin: 0;
text-align: right;
font-family: "Chakra Petch", sans-serif;
color: #ffffff;
font-size: 1rem;
}
.control-grid {
display: grid;
gap: 10px;
}
.control-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
color: var(--hud-soft);
font-size: 0.88rem;
}
.key-pair {
display: inline-flex;
gap: 6px;
align-items: center;
}
kbd {
min-width: 30px;
padding: 4px 8px;
border-radius: 8px;
border: 1px solid rgba(233, 246, 255, 0.35);
background: rgba(255, 255, 255, 0.08);
color: #ffffff;
font-family: "Chakra Petch", sans-serif;
font-size: 0.78rem;
text-align: center;
}
kbd.active {
color: var(--hud-ink);
background: var(--hud-highlight);
border-color: transparent;
box-shadow: 0 0 14px rgba(46, 229, 182, 0.7);
}
.center-stack {
grid-column: 2;
grid-row: 2;
justify-self: center;
align-self: center;
position: relative;
width: min(42vw, 260px);
aspect-ratio: 1;
animation: reticle-in 620ms ease both;
animation-delay: 180ms;
}
.horizon-shell {
position: absolute;
inset: 0;
border-radius: 999px;
border: 1px solid rgba(233, 246, 255, 0.4);
background: radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.32));
overflow: hidden;
}
.horizon-ladder {
position: absolute;
top: 50%;
left: 50%;
width: 130%;
height: 130%;
transform: translate(-50%, -50%);
background:
linear-gradient(180deg, rgba(124, 193, 241, 0.6), rgba(124, 193, 241, 0.05) 46%, rgba(72, 60, 46, 0.5) 54%, rgba(72, 60, 46, 0.78)),
repeating-linear-gradient(
to bottom,
transparent 0,
transparent 23px,
rgba(233, 246, 255, 0.4) 23px,
rgba(233, 246, 255, 0.4) 25px
);
transition: transform 0.09s linear;
}
.reticle {
position: absolute;
inset: 50% auto auto 50%;
transform: translate(-50%, -50%);
width: 48px;
height: 48px;
border: 2px solid rgba(255, 255, 255, 0.9);
border-radius: 999px;
}
.reticle::before,
.reticle::after {
content: "";
position: absolute;
background: rgba(255, 255, 255, 0.9);
}
.reticle::before {
width: 2px;
height: 68px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.reticle::after {
width: 68px;
height: 2px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.mobile-note {
position: absolute;
bottom: 14px;
left: 50%;
transform: translateX(-50%);
margin: 0;
color: rgba(15, 45, 63, 0.82);
font-weight: 600;
font-family: "Chakra Petch", sans-serif;
font-size: 0.8rem;
letter-spacing: 0.03em;
text-shadow: 0 2px 8px rgba(255, 255, 255, 0.42);
}
@keyframes card-in {
from {
opacity: 0;
transform: translateY(-12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes reticle-in {
from {
opacity: 0;
transform: scale(0.92);
}
to {
opacity: 1;
transform: scale(1);
}
}
.throttle-label {
color: var(--hud-warning);
}
@media (max-width: 900px) {
#ui-root {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto 1fr;
gap: 10px;
padding: 10px;
}
.hud-banner {
grid-column: 1 / 3;
}
.hud-telemetry {
grid-column: 1 / 2;
grid-row: 2;
align-self: start;
}
.hud-controls {
grid-column: 2 / 3;
grid-row: 2;
}
.center-stack {
grid-column: 1 / 3;
grid-row: 3;
width: min(56vw, 230px);
align-self: end;
margin-bottom: 6vh;
}
.mobile-note {
font-size: 0.75rem;
bottom: 8px;
}
}
@media (max-width: 620px) {
#ui-root {
grid-template-columns: 1fr;
grid-template-rows: auto auto auto auto;
}
.hud-banner,
.hud-telemetry,
.hud-controls,
.center-stack {
grid-column: 1;
}
.hud-telemetry,
.hud-controls {
padding: 12px;
}
.center-stack {
width: min(62vw, 210px);
justify-self: end;
margin: 0 8px 5.5vh 0;
}
.hud-controls .control-row:last-child {
margin-top: 6px;
}
}
</style>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js"
}
}
</script>
<script type="module" crossorigin src="/assets/index-DIq_VqFy.js"></script>
</head>
<body>
<div id="game-container"></div>
<div id="ui-root">
<header class="hud-card hud-banner">
<p class="hud-kicker">Flight Simulator</p>
<h1 class="hud-title">Tactical Flight HUD</h1>
<p class="hud-status"><span class="status-dot"></span>Live Simulation Feed</p>
</header>
<section class="hud-card hud-telemetry">
<h2 class="hud-heading">Telemetry</h2>
<dl class="telemetry-grid">
<dt>Speed</dt>
<dd id="hud-speed">0 kn</dd>
<dt>Altitude</dt>
<dd id="hud-altitude">0 m</dd>
<dt>Heading</dt>
<dd id="hud-heading">000 deg</dd>
<dt>Pitch</dt>
<dd id="hud-pitch">0 deg</dd>
<dt>Roll</dt>
<dd id="hud-roll">0 deg</dd>
<dt class="throttle-label">Throttle</dt>
<dd id="hud-throttle">0%</dd>
<dt>FPS</dt>
<dd id="hud-fps">60</dd>
</dl>
<div class="meter-wrap">
<div class="meter-label">
<span>Engine Load</span>
<span id="hud-engine-state">Nominal</span>
</div>
<div class="meter-rail">
<div id="hud-throttle-bar" class="meter-fill"></div>
</div>
</div>
</section>
<section class="hud-card hud-controls">
<h2 class="hud-heading">Controls</h2>
<div class="control-grid">
<div class="control-row">
<span class="key-pair"><kbd id="key-w">W</kbd><kbd id="key-s">S</kbd></span>
<span>Pitch Up and Down</span>
</div>
<div class="control-row">
<span class="key-pair"><kbd id="key-a">A</kbd><kbd id="key-d">D</kbd></span>
<span>Roll Left and Right</span>
</div>
<div class="control-row">
<span class="key-pair"><kbd id="key-q">Q</kbd><kbd id="key-e">E</kbd></span>
<span>Yaw Left and Right</span>
</div>
<div class="control-row">
<span class="key-pair"><kbd id="key-shift">Shift</kbd></span>
<span>Boost Thrust</span>
</div>
<div class="control-row">
<span class="key-pair"><kbd>Cam</kbd></span>
<span>Auto Follow Mode</span>
</div>
</div>
</section>
<div class="center-stack">
<div class="horizon-shell">
<div id="horizon-ladder" class="horizon-ladder"></div>
</div>
<div class="reticle"></div>
</div>
<p class="mobile-note">Best with keyboard on desktop.</p>
</div>
</body>
</html>