Commit Graph

101 Commits

Author SHA1 Message Date
Falkan
3a256ccef5 fix: adminPath reroute — move to hooks.ts universal hook, read config.json directly 2026-03-17 20:36:12 -04:00
Falkan
9e9040d998 feat: adminPath in config.json now drives actual route rewriting via server hook 2026-03-17 20:30:56 -04:00
Falkan
e7752ad4ca fix: results grid uses auto-fill minmax so columns scale with available space 2026-03-17 20:18:19 -04:00
Falkan
ae6a073b7e feat: two-line cards, responsive grid, real uniform font size
- ConversionResult: already two-line layout (value + label/symbol)
- app.css: responsive grid (1/2/3 cols at <480/480-899/≥900px)
- uniformFontSize.ts: JS-measured uniform font size per grid
- config.ts: remove MIN_COLUMN_WIDTH, grid is now CSS-only
- BACKLOG.md: remove resolved 'allow renaming unit/group IDs' item

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 20:17:09 -04:00
Falkan
af83263520 feat: two-line cards, responsive grid, real uniform font size 2026-03-17 20:13:57 -04:00
Falkan
b2adcf05ca feat: bulk delete action with confirmation in admin panel 2026-03-17 20:02:48 -04:00
Falkan
192e852a8c feat: add text-decoration underline to bulk-clear button hover 2026-03-17 20:01:18 -04:00
Falkan
a5d0e988f8 feat: auto-ID generation from label with kebab conversion 2026-03-17 20:00:53 -04:00
Falkan
1317f5e8fb feat: per-group sort order (defined/alpha) in group form and converter 2026-03-17 19:59:02 -04:00
Falkan
6d72242aaa feat: drag-to-reorder groups and units with PUT /admin/api/order 2026-03-17 19:58:17 -04:00
Falkan
c1279c3757 feat: auto-save dirty form guard with field-error highlighting 2026-03-17 19:56:39 -04:00
Falkan
15b763e062 feat: unit descriptions with tooltip action and admin textarea 2026-03-17 19:55:09 -04:00
Falkan
9a8b82eca5 docs: backlog — admin UI for YOLO mode label/description config 2026-03-17 19:51:09 -04:00
Falkan
e2e53ca44a feat: YOLO toggle inline layout; yoloLabel/yoloDescription configurable via config.json 2026-03-17 19:50:59 -04:00
Falkan
78e24017a7 fix: uncontrolled input — stop re-setting value prop on every keystroke, killing focus 2026-03-17 19:27:07 -04:00
Falkan
d2045b7a00 Added some units. 2026-03-17 19:14:13 -04:00
Falkan
b14ae55432 docs: backlog — unit ID rename, descriptions/tooltips, sort order, drag reorder, unsaved-form guard 2026-03-17 19:04:52 -04:00
Falkan
3ff98dff9c docs: backlog — allow renaming group IDs with cascaded reference updates 2026-03-17 18:35:33 -04:00
Falkan
f43f415cfa fix: translate __orphan__ sentinel to null in bulk move; ungrouped units now fully bulk-operable 2026-03-17 18:32:03 -04:00
Falkan
91398174e6 docs: log three backlog improvements 2026-03-17 18:31:23 -04:00
Falkan
ccd25a14fe docs: add BACKLOG.md for non-blocking bugs and improvements 2026-03-17 18:02:34 -04:00
Falkan
e4a989046f docs: correct ghost button hover gotcha — must override CSS vars, not just color 2026-03-17 18:01:12 -04:00
Falkan
6e992bbfae fix: bulk-clear hover — override Pico CSS vars not just color property 2026-03-17 18:00:52 -04:00
Falkan
221dd57deb docs: document plain button hover invisibility gotcha in PICO_CSS.md 2026-03-17 17:58:10 -04:00
Falkan
670833ffa2 fix: bulk-clear hover invisible in light/Dan mode (Pico [role=button] override) 2026-03-17 17:57:14 -04:00
Falkan
7cdb84a4f3 refactor: bulk bar — stable layout, disabled not hidden, stacked group row 2026-03-17 16:22:45 -04:00
Falkan
10d94d676b refactor: bulk bar — two-row layout, better contrast, controls only when active 2026-03-17 16:14:37 -04:00
Falkan
ac6af9e90d refactor: admin left panel — wider, less cluttered, persistent bulk action bar
- Left panel widened to 340px (was 280px)
- Removed redundant edit pencil icons from unit rows — clicking the row selects it
- Group names truncate with ellipsis instead of wrapping
- Added select-all/none checkbox per group header (with indeterminate state)
- Bulk action bar is now persistent at top of left panel, always visible
- Bulk actions use two-dropdown pattern: Action (Move to group) → Target group
- 'Add unit' text shortened to '+ Add unit', no more wrapping
- Delete-group orphan label clarified: 'Delete group only — keep units as Ungrouped'
2026-03-17 15:45:11 -04:00
Falkan
c2179b69cc chore: normalize units.json formatting (no data change) 2026-03-17 14:24:55 -04:00
Falkan
aeeae1e7ce refactor: simplify admin code — extract shared helpers, fix quality issues
- Extract KEBAB_RE, SESSION_COOKIE, SESSION_MAX_AGE_MS, COOKIE_MAX_AGE,
  authRequest(), and sessionResponse() to auth.ts — eliminating 4 copies
  of the auth() wrapper and 3 copies of KEBAB_RE across admin API routes
