Back to Rail Game
SOURCE / PINNED RELEASE

Made of little things.

Rail Game

Release
ccdd5b913413…
Author-recorded commit
ddf0122b6acc…
License
LICENSE
Author’s source reference
nostr://npub1n8ga89w8h6tvwamxusfyzexw8gjy84yxu9rxgnmk955cxtml4ujswzxydd/wss%3A%2F%2Fgit.napplet.soy%2F/n-91ec90c6fdf

Archive hash verified: dad7b678e25f96a3…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

src/styles.css
:root {
  --bg: #101d25; --fg: #e9f2f2; --primary: #78edbb;
  --surface: color-mix(in srgb, var(--bg) 94%, var(--fg));
  --border: color-mix(in srgb, var(--fg) 16%, transparent);
  --muted: color-mix(in srgb, var(--fg) 58%, var(--bg));
  --panel: color-mix(in srgb, var(--bg) 96%, transparent);
  --control-h: 44px;
  color-scheme: dark;
  font: 13px/1.4 "Avenir Next", Avenir, "Segoe UI", sans-serif;
}
* { box-sizing: border-box; }
html, body, #app { height: 100%; margin: 0; background: var(--bg); color: var(--fg); }
body { overflow: hidden; user-select: none; -webkit-user-select: none; }
button { color: inherit; font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
button:focus-visible, canvas:focus-visible { outline: 2px solid var(--primary); outline-offset: -3px; }
button:disabled { opacity: .35; cursor: default; }
button:hover:not(:disabled) { filter: brightness(1.12); }
[hidden] { display: none !important; }
#app { container-type: inline-size; overflow: hidden; }
.game-surface { position: relative; height: 100%; overflow: hidden; }
#game { display: block; width: 100%; height: 100%; touch-action: none; outline: none; }
.hud { position: absolute; inset: max(12px, env(safe-area-inset-top)) 16px auto; display: flex; align-items: center; justify-content: space-between; gap: 16px; pointer-events: none; }
.stage-info { display: flex; flex-direction: column; gap: 3px; }
.stage-info > strong { font-size: 15px; font-weight: 600; letter-spacing: -.3px; }
.micro { color: var(--muted); font: 9px/1.4 ui-monospace, "SFMono-Regular", Consolas, monospace; letter-spacing: 1.4px; }
.micro b { color: var(--fg); margin-left: 5px; font-weight: 500; }
.stats { display: flex; gap: 20px; align-items: center; }
.stats > div { display: flex; flex-direction: column; gap: 2px; }
.stats strong { font: 600 25px/1 ui-monospace, "SFMono-Regular", Consolas, monospace; letter-spacing: -1px; }
.stats > div:first-child strong { color: var(--primary); }
.stat-divider { width: 1px; height: 25px; background: var(--border); }
.actions { display: flex; gap: 4px; pointer-events: auto; }
.icon-button { width: 44px; height: 44px; background: color-mix(in srgb, var(--bg) 70%, transparent); border: 1px solid var(--border); border-radius: 6px; font-size: 20px; position: relative; }
#soundOff { position: absolute; left: 16px; top: 8px; font-size: 19px; }
.route { position: absolute; top: 76px; left: 16px; right: 16px; display: flex; gap: 12px; align-items: center; pointer-events: none; }
.route-track { height: 3px; flex: 1; background: var(--border); position: relative; }
#progress { height: 100%; width: 0; background: var(--primary); }
.route-track i { position: absolute; top: -2px; width: 1px; height: 7px; background: var(--muted); left: 25%; }
.route-track i:nth-last-child(2) { left: 50%; }.route-track i:last-child { left: 75%; }
#routeLabel { color: var(--muted); font: 9px ui-monospace, monospace; letter-spacing: 1px; }
.power-status { position: absolute; top: 100px; left: 16px; color: var(--primary); font: 10px ui-monospace, monospace; letter-spacing: .7px; }
.boss-hud { position: absolute; top: 101px; left: 30%; right: 30%; text-align: center; color: #ff897e; font: 10px ui-monospace, monospace; letter-spacing: 2px; }
.boss-hud > div { height: 5px; background: var(--border); margin-top: 8px; }.boss-hud i { display: block; background: #ff897e; height: 100%; }
.toast { position: absolute; top: 26%; left: 12px; right: 12px; text-align: center; font: 600 14px ui-monospace, monospace; pointer-events: none; opacity: 0; transition: opacity .16s; text-shadow: 0 2px 8px var(--bg); }
.toast[data-visible="true"] { opacity: 1; }.toast[data-tone="good"] { color: var(--primary); }.toast[data-tone="bad"] { color: #f78b7e; }
.overlay { position: absolute; inset: 106px 12px 78px; display: grid; grid-template-columns: minmax(0, 1fr); place-items: center; pointer-events: none; }
.briefing { min-width: 0; pointer-events: auto; width: min(340px, 100%); padding: 16px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 12px 56px #00000024; }
.briefing-top { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.live-dot { height: 6px; width: 6px; border-radius: 50%; background: var(--primary); }
h2 { font-size: 28px; font-weight: 600; line-height: 1.15; letter-spacing: -1.1px; margin: 12px 0 8px; }
.briefing p { color: var(--muted); margin: 0 0 16px; font-size: 12px; line-height: 1.65; }
.legend { display: flex; gap: 12px; font-size: 10px; color: var(--muted); margin-bottom: 16px; }
.legend span { display: flex; align-items: center; gap: 4px; }.legend i { height: 6px; width: 6px; border-radius: 1px; }
.cyan { background: #77dadd; }.green { background: #a0edac; }.coral { background: #df6f69; }
.stage-picker { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; margin-bottom: 12px; }
.stage-picker button { flex: 1; height: 44px; background: transparent; border: 1px solid var(--border); border-radius: 4px; font: 11px ui-monospace, monospace; }
.stage-picker button[aria-pressed="true"] { background: color-mix(in srgb, var(--primary) 9%, var(--bg)); border-color: var(--primary); color: var(--primary); }
.primary-button { display: flex; align-items: center; justify-content: space-between; padding: 0 12px; width: 100%; min-height: 44px; background: var(--primary); color: var(--button-fg, #102a24); border: 0; border-radius: 4px; font-weight: 700; }
.primary-button span { font-size: 20px; }.secondary-button { width: 100%; min-height: 36px; border: 0; background: transparent; color: var(--muted); margin-top: 4px; font-size: 11px; }
.save-status { margin-top: 10px; font: 9px ui-monospace, monospace; color: var(--muted); text-align: center; }
.result-stats { display: flex; justify-content: space-between; margin: 16px 0; gap: 8px; font: 10px ui-monospace, monospace; color: var(--muted); }
.result-stats strong { display: block; margin-top: 4px; font-size: 20px; color: var(--fg); }
.controls { position: absolute; bottom: max(12px, env(safe-area-inset-bottom)); left: 16px; right: 16px; display: flex; align-items: center; justify-content: space-between; gap: 8px; pointer-events: none; }
.controls > button { pointer-events: auto; touch-action: none; width: 68px; height: 44px; background: color-mix(in srgb, var(--bg) 82%, transparent); border: 1px solid var(--border); border-radius: 6px; font-size: 22px; }
.controls > button:active, .controls > button[data-held="true"] { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 16%, var(--bg)); }
.control-hint { display: flex; gap: 16px; align-items: center; color: var(--muted); font: 10px ui-monospace, monospace; }
.keyboard-hint { display: inline-flex; gap: 4px; align-items: center; }kbd { border: 1px solid var(--border); border-radius: 3px; padding: 2px 5px; font: inherit; }
.auto-fire { display: flex; align-items: center; gap: 6px; font-size: 9px; letter-spacing: 1.4px; }.auto-fire i { width: 4px; height: 4px; border-radius: 50%; background: var(--primary); }
.touch-hint { display: none; }.too-small { display: none; }
@media (max-width: 600px) {
  .hud { gap: 8px; inset-inline: 12px; }.stage-info > strong { font-size: 12px; }.stage-info .micro { font-size: 8px; letter-spacing: .5px; }
  .stats { gap: 9px; }.stats strong { font-size: 21px; }.stats .micro { font-size: 8px; letter-spacing: .8px; }.score-stat { display: none !important; }
  .actions { gap: 2px; }.icon-button { width: 36px; border-color: transparent; }.route { left: 12px; right: 12px; top: 68px; }#routeLabel { font-size: 8px; letter-spacing: .5px; }
  .keyboard-hint { display: none; }.touch-hint { display: block; font-size: 8px; letter-spacing: .7px; }.control-hint { flex-direction: column; gap: 6px; }
  .controls { left: 12px; right: 12px; }.controls > button { width: 64px; height: 48px; }.power-status { top: 88px; font-size: 9px; }.boss-hud { top: 109px; left: 22%; right: 22%; }
}
@media (pointer: coarse) { .keyboard-hint { display: none; }.touch-hint { display: block; }.icon-button { min-width: 44px; }.secondary-button { min-height: 44px; } }
@media (max-width: 350px) { .stage-info > strong { max-width: 84px; font-size: 11px; }.stats { gap: 7px; }.stats strong { font-size: 19px; }.stat-divider { display: none; }.legend { gap: 8px; font-size: 9px; }.briefing { padding: 12px; }h2 { font-size: 25px; } }
@media (max-height: 500px) and (min-width: 480px) {
  .hud { top: 8px; }.route { top: 64px; }.overlay { inset: 78px 92px 62px; }.briefing { width: min(540px, 100%); display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; padding: 12px; }
  .briefing-top, h2, .briefing p, .legend, .result-stats { grid-column: 1; }.briefing-top { grid-row: 1; }h2 { grid-row: 2; font-size: 24px; margin: 0; }.briefing p { grid-row: 3 / 5; margin: 0; font-size: 10px; }.legend { display: none; }
  .stage-picker { grid-column: 2; grid-row: 1 / 3; margin: 0; align-self: end; }.primary-button { grid-column: 2; grid-row: 3; }.save-status { grid-column: 2; margin: 0; grid-row: 5; font-size: 8px; }.secondary-button { grid-column: 2; grid-row: 4; min-height: 28px; margin: 0; }.result-stats { grid-row: 5; margin: 0; }.result-stats strong { font-size: 14px; }
  .power-status { top: 77px; }.boss-hud { top: 80px; }.toast { top: 30%; }
}
@media (max-height: 470px) and (max-width: 479px) { .overlay { inset: 83px 12px 66px; }.briefing { padding: 10px; }h2 { margin: 6px 0; font-size: 22px; }.briefing p { font-size: 10px; margin-bottom: 8px; }.legend { display: none; }.stage-picker { margin-bottom: 8px; }.save-status { margin-top: 5px; }.result-stats { margin: 8px 0; } }
@media (max-width: 239px), (max-height: 279px) { .game-surface { display: none; }.too-small { display: grid; height: 100%; place-content: center; padding: 8px; text-align: center; color: var(--muted); font-size: 12px; } }
@media (max-height: 380px) and (max-width: 479px) {
  .overlay { inset: 77px 12px 66px; }.briefing { padding: 8px; }
  .briefing p, .briefing-top, .save-status, .result-stats { display: none; }
  h2 { font-size: 18px; margin: 0 0 8px; }.stage-picker { margin-bottom: 8px; grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 44px; overflow-x: auto; }
  .stage-picker button { height: 32px; font-size: 9px; }
  .secondary-button { min-height: 30px; }.toast { top: 31%; font-size: 11px; }
}
@media (max-width: 280px) { .stage-info > strong { display: none; }.stage-info .micro b { display: block; margin-left: 0; }.hud { gap: 4px; }.stats { gap: 6px; }.actions { gap: 0; } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; } }