Skip to content

Commit 1a2a08e

Browse files
committed
feat(practice): centre kbd-hint via 3-col grid + shrink watermark for multi-digit Q.N
Layout change: - actionbar-inner is now a 3-column grid: timer (left) | kbd-hint (centre) | buttons (right). With equal-fr outer columns, the kbd-hint sits on true visual centre of the bar regardless of how wide the timer or buttons cluster grow. - HTML: kbd-hint moved out of .actionbar-left to become a direct grid child so it can be addressed by grid-column. - Mobile (≤720px): kbd-hint is already display:none; mobile collapses the grid to 2 columns (auto / 1fr) so the buttons get the full remaining width whether or not the timer is showing. Watermark fix: - Q.N watermark was overlapping the wrapped question text once N reached 2+ digits. Two reinforcing fixes: * Cap the watermark font-size lower (clamp max 2.1rem, was 2.75rem) with max-width:6rem + white-space:nowrap so width is bounded. * Bump #quiz-question's reserved right padding to 6rem desktop / 4rem mobile so wrapped text always clears the watermark zone.
1 parent ecc3c63 commit 1a2a08e

2 files changed

Lines changed: 70 additions & 44 deletions

File tree

practice/index.html

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
href="https://fonts.googleapis.com/css2?family=Geist:wght@300..700&family=Geist+Mono:wght@400..600&display=swap">
1313

1414
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" crossorigin="anonymous">
15-
<link rel="stylesheet" href="styles.css?v=32">
15+
<link rel="stylesheet" href="styles.css?v=33">
1616
</head>
1717
<body>
1818
<a class="skip-link" href="#main">Skip to content</a>
@@ -171,12 +171,14 @@ <h3 id="modal-title" class="modal-title">Confirm</h3>
171171
</div>
172172

173173
<!-- ============== STICKY BOTTOM ACTION BAR (quiz mode only) ==============
174-
Layout (row 1): [Timer ←] … [kbd-hint] [Next/Skip/Submit →]
175-
Layout (row 2): [session stats · bank stats · Stats Settings Reset Switch]
176-
177-
Primary actions live on the RIGHT (thumb-reachable for right-handed
178-
users + standard mobile convention). Timer + ambient kbd-hint sit
179-
on the left as passive information. -->
174+
Row 1 is a 3-column grid:
175+
[Timer (left)] [kbd-hint (center)] [Next/Skip/Submit (right)]
176+
Row 2 spans all columns:
177+
[session · bank stats · Stats Settings Reset Switch bank]
178+
179+
The kbd-hint sits in the centre column (independent of timer/buttons)
180+
so it stays optically centred regardless of timer state. On mobile
181+
the centre column is hidden entirely. -->
180182
<div class="actionbar" id="actionbar" hidden>
181183
<div class="actionbar-inner">
182184
<span id="quiz-timer" class="actionbar-timer" hidden
@@ -193,15 +195,15 @@ <h3 id="modal-title" class="modal-title">Confirm</h3>
193195
</span>
194196
<span class="timer-value">00:00</span>
195197
</span>
198+
<span class="kbd-hint" aria-hidden="true" id="kbd-hint-pre">
199+
<kbd>1</kbd><kbd>2</kbd><kbd>3</kbd><kbd>4</kbd> or <kbd></kbd><kbd></kbd> select &nbsp;
200+
<kbd></kbd> / <kbd>Space</kbd> submit &nbsp;
201+
<kbd>S</kbd> skip
202+
</span>
203+
<span class="kbd-hint" aria-hidden="true" id="kbd-hint-post" hidden>
204+
<kbd></kbd> / <kbd>Space</kbd> / <kbd>N</kbd> / <kbd></kbd> next question
205+
</span>
196206
<div class="actionbar-left">
197-
<span class="kbd-hint" aria-hidden="true" id="kbd-hint-pre">
198-
<kbd>1</kbd><kbd>2</kbd><kbd>3</kbd><kbd>4</kbd> or <kbd></kbd><kbd></kbd> select &nbsp;
199-
<kbd></kbd> / <kbd>Space</kbd> submit &nbsp;
200-
<kbd>S</kbd> skip
201-
</span>
202-
<span class="kbd-hint" aria-hidden="true" id="kbd-hint-post" hidden>
203-
<kbd></kbd> / <kbd>Space</kbd> / <kbd>N</kbd> / <kbd></kbd> next question
204-
</span>
205207
<!-- Source order is "Next, Skip, Submit" so the rightmost visible
206208
button is always the primary action: Submit before submit,
207209
Next after. -->

