The setup screen stops drawing the man twice, and her whites take a real colour

Oliver, on the picker: the gender tiles "themselves have the player but front
facing and that does not react to the kit and skin — so that's double somehow
and wastes space", the screen "is pretty crowded now", and the women's wash was
"a little too subtle on the white — could be more".

THE TILES ARE GONE. They were a second drawing of the same man, facing the wrong
way and deaf to every colour on the screen, and they cost the height that pushed
the court list under the fold. Who-you-are is two words now, and the live player
— which does react — stands beside every control that changes him, so a tap and
its result are a thumb apart. Four stacked sections became one block; all four
courts and SERVE UP fit a phone without scrolling.

THE WASH goes 0.30/0.93 -> 0.55/0.86: dyed from across the court, folds intact.
Past about 0.70 it stops reading as tennis whites at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-08-15 15:37:35 +02:00
1 parent b5838b2b24
commit ad258ace97
3 files changed
+54 -36

No files matched your search

+43 -32
View File
@@ -213,29 +213,34 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
.two .btn { margin-bottom: 0; }
.btn.sec i { display: block; margin-top: 4px; font: 400 9px Silkscreen, monospace;
font-style: normal; color: var(--dim); letter-spacing: 0.5px; }
/* the tour: two tiles SIDE BY SIDE, not two more full-width rows. The figures face the camera —
in play you only ever see your player from behind, so a rear view would show nothing. */
#tours { display: flex; gap: 8px; }
#tours button { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px;
padding: 8px 6px 10px; background: var(--panel); border: 2px solid var(--line);
color: inherit; font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#tours button.on { border-color: var(--acid); background: rgba(188,212,85,0.09); }
#tours img { height: 88px; width: auto; display: block; image-rendering: pixelated; }
#tours b { font: 400 11px Silkscreen, monospace; color: var(--cream); letter-spacing: 0.5px; }
/* KIT and SKIN: a row of colour squares. That is the whole UI — the pick has no meters and no art
to show, and a labelled tile per colour would be five times the screen for a choice you make by
looking at the colour. The selected one's NAME rides in the h3 on the right, the same slot the
draw screen puts its state in, so nothing on the row is unlabelled. */
.swrow { display: flex; gap: 7px; }
/* THE PLAYER BLOCK: the live man on the left, everything that changes him on the right, so a tap
and its result are never more than a thumb apart and the whole of "who am I" is one screenful. */
#who { display: flex; gap: 12px; align-items: flex-start; }
#whoCtl { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
/* The live player. `position: static` is not decoration: the bare `canvas` rule above is the COURT
— fixed, full-bleed, 100dvh — and it catches any canvas in the document, so this one flew to the
top-left corner of the screen until it was told otherwise. Every geometry property that rule
sets has to be undone here. The buffer is the sprite's own 96x224, so width follows height. */
#look { position: static; display: block; flex: none; margin: 0;
width: auto; height: 176px; touch-action: auto; image-rendering: pixelated; }
/* the tour is now TWO WORDS, not two portraits — the live player next to them is the picture, and
a second drawing of the same man (front-facing, and deaf to every colour on this screen) was
both a duplicate and the reason the court list started below the fold */
#tours { display: flex; gap: 7px; }
#tours button { flex: 1; padding: 10px 2px; background: var(--panel); border: 2px solid var(--line);
color: var(--dim); font: 400 10px Silkscreen, monospace; letter-spacing: 1px;
cursor: pointer; -webkit-tap-highlight-color: transparent; }
#tours button.on { border-color: var(--acid); background: rgba(188,212,85,0.09); color: var(--cream); }
/* KIT and SKIN: a row of colour squares, under a label that names whatever is selected. That is
the whole UI — the pick has no meters and no art to show, and a labelled tile per colour would
be five times the screen for a choice you make by looking at the colour. */
.swlab { display: flex; justify-content: space-between; margin-top: 2px; text-decoration: none;
font: 400 9px Silkscreen, monospace; color: var(--dim); letter-spacing: 1.5px; }
.swlab i { font-style: normal; color: var(--cream); }
.swrow { display: flex; gap: 6px; }
.swrow button { flex: 1; aspect-ratio: 1; min-width: 0; padding: 0; border: 2px solid var(--line);
cursor: pointer; -webkit-tap-highlight-color: transparent; }
.swrow button.on { border-color: var(--acid); box-shadow: inset 0 0 0 2px var(--ink); }
/* The live player, sitting between the tour tiles and the colours it answers to. `position: static`
is not decoration: the bare `canvas` rule above is the COURT — fixed, full-bleed, 100dvh — and it
catches any canvas in the document, so this one flew to the top-left corner of the screen until
it was told otherwise. Every geometry property that rule sets has to be undone here. */
#look { position: static; display: block; margin: 12px auto 0;
width: auto; height: 150px; touch-action: auto; image-rendering: pixelated; }
/* THE BOSS PICKER (back room). Two columns of portraits, because you pick a boss by looking at
him — the tile is mostly art. Same plate as the tour tiles above; the grid is what makes ten
of them fit on a phone. */
@@ -467,18 +472,24 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
</div>
<div id="setup">
<div class="hdr"><button class="chev" id="sBack">&lsaquo;</button><h2>MATCH SETUP</h2></div>
<!-- ONE PLAYER BLOCK. It was four stacked sections — two big portrait tiles, then the live
player, then a kit row, then a skin row — which said the same thing twice (the tiles were
a second, FRONT-FACING drawing of a man who does not react to any of the colours) and ran
the court off the bottom of the phone. The tiles are gone: the live player IS the picture,
so who-you-are shrinks to two words, and every control that changes him stands beside him
where you can watch it land. Kit and skin rows are built in main.js from the tables. -->
<h3>01 · PLAYER</h3>
<div id="tours"></div>
<!-- THE LIVE PLAYER. Not an illustration of the pick — the actual sprite the court will draw,
through the actual tint, so the menu can never promise a colour the match does not keep. -->
<canvas id="look" width="112" height="150"></canvas>
<!-- KIT and SKIN. Both rows are built in main.js from config.KITS/SKINS, so a colour added
there needs no markup — the same rule the tour tiles and the court rows follow. -->
<h3>02 · KIT<span id="kitName"></span></h3>
<div id="kitRow" class="swrow"></div>
<h3>03 · SKIN<span id="skinName"></span></h3>
<div id="skinRow" class="swrow"></div>
<h3>04 · COURT</h3>
<div id="who">
<canvas id="look" width="96" height="224"></canvas>
<div id="whoCtl">
<div id="tours"></div>
<u class="swlab">KIT<i id="kitName"></i></u>
<div id="kitRow" class="swrow"></div>
<u class="swlab">SKIN<i id="skinName"></i></u>
<div id="skinRow" class="swrow"></div>
</div>
</div>
<h3>02 · COURT</h3>
<div id="courtList"></div>
<div class="foot">
<p id="sSum"></p>
@@ -570,6 +581,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
</div>
</div>
</div>
<script type="module" src="src/main.js?v=264"></script>
<script type="module" src="src/main.js?v=265"></script>
</body>
</html>
+8 -3
View File
@@ -760,8 +760,10 @@ export const TOURS = [
// life and gives rose / powder blue / mint / lilac rather than a solid block of colour.
// Her hair and skin fall out of it on lightness alone, which is why this is safe where
// a dye was not.
{ id: 'men', name: "MEN'S SINGLES", tile: 'tour_m', sfx: null, kit: 'dye' },
{ id: 'women', name: "WOMEN'S SINGLES", tile: 'tour_w', sfx: '_f', kit: 'wash', dx: 0.46, apex: 0.78, tossDx: -0.59,
// no `tile` any more: the setup screen draws the LIVE player instead, so assets/tour_m.png and
// tour_w.png are unreferenced (left on disk — they are generated art, not code).
{ id: 'men', name: "MEN'S SINGLES", sfx: null, kit: 'dye' },
{ id: 'women', name: "WOMEN'S SINGLES", sfx: '_f', kit: 'wash', dx: 0.46, apex: 0.78, tossDx: -0.59,
oDx: 0.48, oApex: 0.73 },
];
@@ -834,7 +836,10 @@ export const SKINS = [
export const TINT = {
kit: [150, 300], oKit: [345, 15], skin: [10, 45],
satKit: 0.15, satSkin: 0.28, lumSkin: 0.80,
whiteLum: 0.72, whiteSat: 0.60, washS: 0.30, washL: 0.93,
// washS/washL retuned after Oliver played it: 0.30/0.93 was a hint of colour rather than a kit
// ("a little too subtle on the white — could be more"). 0.55/0.86 reads as dyed from across the
// court and still keeps every fold; past about 0.70 it stops looking like tennis whites at all.
whiteLum: 0.72, whiteSat: 0.60, washS: 0.55, washL: 0.86,
};
// netW was the singles-stick width (10.06) while the court is drawn to the DOUBLES lines, so the
+3 -1
View File
@@ -182,7 +182,9 @@ const tourList = document.getElementById('tours');
for (const t of TOURS) {
const b = document.createElement('button');
b.className = t.id === pickedTour ? 'on' : '';
b.innerHTML = `<img src="assets/${t.tile}.png?v=${SPRV}" alt=""><b>${t.name}</b>`;
// just the word now — the live player beside it is the portrait, and the tile art was a SECOND
// drawing of the same man that no colour on this screen could reach
b.textContent = t.name.replace(' SINGLES', '');
b.addEventListener('click', () => {
pickedTour = t.id;
for (const el of tourList.children) el.classList.toggle('on', el === b);