Sixty words on the wall became a dozen. The handoff's own summary of the rule:
Jersey 15 NAMES (screen titles, rooms, cards), Bangers CALLS exactly once per
screen (the fixture, the primary button, a modal headline), Silkscreen INFORMS
(numbers, labels, chips) — and a sentence survives only where it carries a
decision. Everything else moved into a bar, a pip or the modal that opens with
the mode.
· Jersey 15 bundled subset (9 KB) and Bungee retired after one afternoon
· SPLASH: the plaque is one row, the goal line is gone (the fixture button
below said it already), the two doors carry a number each
· PICK A GAME: rooms are one word, posters are their names, the fixture is a
hero with the only second line — the whole wall fits one screen now
· MATCH SETUP: unnumbered blocks, the meters' legend once instead of a
description per court, no summary footer
· DIFFICULTY: three pips instead of three sentences
· TRAINING: the revanche is a full-width row, rungs are numbers, the list
ends on the league that opens the rest of the ladder
· VS: three paragraphs became YOU / HOST / JOIN
· MODALS: one rule per row (the sub was the lead again in other words), the
blood pool as pips on that same line, and the walk-on's two levels in ONE
face at ONE size — a comparison drawn at two sizes is a headline with a
footnote (Oliver)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Handoff: Menüführung — Text reduzieren (Splatter Tennis)
Overview
Die funktionalen Screens von Splatter Tennis (Splash, PICK A GAME, MATCH SETUP, DIFFICULTY,
TRAINING, VS A FRIEND und die In-Game-Modals) tragen heute mehr Text als eine Entscheidung
braucht — auf PICK A GAME rund 60 Wörter, verteilt auf drei Rubriken mit Straps plus sechs
Poster mit je einer Regelzeile. Das Ergebnis dieser Session: eine reduzierte Fassung aller
funktionalen Screens (~12–18 Wörter auf der Wand) und ein Wechsel der aufrechten Display-Schrift
von Bungee auf Jersey 15.
Gameplay, Stats-Screens und Canvas-HUD sind bewusst NICHT Teil dieses Pakets.
About the Design Files
Menues.dc.html ist eine Design-Referenz in HTML — ein Prototyp, der Aussehen und Struktur
zeigt, kein Produktionscode zum Kopieren. Splatter Tennis ist Vanilla JS ohne Build-Step
(CLAUDE.md, Punkt 5: „Zero dependencies, no build step, no framework"), also wird die Fassung
in der bestehenden Umgebung nachgebaut: DOM-Menüs in index.html + src/main.js, Canvas-Modals
in src/render.js, Texte in src/config.js. Kein neues Framework, keine neuen Dateien ausser
der Schriftdatei.
Die Datei enthält mehrere Runden untereinander, neueste oben. Verbindlich ist Runde 5
(„GESETZT — ALLE SCREENS IN JERSEY 15"). Darunter liegen als Historie: Runde 4 (Schrift-Kandidaten
Bebas Neue / Oswald / Jersey 15), Runde 3a (derselbe Satz in Bebas), Runde 2 (Bungee vs. Bangers),
Runde 1 (die zwei Grundrichtungen) und ganz unten der IST-Stand, pixelgenau aus dem heutigen
index.html nachgebaut — nützlich als Vor/Nach-Vergleich.
Fidelity
High-fidelity. Palette, Masse, Schriftgrössen und Copy sind aus dem Repo übernommen
(index.html CSS, config.MODES / MENU / COURTS / LEAGUES / OPPONENTS, beats.js
Modal-Payloads). Alle Sprites/Poster im Prototyp sind echte Repo-Assets. Übernahme darf 1:1
erfolgen.
Die drei Register (die eigentliche Entscheidung)
| Rolle | heute | neu |
|---|---|---|
| benennen — Screen-Titel, Rubriken, Karten- und Poster-Namen | Bungee | Jersey 15 |
| rufen — einmal pro Screen: Fixture, Primär-Button, Modal-Headline | Bangers | Bangers (unverändert) |
| informieren — Zahlen, Labels, Chips | Silkscreen | Silkscreen (unverändert) |
Begründung Bungee → Jersey 15: Bungee ist Single-Weight und sehr fett/blockig; Jersey 15 sitzt auf demselben Pixelraster wie Silkscreen (wirkt als Schriftfamilie mit der Sprite-Art), läuft proportional und deutlich leichter. Beide sind SIL OFL.
Grössen-Umrechnung Bungee → Jersey 15: ca. +40 % (Jersey sitzt tiefer im Kasten und läuft leichter). Konkrete Werte im Abschnitt „Design Tokens".
Schrift einbauen
Jersey15-Regular.ttfvon Google Fonts holen, wie Bungee subsetten (pyftsubset, Befehl steht inPROJECT.md) →assets/fonts/Jersey15-Subset.ttf.- In
index.htmldas@font-facevon Bungee ersetzen (?v=mitziehen wie bei den anderen drei):@font-face { font-family: 'Jersey 15'; font-weight: 400; font-display: block; src: url('assets/fonts/Jersey15-Subset.ttf?v=87') format('truetype'); } - Alle
Bungee-Vorkommen inindex.htmlauf'Jersey 15'umstellen (Liste unten),Bungee-Subset.ttfundBungee-OFL.txtlöschen,Jersey15-OFL.txtdaneben legen. main.js?v=Ninindex.htmlbumpen (CLAUDE.md, Punkt 4).
Screens / Views
1 — Splash (#splash in index.html)
Zweck: Eintritt; die Plakette zeigt wer du bist, der Primär-Button das nächste Fixture.
Änderungen:
- Plakette (
#plaque) wird eine Zeile statt vier Grid-Areas: Wappen links (50px), rechts Name +LEVEL 12in einer Baseline-Zeile, darunter der XP-Balken mit der Ziel-Zahl rechts.#plGoalentfällt komplett — „WIN THE CUP TO REACH LEAGUE 4" sagt der Fixture-Button darunter schon. Grid-Areasname/lv/bar/goalwerden zu einem Flex-Row mit zwei Spalten.- Name: Jersey 15 21px,
#ccd7ca,letter-spacing:0.5px(war Silkscreen 700 13px) LEVEL 12: Silkscreen 700 10px,#bcd455(war Bangers 26px als#plLv— der Ruf gehört dem Button unten, nicht der Plakette)- Balken unverändert (6px,
#2c4238Rahmen, Gradient#3f9560 → #bcd455 55% → #e8b23a)
- Name: Jersey 15 21px,
- Fixture-Button (
#mStart) bleibt Bangers 26px; die zweite Zeile (#msLine) verliert das Rundenpräfix:ROUND ONE: THE STRAWBERRY SELLERstatt4 ROUNDS · ROUND ONE: THE STRAWBERRY SELLER. → inconfig.cupFixturedielinekürzen (rounds.length + ' ROUNDS · 'fällt weg; die Rundenzahl steht im Modal). #mOtherverliert seinen Strap (<i>CLIMB · TRAINING · GORE · A FRIEND</i>löschen), Label auf Jersey 15 19px.#mStats/#mRanks: Straps ersetzt durch je eine Zahl aus lokalem Stand —STATS / 4 812(Kill-Count, wie heute) undBOARD / BEST 612(eigener Bestwert; kein Weltrang, der Splash lädt/data/scores.jsonnicht). Label Jersey 15 16px, Zahl Silkscreen 700 10px#bcd455.- Logo, Slogan (
Fifteen. Thirty. Forty. Dead.),#buildunverändert.
2 — PICK A GAME (#stmode / #modeList, gebaut in main.buildTops)
Zweck: einen Modus wählen. Das ist der Screen, der „erschlägt".
- Rubriken (
#modeList .mgroup > header) verlieren ihren Strap (<i>) und werden ein Wort:THE SEASON → SEASON,THE TRAINING → TRAINING,OUT OF COMPETITION → CASUAL. Jersey 15 17px,#bcd455,letter-spacing:2px. →config.MENU:subder dreigroup-Rows löschen,group-Text kürzen; inmain.buildTopsdas<i>aus demheader-Template nehmen. - Poster tragen nur noch den Namen —
<i>${card.sub}</i>fällt inmain.banner()weg. Damit werden diesub-Felder inconfig.MODESfür die Wand irrelevant (Aufbewahren lohnt: die Modals nutzen dieselben Sätze). - Hero-Poster (das Fixture,
mode:'cup') ist der einzige mit einer zweiten Zeile und dem einzigen Ruf: Name in Bangers 32px, darunter die Fixture-Zeile in Silkscreen 10px#f0cfc4. Höhe 142px..way-Ribbon („THE WAY UP") unverändert. - Übrige Poster in Jersey 15, Höhe gestaffelt statt einheitlich 148px:
- TRAINING-Raum: zwei Poster nebeneinander, je
flex:1, Höhe 106px, Name 27px - CASUAL-Raum: drei Poster gestapelt, Höhe 84px, Name 30px
- TRAINING-Raum: zwei Poster nebeneinander, je
- Regeln, die wirklich anders sind, bleiben als Chip (
.last-Optik, Silkscreen 8px, acid,rgba(0,0,0,0.72)Grund):18 RUNGSauf TRAINING,LASTauf dem zuletzt gespielten. - Ergebnis: der ganze Wall passt in 844px (heute zwei Bildschirme). Gerechnet mit Header 64 + Padding 14 + 142/106/84 + Gaps 17/8.
3 — MATCH SETUP (#setup)
<h3 id="s01">01 · PLAYER</h3>/02 · COURT→ Rubrik-Zeile wie auf der Wand: Jersey 15 17px acid, TextPLAYER/COURT. Die Nummerierung entfällt (es sind zwei Blöcke auf einem Screen, keine Schritte).- Über der Platzliste steht die Legende einmal: rechts in der Rubrik-Zeile
BOUNCE · PACE(Silkscreen 8px, dim). - Platz-Zeilen (
#courtList button.court) verlieren<i>${court.sub}</i>— Name (Jersey 15 19px) plus die zwei Meter, die dasselbe wortlos sagen. Bildhöhe 66 → 60px. - Gesperrte Plätze (
.court.lock) behalten Bild und Namen, statt einer Erklärung nurLEAGUE 4in#cf5a4e, Silkscreen 9px. - Tour-Tiles:
MEN'S SINGLES/WOMEN'S SINGLES→MEN'S/WOMEN'S, Jersey 15 16px. #sSum(die Zusammenfassungszeile über SERVE UP) entfällt — alle drei genannten Werte sind auf dem Screen sichtbar markiert.SERVE UPbleibt Bangers 26px auf#a4231f.
4 — DIFFICULTY (#stsub / #modeSub button.chip, aus config.DIFFS)
- Chip wird zweispaltig: Name links (Jersey 15 30px), drei Pips rechts (je 10×10px, kein
Radius) — 1/2/3 gefüllt. EASY/MEDIUM acid
#bcd455, HARD#cf5a4e; leere Pipsrgba(255,255,255,0.12). - Kein Erklärtext. Padding 26px/16px,
gap:10px. LAST-Chip bleibt oben rechts im gewählten.
5 — TRAINING (#train / #trainList, gebaut in main.buildTrain)
<h3>PICK YOUR OPPONENT<span>ONE GAME · GO AGAIN</span></h3>entfällt — der Screen-TitelTRAININGgenügt.- Revanche-Tile (
profile.prof.out) wird eine breite Zeile über dem Raster: Kopf 52px links, Name (Jersey 15 24px), darunterPUT YOU OUT(stattPUT YOU OUT OF THE CUP) in#e08a7c, Chevron rechts. Rahmen#a4231f, Grundrgba(164,35,31,0.16). - Übrige Rungs bleiben das 2-spaltige Raster: Kopf 44px, Name Jersey 15 17px zentriert,
Rangnummer zweistellig (
01,02, …) stattNo. 1— Silkscreen 8px dim. - Letzte Kachel ist ein Ziel, keine Liste: gestrichelter Rahmen
#2c4238,LEAGUE 4und13 — 15in#4a5a52. (Heute endet die Liste einfach am Band-Cap.)
6 — VS A FRIEND (#vs / #vsPick)
- Die drei
<h3>mit Straps (01 · YOUR NAME / ON THEIR SCOREBOARD,02 · HOST A MATCH / THEY COME TO YOU,OR JOIN THEIRS / WITH THEIR CODE) werden drei Wörter:YOU/HOST/JOIN, Jersey 15 17px acid. - Host-Buttons:
CLASSIC TENNIS/DEATH MATCH→CLASSIC/DEATH MATCHnebeneinander, Jersey 15 19px, Padding 20px. - Join-Zeile: Code-Feld plus Button
GO(stattJOIN— daneben steht die Rubrik JOIN), Feld-Letterspacing 6px. #vsErr-Meldungen unverändert (THE CODE IS FOUR LETTERS).
7 — In-Game-Modals (render.drawModal, Payloads aus beats.js)
Die Box-Sprache aus dem 2026-08-31-Pass bleibt (MODAL_PAD 14, MODAL_GAP 13, MODAL_BTN 30,
MODAL_FOOT 8, Breite min(W-44, 244), Fill rgba(8,22,16,0.93), Edge rgba(120,150,130,0.45),
Rules rgba(120,150,130,0.22)). Reduziert wird der Inhalt einer Row:
- Eine Regel pro Row, keine Unterzeile. Heute rendert
modalRowsprom.rules-Eintraglead+sub; dersubformuliert in fast allen Fällen denleadnur um (YOUR LEAGUE, ROUND BY ROUND/WIN IT ALL — MOVE UP A LEAGUE). Neu: eine Zeile, die das Ergebnis nennt —WIN IT ALL — MOVE UP A LEAGUE. Also inbeats.jsdierules-Arrays auf je einen String reduzieren undmodalRowsentsprechend vereinfachen;m.bodybleibt als Fallback unverändert. - Blut ist Pips, kein Satz: Row
POINTS DRAW BLOOD(gekürzt vonITS POINTS DRAW BLOOD) plusTUNE.matchPlayerHpPips in derselben Zeile rechts, statt Zeile + Unterzeile (AT ZERO YOU ARE EATEN) + Pips darunter. - Masthead: Titel Bangers 27px in der Modal-Farbe, darunter EINE Silkscreen-10px-Zeile.
Beim Rules-Modal ist das die Sachzeile (
LEAGUE 3 · 4 ROUNDS) — hier landet die Rundenzahl, die auscupFixture.linegenommen wurde. Beim Walk-on bleibt esfoe.line(CREAM WITH THAT?). - Walk-on (Gegner): Kopf-Sprite 56px, Name,
foe.line, dann EINE Row mit den zwei Leveln gegenüber (LEVEL 14hot links,YOURS 12dim rechts) — statt zwei Textzeilen plus Split-Figur. - Footer-Button unverändert (
WALK ON/GOT IT/PLAY ON,m.btnüberschreibt).
8 — Quit-Modal (#qAsk / .qBox)
Unverändert übernehmen — es ist schon lean. Nur LEAVE THE MATCH? von Silkscreen 12px auf
Bangers 20px (es ist eine Frage, die ruft), PLAY ON auf Jersey 15 17px.
Interactions & Behavior
Keine Änderung an Navigation oder Zustandslogik. Alles Bestehende bleibt:
go(stage)/#intro[data-stage], ein Overlay, vier Panels- Tap auf ein Poster antwortet UND geht weiter (
main.buildTops),pickModeschreibtlocalStorage.mode - Die Deal-in-Animation (
#intro.deal,dealIn0.28scubic-bezier(0.34,1.56,0.64,1), Delays 0.02/0.09/0.16/0.23/0.30s,.mgroup-Staffel 0.09/0.17/0.25s) gilt weiter — die Rubriken bleiben<section class="mgroup">, damit sie greift prefers-reduced-motion: reduceschaltet sie weiter ab- Modal-Dismiss-Regeln unverändert (
m.in < 1schluckt die Gesture, Tap überall entlässt,G.seen.<key>gated) - Swipe-links-zurück im Shell bleibt unberührt
State Management
Nichts Neues. Zwei Werte werden neu GELESEN, beide existieren schon:
profile.prof.out(der Rung, der dich aus dem Cup geworfen hat) → Revanche-Zeile; wird bereits vonbuildTraingenutzt- der eigene Bestwert für die BOARD-Kachel → aus
stats(lokal), nicht vom Server
Design Tokens
Unverändert aus index.html:
--ink #0e1714 --panel rgba(42,62,54,0.42) --line #2c4238
--acid #bcd455 --cream #ccd7ca --dim #6c7f74
--red #a4231f --bad #cf5a4e --solid #16211d
Poster-Veil: linear-gradient(0deg, rgba(6,10,8,0.94) 0%, rgba(6,10,8,0.86) 22%,
rgba(6,10,8,0.5) 58%, rgba(6,10,8,0) 100%) — Höhe 52–62 % je Kachelhöhe
Modal: fill rgba(8,22,16,0.93) · edge rgba(120,150,130,0.45) · rule rgba(120,150,130,0.22)
Rahmen: 2px überall in den Menüs, 1px im Canvas-Modal
Typografie neu (Bungee-Wert → Jersey-15-Wert):
Screen-Titel (.hdr h2) 23px → 33px/1 letter-spacing 1px
Rubrik / Raum-Label 15px → 17px letter-spacing 2px
Poster-Name, Hero — → Bangers 32px/0.95 (der eine Ruf)
Poster-Name, TRAINING-Paar 17px → 27px/1
Poster-Name, CASUAL-Stapel 19px → 30px/1
Karten-/Platz-Name 15px → 22px
Difficulty-Chip 22px → 30px
Training-Tile-Name 12px → 17px/1
Sekundär-Button 13px → 18px
Zahlen, Labels, Chips Silkscreen 8–10px (unverändert)
Primär-Button Bangers 26px (unverändert)
Assets
Alle Assets im Prototyp stammen aus dem Repo, unverändert — nichts muss neu gezeichnet werden:
assets/logo.png, menu_bg.png, mode_cup|arcade|train|gore|classic|vs.png,
court_clay|hard|grass|gloom.png, badge_l3.png, z_{sh,bb,sp,gk,rm,st,ma,ru,sb,sg,lj,cu}head.png,
fonts/{Silkscreen-Regular,Silkscreen-Bold,Bangers-Regular}.ttf.
NEU nötig: fonts/Jersey15-Subset.ttf (Google Fonts, SIL OFL) — ersetzt Bungee-Subset.ttf.
Files
Menues.dc.html— der Prototyp. Runde 5 oben ist verbindlich; darunter Runde 4 (Schriftwahl), 3a (Bebas-Fassung), 2 (Bungee vs. Bangers), 1 (Grundrichtungen), IST-Stand.support.js— Runtime des Prototyps, für die Implementierung irrelevant.assets/— die Repo-Assets, die der Prototyp lädt.
Betroffene Repo-Dateien: index.html (CSS + Markup der Panels), src/main.js
(banner, buildTops, buildSub, buildTrain, refreshSplash), src/config.js
(MENU-Gruppen, cupFixture.line, ggf. MODES.sub), src/render.js (modalRows,
modalLayout), src/beats.js (die rules-Payloads).
Vor dem Commit
node test.js muss grün sein (CLAUDE.md, Punkt 2) — die Fixture-Deskriptor-Tests hängen an
cupFixture, also die line-Kürzung dort mit anpassen. main.js?v=N bumpen.