- Remove timing side-channel: drop a.length !== b.length early-return
  before timingSafeEqual in verifySession (SHA-256 HMAC always 64 chars)
- Fix YOLO localStorage write-before-read race using initialization guard
- Fix admin layout /api/ bypass to return {} instead of {authenticated:true}
- Extract extractError() helper in admin page — removes 4 inline patterns
- Parallel Promise.all in admin loadData() — halves round-trip latency
- Parallel Promise.all in moveCheckedUnits() + surface per-request errors
- Hoist Big(inputValue) above .map() in converter — one alloc per recompute
- O(n) single-pass orderedResults using Map instead of O(n*groups) filters
- Fix expandedGroups.add() mutation — use Set assignment for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:04:33 -04:00
Falkan
d1f51c141e feat: admin page with dynamic converter loading
Implements full admin interface for managing units and groups.
Migrates converter from static imports to server-side data loading.

- Switch adapter-static → adapter-node
- Add bcryptjs session auth with HMAC-signed cookies
- Add data/units.json and data/config.json data layer
- Add atomic file writes via temp-file rename
- Add public GET /api/units endpoint
- Add auth-gated admin CRUD API for units and groups
- Add two-panel admin UI with group tree and edit forms
- Add YOLO mode toggle for cross-group conversions
- Add visual group dividers in converter results grid
- Update ResultItem type for nullable convertedValue and isYolo flag
- Group deletion supports reassign/orphan with toBase recalculation

