moonshot / src /style.css
DJLougen's picture
MOONSHOT: cosmic night-league batting (static Three.js game)
db520fb verified
Raw History Blame Contribute Delete
13 kB
/* MOONSHOT — atomic-age space-poster shell.
Palette mirrors src/palette.js (frozen hexes) in oklch:
ink #16121F ≈ oklch(0.194 0.026 298)
night #1E1B3A ≈ oklch(0.243 0.058 286)
cream #F4E9D2 ≈ oklch(0.937 0.033 85)
red #E8452C ≈ oklch(0.623 0.204 32)
gold #F2B33D ≈ oklch(0.806 0.147 79)
teal #35C4B5 ≈ oklch(0.743 0.119 184)
grass #3F7D4E ≈ oklch(0.535 0.098 150)
dirt #C98A5B ≈ oklch(0.686 0.099 57)
white #FFF8EC ≈ oklch(0.981 0.018 81) */
/* ---------- reset (good-css foundations) ---------- */
*,
*::before,
*::after {
box-sizing: border-box;
min-inline-size: 0;
}
:root {
/* color tokens */
--ink: oklch(0.194 0.026 298);
--night: oklch(0.243 0.058 286);
--cream: oklch(0.937 0.033 85);
--red: oklch(0.623 0.204 32);
--gold: oklch(0.806 0.147 79);
--teal: oklch(0.743 0.119 184);
--grass: oklch(0.535 0.098 150);
--dirt: oklch(0.686 0.099 57);
--white: oklch(0.981 0.018 81);
--ink-55: color-mix(in oklch, var(--ink) 55%, transparent);
--ink-90: color-mix(in oklch, var(--ink) 90%, transparent);
--ink-dim: color-mix(in oklch, var(--ink) 72%, var(--cream));
/* type + display-size tokens */
--font-display: 'Arial Black', 'Arial Narrow Bold', Impact, 'Haettenschweiler', sans-serif;
--font-mono: 'Courier New', Courier, monospace;
--display: clamp(2.4rem, 1.5rem + 4vw, 4.8rem); /* the one fluid display size */
--stamp-size: clamp(2.8rem, 1.4rem + 7.5vw, 7rem);
--text-ui: clamp(0.9rem, 0.8rem + 0.4vw, 1.05rem);
/* print-chrome geometry */
--border: 3px solid var(--ink);
--shadow: 4px 4px 0 var(--ink);
--radius: 4px;
/* motion */
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
color-scheme: dark;
font-synthesis: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
}
body {
margin: 0;
block-size: 100dvb;
overflow: clip; /* fullscreen game shell, no scroll */
background: var(--night);
color: var(--cream);
font-family: var(--font-display);
/* controls carry their own user-select: none below */
}
h1, h2, p { margin: 0; }
::selection {
background: var(--gold);
color: var(--ink);
}
/* hidden must always win over display rules below */
[hidden] { display: none !important; }
/* ---------- canvas mount ---------- */
#game {
position: fixed;
inset: 0;
cursor: crosshair;
}
#game canvas {
display: block;
inline-size: 100%;
block-size: 100%;
}
/* ---------- print overlays: halftone grain + scanlines ---------- */
.grain,
.scanlines,
#flash {
position: fixed;
inset: 0;
pointer-events: none;
}
/* halftone dots + paper mottle, pure layered gradients */
.grain {
z-index: 2;
opacity: 0.28;
background-image:
radial-gradient(circle,
var(--ink-90) 0 0.5px, transparent 0.65px),
radial-gradient(circle,
color-mix(in oklch, var(--white) 35%, transparent) 0 0.6px,
transparent 0.75px),
radial-gradient(120% 90% at 50% 40%,
transparent 55%, var(--ink-55) 100%);
background-size: 6px 6px, 10px 10px, 100% 100%;
background-position: 0 0, 3px 5px, 0 0;
}
.scanlines {
z-index: 3;
opacity: 0.5;
background-image: repeating-linear-gradient(
0deg,
var(--ink-90) 0 1px,
transparent 1px 4px
);
}
/* hit flash: cream screen; main.js sets .style.opacity, so NO transition here */
#flash {
z-index: 4;
background: var(--cream);
opacity: 0;
}
/* ---------- HUD: minor-league scoreboard corners ---------- */
#hud {
position: fixed;
inset-block-start: 0;
inset-inline: 0;
z-index: 10;
display: flex;
justify-content: space-between;
align-items: flex-start;
padding-block-start: clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
padding-inline: clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
pointer-events: none;
}
.hud-block {
background: var(--cream);
color: var(--ink);
border: var(--border);
box-shadow: var(--shadow);
padding-block: 0.5rem 0.65rem;
padding-inline: 0.85rem 1rem;
text-transform: uppercase;
}
.hud-level { rotate: -1deg; }
/* push the right block below the fixed mute button (resolves top-right conflict) */
.hud-score {
rotate: 1deg;
margin-block-start: 3.4rem;
text-align: end;
}
#level-num,
#hr-count {
font-family: var(--font-mono);
font-weight: bold;
font-size: var(--text-ui);
letter-spacing: 0.06em;
}
#level-name {
font-size: clamp(0.85rem, 0.7rem + 0.5vw, 1.1rem);
color: var(--red);
letter-spacing: 0.04em;
}
#total-hr {
font-family: var(--font-mono);
font-weight: bold;
font-size: 0.8rem;
letter-spacing: 0.1em;
color: var(--ink-dim);
}
/* pitch dots: ink squares, red once used (main.js fills <i>) */
#pitch-dots {
display: flex;
justify-content: flex-end;
gap: 5px;
margin-block: 0.35rem;
}
#pitch-dots i {
inline-size: 11px;
block-size: 11px;
background: var(--ink);
border: 1px solid var(--ink);
}
#pitch-dots i.used {
background: var(--red);
}
/* ---------- center result stamp ---------- */
#stamp,
#stamp-sub {
position: fixed;
inset-inline: 0;
z-index: 15;
text-align: center;
pointer-events: none;
opacity: 0;
-webkit-text-stroke: 2px var(--ink);
paint-order: stroke fill;
}
#stamp {
inset-block-start: 50%;
translate: 0 -52%;
font-size: var(--stamp-size);
letter-spacing: 0.02em;
rotate: -2deg;
}
#stamp-sub {
inset-block-start: calc(50% + var(--stamp-size) * 0.62);
font-family: var(--font-mono);
font-weight: bold;
font-size: clamp(1rem, 0.85rem + 1vw, 1.4rem);
letter-spacing: 0.18em;
-webkit-text-stroke-width: 0;
color: var(--cream);
}
#stamp.show,
#stamp-sub.show { opacity: 1; }
/* kind colors — misprint = accent offset behind the ink outline */
#stamp.homerun {
color: var(--gold);
text-shadow: 5px 5px 0 var(--red), 7px 7px 0 var(--ink-90);
}
#stamp.inplay {
color: var(--white);
text-shadow: 4px 4px 0 var(--teal), 6px 6px 0 var(--ink-90);
}
#stamp.popup {
color: var(--cream);
text-shadow: 4px 4px 0 var(--dirt), 6px 6px 0 var(--ink-90);
}
#stamp.foul {
color: var(--cream);
text-shadow: 4px 4px 0 var(--red), 6px 6px 0 var(--ink-90);
}
#stamp.planet {
color: var(--cream);
text-shadow: 5px 5px 0 var(--gold), 8px 8px 0 var(--red), 10px 10px 0 var(--ink-90);
}
#stamp.sign {
color: var(--gold);
text-shadow: 4px 4px 0 var(--red), 6px 6px 0 var(--ink-90);
}
#stamp.wall {
color: var(--teal);
text-shadow: 4px 4px 0 var(--ink-90);
}
#stamp.crowd {
color: var(--gold);
text-shadow: 4px 4px 0 var(--teal), 6px 6px 0 var(--ink-90);
}
#stamp.whiff {
color: var(--red);
text-shadow: 4px 4px 0 var(--ink-90);
}
#stamp.strike {
color: var(--gold);
text-shadow: 4px 4px 0 var(--ink-90);
}
#stamp.ball {
color: var(--teal);
text-shadow: 4px 4px 0 var(--ink-90);
}
@keyframes stamp-in {
0% { scale: 1.6; rotate: 3deg; opacity: 0; }
60% { scale: 0.94; opacity: 1; }
80% { scale: 1.04; }
100% { scale: 1; rotate: 0deg; opacity: 1; }
}
/* ---------- home-run distance readout ---------- */
#distance {
position: fixed;
inset-block-end: clamp(3.2rem, 2rem + 5vw, 6rem);
inset-inline: 0;
z-index: 16;
display: flex;
align-items: baseline;
justify-content: center;
gap: 0.4rem;
pointer-events: none;
font-family: var(--font-display);
font-size: clamp(2.2rem, 1.2rem + 5vw, 4.6rem);
line-height: 1;
color: var(--gold);
text-shadow: 4px 4px 0 var(--red), 6px 6px 0 var(--ink-90);
opacity: 0;
translate: 0 12px;
transition: opacity 0.3s var(--ease-out), translate 0.3s var(--ease-out);
}
#distance.show {
opacity: 1;
translate: 0 0;
}
#distance .ft-unit {
font-size: 0.42em;
letter-spacing: 0.12em;
color: var(--cream);
text-shadow: 3px 3px 0 var(--ink-90);
}
/* ---------- hint + mute button ---------- */
#hint {
position: fixed;
inset-block-end: clamp(0.8rem, 0.5rem + 1vw, 1.4rem);
inset-inline: 0;
z-index: 10;
text-align: center;
font-family: var(--font-mono);
font-weight: bold;
font-size: 0.85rem;
letter-spacing: 0.22em;
color: var(--teal);
text-shadow: 2px 2px 0 var(--ink-90);
pointer-events: none;
}
#btn-mute {
position: fixed;
inset-block-start: clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
inset-inline-end: clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
z-index: 40;
padding-block: 0.45rem;
padding-inline: 0.8rem;
font-family: var(--font-mono);
font-weight: bold;
font-size: 0.8rem;
letter-spacing: 0.08em;
}
/* ---------- overlay cards ---------- */
#overlay {
position: fixed;
inset: 0;
z-index: 20;
display: grid;
place-items: safe center;
overflow: clip;
padding-inline: 1rem;
pointer-events: none;
}
#overlay.dim {
background: var(--ink-55);
pointer-events: auto;
}
.card {
pointer-events: auto;
background: var(--cream);
color: var(--ink);
border: var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
rotate: -1deg;
inline-size: min(34rem, calc(100vi - 2.5rem));
padding-block: clamp(1.5rem, 1rem + 2vw, 2.5rem);
padding-inline: clamp(1.25rem, 0.9rem + 1.5vw, 2rem);
text-align: center;
text-transform: uppercase;
}
/* title card logo: red/gold misprint offsets */
.logo {
font-size: var(--display);
line-height: 0.95;
letter-spacing: 0.02em;
color: var(--ink);
text-shadow:
3px 3px 0 var(--red),
6px 6px 0 var(--gold);
}
.tagline {
margin-block-start: 0.4rem;
font-family: var(--font-mono);
font-weight: bold;
font-size: 0.8rem;
letter-spacing: 0.3em;
color: var(--red);
}
.howto {
margin-block: 1.1rem 1.4rem;
font-family: var(--font-mono);
font-size: 0.8rem;
line-height: 1.6;
letter-spacing: 0.08em;
}
.foot {
margin-block-start: 1.4rem;
font-family: var(--font-mono);
font-size: 0.7rem;
letter-spacing: 0.25em;
color: var(--ink-dim);
}
.card-title {
font-size: clamp(1.6rem, 1.2rem + 1.8vw, 2.4rem);
line-height: 1;
letter-spacing: 0.03em;
color: var(--ink);
text-shadow: 2px 2px 0 var(--gold);
}
.goal {
margin-block-start: 0.6rem;
font-family: var(--font-mono);
font-weight: bold;
font-size: 1rem;
letter-spacing: 0.14em;
color: var(--red);
}
.blurb {
margin-block: 1rem 1.5rem;
font-family: var(--font-mono);
font-size: 0.85rem;
line-height: 1.55;
letter-spacing: 0.04em;
text-transform: none;
color: var(--ink-dim);
}
.stats {
margin-block: 0.9rem 1.5rem;
font-family: var(--font-mono);
font-weight: bold;
font-size: 0.95rem;
line-height: 1.7;
letter-spacing: 0.08em;
white-space: pre-line;
}
/* modifier chips (main.js fills #intro-mods) */
.chips {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.45rem;
margin-block-start: 0.8rem;
}
.chips:empty { display: none; }
.chips > * {
background: var(--gold);
color: var(--ink);
border: 2px solid var(--ink);
box-shadow: 2px 2px 0 var(--ink);
padding-block: 0.2rem;
padding-inline: 0.6rem;
font-family: var(--font-mono);
font-weight: bold;
font-size: 0.7rem;
letter-spacing: 0.12em;
}
/* ---------- buttons ---------- */
button {
font-family: var(--font-display);
font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--ink);
background: var(--cream);
border: var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding-block: 0.75rem;
padding-inline: 1.6rem;
cursor: pointer;
touch-action: manipulation;
user-select: none;
-webkit-user-select: none;
}
button:active {
translate: 2px 2px;
box-shadow: 2px 2px 0 var(--ink);
}
.btn-row {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.9rem;
}
/* focus: ink ring on cream cards, teal ring on night for the mute button */
button:focus-visible {
outline: max(3px, 0.12em) solid var(--ink);
outline-offset: 3px;
}
#btn-mute:focus-visible {
outline-color: var(--teal);
}
@media (hover: hover) and (pointer: fine) {
button:hover {
translate: 0 -2px;
box-shadow: 4px 6px 0 var(--ink);
}
button:hover:active {
translate: 2px 2px;
box-shadow: 2px 2px 0 var(--ink);
}
}
/* ---------- motion: opt-in, named properties ---------- */
@media (prefers-reduced-motion: no-preference) {
button {
transition:
translate 120ms var(--ease-out),
box-shadow 120ms var(--ease-out),
background-color 120ms var(--ease-out);
}
#overlay {
transition: background-color 180ms var(--ease-out);
}
#stamp.show,
#stamp-sub.show {
animation: stamp-in 0.42s var(--ease-out) both;
}
}
/* ---------- noscript ---------- */
noscript {
position: fixed;
inset: 0;
z-index: 60;
display: grid;
place-items: center;
background: var(--night);
}
noscript p {
background: var(--cream);
color: var(--ink);
border: var(--border);
box-shadow: var(--shadow);
rotate: -1deg;
padding-block: 1rem;
padding-inline: 1.5rem;
font-family: var(--font-mono);
font-weight: bold;
}