Word Search mobile: focused viewport, theme placement, unique-per-size words
Per field feedback. * Each day is now THREE distinct puzzles: the three sizes draw DISJOINT word slices from a date-shuffled pool (small/med/large = 6/9/13, sum 28 unique). Curated fallback themes expanded to 30 words each; LLM proposals accepted only if they supply >= 28 unique words, else fall back. No more repeats across sizes. * Word Search is now a focused game screen on mobile (same as Daily Word): body scroll locked + footer hidden (generalized .playing-game), and the grid sizes to the largest square that fits between the theme and the palette (container query) — the whole puzzle is on screen, no page scroll. * Theme placement: full "Today's theme · <name>" on the size-selection screen; just the theme name on the puzzle itself, saving vertical space for Large. * cosy → cozy. 🇺🇸 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -147,18 +147,20 @@
|
||||
{:else if !words.length}
|
||||
<p class="muted">Could not load today’s word search.</p>
|
||||
{:else}
|
||||
<p class="theme"><span class="lbl">Today’s theme</span>{theme}</p>
|
||||
<p class="theme">{theme}</p>
|
||||
|
||||
<div class="grid" class:ok={okFlash} class:done={status === 'done'} bind:this={gridEl} style="--n:{n}"
|
||||
role="application" aria-label="Word search grid — drag across letters to find words"
|
||||
onpointerdown={down} onpointermove={move} onpointerup={up} onpointercancel={up}>
|
||||
{#each grid as rowStr, r (r)}
|
||||
{#each rowStr.split('') as ch, c (c)}
|
||||
{@const key = r + ',' + c}
|
||||
<div class="cell" class:sel={selSet.has(key)}
|
||||
style={cellColor.has(key) && !selSet.has(key) ? `background:${PALETTE[cellColor.get(key)]};color:#2a2f36` : ''}>{ch}</div>
|
||||
<div class="gridwrap">
|
||||
<div class="grid" class:ok={okFlash} class:done={status === 'done'} bind:this={gridEl} style="--n:{n}"
|
||||
role="application" aria-label="Word search grid — drag across letters to find words"
|
||||
onpointerdown={down} onpointermove={move} onpointerup={up} onpointercancel={up}>
|
||||
{#each grid as rowStr, r (r)}
|
||||
{#each rowStr.split('') as ch, c (c)}
|
||||
{@const key = r + ',' + c}
|
||||
<div class="cell" class:sel={selSet.has(key)}
|
||||
style={cellColor.has(key) && !selSet.has(key) ? `background:${PALETTE[cellColor.get(key)]};color:#2a2f36` : ''}>{ch}</div>
|
||||
{/each}
|
||||
{/each}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palette">
|
||||
@@ -189,9 +191,8 @@
|
||||
<style>
|
||||
.wordsearch { max-width: 520px; margin: 0 auto; opacity: 0; transform: translateY(6px); }
|
||||
.wordsearch.ready { opacity: 1; transform: none; transition: opacity 0.3s ease, transform 0.3s ease; }
|
||||
.theme { text-align: center; font-family: var(--serif); font-size: 1.3rem; color: var(--accent-deep); margin: 0 0 14px; }
|
||||
.theme .lbl { display: block; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.64rem;
|
||||
font-family: var(--label); color: var(--muted); margin-bottom: 2px; }
|
||||
.theme { text-align: center; font-family: var(--serif); font-size: 1.4rem; color: var(--accent-deep); margin: 0 0 12px; }
|
||||
.gridwrap { display: flex; justify-content: center; }
|
||||
.grid {
|
||||
/* Cells are ~32px on a wide screen (board grows with the grid) and shrink via
|
||||
1fr to fit a narrow phone — capped by max-width so it can never overflow. */
|
||||
@@ -224,4 +225,21 @@
|
||||
padding: 11px 26px; font: inherit; font-weight: 600; cursor: pointer; }
|
||||
.share:hover { background: var(--accent-deep); }
|
||||
.muted { color: var(--muted); text-align: center; }
|
||||
|
||||
/* Mobile: a focused game screen (matches Daily Word). The grid sizes to the
|
||||
largest square that fits the space left between the theme and the palette,
|
||||
so the whole puzzle is on screen with no page scroll. */
|
||||
@media (max-width: 720px) {
|
||||
.wordsearch { display: flex; flex-direction: column; height: 100%; max-width: 100%; }
|
||||
.theme { flex-shrink: 0; font-size: 1.2rem; margin: 4px 0 8px; }
|
||||
.gridwrap { flex: 1; min-height: 0; container-type: size; align-items: center; padding: 2px 0; }
|
||||
.grid { width: min(100%, 100cqh, calc(var(--n) * 40px)); max-width: none; margin: 0; }
|
||||
.palette { flex-shrink: 0; margin: 10px auto 0; padding: 9px 12px 10px; max-width: 100%;
|
||||
width: 100%; box-sizing: border-box; }
|
||||
.plabel { margin-bottom: 7px; }
|
||||
.words { gap: 6px; }
|
||||
.words li { font-size: 0.78rem; padding: 3px 9px; }
|
||||
.hint { flex-shrink: 0; padding: 9px 0 calc(env(safe-area-inset-bottom) + 6px); }
|
||||
.result { flex-shrink: 0; padding-bottom: calc(env(safe-area-inset-bottom) + 6px); }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user