practice/styles.css

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,10 @@ button.link.danger:hover { color: var(--negative); }
844844
right: 1.25rem;
845845
font-family: var(--mono);
846846
font-weight: 500;
847-
font-size: clamp(1.8rem, 4.5vw, 2.75rem);
847+
/* Cap the font-size lower so 3-digit Q-numbers (Q.100, Q.150 …) still
848+
fit inside the reserved padding zone on #quiz-question without
849+
overlapping the wrapped text. */
850+
font-size: clamp(1.55rem, 3.2vw, 2.1rem);
848851
letter-spacing: -0.05em;
849852
line-height: 1;
850853
/* Light theme: dark ink on a near-white surface — needs more opacity
@@ -855,6 +858,10 @@ button.link.danger:hover { color: var(--negative); }
855858
user-select: none;
856859
font-variant-numeric: tabular-nums;
857860
z-index: 0;
861+
/* Anchor right edge so widths stay bounded as N grows */
862+
max-width: 6rem;
863+
text-align: right;
864+
white-space: nowrap;
858865
}
859866
/* Dark theme: bright ink on a near-black surface — same opacity would
860867
pop too much, so we dial it back. */
@@ -865,7 +872,7 @@ button.link.danger:hover { color: var(--negative); }
865872
}
866873
.question-card > *:not(.q-watermark) { position: relative; z-index: 1; }
867874
@media (max-width: 540px) {
868-
.q-watermark { top: 0.5rem; right: 0.85rem; font-size: 1.5rem; opacity: 0.07; }
875+
.q-watermark { top: 0.5rem; right: 0.85rem; font-size: 1.3rem; opacity: 0.07; max-width: 4rem; }
869876
:root[data-theme="dark"] .q-watermark { opacity: 0.055; }
870877
@media (prefers-color-scheme: dark) {
871878
:root[data-theme="auto"] .q-watermark { opacity: 0.055; }
@@ -890,12 +897,12 @@ button.link.danger:hover { color: var(--negative); }
890897
color: var(--fg);
891898
margin: 0 0 1.75rem 0;
892899
/* Reserve right-side space for the Q.N watermark in the card corner.
893-
Without this, long single-line questions wrap into the watermark
894-
zone and the two read as a visual collision. */
895-
padding-right: 4rem;
900+
Sized to clear up to "Q.150" comfortably (5 chars at the capped
901+
watermark font-size + right offset). */
902+
padding-right: 6rem;
896903
}
897904
@media (max-width: 540px) {
898-
#quiz-question { padding-right: 2.75rem; }
905+
#quiz-question { padding-right: 4rem; }
899906
}
900907
#quiz-question p { margin: 0.5rem 0; }
901908
#quiz-question p:first-child { margin-top: 0; }
@@ -1019,39 +1026,45 @@ fieldset#quiz-choices label.incorrect .choice-text { color: var(--negative); }
10191026
}
10201027
.actionbar[hidden] { display: none; }
10211028

1029+
/* 3-column grid for row 1 keeps the kbd-hint optically centred no matter
1030+
how wide the timer or button cluster grows. Row 2 (actionbar-right)
1031+
spans all columns via grid-column: 1 / -1. */
10221032
.actionbar-inner {
10231033
max-width: 1080px;
10241034
margin: 0 auto;
10251035
padding: 0.85rem 1.5rem;
1026-
display: flex;
1036+
display: grid;
1037+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
10271038
align-items: center;
1028-
gap: 1.25rem;
1029-
flex-wrap: wrap;
1039+
gap: 0.5rem 1rem;
10301040
min-height: 64px;
10311041
}
10321042

