testsAndMisc/reverse_survivors/src/styles.css
Krzysztof kuhy Rudnicki 5d0caa9725
Some checks failed
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
reverse-survivors CI / check (push) Has been cancelled
reverse_survivors: difficulty tiers
Haunting, Normal and Crusade scale enemy hp and speed, the survivor's
health, your income, and the length of the night. Normal is exactly 1.0 on
every multiplier — it is the identity tier, which is what lets every
existing raw-value assertion keep passing untouched.

Enemy speed now derives from a single helper, so difficulty and frenzy
compose in one place rather than fighting at three call sites.

Also fixes a bug this surfaced: handleRestart ignored the selected tier, so
restarting after choosing Crusade silently reverted to Normal. The
react-hooks purity rule flagged Date.now() in the new handler, and
extracting restartSeed() exposed the omission.

Endless mode is deliberately left out — fmtTime(Infinity) renders
Infinity:NaN, which would cost a guard plus tests for a mode whose only
content is the same game but longer.

README rewritten for all four features, including the reversal of its old
placement promise.

160 tests, 100% coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VFyXexNjMQG9V7K8de17fc
2026-08-09 23:17:07 +02:00

277 lines
5.3 KiB
CSS

:root {
--void: #140b1c;
--panel: #1e1229;
--panel-edge: #34204a;
--bone: #e8dcc8;
--bone-dim: #9c8f7a;
--blood: #c94f7c;
--arcane: #b06ce8;
--holy: #7ce0c3;
--font-display: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
--font-data: ui-monospace, "Cascadia Mono", "JetBrains Mono", Menlo, monospace;
}
* { box-sizing: border-box; }
body {
margin: 0;
background:
radial-gradient(1200px 500px at 50% -10%, #241335 0%, var(--void) 60%);
color: var(--bone);
font-family: var(--font-data);
min-height: 100vh;
}
.frame {
max-width: 1280px;
margin: 0 auto;
padding: 16px 20px 28px;
display: flex;
flex-direction: column;
gap: 14px;
}
.masthead {
display: flex;
align-items: baseline;
gap: 16px;
border-bottom: 1px solid var(--panel-edge);
padding-bottom: 10px;
}
.masthead h1 {
font-family: var(--font-display);
font-size: 1.7rem;
letter-spacing: 0.06em;
margin: 0;
color: var(--bone);
}
.tagline {
margin: 0;
color: var(--bone-dim);
font-size: 0.8rem;
flex: 1;
}
.clock {
margin: 0;
font-size: 1.1rem;
color: var(--arcane);
}
.board {
display: flex;
gap: 14px;
align-items: flex-start;
}
.stage {
border: 1px solid var(--panel-edge);
border-radius: 6px;
background: var(--void);
width: 100%;
max-width: 960px;
height: auto;
display: block;
}
.hud {
width: 270px;
min-width: 220px;
display: flex;
flex-direction: column;
gap: 14px;
position: relative;
}
.hud-block {
background: var(--panel);
border: 1px solid var(--panel-edge);
border-radius: 6px;
padding: 12px 14px;
}
.hud-label {
font-family: var(--font-display);
font-size: 0.95rem;
letter-spacing: 0.12em;
text-transform: uppercase;
margin: 0 0 8px;
color: var(--bone-dim);
}
.hud-num { margin: 6px 0 0; font-size: 0.85rem; }
.phials { display: flex; gap: 5px; }
.phial {
width: 18px;
height: 26px;
border: 1px solid var(--panel-edge);
border-radius: 3px 3px 8px 8px;
background: transparent;
}
.phial-full {
background: linear-gradient(180deg, var(--arcane), #6d3aa8);
border-color: var(--arcane);
box-shadow: 0 0 8px rgba(176, 108, 232, 0.45);
}
.hpbar {
height: 10px;
border: 1px solid var(--panel-edge);
border-radius: 5px;
overflow: hidden;
background: #120b18;
}
.hpbar-fill {
height: 100%;
background: linear-gradient(90deg, #2e5c50, var(--holy));
transition: width 120ms linear;
}
.feed {
list-style: none;
margin: 8px 0 0;
padding: 0;
font-size: 0.75rem;
color: var(--holy);
}
.feed li::before { content: "▲ "; color: var(--bone-dim); }
.status-chips {
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 6px;
margin: 8px 0 0;
padding: 0;
}
.chip {
font-family: var(--font-data);
font-size: 0.68rem;
letter-spacing: 0.04em;
padding: 2px 7px;
border-radius: 999px;
border: 1px solid currentcolor;
opacity: 0.85;
}
.chip-slow { color: var(--arcane); }
.chip-suppress { color: var(--blood); }
.chip-bleed { color: var(--bone-dim); }
.spawnbar {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.card {
font-family: var(--font-data);
background: var(--panel);
color: var(--bone);
border: 1px solid var(--panel-edge);
border-radius: 6px;
padding: 10px 14px;
display: flex;
flex-direction: column;
gap: 3px;
cursor: pointer;
min-width: 118px;
text-align: left;
}
.card:hover:not(:disabled) {
border-color: var(--blood);
box-shadow: 0 0 10px rgba(201, 79, 124, 0.35);
}
.card:focus-visible {
outline: 2px solid var(--arcane);
outline-offset: 2px;
}
.card:disabled { opacity: 0.42; cursor: not-allowed; }
.card-name { font-family: var(--font-display); letter-spacing: 0.05em; }
.card-cost { font-size: 0.72rem; color: var(--blood); }
.card-boss { border-color: #5c2440; }
.card-wave { border-color: #3d2f63; }
.overlay {
background: var(--panel);
border-radius: 6px;
padding: 16px;
text-align: center;
}
.overlay h2 { font-family: var(--font-display); margin: 0 0 6px; }
.overlay p { margin: 0 0 12px; font-size: 0.8rem; color: var(--bone-dim); }
.overlay-win { border: 1px solid var(--blood); }
.overlay-loss { border: 1px solid var(--holy); }
.overlay button {
font-family: var(--font-display);
background: var(--blood);
color: var(--void);
border: none;
border-radius: 5px;
padding: 9px 16px;
cursor: pointer;
letter-spacing: 0.04em;
}
.overlay-loss button { background: var(--holy); }
@media (prefers-reduced-motion: reduce) {
.hpbar-fill { transition: none; }
}
@media (max-width: 900px) {
.board { flex-direction: column; }
.hud { width: 100%; }
}
.card-power { border-color: var(--arcane); }
.card-rift { border-color: var(--bone-dim); }
.card-rift-active { border-color: var(--holy); color: var(--holy); }
.frenzy-banner {
margin: 10px 0 0;
padding: 5px 9px;
border: 1px solid var(--blood);
border-radius: 4px;
color: var(--blood);
font-family: var(--font-data);
font-size: 0.72rem;
letter-spacing: 0.06em;
text-align: center;
}
.difficulty { display: flex; gap: 6px; justify-content: center; margin-top: 6px; }
.diff {
background: none;
border: 1px solid var(--panel-edge);
border-radius: 4px;
color: var(--bone-dim);
cursor: pointer;
font-family: var(--font-data);
font-size: 0.7rem;
padding: 3px 10px;
}
.diff-on { border-color: var(--holy); color: var(--holy); }