Bump version to 0.4.0, update changelog, fix Swedish typos

Covers the choice events, NPC chains, location text variety, ambient
visual reactivity, intro screen, win/loss art, and the abandon option
added across the last few changes. Also fixes a handful of spelling
and word-choice mistakes found in a sweep of the event text
("blinkmat"→"blinkat", a "summera"/summon false-friend, a stray
English "return" in "Returndatumet", and one word that didn't fit).

Intro and win/loss screens now use a constrained gradient scrim
around the text instead of a flat overlay covering the whole image,
so the artwork stays visible instead of being crushed to black.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Fredrik Johansson
2026-07-13 10:01:35 +02:00
parent 4d47409e03
commit efc19bac1d
4 changed files with 44 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
export const VERSION = '0.3.0'; export const VERSION = '0.4.0';
export interface ChangelogEntry { export interface ChangelogEntry {
version: string; version: string;
@@ -7,6 +7,19 @@ export interface ChangelogEntry {
} }
export const CHANGELOG: ChangelogEntry[] = [ export const CHANGELOG: ChangelogEntry[] = [
{
version: '0.4.0',
date: '2026-07-13',
changes: [
'Vissa händelser ställer nu ett val istället för att bara hända — vad ni svarar Broder Lindqvist spelar roll',
'Syster Hassan och Broder Lindqvist har fått egna, flerstegs historielinjer som reagerar på tidigare val',
'Nya platsbesök: varje plats har nu flera varianter av vad som möter er, inte bara en fast rad text',
'Skärmen reagerar nu på tillståndet i källaren — högre dread färgar allt, låg hemlighet blöder rött i kanterna, kaos-händelser skakar bilden',
'Ny introskärm innan ritualen börjar, med egen bakgrund',
'Seger och nederlag har nu egen bakgrundskonst istället för bara text på svart',
'Ny knapp: Avbryt — överge kulten i förtid om ni ångrar er',
],
},
{ {
version: '0.3.0', version: '0.3.0',
date: '2026-07-08', date: '2026-07-08',

View File

@@ -172,7 +172,7 @@ export const STANDARD_EVENTS: GameEvent[] = [
// ── Anders Fager-register: vardagssvenska möter det ofattbara ── // ── Anders Fager-register: vardagssvenska möter det ofattbara ──
{ {
id: 'ica_maxi', id: 'ica_maxi',
text: 'Kassörskan på ICA Maxi vid Fosie har inte blinkmat på tre veckor. Kunden bakom i kön räknade. Ingen anmälde det. Det är Malmö.', text: 'Kassörskan på ICA Maxi vid Fosie har inte blinkat på tre veckor. Kunden bakom i kön räknade. Ingen anmälde det. Det är Malmö.',
effect: { dread: 7, kaos: 4 }, effect: { dread: 7, kaos: 4 },
weight: 9, weight: 9,
}, },
@@ -560,7 +560,7 @@ export const STANDARD_EVENTS: GameEvent[] = [
}, },
{ {
id: 'hassan_chain_2b', id: 'hassan_chain_2b',
text: 'Syster Hassans anteckningsbok är full nu. Hon slutar be om lov att tala. Det märks inte i mötena — hon sitter tyst och riktig — men ni ser henne titta på dörren mot Värnhemstorget på ett nytt sätt.', text: 'Syster Hassans anteckningsbok är full nu. Hon slutar be om lov att tala. Det märks inte i mötena — hon sitter tyst och rak — men ni ser henne titta på dörren mot Värnhemstorget på ett nytt sätt.',
effect: { hemlighet: -5, dread: 8 }, effect: { hemlighet: -5, dread: 8 },
weight: 8, weight: 8,
requires: { flag: 'hassan_sidelined', completedEventId: 'hassan_ambition', minDread: 35 }, requires: { flag: 'hassan_sidelined', completedEventId: 'hassan_ambition', minDread: 35 },
@@ -658,7 +658,7 @@ export const KAOS_EVENTS: GameEvent[] = [
}, },
{ {
id: 'k_rival_cult', id: 'k_rival_cult',
text: 'En rivaliserande sekt med bas i Hässleholm försöker summera en annan entitet. De summerar fel. De summerar IKEA:s kundtjänst. Det är värre.', text: 'En rivaliserande sekt med bas i Hässleholm försöker mana fram en annan entitet. De manar fel. De manar fram IKEA:s kundtjänst. Det är värre.',
effect: { kaos: -45, dread: 50, hemlighet: 10 }, effect: { kaos: -45, dread: 50, hemlighet: 10 },
weight: 7, weight: 7,
}, },
@@ -718,7 +718,7 @@ export const KAOS_EVENTS: GameEvent[] = [
}, },
{ {
id: 'k_fager_library', id: 'k_fager_library',
text: 'Stadsbiblioteket på Kung Oscars väg har ett rum i källaren som bara öppnas under kaos. Vi var sist dit. Samlingen är imponerande. Returndatumet är omöjligt.', text: 'Stadsbiblioteket på Kung Oscars väg har ett rum i källaren som bara öppnas under kaos. Vi var sist dit. Samlingen är imponerande. Returdatumet är omöjligt.',
effect: { kaos: -55, ritual: 12, dread: 20 }, effect: { kaos: -55, ritual: 12, dread: 20 },
weight: 5, weight: 5,
requires: { minDread: 30 }, requires: { minDread: 30 },

View File

@@ -240,20 +240,20 @@ body {
background-position: center; background-position: center;
background-color: var(--bg); background-color: var(--bg);
align-items: center; align-items: center;
justify-content: center; justify-content: flex-end;
} }
#intro-screen.visible { display: flex; } #intro-screen.visible { display: flex; }
.intro-scrim { .intro-scrim {
background: linear-gradient(180deg, rgba(6,6,14,0.55) 0%, rgba(6,6,14,0.88) 70%, rgba(6,6,14,0.96) 100%); background: linear-gradient(180deg, rgba(6,6,14,0) 0%, rgba(6,6,14,0.75) 35%, rgba(6,6,14,0.97) 100%);
width: 100%; width: 100%;
height: 100%; height: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
padding-bottom: 10vh; padding: 18vh 20px 8vh;
text-align: center; text-align: center;
gap: 12px; gap: 12px;
} }
@@ -286,19 +286,29 @@ body {
display: none; display: none;
position: fixed; position: fixed;
inset: 0; inset: 0;
background: rgba(6, 6, 14, 0.92); background-color: var(--bg);
background-size: cover; background-size: cover;
background-position: center; background-position: center;
z-index: 1000; z-index: 1000;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column;
gap: 16px;
text-align: center;
} }
#overlay.visible { display: flex; } #overlay.visible { display: flex; }
.overlay-scrim {
background: radial-gradient(ellipse 60% 55% at center, rgba(6,6,14,0.94) 0%, rgba(6,6,14,0.8) 55%, rgba(6,6,14,0.35) 80%, transparent 100%);
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16px;
text-align: center;
padding: 20px;
}
.overlay-title { .overlay-title {
font-size: 28px; font-size: 28px;
font-weight: 700; font-weight: 700;

View File

@@ -139,9 +139,11 @@ export function initUI(
</div> </div>
<div id="overlay"> <div id="overlay">
<div class="overlay-title" id="overlay-title"></div> <div class="overlay-scrim">
<div class="overlay-body" id="overlay-body"></div> <div class="overlay-title" id="overlay-title"></div>
<button class="overlay-btn" id="overlay-btn">Börja om</button> <div class="overlay-body" id="overlay-body"></div>
<button class="overlay-btn" id="overlay-btn">Börja om</button>
</div>
</div> </div>
<div id="danger-vignette"></div> <div id="danger-vignette"></div>
@@ -344,17 +346,17 @@ function showOverlay(state: State): void {
const title = document.getElementById('overlay-title')!; const title = document.getElementById('overlay-title')!;
const body = document.getElementById('overlay-body')!; const body = document.getElementById('overlay-body')!;
if (state.phase === 'won') { if (state.phase === 'won') {
ov.style.backgroundImage = "linear-gradient(rgba(6,6,14,0.72), rgba(6,6,14,0.85)), url('/img/win.webp')"; ov.style.backgroundImage = "url('/img/win.webp')";
title.textContent = 'FULLBORDAT'; title.textContent = 'FULLBORDAT';
title.className = 'overlay-title won'; title.className = 'overlay-title won';
body.textContent = 'Det är gjort. Turning Torso pekar rakt ned. Havet är stilla — alltför stilla. Malmö fortsätter som vanligt. Det är det värsta.'; body.textContent = 'Det är gjort. Turning Torso pekar rakt ned. Havet är stilla — alltför stilla. Malmö fortsätter som vanligt. Det är det värsta.';
} else if (state.phase === 'abandoned') { } else if (state.phase === 'abandoned') {
ov.style.backgroundImage = "linear-gradient(rgba(6,6,14,0.72), rgba(6,6,14,0.85)), url('/img/fail.webp')"; ov.style.backgroundImage = "url('/img/fail.webp')";
title.textContent = 'ÖVERGIVET'; title.textContent = 'ÖVERGIVET';
title.className = 'overlay-title lost'; title.className = 'overlay-title lost';
body.textContent = 'Ni lämnar källaren. Cirkeln bryts. Den Sovande sover vidare, ovetande, ofärdig.'; body.textContent = 'Ni lämnar källaren. Cirkeln bryts. Den Sovande sover vidare, ovetande, ofärdig.';
} else { } else {
ov.style.backgroundImage = "linear-gradient(rgba(6,6,14,0.72), rgba(6,6,14,0.85)), url('/img/fail.webp')"; ov.style.backgroundImage = "url('/img/fail.webp')";
title.textContent = 'AVSLÖJAD'; title.textContent = 'AVSLÖJAD';
title.className = 'overlay-title lost'; title.className = 'overlay-title lost';
body.textContent = state.lostReason ?? 'Utredarna kom.'; body.textContent = state.lostReason ?? 'Utredarna kom.';