1043+
#quiz-timer.actionbar-timer {
1044+
grid-column: 1;
1045+
justify-self: start;
1046+
}
1047+
1048+
.actionbar-inner > .kbd-hint {
1049+
grid-column: 2;
1050+
justify-self: center;
1051+
text-align: center;
1052+
margin-left: 0; /* override the inline-flow margin-left */
1053+
white-space: nowrap;
1054+
}
1055+
10331056
.actionbar-left {
1057+
grid-column: 3;
1058+
justify-self: end;
10341059
display: inline-flex;
10351060
align-items: center;
10361061
gap: 0.75rem;
10371062
flex-wrap: wrap;
1063+
justify-content: flex-end;
10381064
}
10391065

1040-
/* New layout: Timer on the LEFT (passive info), Submit/Skip cluster
1041-
pushed to the RIGHT (thumb-reach for right-handers). Stats + nav
1042-
wrap to row 2 below via flex-basis:100%.
1043-
Row 1: [Timer ←] … [kbd-hint] [Next] [Skip] [Submit →]
1044-
Row 2: [session stats · bank stats · ... · Switch bank]
1045-
*/
1046-
#quiz-timer.actionbar-timer {
1047-
order: 0;
1048-
margin-left: 0;
1049-
}
1050-
.actionbar-left {
1051-
order: 1;
1052-
margin-left: auto; /* push the cluster to the right edge */
1053-
}
10541066
.actionbar-right {
1067+
grid-column: 1 / -1; /* row 2 spans the full width */
10551068
display: inline-flex;
10561069
align-items: center;
10571070
gap: 0.85rem;
@@ -1062,8 +1075,6 @@ fieldset#quiz-choices label.incorrect .choice-text { color: var(--negative); }
10621075
letter-spacing: 0.02em;
10631076
color: var(--muted);
10641077
font-variant-numeric: tabular-nums;
1065-
flex-basis: 100%;
1066-
order: 2;
10671078
}
10681079
.actionbar-right #session-stats,
10691080
.actionbar-right #bank-stats { color: var(--fg-soft); }
@@ -1895,10 +1906,23 @@ fieldset#quiz-choices input[type=radio]:checked:focus-visible {
18951906
#stats table { font-size: 0.85rem; }
18961907
#stats th, #stats td { padding: 0.6rem 0.55rem; }
18971908

1898-
/* Action bar — Submit/Skip cluster fills the row but stays right-aligned
1899-
so the thumb-reach side keeps the primary action even when wrapped */
1900-
.actionbar-inner { padding: 0.55rem 0.9rem; gap: 0.5rem; min-height: 56px; }
1901-
.actionbar-left { gap: 0.5rem; width: 100%; justify-content: flex-end; }
1909+
/* On mobile the kbd-hint hides (centre column not needed), so the grid
1910+
collapses to a 2-column layout: timer left + buttons right. When the
1911+
timer is also off (practice mode), col1 collapses to 0 and buttons
1912+
get the full width — no awkward empty half. */
1913+
.actionbar-inner {
1914+
padding: 0.55rem 0.9rem;
1915+
gap: 0.5rem;
1916+
min-height: 56px;
1917+
grid-template-columns: auto 1fr;
1918+
}
1919+
#quiz-timer.actionbar-timer { grid-column: 1; }
1920+
.actionbar-left {
1921+
grid-column: 2;
1922+
gap: 0.5rem;
1923+
justify-content: flex-end;
1924+
}
1925+
.actionbar-right { grid-column: 1 / -1; }
19021926
.actionbar-left button.primary { padding: 0.75rem 1.1rem; font-size: 0.9rem; }
19031927
.actionbar-left button.ghost { padding: 0.65rem 1rem; font-size: 0.85rem; }
19041928
.actionbar-timer { padding: 0.4rem 0.75rem 0.4rem 0.6rem; }

0 commit comments

Comments
 (0)