feat(machine): add markdown-driven support pages

Add support/help pages accessible via a ? button on the idle screen.
Pages are driven by .md files in /var/lib/lamassu-atm/support/ —
operators can customize content without rebuilding the app.

Features:
- Tabbed view with markdown rendering (via marked)
- Standalone URLs auto-render as QR codes (scannable from phone)
- Table URLs: click-to-reveal QR codes (prevents accidental scans)
- Yes/No rendered as green checkmarks / red X marks
- Wallet comparison table with download QR codes
- FAQ with Lightning-only clarification
- Support page with operator Nostr QR placeholder
- Custodial vs non-custodial footnote
- Large text for touchscreen accessibility
- Centered layout for short-content pages

Closes #36

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-03-28 14:11:54 -04:00
commit d71815a15d
26 changed files with 825 additions and 2 deletions

30
pnpm-lock.yaml generated
View file

@ -41,6 +41,9 @@ importers:
'@scure/base':
specifier: ^1.2.0
version: 1.2.6
'@tanstack/vue-table':
specifier: ^8.21.3
version: 8.21.3(vue@3.5.27(typescript@5.9.3))
'@vueuse/core':
specifier: ^14.1.0
version: 14.1.0(vue@3.5.27(typescript@5.9.3))
@ -56,6 +59,9 @@ importers:
lucide-vue-next:
specifier: ^0.563.0
version: 0.563.0(vue@3.5.27(typescript@5.9.3))
marked:
specifier: ^17.0.5
version: 17.0.5
nostr-tools:
specifier: ^2.10.0
version: 2.19.4(typescript@5.9.3)
@ -1370,9 +1376,19 @@ packages:
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
'@tanstack/table-core@8.21.3':
resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==}
engines: {node: '>=12'}
'@tanstack/virtual-core@3.13.18':
resolution: {integrity: sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==}
'@tanstack/vue-table@8.21.3':
resolution: {integrity: sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==}
engines: {node: '>=12'}
peerDependencies:
vue: '>=3.2'
'@tanstack/vue-virtual@3.13.18':
resolution: {integrity: sha512-6pT8HdHtTU5Z+t906cGdCroUNA5wHjFXsNss9gwk7QAr1VNZtz9IQCs2Nhx0gABK48c+OocHl2As+TMg8+Hy4A==}
peerDependencies:
@ -2518,6 +2534,11 @@ packages:
resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
marked@17.0.5:
resolution: {integrity: sha512-6hLvc0/JEbRjRgzI6wnT2P1XuM1/RrrDEX0kPt0N7jGm1133g6X7DlxFasUIx+72aKAr904GTxhSLDrd5DIlZg==}
engines: {node: '>= 20'}
hasBin: true
matcher@3.0.0:
resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
engines: {node: '>=10'}
@ -4226,8 +4247,15 @@ snapshots:
tailwindcss: 4.1.18
vite: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)
'@tanstack/table-core@8.21.3': {}
'@tanstack/virtual-core@3.13.18': {}
'@tanstack/vue-table@8.21.3(vue@3.5.27(typescript@5.9.3))':
dependencies:
'@tanstack/table-core': 8.21.3
vue: 3.5.27(typescript@5.9.3)
'@tanstack/vue-virtual@3.13.18(vue@3.5.27(typescript@5.9.3))':
dependencies:
'@tanstack/virtual-core': 3.13.18
@ -5651,6 +5679,8 @@ snapshots:
- bluebird
- supports-color
marked@17.0.5: {}
matcher@3.0.0:
dependencies:
escape-string-regexp: 4.0.0