diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh new file mode 100755 index 0000000..4044a62 --- /dev/null +++ b/.claude/hooks/session-start.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail + +# Only run in Claude Code web sessions. +if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then + exit 0 +fi + +cd "$CLAUDE_PROJECT_DIR" + +# 1. Node dependencies. +if [ ! -d node_modules ] || [ package-lock.json -nt node_modules ] || [ package.json -nt node_modules ]; then + npm install --no-audit --no-fund +fi + +# 2. Playwright browser + OS libs for headless Chromium. +# Prefer --with-deps (installs apt packages Chromium needs). +# If that fails (e.g. broken third-party PPA), fall back to a plain +# browser install so tests can still run when libs are already present. +if ! npx --yes playwright install --with-deps chromium; then + echo "Warning: --with-deps failed, retrying without system deps..." >&2 + npx --yes playwright install chromium +fi diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..e06b033 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,14 @@ +{ + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh" + } + ] + } + ] + } +} diff --git a/.gitignore b/.gitignore index ef1b670..ff7d55e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ dist/ playwright-report/ test-results/ tests/screenshots/ -.claude/ +.claude/* +!.claude/settings.json +!.claude/hooks/ +.claude/settings.local.json diff --git a/src/components/SectionHead.vue b/src/components/SectionHead.vue index 8c1ca9d..53b58ee 100644 --- a/src/components/SectionHead.vue +++ b/src/components/SectionHead.vue @@ -4,7 +4,7 @@
{{ eyebrow }}

{{ title }}

-
+
{{ subtitle }}
diff --git a/src/components/TheDenominations.vue b/src/components/TheDenominations.vue index 3004380..86b7c04 100644 --- a/src/components/TheDenominations.vue +++ b/src/components/TheDenominations.vue @@ -25,8 +25,8 @@ >
-
{{ d.value }} bral
-
{{ d.name }}
+
{{ d.value }} bral
+
{{ d.name }}
@@ -36,20 +36,20 @@
-
+
Obverse · actual size × 1.4
Specimen · {{ sel.name }}
- {{ sel.value }}bral + {{ sel.value }}bral
- +
{{ row[0] }}{{ row[0] }} {{ sel.value }} standard beer{{ sel.value === 1 ? '' : 's' }} diff --git a/src/components/TheExchange.vue b/src/components/TheExchange.vue index 4331314..617fd9f 100644 --- a/src/components/TheExchange.vue +++ b/src/components/TheExchange.vue @@ -10,46 +10,55 @@
-
Official Conversion Engine
+
Official Conversion Engine
Convert between Bral and Beer.
-
+
-
You deposit
+
{{ from }}
-
+ -
-
You receive
+
+
You receive
{{ fmt(result) }}
{{ to }}
-
+
≡ {{ fmt(result * 330) }} mL · {{ (result * 0.33).toFixed(2) }} L
@@ -63,7 +72,7 @@
-
Historical Rate · BRAL / BEER
+
Historical Rate · BRAL / BEER
Stability, by design.
@@ -87,7 +96,7 @@
-
{{ stat.label }}
+
{{ stat.label }}
{{ stat.value }}
diff --git a/src/components/TheHeader.vue b/src/components/TheHeader.vue index c3b528c..c4a3e58 100644 --- a/src/components/TheHeader.vue +++ b/src/components/TheHeader.vue @@ -83,7 +83,7 @@ onUnmounted(() => document.removeEventListener('keydown', onKeydown)) text-decoration: none; color: inherit; } -.header-tagline { opacity: 0.55; white-space: nowrap; } +.header-tagline { opacity: 0.78; white-space: nowrap; } .header-nav { margin-left: auto; display: flex; diff --git a/src/components/TheHero.vue b/src/components/TheHero.vue index 339e9da..8db7e5b 100644 --- a/src/components/TheHero.vue +++ b/src/components/TheHero.vue @@ -6,7 +6,7 @@
◆ Nº 001 - — A Communiqué From The Treasury — + — A Communiqué From The Treasury —

@@ -30,8 +30,8 @@
Ratified · MMXXIV
-
M. Linnet
-
Governor, Banco·Bral
+
M. Linnet
+
Governor, Banco·Bral
@@ -42,7 +42,7 @@ class="stats-item" :style="{ borderLeft: i === 0 ? 'none' : '1px solid var(--ink)' }" > -
{{ stat.key }}
+
{{ stat.key }}
{{ stat.value }}
@@ -72,7 +72,7 @@
-
+
Fig. 001 — Ten Bral, obverse
diff --git a/src/components/TheManifesto.vue b/src/components/TheManifesto.vue index 721bded..afac869 100644 --- a/src/components/TheManifesto.vue +++ b/src/components/TheManifesto.vue @@ -14,7 +14,7 @@ >
{{ a.num }}
-
Article
+
Article

{{ a.title }}

{{ a.body }}

diff --git a/src/components/TheMembers.vue b/src/components/TheMembers.vue index 7f219bd..d7ff1d4 100644 --- a/src/components/TheMembers.vue +++ b/src/components/TheMembers.vue @@ -7,11 +7,17 @@ /> -
+
-
{{ m.role }}
+
{{ m.role }}
{{ m.name.split(' ')[0] }}
-
+
Licensed Minter · {{ sel.id }}
{{ sel.name }}
-
{{ sel.role }}
+
{{ sel.role }}
"{{ sel.motto }}"
-
Statistics, to Date
+
Statistics, to Date
{{ label }} @@ -86,7 +98,7 @@
-
Certification of Authority
+
Certification of Authority
Let it be known that {{ sel.name }} is duly licensed to strike, assay, and countersign Bral coin in the name of the Banco·Bral. @@ -94,7 +106,7 @@
M. Linnet
-
Governor
+
Governor
@@ -123,6 +135,16 @@ function statsFor(m) { ['Cans Contributed', m.cans, 500], ] } + +function onTabKey(e) { + const max = members.length - 1 + if (e.key === 'ArrowRight') { selIdx.value = selIdx.value === max ? 0 : selIdx.value + 1; e.preventDefault() } + else if (e.key === 'ArrowLeft') { selIdx.value = selIdx.value === 0 ? max : selIdx.value - 1; e.preventDefault() } + else if (e.key === 'Home') { selIdx.value = 0; e.preventDefault() } + else if (e.key === 'End') { selIdx.value = max; e.preventDefault() } + else return + document.getElementById(`member-tab-${members[selIdx.value].id}`)?.focus() +}