|
|
|
@@ -232,14 +232,6 @@
|
|
|
|
|
deleteRow = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Centre a focused name input above the soft keyboard: the keyboard shrinks the screen (--vvh),
|
|
|
|
|
// so wait a beat for it to open + the layout to settle, then scroll the field into view (the
|
|
|
|
|
// default focus-scroll leaves a bottom row hidden behind the keyboard).
|
|
|
|
|
function bringIntoView(e: FocusEvent): void {
|
|
|
|
|
const el = e.currentTarget as HTMLElement;
|
|
|
|
|
setTimeout(() => el.scrollIntoView({ block: 'center' }), 300);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setHostPlays(yes: boolean): void {
|
|
|
|
|
askHostPlays = false;
|
|
|
|
|
if (!yes) return;
|
|
|
|
@@ -286,10 +278,7 @@
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<Screen title={t('new.title')} back="/">
|
|
|
|
|
<!-- The hotseat form flows naturally and scrolls with the screen's own scroll (scrollform: no
|
|
|
|
|
forced full height, no pinned button) so a focused name input's soft keyboard just scrolls the
|
|
|
|
|
page rather than fighting a nested scroll region. -->
|
|
|
|
|
<div class="page" class:scrollform={mode === 'friends' && offlineMode.active}>
|
|
|
|
|
<div class="page">
|
|
|
|
|
<!-- The auto/friends selector. Online it is hidden for guests (no friends to invite). Offline
|
|
|
|
|
it is always shown: "quick" is the local vs_ai flow, "with friends" is the local
|
|
|
|
|
pass-and-play (hotseat) flow. -->
|
|
|
|
@@ -333,7 +322,6 @@
|
|
|
|
|
<input type="checkbox" bind:checked={multipleWords} />
|
|
|
|
|
</label>
|
|
|
|
|
{/if}
|
|
|
|
|
<div class="grow"></div>
|
|
|
|
|
<p class="movelimit">{opponent === 'ai' ? t('new.aiInactiveLimit') : t('new.moveLimit', { n: AUTO_MATCH_HOURS })}</p>
|
|
|
|
|
{#if opponent === 'random'}<p class="searchhint">{t('new.searchHint')}</p>{/if}
|
|
|
|
|
<button
|
|
|
|
@@ -382,7 +370,6 @@
|
|
|
|
|
disabled={!hostPin}
|
|
|
|
|
placeholder={t('hotseat.playerName')}
|
|
|
|
|
maxlength="40"
|
|
|
|
|
onfocus={bringIntoView}
|
|
|
|
|
oninput={() => (row.committed = commitName(row.name, row.committed))}
|
|
|
|
|
onblur={() => (row.name = row.committed)}
|
|
|
|
|
/>
|
|
|
|
@@ -484,20 +471,16 @@
|
|
|
|
|
</Screen>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
/* Natural-flow content (matching the Profile sub-view): no forced height and no pinned CTA, so the
|
|
|
|
|
screen's own scroll (Screen .content + --vvh) handles overflow and a focused input scrolls into
|
|
|
|
|
view above the soft keyboard with a single, clean scroll container. */
|
|
|
|
|
.page {
|
|
|
|
|
padding: var(--pad);
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 14px;
|
|
|
|
|
height: 100%;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
}
|
|
|
|
|
/* The hotseat form: natural height (grows past the viewport → the screen's own scroll takes over)
|
|
|
|
|
with no full-height pinning, so a focused name input just scrolls the page above the keyboard. */
|
|
|
|
|
.page.scrollform {
|
|
|
|
|
height: auto;
|
|
|
|
|
min-height: 100%;
|
|
|
|
|
}
|
|
|
|
|
.subtitle {
|
|
|
|
|
color: var(--text-muted);
|
|
|
|
|
margin: 0;
|
|
|
|
@@ -580,8 +563,6 @@
|
|
|
|
|
border-color: var(--accent);
|
|
|
|
|
}
|
|
|
|
|
.fg {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-height: 0;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 10px;
|
|
|
|
@@ -604,9 +585,6 @@
|
|
|
|
|
border-radius: var(--radius-sm);
|
|
|
|
|
}
|
|
|
|
|
.friends-scroll {
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-height: 0;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 6px;
|
|
|
|
@@ -667,11 +645,6 @@
|
|
|
|
|
color: var(--text-muted);
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
/* Pushes the auto-match start cluster (move-limit hint + Start button) to the bottom,
|
|
|
|
|
mirroring the friend-game invite button pinned by the .fg scroll area. */
|
|
|
|
|
.grow {
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
.invite {
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
padding: 14px;
|
|
|
|
|