diff --git a/src/ui/Panel.module.css b/src/ui/Panel.module.css index 907dda3..f7a7234 100644 --- a/src/ui/Panel.module.css +++ b/src/ui/Panel.module.css @@ -1,4 +1,10 @@ -/* Measured geometry: 8 + 36 + 8 + 124 + 10 + 134 + 10 + 187 + 8 = 525. */ +/* Measured geometry: 8 + 36 + 8 + 124 + 10 + 134 + 10 + 187 + 8 = 525. + * + * Ordering matters here: the state classes (.lit, .sel, .held, .down) live at + * the BOTTOM of this file. They are single-class selectors, same specificity as + * .pad or .fx, so whichever comes last wins. With .pad declared after .lit, a + * lit pad kept its grey text and only the border turned orange — pads looked + * unhighlighted next to every other key. */ .panel { height: var(--panel-h); @@ -16,11 +22,6 @@ -webkit-touch-callout: none; } -/* Pressed, whether or not it is lit. */ -.down { - transform: scale(0.95); -} - /* ---- shared key look ---- */ .key, @@ -53,27 +54,6 @@ overflow: hidden; } -/* Lit is an outline, not a fill. The SHIFT layer lights 35 of 54 controls, and - 35 solid orange keys is a wall; solid is reserved for the selected one. */ -.lit { - border-color: var(--accent); - color: var(--accent); - font-weight: 700; -} - -.sel { - background: var(--accent); - border-color: var(--accent); - color: var(--on-accent); - font-weight: 700; -} - -.held { - background: var(--ink); - color: var(--page); - font-weight: 700; -} - .badge { position: absolute; top: 1px; @@ -102,20 +82,6 @@ color: var(--pad-ink); } -/* A round key cannot hold a lit function's label at full size: SHIFT + VALUE is - "MARK FN", which spilled outside the circle. Clip it, and shrink when lit. */ -.knob, -.valueKnob { - overflow: hidden; -} - -.knob.lit, -.knob.sel, -.valueKnob.lit, -.valueKnob.sel { - font-size: 6px; -} - /* ---- fx and the screen ---- */ .screenRow { @@ -286,6 +252,11 @@ border-radius: 4px; } +.side { + color: var(--accent); + font-weight: 700; +} + /* The pad's number, as printed on the hardware. */ .num { font-family: var(--mono); @@ -294,7 +265,39 @@ color: var(--muted); } -.side { +/* ---- state: LAST in the file, so it wins over .pad, .fx, .side and .knob ---- */ + +/* Lit is an outline, not a fill. The SHIFT layer lights 35 of 54 controls, and + 35 solid orange keys is a wall; solid is reserved for the selected one. */ +.lit { + border-color: var(--accent); color: var(--accent); font-weight: 700; } + +.sel { + background: var(--accent); + border-color: var(--accent); + color: var(--on-accent); + font-weight: 700; +} + +.held { + background: var(--ink); + color: var(--page); + font-weight: 700; +} + +/* A round key cannot hold a lit function's label at full size: SHIFT + VALUE is + MARK FN, which spilled outside the circle. Shrink it when lit. */ +.knob.lit, +.knob.sel, +.valueKnob.lit, +.valueKnob.sel { + font-size: 6px; +} + +/* Pressed, whether or not it is lit. */ +.down { + transform: scale(0.95); +} diff --git a/src/ui/native.ts b/src/ui/native.ts index b5d158e..64e2554 100644 --- a/src/ui/native.ts +++ b/src/ui/native.ts @@ -9,18 +9,33 @@ import { Haptics, ImpactStyle, NotificationType } from "@capacitor/haptics"; const isNative = (): boolean => Capacitor.isNativePlatform(); +/** + * Swallowing these was a mistake: haptics did nothing on the device and the + * reason had been discarded. Report once per distinct failure — enough to read + * in logcat, quiet enough not to spam on every key press. + */ +const reported = new Set(); + +function report(where: string, error: unknown): void { + const message = error instanceof Error ? error.message : String(error); + const key = where + ":" + message; + if (reported.has(key)) return; + reported.add(key); + console.error("haptics " + where + " failed:", message); +} + /** A light tick under every key press, as the reference's buzz() did. */ export function tapFeedback(): void { if (!isNative()) return; - void Haptics.impact({ style: ImpactStyle.Light }).catch(() => {}); + Haptics.impact({ style: ImpactStyle.Light }).catch((e) => report("impact", e)); } /** Shaped feedback on a graded answer: right and wrong should feel different. */ export function gradeFeedback(correct: boolean): void { if (!isNative()) return; - void Haptics.notification({ + Haptics.notification({ type: correct ? NotificationType.Success : NotificationType.Error, - }).catch(() => {}); + }).catch((e) => report("notification", e)); } export function exitApp(): void {