diff --git a/PROJECT.md b/PROJECT.md index 05260b4..408a09a 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -491,7 +491,73 @@ zombie (now an occasional opponent, `TUNE.racketEvery`, not the every-game fixtu `RETURNED`, `DOUBLE KILL`) is a footnote to something you already watched happen. Sharing the loud FACE with the milestone cards is right; sharing their SIZE made every footnote read as a milestone. -## THE SEASON — the tournament is the story (2026-08-31, AGREED in discussion; NOT BUILT YET) +## Session log: THE SEASON, PHASES 1-4 — the front door, the record, the rooms, the season beat (2026-08-31, STAGING ONLY) + +All four phases of the plan below, plus the overlay consolidation Oliver asked for in the same +breath ("die modals haben manchmal 2 boxen manchmal eine manchmal keine... der tap wird zu einem +echten button im footer der box... zudem noch das run-ende, hier bitte auch mehr struktur"). + +**THE MODAL IS ONE BOX** (`render.drawModal`). Three drawers — the plain announcement, the rules +card, the walk-on — became one renderer with slots: a MASTHEAD (art beside the title, with the +body's strap under it), a stack of ROWS separated by hairlines (statement over consequence, the +split figure of his level against yours, the blood pool as pips), and a FOOTER BUTTON. The payload +is untouched: `title/body/icon/rules/foe` are the same fields beats.js has always sent, so the +suite and every call site are unaffected — this is a layout. Two consequences worth knowing: +- The entrance is now ONE object flying in from the right. The old per-element stagger would tear + a box apart, and a box that assembles itself out of flying pieces is not a box. +- The button says what HAPPENS (`PLAY ON` / `GOT IT` / `WALK ON`, `m.btn` overrides) instead of + what gesture to make, and it appears only once the box has landed. **A tap anywhere still + dismisses** — the button is the affordance, not a hit target. A modal you could only leave + through one 26px strip would be a worse wall than the one we had. + +**THE RUN-END WEARS THE SAME BOX, AND HANDS OVER.** Headline and the run's line, then the xp it +paid, then the mark, then THE FIXTURE with its buttons — `ENTER THE DRAW` beside `PLAY AGAIN` +(or `THE CLUBHOUSE` when the run just played was the cup). `render.endHit(nx, ny)` gives the +rects back to `main.maybeRestart`, which is where the tap already lived; a tap anywhere else is +the old behaviour exactly, so nothing that worked before stopped working. Netplay gets ONE door +(the clubhouse): dealing a solo cup into a session whose socket is still tearing down is not a +handover, it is a bug waiting for a phone verdict. + +**THE CUP'S OWN EXIT IS A CEREMONY.** `OUT IN THE QUARTER-FINAL.` over `YOUR BEST STANDS: THE +SEMI-FINAL` (or `THE BOARD NOTES IT` when the attempt IS the new record). The board's felled count +is suppressed there — two bests answering different questions in one box was the wall of text this +pass exists to remove. + +**THE RECORD** (`profile.cups` / `profile.out`, `recordCup`, `cupBest`). Two small fields: rounds +ever reached per league, and the rung of the body that ended the last attempt. Written by the two +places a cup run can end (`zombies.killPlayer`, `beats.cupWon`), mirrored server-side beside the +xp (`server.clean_profile` re-derives them like every other field), merged FORWARD on pull. Shown +on the plaque (which stopped repeating "win the cup to advance" — the fixture button below says +that), in the league panel, and in the summary. Training reps write nothing: a rep is not an +attempt. + +**THE FRONT DOOR IS THE FIXTURE.** `PLAY MATCH` became `LEAGUE 3 · THE CUP / 4 ROUNDS · ROUND ONE: +THE STRAWBERRY SELLER` and enters the draw directly — the cup has no court to pick and no opponent +to choose, so the setup screen there was a confirmation page with nothing on it to confirm. The +poster wall moved one tap down behind `OTHER GAMES`. `config.cupFixture` is the single descriptor +all three screens read, so the splash, the summary and the promotion cannot drift apart on its +wording. + +**THE ROOMS.** The wall deals three named groups now — THE SEASON (the cup, alone), THE TRAINING +(the climb, the training court), OUT OF COMPETITION (gore, classic, a friend) — and the cup left +the ZOMBIE TENNIS pocket for the top. That also emptied the second step of everything except +CLASSIC's difficulty chips. `MENU` rows with a `group` key are headings, not posters. + +**THE REVANCHE.** The training list puts the body that knocked you out of the cup FIRST, in a red +tile that says `PUT YOU OUT OF THE CUP`. One remembered rung turns a shelf of eighteen equal tiles +into the obvious answer to the last defeat — the cheapest coupling of Beiwerk to canon we have. + +**THE SEASON BEAT** rides inside the promotion (no new screen): `NEXT: LEAGUE 4 · THE CUP` over +its rounds and its first body — or, for the champion, the title he now has to hold. + +Tests: two added (127 total) — the fixture descriptor against every league (including the +champion's defence), and the record's forward-only write with the eliminator it names. `freshSplatter` +resets `cups`/`out` for the same reason it resets the league: a cup ending writes them for real. + +Open for the phone: whether the fixture button should ever go to the setup screen (it does not +now), and whether the promotion's WALK ON should enter the draw instead of the clubhouse. + +## THE SEASON — the tournament is the story (2026-08-31, AGREED in discussion; PHASES 1-4 BUILT ON STAGING — see the log above) Oliver's diagnosis, and it is right: "alles ist irgendwie beliebig... die Menüführung und die Start- und Endscreens enforcen keine Story-Line". The cause is not a missing story — THE LEAGUES already diff --git a/index.html b/index.html index fa44680..1d3f10a 100644 --- a/index.html +++ b/index.html @@ -237,6 +237,12 @@ if (location.hostname !== 'splatter-tennis.wuwi.one' && !window.Capacitor?.isNat hierarchy is carried by colour rather than by art. */ .btn.big { padding: 13px 10px 11px; background: var(--red); border-color: #69201c; color: #f6e7dc; font: 400 26px Bangers, cursive; letter-spacing: 2px; line-height: 1.15; } + /* THE FIXTURE BUTTON (THE SEASON): the shout stays the shout, and the fixture itself is the + quiet line under it — the same two-register rule the cards follow (Bangers announces, Silkscreen + informs). `b` is not bold here, it IS the announcement face. */ + .btn.big b { display: block; font: inherit; } + .btn.big i { display: block; margin-top: 3px; font: 400 9px Silkscreen, monospace; + font-style: normal; letter-spacing: 0.5px; color: #f0cfc4; } .two { display: flex; gap: 8px; } .two .btn { margin-bottom: 0; } .btn.sec i { display: block; margin-top: 4px; font: 400 9px Silkscreen, monospace; @@ -413,11 +419,21 @@ if (location.hostname !== 'splatter-tennis.wuwi.one' && !window.Capacitor?.isNat text-align: center; line-height: 1.35; } #bossList i, #trainList i { font: 400 8px Silkscreen, monospace; color: var(--dim); font-style: normal; letter-spacing: 1px; } + /* THE REVANCHE TILE (THE SEASON): the one that put you out of the cup, marked and standing + first. Red border and a red line, because it is the only tile on this screen with a reason. */ + #trainList button.put { border-color: var(--red); } + #trainList button.put i { color: #e08a7c; } /* the training picker is 18 rungs deep — the tile carries the HEAD (the same z_*head crop the draw and the walk-on wear), which reads at a third of the boss portrait's height */ #trainList img { height: 44px; width: auto; display: block; image-rendering: pixelated; } /* START is genuinely unreachable until the draw has landed — the wait IS the ceremony */ .btn[disabled] { opacity: 0.32; cursor: default; } + /* the fixture line under the new court: the same two registers the plaque uses — the name in + the league's own acid, what it costs you in the quiet face */ + #prNext { margin: 12px 0 0; font: 400 10px Silkscreen, monospace; color: var(--acid); + letter-spacing: 1px; line-height: 1.6; } + #prNext u { display: block; margin-top: 3px; font-size: 9px; color: var(--dim); + text-decoration: none; letter-spacing: 0.5px; } /* a row, not a stacked tile: three 3:2 tiles stacked fill a phone twice over, and the art still reads at this size. -webkit-tap-highlight-color kills iOS's blue flash over the pixel art. */ /* MODE posters are pure BUTTONS, not selectors (Oliver: the remembered highlight made each one @@ -439,6 +455,15 @@ if (location.hostname !== 'splatter-tennis.wuwi.one' && !window.Capacitor?.isNat at cream-on-crowd was the report from the first live look */ #modeList i, #modeSub i { color: #fff; font-size: 10px; margin-bottom: 0; text-shadow: 0 1px 0 #000, 1px 0 0 #000, -1px 0 0 #000, 0 -1px 0 #000, 0 0 7px #000; } + /* THE GROUP HEADINGS (THE SEASON): what the posters under them are FOR — one path up, a room to + practise in, a room where nothing counts. Deliberately quiet: the posters are the loud objects + on this screen, and a heading competing with them would just be a fourth poster. */ + #modeList .mgroup { margin: 16px 0 7px; } + #modeList .mgroup:first-child { margin-top: 2px; } + #modeList .mgroup b { display: block; font: 400 12px Silkscreen, monospace; letter-spacing: 2px; + color: var(--acid); text-shadow: none; } + #modeList .mgroup i { display: block; margin: 3px 0 0; font: 400 9px Silkscreen, monospace; + font-style: normal; font-size: 9px; color: var(--dim); text-shadow: none; } /* THE SECOND STEP (config.MENU) has its own SCREEN in the wizard: sub-mode cards are full-height posters centred on their scene, and the difficulty chips are plain acid-outline buttons stacked tall — art for EASY/MEDIUM/HARD would be forced, and the chip reads faster. */ @@ -632,7 +657,12 @@ if (location.hostname !== 'splatter-tennis.wuwi.one' && !window.Capacitor?.isNat you can press before the sheets have landed is how you reach the stats screen with half the zombies missing. Swapped by #splash.busy, see main.js. -->