Rollback point: 067fd44

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:55:11 -04:00
Falkan
067fd445ef chore: track MEMORY directory 2026-03-17 13:22:32 -04:00
Falkan
5280a5dc61 tweak: slow Dan Mode banner blink to 1.2s 2026-03-17 11:36:22 -04:00
Falkan
04a6d00549 feat: DAN MODE ACTIVATED banner (blinking), cycle order light→dark→dan 2026-03-17 11:35:49 -04:00
Falkan
7cc893d48f feat: Dan Mode v2 — no grey anywhere, maximum neon
- Override --pico-box-shadow (had grey rgba values) with pure magenta/yellow glow
- Article/card: white bg, magenta border, yellow+magenta box-shadow
- Inputs/selects: yellow bg, magenta border, blue text (!important to beat Pico specificity)
- Dropdown: yellow bg, magenta border
- Footer: yellow bg, magenta border, red text
- Sharp corners (--pico-border-radius: 0) for brutalist aesthetic
- Hotkey hint: magenta
- Nav hover: red
- Header: yellow + red drop-shadow
2026-03-17 11:33:29 -04:00
Falkan
da99b63916 feat: Dan Mode (third theme), Pico CSS notes, cycle theme toggle
Dan Mode: pure white backgrounds, electric blue text (#0000ff), nuclear
yellow accents (#ffff00), hot magenta borders (#ff00ff), red labels,
glowing box-shadows. Maximum saturation. Hostile to human vision by design.

Theme toggle now cycles light → dark → dan → light (icons: 🌙 😎 ☀️).

PICO_CSS.md: documents [role=button] color clobber, palette scoping rules,
and theme toggling pattern for future reference.
2026-03-17 11:28:42 -04:00
Falkan
0f648ab9b8 fix: correct invisible text in result tiles (light mode)
Root cause: .result-tile has role="button", which triggers Pico's button
rule setting --pico-color: var(--pico-primary-inverse) = #fff in light mode.
Text inherited this white color, invisible on white card backgrounds.

Fix: override --pico-color: initial and set explicit color: var(--pico-contrast)
on .result-tile. --pico-contrast is #181c25 in light mode and #dfe3eb in dark —
both legible against their respective card backgrounds.
2026-03-17 11:19:00 -04:00
Falkan
510e61a553 fix+feat: fix invisible result values, inline symbol into label
Fix: .result-value was using color: var(--pico-color) which broke when
our custom palette variables weren't in scope. Now inherits body color —
Pico handles light/dark correctly without us needing to re-assert it.

Feat: unit symbol merged inline into label as 'Blurbs (bl)', replacing
the separate third line. Removes .result-symbol CSS rule. Cards are
shorter and less cluttered.
2026-03-17 11:00:38 -04:00
Falkan
062850280c fix+feat: correct light/dark palette scoping, add theme toggle
Fix: palette overrides now use @media(prefers-color-scheme:light) +
[data-theme=light] only — no more :root:not([data-theme=dark]) which
incorrectly matched OS-dark with no attribute set.

Feat: theme toggle button in nav (🌙/☀️), persisted to localStorage,
applied via data-theme attribute on <html>. Respects OS preference on
first visit.
2026-03-17 10:55:10 -04:00
Falkan
6f3d02d31c fix: scope palette overrides to light mode only — prevent dark mode text/bg collision
Root cause: --pico-color and --pico-card-background-color were overridden
unconditionally at :root, clobbering Pico's dark mode tokens. Light-colored
text (#2C2C2C) became invisible against dark card backgrounds (#181c25).

Fix: move Pico token overrides under light-mode selectors only. Dark mode
now inherits Pico's correct dark palette. --color-label (app-specific var)
gets an explicit dark-mode value since Pico doesn't define it.
2026-03-17 10:52:57 -04:00
Falkan
b05f421bcb highlight: remove symbol line, reduce height to 5rem 2026-03-17 10:49:45 -04:00
Falkan
7ca0fc4032 highlight: inline equation layout with responsive stacked fallback
- From and result now on one line: '1.00 Units = 0.09 OtherUnits'
- Same font size and color for both sides (pico-color, 600 weight)
- Container query switches to over-under at <420px with '= ' prefix on result line
- Separator '=' shown inline; muted color/normal weight to visually anchor the equation
- Removed old two-tier font sizing (small grey from, large blue result)
2026-03-17 10:47:27 -04:00
Falkan
ee162fc0f7 Improve: stable highlight height, equation display format, responsive font sizes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:26:02 -04:00
Falkan
66f77a6394 Simplify: promote inline Big import type, merge duplicate hover/highlighted CSS rules
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:22:48 -04:00
Falkan
af5f10a4ec Fix: shift+click preserves input value, Ctrl+click adopts value, stable highlight layout
- shift+click now only sets fromUnitId; inputValue is unchanged so all outputs
  recalculate correctly from the original user input
- Ctrl+click is a new gesture that sets both fromUnitId and inputValue to the
  tile's displayed converted value (the "pivot" action)
- highlighted-result block always renders with min-height:8rem so the page
  below it never jumps when a highlight is added or cleared
- hotkey hint updated to document all three click gestures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:21:22 -04:00
Falkan
d9489a5db2 Simplify: token-ify hardcoded colors, remove redundant Big ternary, guard no-op shift-click
- Replace 5 hardcoded #2C2C2C/#555550/#888880 literals with var(--pico-color),
  var(--color-label), var(--pico-muted-color); add --color-label token to :root
- Remove inline Big(inputValue) ternary in results derived — convert.ts already
  handles same-unit identity via its own from.id === to.id guard
- Drop now-unused Big import from +page.svelte
- Guard onshiftclick in ConversionResult: no-op when tile is already the from-unit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:07:37 -04:00
Falkan
d22885b708 Fix: card text contrast, stable grid order, independent highlight/input states, highlight dismiss
- Explicit dark colors on .result-value, .result-label, .result-symbol, .highlighted-value, .highlighted-label
- Include from-unit in results grid (stable definition-order); from-unit tile shows Big(inputValue) and gets is-input-unit dashed-border class
- Shift+click no longer clears highlightedUnitId — fromUnitId and highlightedUnitId are now fully independent states
- Add × dismiss button (aria-label="Remove highlight") to .highlighted-result banner; .highlighted-result gains position:relative

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 22:03:01 -04:00
Falkan
15b381f08c Style: warm neutral palette, full-width grid columns, subtle card elevation 2026-03-16 21:48:42 -04:00
Falkan
8f835c35d2 Phase 2: core converter, live conversion, URL state, highlight interaction 2026-03-16 21:34:16 -04:00
Falkan
65f8bc1b9f Phase 1: scaffold, types, schema, layout shell
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:22:34 -04:00