diff --git a/docs/api-reference.md b/docs/api-reference.md index 1a571ca..8038546 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -145,23 +145,22 @@ All endpoints require login (session cookie or `Authorization: Bearer ` |--------|------|-------------| | GET | `/api/search` | Semantic + keyword search across notes and tasks. Params: `q`, `type` (`note`/`task`/`all`), `limit` | -## Briefing +## Journal | Method | Path | Description | |--------|------|-------------| -| GET | `/api/briefing/config` | Get briefing configuration | -| PUT | `/api/briefing/config` | Save briefing configuration | -| GET | `/api/briefing/feeds` | List RSS feeds | -| POST | `/api/briefing/feeds` | Add RSS feed `{url, name?, category?}` | -| DELETE | `/api/briefing/feeds/:id` | Delete feed | -| POST | `/api/briefing/feeds/refresh` | Trigger immediate feed refresh → `{feeds_refreshed, new_items}` | -| GET | `/api/briefing/weather` | Get weather configuration | -| PUT | `/api/briefing/weather` | Save weather locations | -| POST | `/api/briefing/weather/geocode` | Geocode address `{query}` → `{lat, lon, label}` | -| POST | `/api/briefing/trigger` | Manually fire a briefing slot `{slot}` | -| GET | `/api/briefing/conversations` | List past briefing conversations | -| GET | `/api/briefing/conversations/today` | Get/create today's briefing conversation | -| GET | `/api/briefing/conversations/:id/messages` | Get messages for a briefing conversation | +| GET | `/api/journal/config` | Get journal configuration (locations, temp_unit, prep schedule) | +| PUT | `/api/journal/config` | Save journal configuration; live-reschedules the prep job | +| GET | `/api/journal/today` | Get/create today's journal conversation + messages | +| GET | `/api/journal/day/:iso` | Get a specific day's journal conversation (read-only) | +| GET | `/api/journal/days` | List dates with journal content, newest first | +| POST | `/api/journal/trigger-prep` | Force-regenerate today's prep (or `{date}` for a specific day) | +| GET | `/api/journal/weather` | Cached weather rows; auto-refreshes stale rows in the background | +| GET | `/api/journal/weather/current` | Live current conditions for the primary configured location | +| POST | `/api/journal/weather/refresh` | Manual refresh of all configured locations | +| POST | `/api/journal/weather/geocode` | Geocode place name `{query}` → `{lat, lon, label}` | +| POST | `/api/journal/moments/:id/update` | Update a recorded moment | +| DELETE | `/api/journal/moments/:id` | Delete a moment | ## Settings diff --git a/docs/architecture.md b/docs/architecture.md index bb3a6e0..2c8cf3c 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -133,11 +133,11 @@ Indexes: GIN on `tags`, B-tree on `status`, B-tree on `title`. ### Settings -Composite PK `(user_id, key)`. Per-user key-value store. CRUD via `services/settings.py`. Used for: `default_model`, `assistant_name`, `briefing_enabled`, `briefing_locations`, `office_days`, etc. +Composite PK `(user_id, key)`. Per-user key-value store. CRUD via `services/settings.py`. Used for: `default_model`, `assistant_name`, `journal_config` (JSON: locations, temp_unit, prep schedule), `user_timezone`, `voice_*`, etc. ### Conversations / Messages -`conversations`: `id`, `title`, `model`, `user_id`, `conversation_type` (`chat`/`briefing`/`mcp`), `briefing_date`, `rag_project_id` (nullable int — RAG scope: NULL=orphan-only, -1=all, positive=project), `created_at`, `updated_at`. +`conversations`: `id`, `title`, `model`, `user_id`, `conversation_type` (`chat`/`journal`/`mcp`), `day_date` (YYYY-MM-DD for journal conversations), `rag_project_id` (nullable int — RAG scope: NULL=orphan-only, -1=all, positive=project), `created_at`, `updated_at`. `messages`: `id`, `conversation_id` FK CASCADE, `role` (`user`/`assistant`), `content`, `status` (`done`/`generating`), `created_at`. Title auto-generated by LLM on first exchange, re-generated every 10th message. @@ -155,11 +155,9 @@ Title auto-generated by LLM on first exchange, re-generated every 10th message. Permission resolution is centralised in `services/access.py`. `get_project_permission(uid, project_id)` checks ownership → direct share → group-based share → note→project inheritance, returning the highest applicable permission. -### Briefing-Related Tables +### Journal-Related Tables -`rss_feeds`: `id`, `user_id`, `url`, `name`, `category`, `last_fetched_at`. -`rss_items`: `id`, `feed_id` FK, `guid`, `title`, `url`, `summary`, `pub_date`. -`weather_cache`: per-user cache with `lat`, `lon`, `location_name`, `forecast_json`, `fetched_at`. +`weather_cache`: per-user, per-`location_key` cache. Columns: `user_id`, `location_key` (`home`/`work`/etc.), `location_label`, `forecast_json` (Open-Meteo response), `previous_json` (last forecast, used to detect changes), `fetched_at`. Lat/lon are *not* stored on the cache row — they live in the user's `journal_config.locations.{home|work}` setting and are used at refresh time. ### API Keys @@ -188,14 +186,14 @@ Permission resolution is centralised in `services/access.py`. `get_project_permi | `routes/api.py` | `/api` blueprint; `GET /api/health` (public) | | `routes/auth.py` | Register, login, logout, me, password/email change, password reset, invite registration, OAuth login+callback; rate limiting; `LOCAL_AUTH_ENABLED` guards | | `routes/admin.py` | Backup, restore, user management, registration toggle, invitations, base URL, SMTP (admin only) | -| `routes/chat.py` | Conversations CRUD; SSE generation stream; model pull/delete/list/warm; briefing conversation routes | +| `routes/chat.py` | Conversations CRUD; SSE generation stream; model pull/delete/list/warm | | `routes/notes.py` | Notes CRUD + wikilinks + backlinks + assist + link suggestions + version history + drafts | | `routes/tasks.py` | Tasks CRUD; `POST` accepts `project` name string (resolved to `project_id`) | | `routes/task_logs.py` | Task work log CRUD (`GET/POST/DELETE /api/tasks/:id/logs`) | | `routes/projects.py` | Projects CRUD + summary endpoint | | `routes/milestones.py` | Milestones CRUD under `/api/projects/:id/milestones` | | `routes/settings.py` | Per-user settings key-value (`GET/PUT /api/settings/:key`) | -| `routes/briefing.py` | Briefing conversation + reply + history; RSS feed management | +| `routes/journal.py` | Journal config CRUD; today/day/days conversation accessors; weather endpoints (cached/current/refresh/geocode); moments CRUD; trigger-prep | | `routes/groups.py` | Group CRUD + membership management (admin) | | `routes/shares.py` | Share project/note with user or group; revoke; list incoming shares | | `routes/in_app_notifications.py` | In-app notification list + mark-read + count | @@ -227,10 +225,11 @@ Permission resolution is centralised in `services/access.py`. `get_project_permi | `services/groups.py` | Group CRUD; membership management | | `services/notifications.py` | Create/read/mark-read in-app notifications | | `services/task_logs.py` | Append/list/delete work log entries on tasks | -| `services/briefing_pipeline.py` | Two-lane parallel gather → LLM synthesis → `GenerationBuffer` stream | -| `services/briefing_scheduler.py` | APScheduler `BackgroundScheduler`; slots with catch-up logic; async-safe via `asyncio.create_task` | -| `services/briefing_conversations.py` | Briefing conversation persistence and history queries | -| `services/briefing_profile.py` | Per-user profile note that the assistant updates over time | +| `services/journal_prep.py` | Deterministic data gather (tasks/events/weather/projects/recent moments/open threads) → LLM prose opener; persisted as the first assistant message of today's journal Conversation | +| `services/journal_pipeline.py` | System-prompt builder for journal conversations; calls `build_profile_context()` so the LLM sees the user's profile + learned summary | +| `services/journal_scheduler.py` | APScheduler `BackgroundScheduler`; per-user prep job; live-reschedule via `update_user_schedule()`; catch-up logic for missed runs | +| `services/journal_search.py`, `services/moments.py` | Moment recording + search across journal history | +| `services/user_profile.py` | `build_profile_context()` consolidates profile + observations + learned_summary into a system-prompt block | | `services/research.py` | SearXNG research pipeline: sub-queries → parallel fetch → outline → section synthesis → executive summary → index note with linked section notes | | `services/events.py` | Internal events CRUD: `list_events`, `create_event`, `update_event`, `delete_event`, `get_event`; source of truth for all event LLM tools | | `routes/events.py` | `/api/events` — event CRUD routes | @@ -293,8 +292,8 @@ Permission resolution is centralised in `services/access.py`. `get_project_permi | `services/generation_task.py` | SSE streaming, tool-call loop, GenerationBuffer management | | `services/tools/` | LLM tool implementations (38 tools across 11 modules); decorator-based registry | | `services/embeddings.py` | `upsert_note_embedding()`, `semantic_search_notes()` | -| `services/briefing_pipeline.py` | Two-lane parallel gather → LLM synthesis → briefing output | -| `services/briefing_scheduler.py` | APScheduler integration, catch-up logic for missed slots | +| `services/journal_prep.py` | Data gather → LLM prose opener; persisted into today's journal conversation | +| `services/journal_scheduler.py` | APScheduler integration, per-user prep job, catch-up for missed runs | | `services/backup.py` | Full and per-user backup export/restore (version 2 format) | | `services/weather.py` | Nominatim geocoding + Open-Meteo forecast fetch + DB cache | | `services/rss.py` | feedparser-based fetch, per-feed DB cache, prune-to-100 | diff --git a/docs/design-system.md b/docs/design-system.md index 4ad6795..ab9f373 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -362,7 +362,7 @@ If using Tailwind, extend the theme with these tokens rather than relying on def > This section tracks decisions made while adapting the FabledSword baseline above for Scribe specifically. Items here are *in progress* — once they feel solid, they get folded into the main body of the document (either as Scribe-specific extensions in the per-app section, or as updates to the universal rules where Scribe's needs reveal a gap in the baseline). -*Iteration started: 2026-04-26.* +*Iteration started: 2026-04-26. Foundation pass shipped 2026-04-27 in `7a9a8b7` (palette, fonts, light mode, action tokens, hardcoded indigo cleanup, warm-gold deprecation). Surface phase shipped 2026-04-27 across `93a3beb` → `3c1ec40` (Lucide migration, Hybrid-rule button reclassification per surface, long-form line-height, two-weights-only). The system is now applied end-to-end; this section will fold into the main body once the result has had time to settle in real use.* ## Decisions made so far @@ -531,4 +531,43 @@ Border weight is not load-bearing for Scribe — happy to use the doc's 0.5px ha ## Open threads (next iterations) -*All initial-iteration threads resolved. Next phase is the polish pass — applying the system to existing UI, component by component. New threads will accumulate here as we discover gaps in the polish pass.* +### Foundation pass — shipped 2026-04-27 (`7a9a8b7`) + +Mechanical token + font + light-mode rewrite of `frontend/src/assets/theme.css`, plus a sweep of hardcoded indigo and `--color-accent-warm` references across ~14 component files. Action tokens (`--color-action-primary` Moss, `--color-action-secondary` Bronze, `--color-action-destructive` Oxblood, `--color-action-ghost-border` Pewter) are defined but not yet applied — buttons still flow through `--color-primary` and read as dusty-violet gradients in the meantime, by design. Spec lives at `docs/superpowers/specs/2026-04-27-design-system-polish-foundation-design.md` (gitignored, local-only). + +### Surface phase — shipped 2026-04-27 (`93a3beb` → `3c1ec40`) + +Bundled as Hybrid (option C from the brainstorm): Lucide cross-cutting first, then surface-by-surface for the judgment work. Spec lives at `docs/superpowers/specs/2026-04-27-design-system-polish-surface-design.md` (gitignored, local-only). Seven PRs landed on `dev`: + +| PR | Commit | Surface | Notes | +|---|---|---|---| +| 1 | `93a3beb` | Lucide cross-cutting | 60 hand-inlined SVGs across 15 files → `lucide-vue-next`. Every chrome icon at 16 or 24. Emoji-as-icons (`✕`, `✓`, `🎤`, `📎`, `↻`, `↑`, `×`, `☀`/`☾`) swept across the chrome. AppLogo wordmark and the GraphView D3 mount kept as the legitimate exceptions. | +| 2 | `3d916d7` | Journal | Buttons audited; `↻` weather refresh → Lucide `RotateCcw`; assistant bubble line-height bumped; redundant `.journal-title` font-family dropped; dead `.news-section` CSS removed. | +| 3 | `4192a64` | Chat | `.message-content` long-form 1.7 line-height on assistant bubbles; ToolCallCard outer border removed (bubble already contains it; error state moved to a left-edge accent); bulk-delete recolored to Oxblood with Trash2 icon; `.bulk-link` accent → muted text. | +| 4 | `efb3534` | Knowledge cluster | `.prose` line-height bumped to 1.7 globally so all reading surfaces inherit. Save → Moss; Delete → Oxblood + Trash2; Edit / Advance → Moss; Convert / Share → Bronze. | +| 5 | `ff498ce` | Project + Workspace | Project save panel → Moss; milestone confirm/cancel → Moss/Bronze; modal-btn-danger and per-row delete affordances → Oxblood; "Open Workspace" stays accent (project-surface brand moment). | +| 6 | `541e2ed` | Settings | Densest button surface — every `.btn-save`, `.btn-primary`, `.btn-secondary`, `.btn-danger`, `.btn-danger-outline`, `.btn-toggle-open` reclassified per Hybrid; missing `.btn-danger` style block added (was unstyled before). | +| 7 | `3c1ec40` | Edge surfaces | Calendar `New Event` → Moss; EventSlideOver Save/Cancel/Delete reclassified; HomeView hero CTA stays accent (brand moment); two-weights-only sweep across Header/Home/Calendar/Graph. | + +**Cross-cutting changes folded in as the work touched files:** + +- Long-form 1.7 line-height on `.prose` (PR 4) — applies to Note viewer, Task viewer, chat assistant bubbles, anywhere markdown renders into a reading surface. +- Two-weights-only (400 + 500) — every `font-weight: 600` and `700` snapped to `500` across all surface PRs. +- Hardcoded `--color-danger` in destructive button contexts → `--color-action-destructive` (Oxblood). `--color-danger` (Error terracotta) preserved for validation/error messages, per the doc's distinction between Error and Destructive. +- Adjacent `×` / `✕` / unicode-arrow emoji swept opportunistically as files were touched (PRs 5, 7). + +### Out of scope — deferred indefinitely + +Items deliberately not addressed in this round; revisit when a real need surfaces: + +- Lucide stroke-weight overrides (doc spec: 1.5 at 24, 1 at 16; current: Lucide default 2). Touched components if they read too heavy in practice. +- Filled-as-active icon state — no current affordance uses it; introduce when bookmark/pin/star toggles are added. +- Type-scale / spacing-scale CSS variables — components keep literal values. +- Token rename to `--fs-*` namespace — Scribe is the only FabledSword app sharing this codebase. +- FabledSword lockup placement — waiting on the actual heraldic mark to be drawn. +- Standalone voice/tone audit across every UI string — opportunistic-only; full sweep deferred unless drift becomes visible. +- A handful of editor utility buttons (`.btn-suggest-tags`, `.btn-link-all`, AI assist generate/proofread/accept/reject set, etc.) — currently ghost-styled and visually compliant; revisited only if they read off in practice. + +### Open threads + +*New threads will accumulate here as gaps surface in real use.* diff --git a/docs/features.md b/docs/features.md index e9bbec4..7cbea3a 100644 --- a/docs/features.md +++ b/docs/features.md @@ -52,19 +52,22 @@ Full conversation history with SSE streaming. Features: - **Bulk delete** — Select and delete multiple conversations. - **Retention** — Conversations auto-pruned after configurable days (default 90). -## Daily Briefing +## Daily Journal -`/briefing` is a scheduled, dialogue-based morning briefing. The assistant compiles tasks, calendar events, projects, weather forecast, and RSS digest at configurable times, then checks in throughout the day. You can reply interactively. +`/journal` is a conversational daily surface — each day is a chat-style conversation seeded with an LLM-generated daily prep as the first assistant message. The prep pulls together today's tasks, calendar events, weather, recent moments, and active projects in flowing prose, then invites the user to continue the conversation throughout the day. -**Schedule** — Configurable slots: morning (default 4am compile), midday (8am check-in), evening (12pm check-in), night (4pm). Scheduler catches up missed slots on startup. +**Schedule** — Daily prep generates at a configurable time (default 5:00am). The "day rollover hour" controls when the journal switches to a new day (default 4am — late-night entries 1–3am still count as the previous day). Scheduler catches up missed runs on startup. -**Configuration** — Settings → Briefing: enable toggle, location geocoding, office days, time slot toggles, RSS feed management, push notification toggle. +**Right rail** — The journal view shows current weather conditions and upcoming events for the next two weeks alongside the conversation. Both surfaces draw from the same data the prep references. -**RSS feeds** — Add feed URLs with optional name and category. Feeds are fetched and cached; the briefing digest includes recent items. Category badges shown in the UI. Feeds can be manually refreshed. +**Configuration** — Settings → Profile: +- *Locations* section: home and work place-name inputs (geocoded on blur via Nominatim) and a temperature unit toggle (C/F) +- *Journal* section: prep auto-generate toggle, prep generation time, day rollover hour +- *About You* / *Interests* / *Work Schedule* / *Response Preferences* feed personalization into the prep's system prompt -**Weather** — Location-based forecast via Open-Meteo. Multiple locations supported (home, work, or any city name). Geocoding via Nominatim. +**Weather** — Location-based forecast via Open-Meteo. Up to two named locations (home, work). Cached rows auto-refresh in the background when the journal page loads. -**Profile note** — The assistant maintains a profile note for each user that it updates based on briefing conversations, improving personalisation over time. +**What the assistant has learned** — The assistant maintains a per-user observation log + consolidated summary, generated from journal and chat conversations. The summary is included in the journal's system prompt so the daily prep can reference what it knows about you over time. ## Web Research @@ -115,10 +118,10 @@ Settings are tabbed: |-----|----------| | General | Assistant name, default model, model management (pull/delete) | | Account | Email change, password change, session invalidation | -| Notifications | Push notification subscription, briefing push toggle | +| Notifications | Push notification subscription, journal prep push toggle | +| Profile | About you, response preferences, interests, work schedule, locations + temperature unit, journal prep schedule, learned observations | | Integrations | CalDAV configuration, SearXNG status | | Data | Personal export, backup/restore (admin) | -| Briefing | Enable, location, office days, slots, RSS feeds, weather | | API Keys | Create/revoke API keys, Fable MCP download and install | | Config (admin) | Base URL, SMTP, OIDC settings | | Users (admin) | User list, invite links, registration toggle | diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f7f640e..a460207 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -24,6 +24,7 @@ "@tiptap/vue-3": "^3.0.0", "d3": "^7", "dompurify": "^3.1.0", + "lucide-vue-next": "^0.469.0", "marked": "^17.0.0", "pinia": "^3.0.0", "vue": "3.5.30", @@ -91,6 +92,278 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/linux-x64": { "version": "0.27.3", "cpu": [ @@ -106,6 +379,159 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@floating-ui/core": { "version": "1.7.5", "license": "MIT", @@ -284,6 +710,294 @@ "dev": true, "license": "MIT" }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.59.0", "cpu": [ @@ -296,6 +1010,90 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@tiptap/core": { "version": "3.20.1", "license": "MIT", @@ -1908,6 +2706,15 @@ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0" }, + "node_modules/lucide-vue-next": { + "version": "0.469.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.469.0.tgz", + "integrity": "sha512-EjOap+vY3xEzCMrnaccDHO4BH3k3Lr+sOyvzRQCaayYxkxKla0w6Jr4h3cHAzA4vMSp63Dcy7vDiGeCPcCY+Gg==", + "license": "ISC", + "peerDependencies": { + "vue": ">=3.0.1" + } + }, "node_modules/magic-string": { "version": "0.30.21", "license": "MIT", diff --git a/frontend/package.json b/frontend/package.json index b5951d5..8d17f4b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,6 +25,7 @@ "@tiptap/vue-3": "^3.0.0", "d3": "^7", "dompurify": "^3.1.0", + "lucide-vue-next": "^0.469.0", "marked": "^17.0.0", "pinia": "^3.0.0", "vue": "3.5.30", diff --git a/frontend/src/assets/editor-shared.css b/frontend/src/assets/editor-shared.css index 42123fe..bfff033 100644 --- a/frontend/src/assets/editor-shared.css +++ b/frontend/src/assets/editor-shared.css @@ -50,34 +50,42 @@ border-color: var(--color-primary); color: var(--color-primary); } +/* Save: Moss action-primary per the Hybrid rule. Saving is "operating + the software" — not a brand moment. Accent gradient is reserved for + Send / empty-state CTAs. */ .btn-save { padding: 0.45rem 1.1rem; - background: linear-gradient(135deg, #6366f1, #4f46e5); + background: var(--color-action-primary); color: #fff; border: none; border-radius: var(--radius-sm); cursor: pointer; - font-weight: 600; + font-weight: 500; font-size: 0.875rem; - box-shadow: 0 2px 8px rgba(99, 102, 241, 0.28); - transition: box-shadow 0.15s, opacity 0.15s; + transition: background 0.15s, opacity 0.15s; } .btn-save:hover:not(:disabled) { - box-shadow: 0 4px 14px rgba(99, 102, 241, 0.42); - opacity: 0.95; + background: var(--color-action-primary-hover); } .btn-save:disabled { opacity: 0.55; cursor: default; } +/* Delete: Oxblood action-destructive per Hybrid rule. Should be paired + with a Trash icon at the call site to reinforce intent. */ .btn-delete { padding: 0.45rem 1rem; - background: var(--color-danger); + background: var(--color-action-destructive); color: #fff; border: none; border-radius: var(--radius-sm); cursor: pointer; + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-weight: 500; } +.btn-delete:hover { background: var(--color-action-destructive-hover); } .btn-assist-toggle { margin-left: auto; padding: 0.4rem 0.9rem; @@ -99,7 +107,7 @@ border-bottom: 1.5px solid var(--color-border); border-radius: 0; font-size: 1.5rem; - font-weight: 700; + font-weight: 500; font-family: "Fraunces", Georgia, serif; background: transparent; color: var(--color-text); @@ -112,7 +120,6 @@ } .title-input::placeholder { color: var(--color-text-muted); - font-style: italic; font-weight: 400; } .editor-tabs { @@ -225,7 +232,7 @@ .assist-panel-title { flex: 1; font-size: 0.8rem; - font-weight: 700; + font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.05em; @@ -269,7 +276,7 @@ /* Section list */ .assist-sections-label { font-size: 0.72rem; - font-weight: 700; + font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-text-muted); @@ -362,7 +369,6 @@ .assist-streaming-label { font-size: 0.8rem; color: var(--color-text-secondary); - font-style: italic; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -391,7 +397,6 @@ padding: 0.5rem 0.75rem; font-size: 0.8rem; color: var(--color-text-muted); - font-style: italic; text-align: center; } @@ -411,7 +416,7 @@ align-items: center; justify-content: space-between; font-size: 0.8rem; - font-weight: 600; + font-weight: 500; color: var(--color-text-secondary); } .btn-toggle-view { @@ -454,7 +459,7 @@ width: 1rem; text-align: center; user-select: none; - font-weight: 700; + font-weight: 500; } .diff-text { flex: 1; @@ -464,7 +469,6 @@ .diff-empty { padding: 0.5rem; color: var(--color-text-muted); - font-style: italic; font-size: 0.82rem; } .assist-actions { @@ -562,7 +566,7 @@ border: none; border-bottom: 1px solid var(--color-border); font-size: 0.85rem; - font-weight: 600; + font-weight: 500; color: var(--color-text-secondary); cursor: pointer; text-align: left; @@ -581,7 +585,7 @@ } .sb-label { font-size: 0.78rem; - font-weight: 600; + font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.04em; diff --git a/frontend/src/assets/prose.css b/frontend/src/assets/prose.css index b2d5a2c..b3cf455 100644 --- a/frontend/src/assets/prose.css +++ b/frontend/src/assets/prose.css @@ -1,5 +1,8 @@ .prose { - line-height: 1.6; + /* Long-form reading line-height per the design system — + reading surfaces (notes, tasks, journal, assistant bubbles) want 1.7 + so prose breathes like a book, not a UI snippet. */ + line-height: 1.7; } .prose h1 { diff --git a/frontend/src/assets/theme.css b/frontend/src/assets/theme.css index dd65cb9..c96aed0 100644 --- a/frontend/src/assets/theme.css +++ b/frontend/src/assets/theme.css @@ -1,131 +1,147 @@ -@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&family=Inter:ital,wght@0,400;0,500;1,400&family=JetBrains+Mono:ital,wght@0,400;1,400&display=swap'); :root { - --color-bg: #f5f5fb; - --color-bg-secondary: #ededf5; - --color-bg-card: #ffffff; - --color-surface: #f0f0f8; - --color-text: #1a1a1a; - --color-text-secondary: #666666; - --color-text-muted: #999999; - --color-border: #dddde8; - --color-input-border: #c8c8d8; - --color-primary: #7c3aed; - --color-danger: #d93025; - --color-tag-bg: #ede5ff; - --color-tag-text: #6d28d9; + /* Light mode — warm parchment palette */ + --color-bg: #F5F1E8; + --color-bg-secondary: #FBF8F0; + --color-bg-card: #FBF8F0; + --color-surface: #EFEAE0; + --color-text: #14171A; + --color-text-secondary: #5A5852; + --color-text-muted: #9A9890; + --color-border: #D9D6CE; + --color-input-border: #D9D6CE; + --color-primary: #5B4A8A; + --color-danger: #C04A1F; + --color-tag-bg: rgba(91, 74, 138, 0.12); + --color-tag-text: #5B4A8A; --color-shadow: rgba(0, 0, 0, 0.08); - --color-toast-success: #34a853; - --color-toast-error: #d93025; - --color-status-todo: #5f6368; - --color-status-todo-bg: #e8eaed; - --color-status-in-progress: #7c3aed; - --color-status-in-progress-bg: #ede5ff; - --color-status-done: #34a853; - --color-status-done-bg: #e6f4ea; - --color-priority-low: #5f9ea0; - --color-priority-low-bg: #e0f2f1; - --color-priority-medium: #f9a825; - --color-priority-medium-bg: #fff8e1; - --color-priority-high: #d93025; - --color-priority-high-bg: #fce8e6; - --color-wikilink: #7b1fa2; - --color-wikilink-bg: #f3e5f5; - --color-overdue: #d93025; - --color-code-bg: #f0f0f8; - --color-code-inline-bg: #eaeaf4; - --color-table-stripe: #f4f4fb; - --color-success: #22c55e; - --color-warning: #eab308; - --color-input-bar-bg: #eaeaf3; - --color-input-bar-text: #1a1a1a; - --color-input-bar-placeholder: rgba(0, 0, 0, 0.4); + --color-toast-success: #4A5D3F; + --color-toast-error: #C04A1F; + --color-status-todo: #3F4651; + --color-status-todo-bg: rgba(63, 70, 81, 0.10); + --color-status-in-progress: #5B4A8A; + --color-status-in-progress-bg: rgba(91, 74, 138, 0.12); + --color-status-done: #4A5D3F; + --color-status-done-bg: rgba(74, 93, 63, 0.12); + --color-priority-low: #3D5A6E; + --color-priority-low-bg: rgba(61, 90, 110, 0.12); + --color-priority-medium: #8B6F1E; + --color-priority-medium-bg: rgba(139, 111, 30, 0.12); + --color-priority-high: #C04A1F; + --color-priority-high-bg: rgba(192, 74, 31, 0.12); + --color-wikilink: #5B4A8A; + --color-wikilink-bg: rgba(91, 74, 138, 0.12); + --color-overdue: #C04A1F; + --color-code-bg: #EBEDF0; + --color-code-inline-bg: #EBEDF0; + --color-table-stripe: rgba(20, 23, 26, 0.025); + --color-success: #4A5D3F; + --color-warning: #8B6F1E; + --color-input-bar-bg: #EFEAE0; + --color-input-bar-text: #14171A; + --color-input-bar-placeholder: rgba(20, 23, 26, 0.4); --color-overlay: rgba(0, 0, 0, 0.45); - --color-bubble-user-bg: rgba(0, 0, 0, 0.04); - --color-bubble-user-border: rgba(0, 0, 0, 0.10); - --color-bubble-user-text: #3a3a4a; - --color-bubble-asst-shadow: 0 2px 16px rgba(124, 58, 237, 0.10), 0 1px 4px rgba(0, 0, 0, 0.06); + --color-bubble-user-bg: transparent; + --color-bubble-user-border: #D9D6CE; + --color-bubble-user-text: #5A5852; + --color-bubble-asst-shadow: 0 2px 14px rgba(91, 74, 138, 0.06), 0 1px 4px rgba(0, 0, 0, 0.05); + --color-primary-solid: #5B4A8A; + --color-primary-deep: #3F3560; + --gradient-cta: linear-gradient(135deg, var(--color-primary-solid), var(--color-primary-deep)); + --glow-cta: 0 2px 10px rgba(91, 74, 138, 0.35); + --glow-cta-hover: 0 4px 20px rgba(91, 74, 138, 0.55); + --glow-soft: 0 0 16px rgba(91, 74, 138, 0.35); + --color-primary-faint: rgba(91, 74, 138, 0.08); + --color-primary-tint: rgba(91, 74, 138, 0.12); + --color-primary-wash: rgba(91, 74, 138, 0.20); + + /* Action color set — Hybrid rule: action buttons use these, accent reserved for brand moments */ + --color-action-primary: #4A5D3F; + --color-action-primary-hover: #5A6F4D; + --color-action-secondary: #8B7355; + --color-action-secondary-hover: #A0876A; + --color-action-destructive: #6B2118; + --color-action-destructive-hover: #7E2A1F; + --color-action-ghost-border: #3F4651; + --radius-sm: 6px; --radius-md: 12px; --radius-lg: 18px; --radius-pill: 9999px; - --focus-ring: 0 0 0 2px rgba(124, 58, 237, 0.4); + --focus-ring: 0 0 0 2px rgba(91, 74, 138, 0.5); /* Layout */ --page-max-width: 1200px; --page-padding-x: 1rem; --sidebar-width: 260px; --chat-reading-width: min(1200px, 100%); --chat-context-sidebar-width: 220px; - --color-accent-warm: #b8860b; - --color-accent-warm-light: #d4a017; - --color-primary-solid: #7c3aed; - --color-primary-deep: #5b21b6; - /* Reusable brand patterns */ - --gradient-cta: linear-gradient(135deg, var(--color-primary-solid), var(--color-primary-deep)); - --glow-cta: 0 2px 10px rgba(124, 58, 237, 0.35); - --glow-cta-hover: 0 4px 20px rgba(124, 58, 237, 0.55); - --glow-soft: 0 0 16px rgba(124, 58, 237, 0.35); - --color-primary-faint: rgba(124, 58, 237, 0.08); - --color-primary-tint: rgba(124, 58, 237, 0.12); - --color-primary-wash: rgba(124, 58, 237, 0.20); } [data-theme="dark"] { - --color-bg: #0f0f14; - --color-bg-secondary: #16161f; - --color-bg-card: #1a1a24; - --color-surface: #16161f; - --color-text: #e4e4f0; - --color-text-secondary: #8888a8; - --color-text-muted: #52526a; - --color-border: rgba(124, 58, 237, 0.22); - --color-input-border: rgba(124, 58, 237, 0.35); - --color-primary: #a78bfa; - --color-danger: #f44336; - --color-tag-bg: #2a2a45; - --color-tag-text: #c4b5fd; + /* Dark mode — Obsidian / Iron / Pewter */ + --color-bg: #14171A; + --color-bg-secondary: #1E2228; + --color-bg-card: #1E2228; + --color-surface: #2C313A; + --color-text: #E8E4D8; + --color-text-secondary: #C2BFB4; + --color-text-muted: #9C9A92; + --color-border: #3F4651; + --color-input-border: #3F4651; + --color-primary: #5B4A8A; + --color-danger: #C04A1F; + --color-tag-bg: rgba(91, 74, 138, 0.15); + --color-tag-text: #5B4A8A; --color-shadow: rgba(0, 0, 0, 0.4); - --color-toast-success: #4caf50; - --color-toast-error: #f44336; - --color-status-todo: #9aa0a6; - --color-status-todo-bg: #2a2a35; - --color-status-in-progress: #a78bfa; - --color-status-in-progress-bg: #2a2a45; - --color-status-done: #4caf50; - --color-status-done-bg: #1b3a20; - --color-priority-low: #80cbc4; - --color-priority-low-bg: #1a3a38; - --color-priority-medium: #fdd835; - --color-priority-medium-bg: #3a3520; - --color-priority-high: #f44336; - --color-priority-high-bg: #3a1a1a; - --color-wikilink: #c4b5fd; - --color-wikilink-bg: #2a1a45; - --color-overdue: #f44336; - --color-code-bg: #12121a; - --color-code-inline-bg: #1a1a2a; - --color-table-stripe: #14141e; - --color-success: #4ade80; - --color-warning: #facc15; - --color-input-bar-bg: #1a1a24; - --color-input-bar-text: #e4e4f0; - --color-input-bar-placeholder: rgba(228, 228, 240, 0.35); + --color-toast-success: #4A5D3F; + --color-toast-error: #C04A1F; + --color-status-todo: #3F4651; + --color-status-todo-bg: rgba(63, 70, 81, 0.18); + --color-status-in-progress: #5B4A8A; + --color-status-in-progress-bg: rgba(91, 74, 138, 0.18); + --color-status-done: #4A5D3F; + --color-status-done-bg: rgba(74, 93, 63, 0.18); + --color-priority-low: #3D5A6E; + --color-priority-low-bg: rgba(61, 90, 110, 0.18); + --color-priority-medium: #8B6F1E; + --color-priority-medium-bg: rgba(139, 111, 30, 0.18); + --color-priority-high: #C04A1F; + --color-priority-high-bg: rgba(192, 74, 31, 0.18); + --color-wikilink: #5B4A8A; + --color-wikilink-bg: rgba(91, 74, 138, 0.18); + --color-overdue: #C04A1F; + --color-code-bg: #14171A; + --color-code-inline-bg: #1E2228; + --color-table-stripe: rgba(255, 255, 255, 0.025); + --color-success: #4A5D3F; + --color-warning: #8B6F1E; + --color-input-bar-bg: #1E2228; + --color-input-bar-text: #E8E4D8; + --color-input-bar-placeholder: rgba(232, 228, 216, 0.35); --color-overlay: rgba(0, 0, 0, 0.65); - --color-bubble-user-bg: rgba(255, 255, 255, 0.04); - --color-bubble-user-border: rgba(255, 255, 255, 0.10); - --color-bubble-user-text: #b0b0c8; - --color-bubble-asst-shadow: 0 4px 28px rgba(124, 58, 237, 0.14), 0 2px 8px rgba(0, 0, 0, 0.4); - --color-accent-warm: #d4a017; - --color-accent-warm-light: #e8c45a; - --color-primary-solid: #7c3aed; - --color-primary-deep: #5b21b6; + --color-bubble-user-bg: transparent; + --color-bubble-user-border: #3F4651; + --color-bubble-user-text: #C2BFB4; + --color-bubble-asst-shadow: 0 4px 28px rgba(91, 74, 138, 0.14), 0 2px 8px rgba(0, 0, 0, 0.4); + --color-primary-solid: #5B4A8A; + --color-primary-deep: #3F3560; --gradient-cta: linear-gradient(135deg, var(--color-primary-solid), var(--color-primary-deep)); - --glow-cta: 0 2px 12px rgba(124, 58, 237, 0.45); - --glow-cta-hover: 0 4px 24px rgba(124, 58, 237, 0.65); - --glow-soft: 0 0 18px rgba(124, 58, 237, 0.4); - --color-primary-faint: rgba(124, 58, 237, 0.10); - --color-primary-tint: rgba(124, 58, 237, 0.14); - --color-primary-wash: rgba(124, 58, 237, 0.22); + --glow-cta: 0 2px 12px rgba(91, 74, 138, 0.45); + --glow-cta-hover: 0 4px 24px rgba(91, 74, 138, 0.65); + --glow-soft: 0 0 18px rgba(91, 74, 138, 0.4); + --color-primary-faint: rgba(91, 74, 138, 0.10); + --color-primary-tint: rgba(91, 74, 138, 0.14); + --color-primary-wash: rgba(91, 74, 138, 0.22); + + /* Action color set — identical across themes */ + --color-action-primary: #4A5D3F; + --color-action-primary-hover: #5A6F4D; + --color-action-secondary: #8B7355; + --color-action-secondary-hover: #A0876A; + --color-action-destructive: #6B2118; + --color-action-destructive-hover: #7E2A1F; + --color-action-ghost-border: #3F4651; } *, @@ -138,15 +154,34 @@ body { margin: 0; background: var(--color-bg); color: var(--color-text); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, + "Segoe UI", Roboto, sans-serif; + font-feature-settings: "cv11"; line-height: 1.5; transition: background-color 0.2s, color 0.2s; } -h1, h2, h3 { +h1, h2 { font-family: 'Fraunces', Georgia, serif; font-optical-sizing: auto; + font-weight: 500; + line-height: 1.3; +} + +h3 { + font-family: 'Inter', system-ui, sans-serif; + font-weight: 500; + line-height: 1.3; +} + +code, pre, kbd, samp { + font-family: 'JetBrains Mono', ui-monospace, "SF Mono", Menlo, Consolas, monospace; + font-feature-settings: "liga", "calt"; +} + +::selection { + background: rgba(91, 74, 138, 0.3); + color: var(--color-text); } input:focus-visible, @@ -184,7 +219,7 @@ button:not(:disabled):active, } } -/* Thin indigo-tinted scrollbars */ +/* Neutral hairline scrollbars — chrome is structural, not branded */ ::-webkit-scrollbar { width: 4px; height: 4px; @@ -193,11 +228,11 @@ button:not(:disabled):active, background: transparent; } ::-webkit-scrollbar-thumb { - background: rgba(124, 58, 237, 0.25); + background: var(--color-border); border-radius: 9999px; } ::-webkit-scrollbar-thumb:hover { - background: rgba(124, 58, 237, 0.45); + background: var(--color-text-muted); } /* Floating inline assist button (teleported to body, cannot be scoped) */ diff --git a/frontend/src/components/AppHeader.vue b/frontend/src/components/AppHeader.vue index 7bf8791..f11789e 100644 --- a/frontend/src/components/AppHeader.vue +++ b/frontend/src/components/AppHeader.vue @@ -7,6 +7,7 @@ import { useAuthStore } from "@/stores/auth"; import { useChatStore } from "@/stores/chat"; import AppLogo from "@/components/AppLogo.vue"; import NotificationBell from "@/components/NotificationBell.vue"; +import { Sun, Moon, Settings } from "lucide-vue-next"; const { theme, toggleTheme } = useTheme(); const { toggleShortcuts } = useShortcuts(); @@ -94,15 +95,13 @@ router.afterEach(() => { - - - - +
@@ -137,7 +136,8 @@ router.afterEach(() => { {{ statusShortLabel }} - +
{{ authStore.user?.username }} @@ -151,7 +151,7 @@ router.afterEach(() => { diff --git a/frontend/src/components/ShareDialog.vue b/frontend/src/components/ShareDialog.vue index 23f84ba..305f8b9 100644 --- a/frontend/src/components/ShareDialog.vue +++ b/frontend/src/components/ShareDialog.vue @@ -1,4 +1,5 @@