/* Crosswind — the glass. Everything here sits over a 3D canvas, so the instruments are dark, thin and luminous: readable against bright sky and dark sea without blocking the view. */ :root { --glass: rgba(9, 14, 20, 0.62); --edge: rgba(150, 230, 255, 0.22); --lit: #7fe7ff; --ok: #56f08a; --warn: #ffc34d; --bad: #ff5a5a; --ink: #e8f4fb; --mono: "Share Tech Mono", ui-monospace, monospace; --disp: "Barlow Condensed", "Segoe UI", system-ui, sans-serif; } * { box-sizing: border-box; } /* a display rule outranks the hidden attribute, so say it once and loudly */ [hidden] { display: none !important; } html, body { margin: 0; height: 100%; overflow: hidden; background: #0b1016; color: var(--ink); font-family: var(--disp); -webkit-user-select: none; user-select: none; touch-action: none; } #view { position: fixed; inset: 0; width: 100%; height: 100%; display: block; } /* ---------- loading ---------- */ .loading { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; background: radial-gradient(ellipse at 50% 40%, #16324a, #070c12 70%); } .brand { margin: 0; font-size: clamp(42px, 11vw, 78px); font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink); text-shadow: 0 0 40px rgba(127, 231, 255, 0.35); } .loading-sub { margin: 6px 0 0; text-align: center; font-family: var(--mono); font-size: 13px; color: var(--lit); letter-spacing: 0.1em; } /* ---------- hud frame ---------- */ .hud { position: fixed; inset: 0; pointer-events: none; z-index: 10; } .hud > * { position: absolute; } /* heading ribbon */ .ribbon-wrap { top: calc(8px + env(safe-area-inset-top, 0px)); left: 50%; transform: translateX(-50%); width: min(420px, 74vw); height: 34px; overflow: hidden; background: var(--glass); border: 1px solid var(--edge); border-radius: 8px; backdrop-filter: blur(6px); } .ribbon { position: absolute; top: 0; left: 50%; display: flex; height: 100%; align-items: center; will-change: transform; } .ribbon span { display: inline-block; width: 120px; /* 30° of heading at 4px per degree */ margin-left: -60px; text-align: center; font-family: var(--mono); font-size: 13px; color: rgba(232, 244, 251, 0.75); } .ribbon-mark { position: absolute; left: 50%; top: 0; width: 2px; height: 12px; background: var(--lit); transform: translateX(-50%); } .ribbon-read { position: absolute; left: 50%; bottom: 2px; transform: translateX(-50%); font-family: var(--mono); font-size: 15px; color: var(--lit); text-shadow: 0 0 12px rgba(127, 231, 255, 0.6); } /* speed and altitude tapes */ .tape { top: 50%; transform: translateY(-50%); width: 92px; padding: 10px 8px; display: flex; flex-direction: column; align-items: center; gap: 1px; background: var(--glass); border: 1px solid var(--edge); border-radius: 10px; backdrop-filter: blur(6px); } .tape.left { left: 12px; } .tape.right { right: 12px; } .tape-label { font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(232, 244, 251, 0.55); } .tape-val { font-family: var(--mono); font-size: 30px; line-height: 1.05; color: var(--lit); text-shadow: 0 0 14px rgba(127, 231, 255, 0.45); } .tape-unit { font-size: 11px; letter-spacing: 0.1em; color: rgba(232, 244, 251, 0.5); } .tape-sub { margin-top: 6px; font-family: var(--mono); font-size: 12px; color: rgba(232, 244, 251, 0.8); } /* attitude indicator */ /* the attitude ball sits low and to the centre, where a panel would be — never over the view you are flying through */ .attitude { left: 50%; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); width: 156px; height: 156px; border-radius: 50%; overflow: hidden; border: 2px solid var(--edge); box-shadow: 0 10px 40px rgba(0, 0, 0, 0.45); opacity: 0.92; } .horizon, .horizon-inner { position: absolute; inset: -60%; } .horizon { will-change: transform; } .sky-half, .ground-half { position: absolute; left: 0; right: 0; height: 50%; } .sky-half { top: 0; background: linear-gradient(180deg, #2a70b8, #79b6e8); } .ground-half { bottom: 0; background: linear-gradient(180deg, #7a5a34, #4b3a22); } .horizon-inner::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 2px; background: rgba(255, 255, 255, 0.9); } .pitch-ladder i { position: absolute; left: 50%; top: calc(50% - var(--p) * 1.9px); width: 46px; height: 1px; margin-left: -23px; background: rgba(255, 255, 255, 0.7); } .wings { position: absolute; left: 50%; top: 50%; width: 96px; height: 12px; transform: translate(-50%, -50%); border-left: 34px solid var(--warn); border-right: 34px solid var(--warn); border-bottom: 2px solid var(--warn); box-sizing: border-box; } .stall { position: absolute; left: 50%; top: 22%; transform: translateX(-50%); padding: 3px 12px; border-radius: 4px; background: var(--bad); color: #1a0505; font-weight: 700; letter-spacing: 0.22em; font-size: 13px; animation: flash 0.55s steps(1) infinite; } @keyframes flash { 50% { opacity: 0.25; } } /* engine panel */ .panel { left: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); display: flex; align-items: stretch; gap: 10px; padding: 10px 12px; background: var(--glass); border: 1px solid var(--edge); border-radius: 10px; backdrop-filter: blur(6px); } .throttle-gauge { position: relative; width: 12px; border-radius: 6px; background: rgba(255, 255, 255, 0.1); overflow: hidden; } .throttle-fill { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(180deg, var(--lit), #2f8fb5); transition: height 0.12s linear; } .throttle-gauge { cursor: ns-resize; touch-action: none; } .throttle-gauge:focus-visible { outline: 2px solid var(--lit); outline-offset: 2px; } .throttle-ticks { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; padding: 2px 0; pointer-events: none; } .throttle-ticks i { display: block; height: 1px; background: rgba(232, 244, 251, 0.28); } .throttle-knob { position: absolute; left: -2px; right: -2px; height: 3px; border-radius: 2px; background: var(--ink); box-shadow: 0 0 6px rgba(0, 0, 0, 0.7); transition: bottom 0.12s linear; pointer-events: none; } .panel dl { margin: 0; display: grid; gap: 2px; } .panel dl div { display: flex; justify-content: space-between; gap: 14px; } .panel dt { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(232, 244, 251, 0.5); } .panel dd { margin: 0; font-family: var(--mono); font-size: 12.5px; color: var(--ink); } .panel dd.ok { color: var(--ok); } .panel dd.warn { color: var(--warn); } .fuel { align-self: end; width: 10px; height: 54px; border-radius: 5px; background: rgba(255, 255, 255, 0.1); overflow: hidden; transform: rotate(180deg); } .fuel span { display: block; height: 100%; background: linear-gradient(90deg, var(--ok), #2f8f5a); } /* map */ .map { right: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); width: 128px; padding: 6px 6px 4px; background: var(--glass); border: 1px solid var(--edge); border-radius: 10px; backdrop-filter: blur(6px); } .map svg { display: block; width: 100%; height: auto; border-radius: 6px; } .map-label { display: block; margin-top: 4px; text-align: center; font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em; color: rgba(232, 244, 251, 0.65); } .cam-tag { left: 50%; bottom: calc(178px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); padding: 4px 12px; border-radius: 999px; background: var(--glass); border: 1px solid var(--edge); font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em; color: rgba(232, 244, 251, 0.8); } .plane-tag { left: 50%; bottom: calc(198px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); padding: 3px 12px; border-radius: 999px; background: var(--glass); border: 1px solid var(--edge); font-family: var(--disp); font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--lit); } /* the hangar */ .hangar { width: min(560px, calc(100vw - 32px)); } .planes { display: grid; gap: 8px; margin-bottom: 16px; } .plane-card { display: grid; gap: 2px; padding: 12px 14px; text-align: left; border-radius: 10px; border: 1px solid var(--edge); background: rgba(127, 231, 255, 0.05); color: var(--ink); cursor: pointer; } .plane-card:hover { background: rgba(127, 231, 255, 0.12); } .plane-card.on { border-color: var(--lit); background: rgba(127, 231, 255, 0.18); } .plane-card strong { font-size: 17px; font-weight: 700; letter-spacing: 0.04em; } .plane-spec { font-family: var(--mono); font-size: 11.5px; color: var(--lit); } .plane-blurb { font-size: 13.5px; color: rgba(232, 244, 251, 0.72); line-height: 1.35; } .msg { left: 50%; top: calc(56px + env(safe-area-inset-top, 0px)); transform: translateX(-50%); margin: 0; max-width: min(560px, 88vw); padding: 8px 16px; text-align: center; border-radius: 8px; background: var(--glass); border: 1px solid var(--edge); backdrop-filter: blur(6px); font-size: 15px; letter-spacing: 0.02em; color: var(--ink); } /* ---------- touch controls: hidden on anything with a real pointer ---------- */ .touch { position: fixed; inset: 0; z-index: 12; pointer-events: none; display: none; } @media (hover: none) and (pointer: coarse) { .touch { display: block; } } .stick { position: absolute; left: 16px; bottom: calc(96px + env(safe-area-inset-bottom, 0px)); width: 132px; height: 132px; border-radius: 50%; border: 1px solid var(--edge); background: rgba(9, 14, 20, 0.35); pointer-events: auto; } .knob { position: absolute; left: 50%; top: 50%; width: 52px; height: 52px; margin: -26px 0 0 -26px; border-radius: 50%; background: rgba(127, 231, 255, 0.35); border: 1px solid var(--lit); } .throttle { position: absolute; right: 16px; bottom: calc(96px + env(safe-area-inset-bottom, 0px)); width: 56px; height: 148px; border-radius: 12px; border: 1px solid var(--edge); background: rgba(9, 14, 20, 0.35); pointer-events: auto; display: grid; place-items: end center; padding-bottom: 6px; font-family: var(--mono); font-size: 10px; color: rgba(232, 244, 251, 0.6); } .touch-btns { position: absolute; right: 16px; top: calc(56px + env(safe-area-inset-top, 0px)); display: grid; gap: 6px; pointer-events: auto; } .touch-btns button { width: 56px; padding: 9px 0; border-radius: 8px; border: 1px solid var(--edge); background: var(--glass); color: var(--ink); font-family: var(--mono); font-size: 11px; } /* ---------- cards ---------- */ .card { position: fixed; left: 50%; top: 50%; z-index: 20; transform: translate(-50%, -50%); width: min(420px, calc(100vw - 32px)); max-height: 86vh; overflow-y: auto; padding: 22px; border-radius: 14px; background: rgba(8, 13, 19, 0.92); border: 1px solid var(--edge); backdrop-filter: blur(10px); box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6); pointer-events: auto; } .card h2 { margin: 0 0 8px; font-size: 26px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; } .card p { margin: 0 0 14px; color: rgba(232, 244, 251, 0.78); line-height: 1.45; } .help-lead { font-size: 15.5px; } .card dl { margin: 0 0 16px; display: grid; gap: 7px; } .card dl div { display: flex; justify-content: space-between; gap: 16px; align-items: baseline; } .card dt { font-family: var(--mono); font-size: 12.5px; color: var(--lit); } .card dt em { font-style: normal; color: rgba(232, 244, 251, 0.45); } .card dd { margin: 0; font-size: 14px; color: rgba(232, 244, 251, 0.8); text-align: right; } .card-btns { display: flex; gap: 10px; } .card-btns button { flex: 1; padding: 12px; border-radius: 10px; border: 1px solid var(--lit); background: rgba(127, 231, 255, 0.14); color: var(--ink); font-family: var(--disp); font-size: 15px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; cursor: pointer; } .card-btns button:active { transform: translateY(1px); } /* the pre-flight screen: two lists side by side, each scrolling on its own so that the summary and the Fly button never leave the screen. Declared after .card on purpose — both are single class selectors, so this one only wins by coming later. */ .preflight { width: min(880px, calc(100vw - 32px)); max-height: min(86vh, 700px); padding: 20px 22px 18px; display: flex; flex-direction: column; overflow: hidden; } .pf-lead { margin-bottom: 14px !important; flex: none; } .pf-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 14px; min-height: 0; flex: 1 1 auto; } .pf-col { min-width: 0; min-height: 0; display: flex; flex-direction: column; } .pf-col > header { flex: none; display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding-bottom: 6px; margin-bottom: 8px; border-bottom: 1px solid var(--edge); } .pf-col h3 { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(232, 244, 251, 0.55); } .pf-chosen { font-family: var(--mono); font-size: 12px; color: var(--lit); text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pf-tabs { flex: none; display: flex; gap: 6px; margin-bottom: 8px; } .pf-tabs button { flex: 1; padding: 6px 8px; border-radius: 8px; border: 1px solid var(--edge); background: transparent; color: rgba(232, 244, 251, 0.7); font-family: var(--disp); font-size: 12.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer; } .pf-tabs button.on { border-color: var(--lit); background: rgba(127, 231, 255, 0.16); color: var(--ink); } .pf-col .planes { flex: 1 1 auto; margin-bottom: 0; overflow-y: auto; min-height: 0; align-content: start; padding-right: 4px; } .pf-badge { font-family: var(--mono); font-style: normal; font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--lit); border: 1px solid var(--edge); border-radius: 5px; padding: 1px 5px; vertical-align: 2px; } .pf-weather { flex: none; display: flex; align-items: center; gap: 12px; margin-bottom: 10px; } .pf-weather-label { font-size: 12px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(232, 244, 251, 0.55); } .pf-weather-btns { display: flex; gap: 6px; flex: 1; flex-wrap: wrap; } .pf-weather-btns button { flex: 1 1 auto; padding: 6px 10px; border-radius: 8px; border: 1px solid var(--edge); background: transparent; color: rgba(232, 244, 251, 0.72); font-family: var(--disp); font-size: 12.5px; font-weight: 600; letter-spacing: 0.05em; cursor: pointer; white-space: nowrap; } .pf-weather-btns button.on { border-color: var(--lit); background: rgba(127, 231, 255, 0.16); color: var(--ink); } .pf-summary { flex: none; margin: 0 0 12px !important; padding: 10px 12px; border-radius: 9px; border: 1px solid var(--edge); border-left: 3px solid var(--lit); background: rgba(127, 231, 255, 0.06); font-size: 14px; line-height: 1.4; } .pf-summary.tight { border-left-color: var(--warn); background: rgba(255, 195, 77, 0.08); } .pf-summary.warn { border-left-color: var(--bad); background: rgba(255, 90, 90, 0.09); } .preflight .card-btns { flex: none; } .card-btns button.primary { flex: 1.6; background: var(--lit); color: #06121a; border-color: var(--lit); } @media (max-width: 760px) { /* one column, but each list keeps its own scroll and a bounded height — dropping the bound let the lists overflow their grid rows and paint on top of each other */ .preflight { padding: 16px 16px 14px; max-height: 88vh; } .pf-lead { font-size: 14px; margin-bottom: 10px !important; } .pf-cols { grid-template-columns: 1fr; gap: 12px; } .pf-col .planes { max-height: 25vh; overflow-y: auto; } .pf-summary { font-size: 13px; } .card-btns { flex-wrap: wrap; } .card-btns button { min-width: 44%; } } @media (max-width: 520px) { .attitude { width: 148px; height: 148px; } .tape { width: 76px; padding: 8px 6px; } .tape-val { font-size: 25px; } .map { width: 104px; } } /* ---------- the lesson panel ---------- */ .lesson { left: 50%; top: calc(52px + env(safe-area-inset-top, 0px)); transform: translateX(-50%); width: min(430px, calc(100vw - 32px)); padding: 12px 16px 14px; border-radius: 12px; background: var(--glass); border: 1px solid var(--lit); backdrop-filter: blur(8px); box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45); pointer-events: none; } .lesson-bar { height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.12); overflow: hidden; margin-bottom: 9px; } .lesson-bar span { display: block; height: 100%; background: var(--lit); transition: width 0.4s ease; } .lesson-step { margin: 0; font-family: var(--mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--lit); } .lesson h3 { margin: 2px 0 4px; font-size: 19px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; } .lesson-say { margin: 0; font-size: 14.5px; line-height: 1.4; color: rgba(232, 244, 251, 0.85); } .lesson-hint { margin: 8px 0 0; } .lesson kbd, .card kbd { display: inline-block; padding: 3px 9px; border-radius: 6px; border: 1px solid var(--edge); background: rgba(127, 231, 255, 0.14); font-family: var(--mono); font-size: 12px; color: var(--lit); } /* ---------- wind ---------- */ .wind { right: 12px; top: calc(52px + env(safe-area-inset-top, 0px)); display: flex; align-items: center; gap: 6px; padding: 6px 10px 6px 6px; border-radius: 10px; background: var(--glass); border: 1px solid var(--edge); backdrop-filter: blur(6px); font-family: var(--mono); font-size: 11.5px; color: rgba(232, 244, 251, 0.85); } .wind svg { width: 26px; height: 26px; color: var(--lit); }