@hadoku/resume-bot 3.14.16 → 3.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/builder.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matthaeus Wolff
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/builder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sources":["../src/builder/api.ts","../src/builder/BlockCard.tsx","../node_modules/.pnpm/@wolffm+prefs-client@1.1.5_react@19.2.0_zod@4.1.12/node_modules/@wolffm/prefs-client/dist/index.js","../src/builder/useBuilderAuth.ts","../src/builder/BuilderApp.tsx","../src/builder/entry.tsx"],"sourcesContent":["// Admin builder API client. All calls go through the edge-router (same-origin,\n// credentials:'include') so the caller's admin session cookie is resolved into\n// the X-Hadoku-Tier: admin stamp the worker's requireMinTier('admin') needs.\n\nexport type BlockType = 'experience' | 'project' | 'skills' | 'education' | 'summary' | 'header'\n\nexport interface ResumeBlock {\n id: string\n type: BlockType\n tags: string[]\n title: string\n content: string\n priority: number\n}\n\nexport interface FeedbackEntry {\n text: string\n updated: string\n}\nexport type Feedback = Record<string, FeedbackEntry>\n\nexport class BuilderApiError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message)\n this.name = 'BuilderApiError'\n }\n}\n\n// The API root ('/resume/api'); builder endpoints are appended to it directly.\nlet baseUrl = ''\nexport function setBuilderApiBaseUrl(url: string): void {\n baseUrl = url.replace(/\\/+$/, '')\n}\n\nasync function req<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await fetch(`${baseUrl}/builder${path}`, {\n ...init,\n credentials: 'include',\n headers: { 'Content-Type': 'application/json', ...(init?.headers ?? {}) }\n })\n if (!res.ok) {\n let detail = `${res.status}`\n try {\n const body = (await res.json()) as { error?: string; message?: string }\n detail = body.message ? `${body.error}: ${body.message}` : (body.error ?? detail)\n } catch {\n /* non-JSON error body */\n }\n throw new BuilderApiError(detail, res.status)\n }\n return (await res.json()) as T\n}\n\nexport function fetchBlocks(): Promise<{ blocks: ResumeBlock[]; feedback: Feedback }> {\n return req('/blocks')\n}\n\nexport function saveBlock(block: ResumeBlock): Promise<{ block: ResumeBlock }> {\n return req(`/blocks/${encodeURIComponent(block.id)}`, {\n method: 'PUT',\n body: JSON.stringify(block)\n })\n}\n\nexport function deleteBlock(id: string): Promise<{ deleted: true; id: string }> {\n return req(`/blocks/${encodeURIComponent(id)}`, { method: 'DELETE' })\n}\n\nexport function reorderBlocks(ids: string[]): Promise<{ ids: string[] }> {\n return req('/reorder', { method: 'PUT', body: JSON.stringify({ ids }) })\n}\n\nexport function saveFeedback(id: string, text: string): Promise<{ feedback: Feedback }> {\n return req(`/feedback/${encodeURIComponent(id)}`, {\n method: 'POST',\n body: JSON.stringify({ text })\n })\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { facetOf } from './BuilderApp'\nimport type { BlockType, FeedbackEntry, ResumeBlock } from './api'\n\nconst BLOCK_TYPES: BlockType[] = [\n 'experience',\n 'project',\n 'skills',\n 'education',\n 'summary',\n 'header'\n]\n\ninterface Props {\n block: ResumeBlock\n feedback: FeedbackEntry | undefined\n existingIds: string[]\n isNew?: boolean\n onSave: (block: ResumeBlock) => Promise<void>\n onDelete?: () => Promise<void>\n onCancel?: () => void\n onFeedback: (id: string, text: string) => Promise<void>\n onTagClick: (tag: string) => void\n}\n\nexport function BlockCard({\n block,\n feedback,\n existingIds,\n isNew = false,\n onSave,\n onDelete,\n onCancel,\n onFeedback,\n onTagClick\n}: Props) {\n const [draft, setDraft] = useState<ResumeBlock>(block)\n const [tagsText, setTagsText] = useState(block.tags.join(' '))\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<string | null>(null)\n const [fbText, setFbText] = useState(feedback?.text ?? '')\n const [fbStatus, setFbStatus] = useState('')\n const fbTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n // Keep the draft in sync if the saved block changes underneath us (e.g. after\n // a successful save re-normalises it), but not while the user is mid-edit.\n useEffect(() => {\n if (!isNew) {\n setDraft(block)\n setTagsText(block.tags.join(' '))\n }\n }, [block, isNew])\n\n const dirty =\n isNew || JSON.stringify({ ...draft, tags: parseTags(tagsText) }) !== JSON.stringify(block)\n\n function parseTags(text: string): string[] {\n return [...new Set(text.split(/[\\s,]+/).filter(Boolean))]\n }\n\n const idInvalid =\n isNew && (!/^[a-z0-9][a-z0-9-]*$/.test(draft.id) || existingIds.includes(draft.id))\n\n async function handleSave() {\n setSaving(true)\n setSaveError(null)\n try {\n await onSave({ ...draft, tags: parseTags(tagsText) })\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : 'Save failed')\n } finally {\n setSaving(false)\n }\n }\n\n async function handleDelete() {\n if (!onDelete) return\n if (!confirm(`Delete block \"${block.id}\"? This removes it from the live resume.`)) return\n setSaving(true)\n try {\n await onDelete()\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : 'Delete failed')\n setSaving(false)\n }\n }\n\n function onFbChange(text: string) {\n setFbText(text)\n setFbStatus('typing…')\n clearTimeout(fbTimer.current)\n fbTimer.current = setTimeout(() => {\n onFeedback(block.id, text)\n .then(() => setFbStatus(text.trim() ? 'saved ✓' : ''))\n .catch(() => setFbStatus('save failed'))\n }, 600)\n }\n\n return (\n <div\n className={`rb-block${feedback ? ' rb-block--has-feedback' : ''}${dirty ? ' rb-block--dirty' : ''}`}\n >\n <div className=\"rb-block__row\">\n {isNew ? (\n <input\n className=\"rb-block__id-input\"\n placeholder=\"block-id (kebab-case)\"\n value={draft.id}\n onChange={e => setDraft({ ...draft, id: e.target.value })}\n />\n ) : (\n <span className=\"rb-block__id\">{draft.id}</span>\n )}\n <select\n className=\"rb-block__type\"\n value={draft.type}\n onChange={e => setDraft({ ...draft, type: e.target.value as BlockType })}\n >\n {BLOCK_TYPES.map(t => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <label\n className=\"rb-block__prio\"\n title=\"Priority — how strongly you want this block in a tailored resume. Higher sorts first; a ranking hint, not a hard rule.\"\n >\n prio\n <input\n type=\"number\"\n min={0}\n max={10}\n value={draft.priority}\n onChange={e => setDraft({ ...draft, priority: Number(e.target.value) })}\n />\n </label>\n </div>\n\n <input\n className=\"rb-block__title\"\n placeholder=\"title (review label — not rendered into the resume)\"\n value={draft.title}\n onChange={e => setDraft({ ...draft, title: e.target.value })}\n />\n\n <div className=\"rb-block__chips\">\n {parseTags(tagsText).map(t => (\n <button\n type=\"button\"\n key={t}\n className={`rb-tag rb-tag--${facetOf(t)}`}\n onClick={() => onTagClick(t)}\n title=\"filter by this tag\"\n >\n {t}\n </button>\n ))}\n </div>\n <input\n className=\"rb-block__tags-input\"\n placeholder=\"tags (space or comma separated, e.g. tech:python story:scale)\"\n value={tagsText}\n onChange={e => setTagsText(e.target.value)}\n />\n\n <textarea\n className=\"rb-block__content\"\n rows={8}\n placeholder=\"content (markdown)\"\n value={draft.content}\n onChange={e => setDraft({ ...draft, content: e.target.value })}\n />\n\n <div className=\"rb-block__actions\">\n <button\n type=\"button\"\n className=\"rb-builder__btn rb-builder__btn--primary\"\n onClick={() => {\n void handleSave()\n }}\n disabled={saving || !dirty || idInvalid}\n >\n {saving ? 'Saving…' : isNew ? 'Create' : 'Save'}\n </button>\n {isNew ? (\n <button type=\"button\" className=\"rb-builder__btn\" onClick={onCancel}>\n Cancel\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"rb-builder__btn rb-builder__btn--danger\"\n onClick={() => {\n void handleDelete()\n }}\n disabled={saving}\n >\n Delete\n </button>\n )}\n {idInvalid && <span className=\"rb-block__hint\">id must be unique kebab-case</span>}\n {saveError && <span className=\"rb-block__hint rb-block__hint--error\">{saveError}</span>}\n </div>\n\n {!isNew && (\n <div className=\"rb-block__feedback\">\n <textarea\n rows={2}\n placeholder=\"review note (autosaves)…\"\n value={fbText}\n onChange={e => onFbChange(e.target.value)}\n />\n <span className=\"rb-block__fb-status\">{fbStatus}</span>\n </div>\n )}\n </div>\n )\n}\n","// src/constants.ts\nvar PREFS_API_BASE = \"https://hadoku.me/prefs\";\nvar CACHE_KEY_PREFIX = \"prefs-cache\";\nvar SAVE_DEBOUNCE_MS = 1e3;\n\n// src/storage.ts\nvar localStorageAdapter = {\n get(key) {\n if (typeof window === \"undefined\") return Promise.resolve(null);\n try {\n return Promise.resolve(window.localStorage.getItem(key));\n } catch {\n return Promise.resolve(null);\n }\n },\n set(key, value) {\n if (typeof window === \"undefined\") return Promise.resolve();\n try {\n window.localStorage.setItem(key, value);\n } catch {\n }\n return Promise.resolve();\n },\n remove(key) {\n if (typeof window === \"undefined\") return Promise.resolve();\n try {\n window.localStorage.removeItem(key);\n } catch {\n }\n return Promise.resolve();\n }\n};\nvar memoryStorage = () => {\n const store = /* @__PURE__ */ new Map();\n return {\n get(key) {\n return Promise.resolve(store.get(key) ?? null);\n },\n set(key, value) {\n store.set(key, value);\n return Promise.resolve();\n },\n remove(key) {\n store.delete(key);\n return Promise.resolve();\n }\n };\n};\nvar sessionStorageWrite = (key, value) => {\n if (typeof window === \"undefined\") return;\n try {\n window.sessionStorage.setItem(key, value);\n } catch {\n }\n};\nfunction readCapacitorGlobal() {\n return globalThis.Capacitor;\n}\nfunction capacitorStorage() {\n const cap = readCapacitorGlobal();\n if (!cap?.isNativePlatform?.()) return null;\n const prefs = cap.Plugins?.Preferences;\n if (!prefs) return null;\n return {\n async get(key) {\n const { value } = await prefs.get({ key });\n return value ?? null;\n },\n async set(key, value) {\n await prefs.set({ key, value });\n },\n async remove(key) {\n await prefs.remove({ key });\n }\n };\n}\nfunction detectStorage() {\n return capacitorStorage() ?? localStorageAdapter;\n}\n\n// src/get-device-id.ts\nvar DEVICE_ID_KEY = \"hadoku_device_id\";\nasync function getDeviceId(storage = localStorageAdapter) {\n const existing = await storage.get(DEVICE_ID_KEY);\n if (existing && isUuid(existing)) {\n return existing;\n }\n const fresh = mintUuid();\n await storage.set(DEVICE_ID_KEY, fresh);\n return fresh;\n}\nfunction mintUuid() {\n const c = globalThis.crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (ch) => {\n const r = Math.random() * 16 | 0;\n const v = ch === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n}\nvar UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nfunction isUuid(s) {\n return UUID_RE.test(s);\n}\n\n// src/whoami.ts\nvar ANON_USER_ID = \"anon\";\nvar WHOAMI_GLOBAL = \"__hadokuWhoami\";\nvar SESSION_SCOPE_PREFIX = \"sess:\";\nvar UNSCOPED_ID = \"unscoped\";\nfunction adaptWhoami(body) {\n if (!body || body.valid === false) {\n return { userId: ANON_USER_ID, userType: \"public\", scope: \"anon\" };\n }\n const userType = body.userType === \"admin\" || body.userType === \"wife\" || body.userType === \"service\" || body.userType === \"friend\" || body.userType === \"member\" || body.userType === \"public\" ? body.userType : \"public\";\n const name = typeof body.name === \"string\" ? body.name : null;\n if (typeof body.userId === \"string\" && body.userId) {\n return { userId: body.userId, userType, name, scope: \"user\" };\n }\n if (typeof body.sessionId === \"string\" && body.sessionId) {\n return {\n userId: `${SESSION_SCOPE_PREFIX}${body.sessionId}`,\n userType,\n name,\n scope: \"session\"\n };\n }\n return { userId: UNSCOPED_ID, userType, name, scope: \"none\" };\n}\nasync function fetchWhoamiRaw(url, userKey) {\n const headers = {};\n if (userKey) {\n headers[\"X-User-Key\"] = userKey;\n }\n try {\n const resp = await fetch(url, {\n method: \"GET\",\n headers,\n credentials: \"include\",\n cache: \"no-store\"\n });\n if (!resp.ok) return null;\n return await resp.json();\n } catch {\n return null;\n }\n}\nfunction defaultWhoamiUrl() {\n const loc = globalThis.location;\n if (loc && (loc.protocol === \"http:\" || loc.protocol === \"https:\")) return \"/session/whoami\";\n return `${PREFS_API_BASE.replace(/\\/prefs$/, \"\")}/session/whoami`;\n}\nasync function whoami(opts = {}) {\n const url = opts.whoamiUrl ?? defaultWhoamiUrl();\n if (opts.userKey) {\n return adaptWhoami(await fetchWhoamiRaw(url, opts.userKey));\n }\n const g = globalThis;\n let shared = g[WHOAMI_GLOBAL];\n if (!shared) {\n shared = fetchWhoamiRaw(url);\n g[WHOAMI_GLOBAL] = shared;\n }\n try {\n return adaptWhoami(await shared);\n } catch {\n return { userId: ANON_USER_ID, userType: \"public\", scope: \"anon\" };\n }\n}\n\n// src/client.ts\nfunction createPrefsClient(opts) {\n const apiBase = opts.apiBase ?? PREFS_API_BASE;\n const mirrorOnRead = opts.mirrorBootstrapOnRead ?? false;\n const storage = opts.storage ?? detectStorage();\n const listeners = /* @__PURE__ */ new Set();\n const migrations = opts.migrations ?? [];\n const defaults = opts.defaults ?? {};\n const bootstrapMap = opts.bootstrapToSessionStorage ?? {};\n let userId = null;\n let identityScope = \"anon\";\n let wroteWhileAnon = false;\n let deviceId = opts.deviceId ?? null;\n let currentBlob = null;\n let userVersion = 0;\n let deviceVersion = 0;\n let pendingPatch = {};\n let pendingScope = \"user\";\n const dirtyFields = /* @__PURE__ */ new Set();\n let saveTimer = null;\n let savePromise = null;\n let initPromise = null;\n let bcast = null;\n let destroyed = false;\n const broadcastId = `${Math.random().toString(36).slice(2)}-${Date.now()}`;\n function ensureInit() {\n if (initPromise) return initPromise;\n initPromise = (async () => {\n const who = await whoami({\n userKey: opts.userKey,\n // An EXPLICIT apiBase (a non-prod environment) names where identity lives\n // too. With none, leave it to whoami()'s default — same-origin in a\n // browser — rather than pinning the hadoku.me constant (#419).\n ...opts.apiBase ? { whoamiUrl: `${opts.apiBase.replace(/\\/prefs$/, \"\")}/session/whoami` } : {}\n });\n userId = who.userId;\n identityScope = who.scope;\n if (!deviceId) {\n deviceId = await getDeviceId(storage);\n }\n const cached = await readCache();\n if (cached) {\n userVersion = cached.userVersion;\n deviceVersion = cached.deviceVersion;\n currentBlob = applyDefaultsAndParse(cached.blob);\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n }\n if (canPersist() && typeof BroadcastChannel !== \"undefined\") {\n bcast = new BroadcastChannel(`prefs:${userId}:${opts.appId}`);\n bcast.addEventListener(\"message\", onBroadcast);\n }\n })();\n return initPromise;\n }\n function buildHeaders() {\n const h = { \"Content-Type\": \"application/json\" };\n if (opts.userKey) h[\"X-User-Key\"] = opts.userKey;\n if (deviceId) h[\"X-Device-Id\"] = deviceId;\n return h;\n }\n async function fetchFromServer() {\n const resp = await fetch(`${apiBase}/api/v1/${opts.appId}`, {\n method: \"GET\",\n headers: buildHeaders(),\n credentials: \"include\"\n });\n if (!resp.ok) {\n throw new Error(`prefs-api GET failed: ${resp.status}`);\n }\n return await resp.json();\n }\n async function putToServer(scope, patch, expectedVersion) {\n const resp = await fetch(`${apiBase}/api/v1/${opts.appId}`, {\n method: \"PUT\",\n headers: buildHeaders(),\n credentials: \"include\",\n body: JSON.stringify({\n scope,\n patch,\n expectedVersion\n })\n });\n if (resp.status === 409) {\n const body2 = await resp.json();\n if (body2.current) {\n return { ok: false, conflict: body2.current };\n }\n throw new Error(\"prefs-api 409 without current-state body\");\n }\n if (!resp.ok) {\n throw new Error(`prefs-api PUT failed: ${resp.status}`);\n }\n const body = await resp.json();\n return { ok: true, row: body, scope: body.scope };\n }\n function cacheKey() {\n return `${CACHE_KEY_PREFIX}:${userId ?? ANON_USER_ID}:${opts.appId}`;\n }\n function canPersist() {\n return identityScope !== \"none\";\n }\n function canSync() {\n return identityScope === \"user\" || identityScope === \"session\";\n }\n async function readCache() {\n if (!canPersist()) return null;\n const raw = await storage.get(cacheKey());\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\" && parsed.blob && typeof parsed.blob === \"object\") {\n return parsed;\n }\n } catch {\n }\n return null;\n }\n async function writeCache(env) {\n if (!canPersist()) return;\n await storage.set(cacheKey(), JSON.stringify(env));\n }\n function applyDefaultsAndParse(rawBlob) {\n let withDefaults = { ...defaults, ...rawBlob };\n for (const m of migrations) {\n withDefaults = m(withDefaults);\n }\n const result = opts.schema.safeParse(withDefaults);\n if (result.success) {\n return result.data;\n }\n const fallback = opts.schema.safeParse({ ...defaults });\n return fallback.success ? fallback.data : withDefaults;\n }\n function mirrorBootstrap(blob) {\n for (const [field, sessionKey] of Object.entries(bootstrapMap)) {\n if (typeof sessionKey !== \"string\" || !sessionKey) continue;\n const value = blob[field];\n if (typeof value === \"string\") {\n sessionStorageWrite(sessionKey, value);\n }\n }\n }\n function notify(blob) {\n for (const l of listeners) {\n try {\n l(blob);\n } catch {\n }\n }\n }\n function broadcast(blob) {\n if (!bcast) return;\n try {\n bcast.postMessage({ source: broadcastId, blob });\n } catch {\n }\n }\n function onBroadcast(ev) {\n const data = ev.data;\n if (!data || data.source === broadcastId || !data.blob) return;\n const reconciled = reconcileDirty(data.blob);\n currentBlob = applyDefaultsAndParse(reconciled);\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n }\n function reconcileDirty(remote) {\n if (dirtyFields.size === 0 || !currentBlob) return remote;\n const local = currentBlob;\n const reconciled = { ...remote };\n for (const field of dirtyFields) {\n if (field in local) reconciled[field] = local[field];\n }\n return reconciled;\n }\n async function refreshFromServer() {\n if (!canSync()) {\n if (currentBlob === null) {\n currentBlob = applyDefaultsAndParse({});\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n }\n return;\n }\n const server = await fetchFromServer();\n userVersion = server.user?.version ?? 0;\n deviceVersion = server.device?.version ?? 0;\n const merged = reconcileDirty(server.merged ?? {});\n currentBlob = applyDefaultsAndParse(merged);\n await writeCache({\n blob: merged,\n userVersion,\n deviceVersion,\n cachedAt: Date.now()\n });\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n broadcast(currentBlob);\n }\n function scheduleFlush() {\n if (saveTimer) clearTimeout(saveTimer);\n saveTimer = setTimeout(() => {\n void flushPending();\n }, SAVE_DEBOUNCE_MS);\n }\n async function flushPending() {\n if (Object.keys(pendingPatch).length === 0) return;\n if (savePromise) {\n await savePromise;\n }\n const patchSnapshot = pendingPatch;\n const scopeSnapshot = pendingScope;\n pendingPatch = {};\n if (saveTimer) {\n clearTimeout(saveTimer);\n saveTimer = null;\n }\n if (!canSync()) {\n for (const key of Object.keys(patchSnapshot)) {\n if (!(key in pendingPatch)) dirtyFields.delete(key);\n }\n return;\n }\n const expectedVersion = scopeSnapshot === \"user\" ? userVersion : deviceVersion;\n savePromise = (async () => {\n try {\n const result = await putToServer(scopeSnapshot, patchSnapshot, expectedVersion);\n if (result.ok) {\n if (result.scope === \"user\") {\n userVersion = result.row.version;\n } else {\n deviceVersion = result.row.version;\n }\n await refreshFromServer();\n } else {\n if (scopeSnapshot === \"user\") {\n userVersion = result.conflict.version;\n } else {\n deviceVersion = result.conflict.version;\n }\n await refreshFromServer();\n }\n for (const key of Object.keys(patchSnapshot)) {\n if (!(key in pendingPatch)) dirtyFields.delete(key);\n }\n } catch {\n pendingPatch = { ...patchSnapshot, ...pendingPatch };\n pendingScope = scopeSnapshot;\n } finally {\n savePromise = null;\n }\n })();\n await savePromise;\n }\n const client = {\n appId: opts.appId,\n async read() {\n await ensureInit();\n if (currentBlob === null) {\n try {\n await refreshFromServer();\n } catch {\n currentBlob = applyDefaultsAndParse({});\n }\n } else {\n void refreshFromServer().catch(() => {\n });\n }\n return currentBlob ?? applyDefaultsAndParse({});\n },\n async save(patch, saveOpts) {\n await ensureInit();\n const scope = saveOpts?.scope ?? \"user\";\n if (identityScope === \"anon\") wroteWhileAnon = true;\n const base = currentBlob ?? {};\n const nextBlob = applyDefaultsAndParse({ ...base, ...patch });\n currentBlob = nextBlob;\n await writeCache({\n blob: { ...base, ...patch },\n userVersion,\n deviceVersion,\n cachedAt: Date.now()\n });\n mirrorBootstrap(nextBlob);\n notify(nextBlob);\n broadcast(nextBlob);\n if (Object.keys(pendingPatch).length > 0 && pendingScope !== scope) {\n await flushPending();\n }\n pendingPatch = { ...pendingPatch, ...patch };\n pendingScope = scope;\n for (const key of Object.keys(patch)) dirtyFields.add(key);\n if (saveOpts?.expectedVersion !== void 0) {\n await flushPending();\n } else {\n scheduleFlush();\n }\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n async promoteAnonPrefsToUser() {\n if (!wroteWhileAnon) return;\n const anonKey = `${CACHE_KEY_PREFIX}:${ANON_USER_ID}:${opts.appId}`;\n const raw = await storage.get(anonKey);\n if (!raw) return;\n let anon;\n try {\n anon = JSON.parse(raw);\n } catch {\n return;\n }\n if (!anon.blob || Object.keys(anon.blob).length === 0) return;\n await ensureInit();\n const server = await fetchFromServer();\n if (server.user) {\n await refreshFromServer();\n await storage.remove(anonKey);\n return;\n }\n await putToServer(\"user\", anon.blob, 0);\n await refreshFromServer();\n await storage.remove(anonKey);\n },\n async flush() {\n await flushPending();\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n if (saveTimer) clearTimeout(saveTimer);\n if (bcast) bcast.close();\n listeners.clear();\n }\n };\n return client;\n}\nexport {\n ANON_USER_ID,\n CACHE_KEY_PREFIX,\n DEVICE_ID_KEY,\n PREFS_API_BASE,\n SAVE_DEBOUNCE_MS,\n capacitorStorage,\n createPrefsClient,\n detectStorage,\n getDeviceId,\n localStorageAdapter,\n memoryStorage,\n sessionStorageWrite,\n whoami\n};\n","import { useEffect, useState } from 'react'\nimport { whoami } from '@wolffm/prefs-client'\nimport { logger } from '@wolffm/logger/client'\n\n// Ecosystem auth, matching the command station (hadoku_site ContactAdmin):\n// resolve the caller's tier via edge-router's /session/whoami, and on anything\n// short of admin bounce to the shared /auth sign-in page rather than showing a\n// custom \"enter a key\" dead-end. /auth accepts a valid key (POST /session/create)\n// and redirects back to `return`. No app-specific key handling lives here.\n\n/** Send the browser to the ecosystem sign-in page, returning here afterwards. */\nexport function redirectToAuth(): void {\n if (typeof window === 'undefined') return\n const ret = encodeURIComponent(window.location.pathname + window.location.search)\n window.location.replace(`/auth?return=${ret}`)\n}\n\nexport type AuthStatus = 'checking' | 'authorized' | 'redirecting'\n\nexport interface BuilderAuth {\n status: AuthStatus\n /** Display name from the key registry once authorized (null if unnamed). */\n name: string | null\n}\n\nexport function useBuilderAuth(): BuilderAuth {\n const [status, setStatus] = useState<AuthStatus>('checking')\n const [name, setName] = useState<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n whoami()\n .then(who => {\n if (cancelled) return\n if (who.userType === 'admin') {\n setName(who.name ?? null)\n setStatus('authorized')\n return\n }\n logger.info('[builder] not admin, redirecting to sign in', { userType: who.userType })\n setStatus('redirecting')\n redirectToAuth()\n })\n .catch((err: unknown) => {\n // whoami() itself never rejects (it degrades to public), but stay\n // defensive: any failure means \"not signed in\" → sign-in page.\n if (cancelled) return\n logger.error('[builder] whoami failed', {\n error: err instanceof Error ? err.message : String(err)\n })\n setStatus('redirecting')\n redirectToAuth()\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n return { status, name }\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport { logger } from '@wolffm/logger/client'\nimport {\n fetchBlocks,\n saveBlock,\n deleteBlock as apiDeleteBlock,\n saveFeedback,\n BuilderApiError,\n type ResumeBlock,\n type BlockType,\n type Feedback\n} from './api'\nimport { BlockCard } from './BlockCard'\nimport { useBuilderAuth, redirectToAuth } from './useBuilderAuth'\n\nconst BLOCK_TYPES: BlockType[] = [\n 'experience',\n 'project',\n 'skills',\n 'education',\n 'summary',\n 'header'\n]\n\nexport function facetOf(tag: string): 'tech' | 'layer' | 'story' | 'plain' {\n if (tag.startsWith('tech:')) return 'tech'\n if (tag.startsWith('layer:')) return 'layer'\n if (tag.startsWith('story:')) return 'story'\n return 'plain'\n}\n\ntype SortMode = 'order' | 'priority' | 'type' | 'feedback'\n\nfunction emptyBlock(): ResumeBlock {\n return { id: '', type: 'experience', tags: [], title: '', content: '', priority: 5 }\n}\n\nexport function BuilderApp() {\n const { status: authStatus, name: adminName } = useBuilderAuth()\n const [blocks, setBlocks] = useState<ResumeBlock[]>([])\n const [feedback, setFeedback] = useState<Feedback>({})\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n // Filters\n const [search, setSearch] = useState('')\n const [typeFilter, setTypeFilter] = useState<'' | BlockType>('')\n const [activeTags, setActiveTags] = useState<Set<string>>(new Set())\n const [andMode, setAndMode] = useState(true)\n const [sort, setSort] = useState<SortMode>('order')\n\n const [creating, setCreating] = useState<ResumeBlock | null>(null)\n\n useEffect(() => {\n if (authStatus !== 'authorized') return\n let cancelled = false\n fetchBlocks()\n .then(res => {\n if (cancelled) return\n setBlocks(res.blocks)\n setFeedback(res.feedback)\n })\n .catch((err: unknown) => {\n if (cancelled) return\n // Session lapsed between the whoami check and this call → bounce to\n // sign-in, same as the initial gate. Everything else is a real error.\n if (err instanceof BuilderApiError && (err.status === 401 || err.status === 403)) {\n redirectToAuth()\n return\n }\n const msg = err instanceof Error ? err.message : 'Failed to load blocks'\n setError(msg)\n logger.error('[builder] load failed', { error: msg })\n })\n .finally(() => {\n if (!cancelled) setLoading(false)\n })\n return () => {\n cancelled = true\n }\n }, [authStatus])\n\n const tagCounts = useMemo(() => {\n const counts = new Map<string, number>()\n for (const b of blocks) for (const t of b.tags) counts.set(t, (counts.get(t) ?? 0) + 1)\n return counts\n }, [blocks])\n\n const sortedTags = useMemo(\n () =>\n [...tagCounts.keys()].sort(\n (a, b) => facetOf(a).localeCompare(facetOf(b)) || a.localeCompare(b)\n ),\n [tagCounts]\n )\n\n const visible = useMemo(() => {\n const q = search.trim().toLowerCase()\n let v = blocks.filter(b => {\n if (typeFilter && b.type !== typeFilter) return false\n if (q && !(b.id + b.title + b.content).toLowerCase().includes(q)) return false\n if (activeTags.size) {\n const hits = [...activeTags].filter(t => b.tags.includes(t)).length\n if (andMode ? hits !== activeTags.size : hits === 0) return false\n }\n return true\n })\n if (sort === 'priority') v = [...v].sort((a, b) => b.priority - a.priority)\n else if (sort === 'type') v = [...v].sort((a, b) => a.type.localeCompare(b.type))\n else if (sort === 'feedback')\n v = [...v].sort((a, b) => (feedback[b.id] ? 1 : 0) - (feedback[a.id] ? 1 : 0))\n return v\n }, [blocks, search, typeFilter, activeTags, andMode, sort, feedback])\n\n function toggleTag(tag: string) {\n setActiveTags(prev => {\n const next = new Set(prev)\n if (next.has(tag)) next.delete(tag)\n else next.add(tag)\n return next\n })\n }\n\n async function handleSave(block: ResumeBlock, isNew: boolean): Promise<void> {\n const { block: saved } = await saveBlock(block)\n setBlocks(prev => {\n const idx = prev.findIndex(b => b.id === saved.id)\n if (idx === -1) return [...prev, saved]\n const copy = [...prev]\n copy[idx] = saved\n return copy\n })\n if (isNew) setCreating(null)\n }\n\n async function handleDelete(id: string): Promise<void> {\n await apiDeleteBlock(id)\n setBlocks(prev => prev.filter(b => b.id !== id))\n }\n\n async function handleFeedback(id: string, text: string): Promise<void> {\n const res = await saveFeedback(id, text)\n setFeedback(res.feedback)\n }\n\n function exportJson() {\n const blob = new Blob([JSON.stringify(blocks, null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'blocks.json'\n a.click()\n URL.revokeObjectURL(url)\n }\n\n if (authStatus === 'checking') return <p className=\"rb-builder__status\">Checking access…</p>\n if (authStatus === 'redirecting')\n return <p className=\"rb-builder__status\">Redirecting to sign in…</p>\n if (loading) return <p className=\"rb-builder__status\">Loading blocks…</p>\n if (error) return <p className=\"rb-builder__status rb-builder__status--error\">{error}</p>\n\n return (\n <div className=\"rb-builder\">\n <div className=\"rb-builder__toolbar\">\n <header className=\"rb-builder__header\">\n <h1>Resume Builder</h1>\n <div className=\"rb-builder__count\">\n {visible.length} / {blocks.length} blocks\n </div>\n {adminName && (\n <div className=\"rb-builder__whoami\">\n Signed in as <span className=\"rb-builder__whoami-name\">{adminName}</span>\n </div>\n )}\n <div className=\"rb-builder__header-actions\">\n <button type=\"button\" onClick={exportJson} className=\"rb-builder__btn\">\n Export blocks.json\n </button>\n <button\n type=\"button\"\n onClick={() => setCreating(emptyBlock())}\n className=\"rb-builder__btn rb-builder__btn--primary\"\n disabled={creating !== null}\n >\n + New block\n </button>\n </div>\n </header>\n\n <div className=\"rb-builder__controls\">\n <input\n type=\"search\"\n placeholder=\"Search id, title, content…\"\n value={search}\n onChange={e => setSearch(e.target.value)}\n className=\"rb-builder__search\"\n />\n <select\n value={typeFilter}\n onChange={e => setTypeFilter(e.target.value as '' | BlockType)}\n className=\"rb-builder__select\"\n >\n <option value=\"\">all types</option>\n {BLOCK_TYPES.map(t => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <select\n value={sort}\n onChange={e => setSort(e.target.value as SortMode)}\n className=\"rb-builder__select\"\n >\n <option value=\"order\">render order</option>\n <option value=\"priority\">priority ↓</option>\n <option value=\"type\">type</option>\n <option value=\"feedback\">has feedback</option>\n </select>\n <label className=\"rb-builder__andmode\">\n <input type=\"checkbox\" checked={andMode} onChange={e => setAndMode(e.target.checked)} />\n match all tags\n </label>\n </div>\n\n <div className=\"rb-builder__legend\">\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--tech\" />\n tech:\n </span>\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--layer\" />\n layer:\n </span>\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--story\" />\n story:\n </span>\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--plain\" />\n other / always\n </span>\n <span className=\"rb-builder__legend-item\">\n <strong>prio</strong> = how strongly you want a block (sort/rank hint)\n </span>\n </div>\n\n <div className=\"rb-builder__tagbar\">\n {sortedTags.map(t => (\n <button\n type=\"button\"\n key={t}\n onClick={() => toggleTag(t)}\n className={`rb-tag rb-tag--${facetOf(t)}${activeTags.has(t) ? ' rb-tag--active' : ''}`}\n >\n {t}\n <span className=\"rb-tag__n\">{tagCounts.get(t)}</span>\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"rb-builder__list\">\n {creating && (\n <BlockCard\n key=\"__new__\"\n block={creating}\n feedback={undefined}\n isNew\n existingIds={blocks.map(b => b.id)}\n onSave={b => handleSave(b, true)}\n onCancel={() => setCreating(null)}\n onFeedback={handleFeedback}\n onTagClick={toggleTag}\n />\n )}\n {visible.map(b => (\n <BlockCard\n key={b.id}\n block={b}\n feedback={feedback[b.id]}\n existingIds={blocks.map(x => x.id)}\n onSave={block => handleSave(block, false)}\n onDelete={() => handleDelete(b.id)}\n onFeedback={handleFeedback}\n onTagClick={toggleTag}\n />\n ))}\n </div>\n </div>\n )\n}\n","import { createRoot, type Root } from 'react-dom/client'\nimport { logger } from '@wolffm/logger/client'\nimport { BuilderApp } from './BuilderApp'\nimport { setBuilderApiBaseUrl } from './api'\n// CSS is inlined into the bundle (not emitted as a separate asset) so builder.js\n// is fully self-contained — it can be served from /mf/resume/builder.js and\n// mounted by a bare page with no <link> wiring. Theme tokens come from the host\n// page; builder.css references them with fallbacks so it degrades standalone.\nimport builderCss from './builder.css?inline'\n\nfunction injectStyles() {\n if (document.getElementById('rb-builder-styles')) return\n const style = document.createElement('style')\n style.id = 'rb-builder-styles'\n style.textContent = builderCss\n document.head.appendChild(style)\n}\n\nexport interface ResumeBuilderProps {\n theme?: string\n /** API root, e.g. '/resume/api' — the builder calls ${apiBaseUrl}/builder/*. */\n apiBaseUrl: string\n}\n\ninterface BuilderElement extends HTMLElement {\n __root?: Root\n}\n\nexport function mount(el: HTMLElement, props: ResumeBuilderProps) {\n injectStyles()\n setBuilderApiBaseUrl(props.apiBaseUrl)\n const root = createRoot(el)\n root.render(<BuilderApp />)\n ;(el as BuilderElement).__root = root\n logger.info('[resume-builder] Mounted', { apiBaseUrl: props.apiBaseUrl })\n}\n\nexport function unmount(el: HTMLElement) {\n ;(el as BuilderElement).__root?.unmount()\n logger.info('[resume-builder] Unmounted')\n}\n"],"names":["BuilderApiError","message","status","baseUrl","setBuilderApiBaseUrl","url","req","path","init","res","detail","body","fetchBlocks","saveBlock","block","deleteBlock","id","saveFeedback","text","BLOCK_TYPES","BlockCard","feedback","existingIds","isNew","onSave","onDelete","onCancel","onFeedback","onTagClick","draft","setDraft","useState","tagsText","setTagsText","saving","setSaving","saveError","setSaveError","fbText","setFbText","fbStatus","setFbStatus","fbTimer","useRef","useEffect","dirty","parseTags","idInvalid","handleSave","err","handleDelete","onFbChange","jsxs","jsx","e","t","facetOf","PREFS_API_BASE","ANON_USER_ID","WHOAMI_GLOBAL","SESSION_SCOPE_PREFIX","UNSCOPED_ID","adaptWhoami","userType","name","fetchWhoamiRaw","userKey","headers","resp","defaultWhoamiUrl","loc","whoami","opts","g","shared","redirectToAuth","ret","useBuilderAuth","setStatus","setName","cancelled","who","logger","tag","emptyBlock","BuilderApp","authStatus","adminName","blocks","setBlocks","setFeedback","loading","setLoading","error","setError","search","setSearch","typeFilter","setTypeFilter","activeTags","setActiveTags","andMode","setAndMode","sort","setSort","creating","setCreating","msg","tagCounts","useMemo","counts","b","sortedTags","a","visible","q","v","hits","toggleTag","prev","next","saved","idx","copy","apiDeleteBlock","handleFeedback","exportJson","blob","x","injectStyles","style","builderCss","mount","el","props","root","createRoot","unmount"],"mappings":"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","x_google_ignoreList":[2]}
|
|
1
|
+
{"version":3,"file":"builder.js","sources":["../src/builder/api.ts","../src/builder/BlockCard.tsx","../node_modules/.pnpm/@wolffm+prefs-client@1.1.7_react@19.2.0_zod@4.1.12/node_modules/@wolffm/prefs-client/dist/index.js","../src/builder/useBuilderAuth.ts","../src/builder/BuilderApp.tsx","../src/builder/entry.tsx"],"sourcesContent":["// Admin builder API client. All calls go through the edge-router (same-origin,\n// credentials:'include') so the caller's admin session cookie is resolved into\n// the X-Hadoku-Tier: admin stamp the worker's requireMinTier('admin') needs.\n\nexport type BlockType = 'experience' | 'project' | 'skills' | 'education' | 'summary' | 'header'\n\nexport interface ResumeBlock {\n id: string\n type: BlockType\n tags: string[]\n title: string\n content: string\n priority: number\n}\n\nexport interface FeedbackEntry {\n text: string\n updated: string\n}\nexport type Feedback = Record<string, FeedbackEntry>\n\nexport class BuilderApiError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message)\n this.name = 'BuilderApiError'\n }\n}\n\n// The API root ('/resume/api'); builder endpoints are appended to it directly.\nlet baseUrl = ''\nexport function setBuilderApiBaseUrl(url: string): void {\n baseUrl = url.replace(/\\/+$/, '')\n}\n\nasync function req<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await fetch(`${baseUrl}/builder${path}`, {\n ...init,\n credentials: 'include',\n headers: { 'Content-Type': 'application/json', ...(init?.headers ?? {}) }\n })\n if (!res.ok) {\n let detail = `${res.status}`\n try {\n const body = (await res.json()) as { error?: string; message?: string }\n detail = body.message ? `${body.error}: ${body.message}` : (body.error ?? detail)\n } catch {\n /* non-JSON error body */\n }\n throw new BuilderApiError(detail, res.status)\n }\n return (await res.json()) as T\n}\n\nexport function fetchBlocks(): Promise<{ blocks: ResumeBlock[]; feedback: Feedback }> {\n return req('/blocks')\n}\n\nexport function saveBlock(block: ResumeBlock): Promise<{ block: ResumeBlock }> {\n return req(`/blocks/${encodeURIComponent(block.id)}`, {\n method: 'PUT',\n body: JSON.stringify(block)\n })\n}\n\nexport function deleteBlock(id: string): Promise<{ deleted: true; id: string }> {\n return req(`/blocks/${encodeURIComponent(id)}`, { method: 'DELETE' })\n}\n\nexport function reorderBlocks(ids: string[]): Promise<{ ids: string[] }> {\n return req('/reorder', { method: 'PUT', body: JSON.stringify({ ids }) })\n}\n\nexport function saveFeedback(id: string, text: string): Promise<{ feedback: Feedback }> {\n return req(`/feedback/${encodeURIComponent(id)}`, {\n method: 'POST',\n body: JSON.stringify({ text })\n })\n}\n","import { useEffect, useRef, useState } from 'react'\nimport { facetOf } from './BuilderApp'\nimport type { BlockType, FeedbackEntry, ResumeBlock } from './api'\n\nconst BLOCK_TYPES: BlockType[] = [\n 'experience',\n 'project',\n 'skills',\n 'education',\n 'summary',\n 'header'\n]\n\ninterface Props {\n block: ResumeBlock\n feedback: FeedbackEntry | undefined\n existingIds: string[]\n isNew?: boolean\n onSave: (block: ResumeBlock) => Promise<void>\n onDelete?: () => Promise<void>\n onCancel?: () => void\n onFeedback: (id: string, text: string) => Promise<void>\n onTagClick: (tag: string) => void\n}\n\nexport function BlockCard({\n block,\n feedback,\n existingIds,\n isNew = false,\n onSave,\n onDelete,\n onCancel,\n onFeedback,\n onTagClick\n}: Props) {\n const [draft, setDraft] = useState<ResumeBlock>(block)\n const [tagsText, setTagsText] = useState(block.tags.join(' '))\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<string | null>(null)\n const [fbText, setFbText] = useState(feedback?.text ?? '')\n const [fbStatus, setFbStatus] = useState('')\n const fbTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n\n // Keep the draft in sync if the saved block changes underneath us (e.g. after\n // a successful save re-normalises it), but not while the user is mid-edit.\n useEffect(() => {\n if (!isNew) {\n setDraft(block)\n setTagsText(block.tags.join(' '))\n }\n }, [block, isNew])\n\n const dirty =\n isNew || JSON.stringify({ ...draft, tags: parseTags(tagsText) }) !== JSON.stringify(block)\n\n function parseTags(text: string): string[] {\n return [...new Set(text.split(/[\\s,]+/).filter(Boolean))]\n }\n\n const idInvalid =\n isNew && (!/^[a-z0-9][a-z0-9-]*$/.test(draft.id) || existingIds.includes(draft.id))\n\n async function handleSave() {\n setSaving(true)\n setSaveError(null)\n try {\n await onSave({ ...draft, tags: parseTags(tagsText) })\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : 'Save failed')\n } finally {\n setSaving(false)\n }\n }\n\n async function handleDelete() {\n if (!onDelete) return\n if (!confirm(`Delete block \"${block.id}\"? This removes it from the live resume.`)) return\n setSaving(true)\n try {\n await onDelete()\n } catch (err) {\n setSaveError(err instanceof Error ? err.message : 'Delete failed')\n setSaving(false)\n }\n }\n\n function onFbChange(text: string) {\n setFbText(text)\n setFbStatus('typing…')\n clearTimeout(fbTimer.current)\n fbTimer.current = setTimeout(() => {\n onFeedback(block.id, text)\n .then(() => setFbStatus(text.trim() ? 'saved ✓' : ''))\n .catch(() => setFbStatus('save failed'))\n }, 600)\n }\n\n return (\n <div\n className={`rb-block${feedback ? ' rb-block--has-feedback' : ''}${dirty ? ' rb-block--dirty' : ''}`}\n >\n <div className=\"rb-block__row\">\n {isNew ? (\n <input\n className=\"rb-block__id-input\"\n placeholder=\"block-id (kebab-case)\"\n value={draft.id}\n onChange={e => setDraft({ ...draft, id: e.target.value })}\n />\n ) : (\n <span className=\"rb-block__id\">{draft.id}</span>\n )}\n <select\n className=\"rb-block__type\"\n value={draft.type}\n onChange={e => setDraft({ ...draft, type: e.target.value as BlockType })}\n >\n {BLOCK_TYPES.map(t => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <label\n className=\"rb-block__prio\"\n title=\"Priority — how strongly you want this block in a tailored resume. Higher sorts first; a ranking hint, not a hard rule.\"\n >\n prio\n <input\n type=\"number\"\n min={0}\n max={10}\n value={draft.priority}\n onChange={e => setDraft({ ...draft, priority: Number(e.target.value) })}\n />\n </label>\n </div>\n\n <input\n className=\"rb-block__title\"\n placeholder=\"title (review label — not rendered into the resume)\"\n value={draft.title}\n onChange={e => setDraft({ ...draft, title: e.target.value })}\n />\n\n <div className=\"rb-block__chips\">\n {parseTags(tagsText).map(t => (\n <button\n type=\"button\"\n key={t}\n className={`rb-tag rb-tag--${facetOf(t)}`}\n onClick={() => onTagClick(t)}\n title=\"filter by this tag\"\n >\n {t}\n </button>\n ))}\n </div>\n <input\n className=\"rb-block__tags-input\"\n placeholder=\"tags (space or comma separated, e.g. tech:python story:scale)\"\n value={tagsText}\n onChange={e => setTagsText(e.target.value)}\n />\n\n <textarea\n className=\"rb-block__content\"\n rows={8}\n placeholder=\"content (markdown)\"\n value={draft.content}\n onChange={e => setDraft({ ...draft, content: e.target.value })}\n />\n\n <div className=\"rb-block__actions\">\n <button\n type=\"button\"\n className=\"rb-builder__btn rb-builder__btn--primary\"\n onClick={() => {\n void handleSave()\n }}\n disabled={saving || !dirty || idInvalid}\n >\n {saving ? 'Saving…' : isNew ? 'Create' : 'Save'}\n </button>\n {isNew ? (\n <button type=\"button\" className=\"rb-builder__btn\" onClick={onCancel}>\n Cancel\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"rb-builder__btn rb-builder__btn--danger\"\n onClick={() => {\n void handleDelete()\n }}\n disabled={saving}\n >\n Delete\n </button>\n )}\n {idInvalid && <span className=\"rb-block__hint\">id must be unique kebab-case</span>}\n {saveError && <span className=\"rb-block__hint rb-block__hint--error\">{saveError}</span>}\n </div>\n\n {!isNew && (\n <div className=\"rb-block__feedback\">\n <textarea\n rows={2}\n placeholder=\"review note (autosaves)…\"\n value={fbText}\n onChange={e => onFbChange(e.target.value)}\n />\n <span className=\"rb-block__fb-status\">{fbStatus}</span>\n </div>\n )}\n </div>\n )\n}\n","// src/constants.ts\nvar PREFS_API_BASE = \"https://hadoku.me/prefs\";\nvar CACHE_KEY_PREFIX = \"prefs-cache\";\nvar SAVE_DEBOUNCE_MS = 1e3;\n\n// src/storage.ts\nvar localStorageAdapter = {\n get(key) {\n if (typeof window === \"undefined\") return Promise.resolve(null);\n try {\n return Promise.resolve(window.localStorage.getItem(key));\n } catch {\n return Promise.resolve(null);\n }\n },\n set(key, value) {\n if (typeof window === \"undefined\") return Promise.resolve();\n try {\n window.localStorage.setItem(key, value);\n } catch {\n }\n return Promise.resolve();\n },\n remove(key) {\n if (typeof window === \"undefined\") return Promise.resolve();\n try {\n window.localStorage.removeItem(key);\n } catch {\n }\n return Promise.resolve();\n }\n};\nvar memoryStorage = () => {\n const store = /* @__PURE__ */ new Map();\n return {\n get(key) {\n return Promise.resolve(store.get(key) ?? null);\n },\n set(key, value) {\n store.set(key, value);\n return Promise.resolve();\n },\n remove(key) {\n store.delete(key);\n return Promise.resolve();\n }\n };\n};\nvar sessionStorageWrite = (key, value) => {\n if (typeof window === \"undefined\") return;\n try {\n window.sessionStorage.setItem(key, value);\n } catch {\n }\n};\nfunction readCapacitorGlobal() {\n return globalThis.Capacitor;\n}\nfunction capacitorStorage() {\n const cap = readCapacitorGlobal();\n if (!cap?.isNativePlatform?.()) return null;\n const prefs = cap.Plugins?.Preferences;\n if (!prefs) return null;\n return {\n async get(key) {\n const { value } = await prefs.get({ key });\n return value ?? null;\n },\n async set(key, value) {\n await prefs.set({ key, value });\n },\n async remove(key) {\n await prefs.remove({ key });\n }\n };\n}\nfunction detectStorage() {\n return capacitorStorage() ?? localStorageAdapter;\n}\n\n// src/get-device-id.ts\nvar DEVICE_ID_KEY = \"hadoku_device_id\";\nasync function getDeviceId(storage = localStorageAdapter) {\n const existing = await storage.get(DEVICE_ID_KEY);\n if (existing && isUuid(existing)) {\n return existing;\n }\n const fresh = mintUuid();\n await storage.set(DEVICE_ID_KEY, fresh);\n return fresh;\n}\nfunction mintUuid() {\n const c = globalThis.crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (ch) => {\n const r = Math.random() * 16 | 0;\n const v = ch === \"x\" ? r : r & 3 | 8;\n return v.toString(16);\n });\n}\nvar UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nfunction isUuid(s) {\n return UUID_RE.test(s);\n}\n\n// src/whoami.ts\nvar ANON_USER_ID = \"anon\";\nvar WHOAMI_GLOBAL = \"__hadokuWhoami\";\nvar SESSION_SCOPE_PREFIX = \"sess:\";\nvar UNSCOPED_ID = \"unscoped\";\nfunction adaptWhoami(body) {\n if (!body || body.valid === false) {\n return { userId: ANON_USER_ID, userType: \"public\", scope: \"anon\" };\n }\n const userType = body.userType === \"admin\" || body.userType === \"wife\" || body.userType === \"service\" || body.userType === \"friend\" || body.userType === \"member\" || body.userType === \"public\" ? body.userType : \"public\";\n const name = typeof body.name === \"string\" ? body.name : null;\n if (typeof body.userId === \"string\" && body.userId) {\n return { userId: body.userId, userType, name, scope: \"user\" };\n }\n if (typeof body.sessionId === \"string\" && body.sessionId) {\n return {\n userId: `${SESSION_SCOPE_PREFIX}${body.sessionId}`,\n userType,\n name,\n scope: \"session\"\n };\n }\n return { userId: UNSCOPED_ID, userType, name, scope: \"none\" };\n}\nasync function fetchWhoamiRaw(url, userKey) {\n const headers = {};\n if (userKey) {\n headers[\"X-User-Key\"] = userKey;\n }\n try {\n const resp = await fetch(url, {\n method: \"GET\",\n headers,\n credentials: \"include\",\n cache: \"no-store\"\n });\n if (!resp.ok) return null;\n return await resp.json();\n } catch {\n return null;\n }\n}\nfunction defaultWhoamiUrl() {\n const loc = globalThis.location;\n if (loc && (loc.protocol === \"http:\" || loc.protocol === \"https:\")) return \"/session/whoami\";\n return `${PREFS_API_BASE.replace(/\\/prefs$/, \"\")}/session/whoami`;\n}\nasync function whoami(opts = {}) {\n const url = opts.whoamiUrl ?? defaultWhoamiUrl();\n if (opts.userKey) {\n return adaptWhoami(await fetchWhoamiRaw(url, opts.userKey));\n }\n const g = globalThis;\n let shared = g[WHOAMI_GLOBAL];\n if (!shared) {\n shared = fetchWhoamiRaw(url);\n g[WHOAMI_GLOBAL] = shared;\n }\n try {\n return adaptWhoami(await shared);\n } catch {\n return { userId: ANON_USER_ID, userType: \"public\", scope: \"anon\" };\n }\n}\n\n// src/client.ts\nfunction createPrefsClient(opts) {\n const apiBase = opts.apiBase ?? PREFS_API_BASE;\n const mirrorOnRead = opts.mirrorBootstrapOnRead ?? false;\n const storage = opts.storage ?? detectStorage();\n const listeners = /* @__PURE__ */ new Set();\n const migrations = opts.migrations ?? [];\n const defaults = opts.defaults ?? {};\n const bootstrapMap = opts.bootstrapToSessionStorage ?? {};\n let userId = null;\n let identityScope = \"anon\";\n let wroteWhileAnon = false;\n let deviceId = opts.deviceId ?? null;\n let currentBlob = null;\n let userVersion = 0;\n let deviceVersion = 0;\n let pendingPatch = {};\n let pendingScope = \"user\";\n const dirtyFields = /* @__PURE__ */ new Set();\n let saveTimer = null;\n let savePromise = null;\n let initPromise = null;\n let bcast = null;\n let destroyed = false;\n const broadcastId = `${Math.random().toString(36).slice(2)}-${Date.now()}`;\n function ensureInit() {\n if (initPromise) return initPromise;\n initPromise = (async () => {\n const who = await whoami({\n userKey: opts.userKey,\n // An EXPLICIT apiBase (a non-prod environment) names where identity lives\n // too. With none, leave it to whoami()'s default — same-origin in a\n // browser — rather than pinning the hadoku.me constant (#419).\n ...opts.apiBase ? { whoamiUrl: `${opts.apiBase.replace(/\\/prefs$/, \"\")}/session/whoami` } : {}\n });\n userId = who.userId;\n identityScope = who.scope;\n if (!deviceId) {\n deviceId = await getDeviceId(storage);\n }\n const cached = await readCache();\n if (cached) {\n userVersion = cached.userVersion;\n deviceVersion = cached.deviceVersion;\n currentBlob = applyDefaultsAndParse(cached.blob);\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n }\n if (canPersist() && typeof BroadcastChannel !== \"undefined\") {\n bcast = new BroadcastChannel(`prefs:${userId}:${opts.appId}`);\n bcast.addEventListener(\"message\", onBroadcast);\n }\n })();\n return initPromise;\n }\n function buildHeaders() {\n const h = { \"Content-Type\": \"application/json\" };\n if (opts.userKey) h[\"X-User-Key\"] = opts.userKey;\n if (deviceId) h[\"X-Device-Id\"] = deviceId;\n return h;\n }\n async function fetchFromServer() {\n const resp = await fetch(`${apiBase}/api/v1/${opts.appId}`, {\n method: \"GET\",\n headers: buildHeaders(),\n credentials: \"include\"\n });\n if (!resp.ok) {\n throw new Error(`prefs-api GET failed: ${resp.status}`);\n }\n return await resp.json();\n }\n async function putToServer(scope, patch, expectedVersion) {\n const resp = await fetch(`${apiBase}/api/v1/${opts.appId}`, {\n method: \"PUT\",\n headers: buildHeaders(),\n credentials: \"include\",\n body: JSON.stringify({\n scope,\n patch,\n expectedVersion\n })\n });\n if (resp.status === 409) {\n const body2 = await resp.json();\n if (body2.current) {\n return { ok: false, conflict: body2.current };\n }\n throw new Error(\"prefs-api 409 without current-state body\");\n }\n if (!resp.ok) {\n throw new Error(`prefs-api PUT failed: ${resp.status}`);\n }\n const body = await resp.json();\n return { ok: true, row: body, scope: body.scope };\n }\n function cacheKey() {\n return `${CACHE_KEY_PREFIX}:${userId ?? ANON_USER_ID}:${opts.appId}`;\n }\n function canPersist() {\n return identityScope !== \"none\";\n }\n function canSync() {\n return identityScope === \"user\" || identityScope === \"session\";\n }\n async function readCache() {\n if (!canPersist()) return null;\n const raw = await storage.get(cacheKey());\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\" && parsed.blob && typeof parsed.blob === \"object\") {\n return parsed;\n }\n } catch {\n }\n return null;\n }\n async function writeCache(env) {\n if (!canPersist()) return;\n await storage.set(cacheKey(), JSON.stringify(env));\n }\n function applyDefaultsAndParse(rawBlob) {\n let withDefaults = { ...defaults, ...rawBlob };\n for (const m of migrations) {\n withDefaults = m(withDefaults);\n }\n const result = opts.schema.safeParse(withDefaults);\n if (result.success) {\n return result.data;\n }\n const fallback = opts.schema.safeParse({ ...defaults });\n return fallback.success ? fallback.data : withDefaults;\n }\n function mirrorBootstrap(blob) {\n for (const [field, sessionKey] of Object.entries(bootstrapMap)) {\n if (typeof sessionKey !== \"string\" || !sessionKey) continue;\n const value = blob[field];\n if (typeof value === \"string\") {\n sessionStorageWrite(sessionKey, value);\n }\n }\n }\n function notify(blob) {\n for (const l of listeners) {\n try {\n l(blob);\n } catch {\n }\n }\n }\n function broadcast(blob) {\n if (!bcast) return;\n try {\n bcast.postMessage({ source: broadcastId, blob });\n } catch {\n }\n }\n function onBroadcast(ev) {\n const data = ev.data;\n if (!data || data.source === broadcastId || !data.blob) return;\n const reconciled = reconcileDirty(data.blob);\n currentBlob = applyDefaultsAndParse(reconciled);\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n }\n function reconcileDirty(remote) {\n if (dirtyFields.size === 0 || !currentBlob) return remote;\n const local = currentBlob;\n const reconciled = { ...remote };\n for (const field of dirtyFields) {\n if (field in local) reconciled[field] = local[field];\n }\n return reconciled;\n }\n async function refreshFromServer() {\n if (!canSync()) {\n if (currentBlob === null) {\n currentBlob = applyDefaultsAndParse({});\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n }\n return;\n }\n const server = await fetchFromServer();\n userVersion = server.user?.version ?? 0;\n deviceVersion = server.device?.version ?? 0;\n const merged = reconcileDirty(server.merged ?? {});\n currentBlob = applyDefaultsAndParse(merged);\n await writeCache({\n blob: merged,\n userVersion,\n deviceVersion,\n cachedAt: Date.now()\n });\n if (mirrorOnRead) mirrorBootstrap(currentBlob);\n notify(currentBlob);\n broadcast(currentBlob);\n }\n function scheduleFlush() {\n if (saveTimer) clearTimeout(saveTimer);\n saveTimer = setTimeout(() => {\n void flushPending();\n }, SAVE_DEBOUNCE_MS);\n }\n async function flushPending() {\n if (Object.keys(pendingPatch).length === 0) return;\n if (savePromise) {\n await savePromise;\n }\n const patchSnapshot = pendingPatch;\n const scopeSnapshot = pendingScope;\n pendingPatch = {};\n if (saveTimer) {\n clearTimeout(saveTimer);\n saveTimer = null;\n }\n if (!canSync()) {\n for (const key of Object.keys(patchSnapshot)) {\n if (!(key in pendingPatch)) dirtyFields.delete(key);\n }\n return;\n }\n const expectedVersion = scopeSnapshot === \"user\" ? userVersion : deviceVersion;\n savePromise = (async () => {\n try {\n const result = await putToServer(scopeSnapshot, patchSnapshot, expectedVersion);\n if (result.ok) {\n if (result.scope === \"user\") {\n userVersion = result.row.version;\n } else {\n deviceVersion = result.row.version;\n }\n await refreshFromServer();\n } else {\n if (scopeSnapshot === \"user\") {\n userVersion = result.conflict.version;\n } else {\n deviceVersion = result.conflict.version;\n }\n await refreshFromServer();\n }\n for (const key of Object.keys(patchSnapshot)) {\n if (!(key in pendingPatch)) dirtyFields.delete(key);\n }\n } catch {\n pendingPatch = { ...patchSnapshot, ...pendingPatch };\n pendingScope = scopeSnapshot;\n } finally {\n savePromise = null;\n }\n })();\n await savePromise;\n }\n const client = {\n appId: opts.appId,\n async read() {\n await ensureInit();\n if (currentBlob === null) {\n try {\n await refreshFromServer();\n } catch {\n currentBlob = applyDefaultsAndParse({});\n }\n } else {\n void refreshFromServer().catch(() => {\n });\n }\n return currentBlob ?? applyDefaultsAndParse({});\n },\n async save(patch, saveOpts) {\n await ensureInit();\n const scope = saveOpts?.scope ?? \"user\";\n if (identityScope === \"anon\") wroteWhileAnon = true;\n const base = currentBlob ?? {};\n const nextBlob = applyDefaultsAndParse({ ...base, ...patch });\n currentBlob = nextBlob;\n await writeCache({\n blob: { ...base, ...patch },\n userVersion,\n deviceVersion,\n cachedAt: Date.now()\n });\n mirrorBootstrap(nextBlob);\n notify(nextBlob);\n broadcast(nextBlob);\n if (Object.keys(pendingPatch).length > 0 && pendingScope !== scope) {\n await flushPending();\n }\n pendingPatch = { ...pendingPatch, ...patch };\n pendingScope = scope;\n for (const key of Object.keys(patch)) dirtyFields.add(key);\n if (saveOpts?.expectedVersion !== void 0) {\n await flushPending();\n } else {\n scheduleFlush();\n }\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n async promoteAnonPrefsToUser() {\n if (!wroteWhileAnon) return;\n const anonKey = `${CACHE_KEY_PREFIX}:${ANON_USER_ID}:${opts.appId}`;\n const raw = await storage.get(anonKey);\n if (!raw) return;\n let anon;\n try {\n anon = JSON.parse(raw);\n } catch {\n return;\n }\n if (!anon.blob || Object.keys(anon.blob).length === 0) return;\n await ensureInit();\n const server = await fetchFromServer();\n if (server.user) {\n await refreshFromServer();\n await storage.remove(anonKey);\n return;\n }\n await putToServer(\"user\", anon.blob, 0);\n await refreshFromServer();\n await storage.remove(anonKey);\n },\n async flush() {\n await flushPending();\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n if (saveTimer) clearTimeout(saveTimer);\n if (bcast) bcast.close();\n listeners.clear();\n }\n };\n return client;\n}\nexport {\n ANON_USER_ID,\n CACHE_KEY_PREFIX,\n DEVICE_ID_KEY,\n PREFS_API_BASE,\n SAVE_DEBOUNCE_MS,\n capacitorStorage,\n createPrefsClient,\n detectStorage,\n getDeviceId,\n localStorageAdapter,\n memoryStorage,\n sessionStorageWrite,\n whoami\n};\n","import { useEffect, useState } from 'react'\nimport { whoami } from '@wolffm/prefs-client'\nimport { logger } from '@wolffm/logger/client'\n\n// Ecosystem auth, matching the command station (hadoku_site ContactAdmin):\n// resolve the caller's tier via edge-router's /session/whoami, and on anything\n// short of admin bounce to the shared /auth sign-in page rather than showing a\n// custom \"enter a key\" dead-end. /auth accepts a valid key (POST /session/create)\n// and redirects back to `return`. No app-specific key handling lives here.\n\n/** Send the browser to the ecosystem sign-in page, returning here afterwards. */\nexport function redirectToAuth(): void {\n if (typeof window === 'undefined') return\n const ret = encodeURIComponent(window.location.pathname + window.location.search)\n window.location.replace(`/auth?return=${ret}`)\n}\n\nexport type AuthStatus = 'checking' | 'authorized' | 'redirecting'\n\nexport interface BuilderAuth {\n status: AuthStatus\n /** Display name from the key registry once authorized (null if unnamed). */\n name: string | null\n}\n\nexport function useBuilderAuth(): BuilderAuth {\n const [status, setStatus] = useState<AuthStatus>('checking')\n const [name, setName] = useState<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n whoami()\n .then(who => {\n if (cancelled) return\n if (who.userType === 'admin') {\n setName(who.name ?? null)\n setStatus('authorized')\n return\n }\n logger.info('[builder] not admin, redirecting to sign in', { userType: who.userType })\n setStatus('redirecting')\n redirectToAuth()\n })\n .catch((err: unknown) => {\n // whoami() itself never rejects (it degrades to public), but stay\n // defensive: any failure means \"not signed in\" → sign-in page.\n if (cancelled) return\n logger.error('[builder] whoami failed', {\n error: err instanceof Error ? err.message : String(err)\n })\n setStatus('redirecting')\n redirectToAuth()\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n return { status, name }\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport { logger } from '@wolffm/logger/client'\nimport {\n fetchBlocks,\n saveBlock,\n deleteBlock as apiDeleteBlock,\n saveFeedback,\n BuilderApiError,\n type ResumeBlock,\n type BlockType,\n type Feedback\n} from './api'\nimport { BlockCard } from './BlockCard'\nimport { useBuilderAuth, redirectToAuth } from './useBuilderAuth'\n\nconst BLOCK_TYPES: BlockType[] = [\n 'experience',\n 'project',\n 'skills',\n 'education',\n 'summary',\n 'header'\n]\n\nexport function facetOf(tag: string): 'tech' | 'layer' | 'story' | 'plain' {\n if (tag.startsWith('tech:')) return 'tech'\n if (tag.startsWith('layer:')) return 'layer'\n if (tag.startsWith('story:')) return 'story'\n return 'plain'\n}\n\ntype SortMode = 'order' | 'priority' | 'type' | 'feedback'\n\nfunction emptyBlock(): ResumeBlock {\n return { id: '', type: 'experience', tags: [], title: '', content: '', priority: 5 }\n}\n\nexport function BuilderApp() {\n const { status: authStatus, name: adminName } = useBuilderAuth()\n const [blocks, setBlocks] = useState<ResumeBlock[]>([])\n const [feedback, setFeedback] = useState<Feedback>({})\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n // Filters\n const [search, setSearch] = useState('')\n const [typeFilter, setTypeFilter] = useState<'' | BlockType>('')\n const [activeTags, setActiveTags] = useState<Set<string>>(new Set())\n const [andMode, setAndMode] = useState(true)\n const [sort, setSort] = useState<SortMode>('order')\n\n const [creating, setCreating] = useState<ResumeBlock | null>(null)\n\n useEffect(() => {\n if (authStatus !== 'authorized') return\n let cancelled = false\n fetchBlocks()\n .then(res => {\n if (cancelled) return\n setBlocks(res.blocks)\n setFeedback(res.feedback)\n })\n .catch((err: unknown) => {\n if (cancelled) return\n // Session lapsed between the whoami check and this call → bounce to\n // sign-in, same as the initial gate. Everything else is a real error.\n if (err instanceof BuilderApiError && (err.status === 401 || err.status === 403)) {\n redirectToAuth()\n return\n }\n const msg = err instanceof Error ? err.message : 'Failed to load blocks'\n setError(msg)\n logger.error('[builder] load failed', { error: msg })\n })\n .finally(() => {\n if (!cancelled) setLoading(false)\n })\n return () => {\n cancelled = true\n }\n }, [authStatus])\n\n const tagCounts = useMemo(() => {\n const counts = new Map<string, number>()\n for (const b of blocks) for (const t of b.tags) counts.set(t, (counts.get(t) ?? 0) + 1)\n return counts\n }, [blocks])\n\n const sortedTags = useMemo(\n () =>\n [...tagCounts.keys()].sort(\n (a, b) => facetOf(a).localeCompare(facetOf(b)) || a.localeCompare(b)\n ),\n [tagCounts]\n )\n\n const visible = useMemo(() => {\n const q = search.trim().toLowerCase()\n let v = blocks.filter(b => {\n if (typeFilter && b.type !== typeFilter) return false\n if (q && !(b.id + b.title + b.content).toLowerCase().includes(q)) return false\n if (activeTags.size) {\n const hits = [...activeTags].filter(t => b.tags.includes(t)).length\n if (andMode ? hits !== activeTags.size : hits === 0) return false\n }\n return true\n })\n if (sort === 'priority') v = [...v].sort((a, b) => b.priority - a.priority)\n else if (sort === 'type') v = [...v].sort((a, b) => a.type.localeCompare(b.type))\n else if (sort === 'feedback')\n v = [...v].sort((a, b) => (feedback[b.id] ? 1 : 0) - (feedback[a.id] ? 1 : 0))\n return v\n }, [blocks, search, typeFilter, activeTags, andMode, sort, feedback])\n\n function toggleTag(tag: string) {\n setActiveTags(prev => {\n const next = new Set(prev)\n if (next.has(tag)) next.delete(tag)\n else next.add(tag)\n return next\n })\n }\n\n async function handleSave(block: ResumeBlock, isNew: boolean): Promise<void> {\n const { block: saved } = await saveBlock(block)\n setBlocks(prev => {\n const idx = prev.findIndex(b => b.id === saved.id)\n if (idx === -1) return [...prev, saved]\n const copy = [...prev]\n copy[idx] = saved\n return copy\n })\n if (isNew) setCreating(null)\n }\n\n async function handleDelete(id: string): Promise<void> {\n await apiDeleteBlock(id)\n setBlocks(prev => prev.filter(b => b.id !== id))\n }\n\n async function handleFeedback(id: string, text: string): Promise<void> {\n const res = await saveFeedback(id, text)\n setFeedback(res.feedback)\n }\n\n function exportJson() {\n const blob = new Blob([JSON.stringify(blocks, null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'blocks.json'\n a.click()\n URL.revokeObjectURL(url)\n }\n\n if (authStatus === 'checking') return <p className=\"rb-builder__status\">Checking access…</p>\n if (authStatus === 'redirecting')\n return <p className=\"rb-builder__status\">Redirecting to sign in…</p>\n if (loading) return <p className=\"rb-builder__status\">Loading blocks…</p>\n if (error) return <p className=\"rb-builder__status rb-builder__status--error\">{error}</p>\n\n return (\n <div className=\"rb-builder\">\n <div className=\"rb-builder__toolbar\">\n <header className=\"rb-builder__header\">\n <h1>Resume Builder</h1>\n <div className=\"rb-builder__count\">\n {visible.length} / {blocks.length} blocks\n </div>\n {adminName && (\n <div className=\"rb-builder__whoami\">\n Signed in as <span className=\"rb-builder__whoami-name\">{adminName}</span>\n </div>\n )}\n <div className=\"rb-builder__header-actions\">\n <button type=\"button\" onClick={exportJson} className=\"rb-builder__btn\">\n Export blocks.json\n </button>\n <button\n type=\"button\"\n onClick={() => setCreating(emptyBlock())}\n className=\"rb-builder__btn rb-builder__btn--primary\"\n disabled={creating !== null}\n >\n + New block\n </button>\n </div>\n </header>\n\n <div className=\"rb-builder__controls\">\n <input\n type=\"search\"\n placeholder=\"Search id, title, content…\"\n value={search}\n onChange={e => setSearch(e.target.value)}\n className=\"rb-builder__search\"\n />\n <select\n value={typeFilter}\n onChange={e => setTypeFilter(e.target.value as '' | BlockType)}\n className=\"rb-builder__select\"\n >\n <option value=\"\">all types</option>\n {BLOCK_TYPES.map(t => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <select\n value={sort}\n onChange={e => setSort(e.target.value as SortMode)}\n className=\"rb-builder__select\"\n >\n <option value=\"order\">render order</option>\n <option value=\"priority\">priority ↓</option>\n <option value=\"type\">type</option>\n <option value=\"feedback\">has feedback</option>\n </select>\n <label className=\"rb-builder__andmode\">\n <input type=\"checkbox\" checked={andMode} onChange={e => setAndMode(e.target.checked)} />\n match all tags\n </label>\n </div>\n\n <div className=\"rb-builder__legend\">\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--tech\" />\n tech:\n </span>\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--layer\" />\n layer:\n </span>\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--story\" />\n story:\n </span>\n <span className=\"rb-builder__legend-item\">\n <span className=\"rb-builder__legend-dot rb-builder__legend-dot--plain\" />\n other / always\n </span>\n <span className=\"rb-builder__legend-item\">\n <strong>prio</strong> = how strongly you want a block (sort/rank hint)\n </span>\n </div>\n\n <div className=\"rb-builder__tagbar\">\n {sortedTags.map(t => (\n <button\n type=\"button\"\n key={t}\n onClick={() => toggleTag(t)}\n className={`rb-tag rb-tag--${facetOf(t)}${activeTags.has(t) ? ' rb-tag--active' : ''}`}\n >\n {t}\n <span className=\"rb-tag__n\">{tagCounts.get(t)}</span>\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"rb-builder__list\">\n {creating && (\n <BlockCard\n key=\"__new__\"\n block={creating}\n feedback={undefined}\n isNew\n existingIds={blocks.map(b => b.id)}\n onSave={b => handleSave(b, true)}\n onCancel={() => setCreating(null)}\n onFeedback={handleFeedback}\n onTagClick={toggleTag}\n />\n )}\n {visible.map(b => (\n <BlockCard\n key={b.id}\n block={b}\n feedback={feedback[b.id]}\n existingIds={blocks.map(x => x.id)}\n onSave={block => handleSave(block, false)}\n onDelete={() => handleDelete(b.id)}\n onFeedback={handleFeedback}\n onTagClick={toggleTag}\n />\n ))}\n </div>\n </div>\n )\n}\n","import { createRoot, type Root } from 'react-dom/client'\nimport { logger } from '@wolffm/logger/client'\nimport { BuilderApp } from './BuilderApp'\nimport { setBuilderApiBaseUrl } from './api'\n// CSS is inlined into the bundle (not emitted as a separate asset) so builder.js\n// is fully self-contained — it can be served from /mf/resume/builder.js and\n// mounted by a bare page with no <link> wiring. Theme tokens come from the host\n// page; builder.css references them with fallbacks so it degrades standalone.\nimport builderCss from './builder.css?inline'\n\nfunction injectStyles() {\n if (document.getElementById('rb-builder-styles')) return\n const style = document.createElement('style')\n style.id = 'rb-builder-styles'\n style.textContent = builderCss\n document.head.appendChild(style)\n}\n\nexport interface ResumeBuilderProps {\n theme?: string\n /** API root, e.g. '/resume/api' — the builder calls ${apiBaseUrl}/builder/*. */\n apiBaseUrl: string\n}\n\ninterface BuilderElement extends HTMLElement {\n __root?: Root\n}\n\nexport function mount(el: HTMLElement, props: ResumeBuilderProps) {\n injectStyles()\n setBuilderApiBaseUrl(props.apiBaseUrl)\n const root = createRoot(el)\n root.render(<BuilderApp />)\n ;(el as BuilderElement).__root = root\n logger.info('[resume-builder] Mounted', { apiBaseUrl: props.apiBaseUrl })\n}\n\nexport function unmount(el: HTMLElement) {\n ;(el as BuilderElement).__root?.unmount()\n logger.info('[resume-builder] Unmounted')\n}\n"],"names":["BuilderApiError","message","status","baseUrl","setBuilderApiBaseUrl","url","req","path","init","res","detail","body","fetchBlocks","saveBlock","block","deleteBlock","id","saveFeedback","text","BLOCK_TYPES","BlockCard","feedback","existingIds","isNew","onSave","onDelete","onCancel","onFeedback","onTagClick","draft","setDraft","useState","tagsText","setTagsText","saving","setSaving","saveError","setSaveError","fbText","setFbText","fbStatus","setFbStatus","fbTimer","useRef","useEffect","dirty","parseTags","idInvalid","handleSave","err","handleDelete","onFbChange","jsxs","jsx","e","t","facetOf","PREFS_API_BASE","ANON_USER_ID","WHOAMI_GLOBAL","SESSION_SCOPE_PREFIX","UNSCOPED_ID","adaptWhoami","userType","name","fetchWhoamiRaw","userKey","headers","resp","defaultWhoamiUrl","loc","whoami","opts","g","shared","redirectToAuth","ret","useBuilderAuth","setStatus","setName","cancelled","who","logger","tag","emptyBlock","BuilderApp","authStatus","adminName","blocks","setBlocks","setFeedback","loading","setLoading","error","setError","search","setSearch","typeFilter","setTypeFilter","activeTags","setActiveTags","andMode","setAndMode","sort","setSort","creating","setCreating","msg","tagCounts","useMemo","counts","b","sortedTags","a","visible","q","v","hits","toggleTag","prev","next","saved","idx","copy","apiDeleteBlock","handleFeedback","exportJson","blob","x","injectStyles","style","builderCss","mount","el","props","root","createRoot","unmount"],"mappings":";;;;AAqBO,MAAMA,UAAwB,MAAM;AAAA,EACzC,YACEC,GACSC,GACT;AACA,UAAMD,CAAO,GAFJ,KAAA,SAAAC,GAGT,KAAK,OAAO;AAAA,EACd;AACF;AAGA,IAAIC,IAAU;AACP,SAASC,GAAqBC,GAAmB;AACtD,EAAAF,IAAUE,EAAI,QAAQ,QAAQ,EAAE;AAClC;AAEA,eAAeC,EAAOC,GAAcC,GAAgC;AAClE,QAAMC,IAAM,MAAM,MAAM,GAAGN,CAAO,WAAWI,CAAI,IAAI;AAAA,IACnD,GAAGC;AAAA,IACH,aAAa;AAAA,IACb,SAAS,EAAE,gBAAgB,oBAAoB,GAAIA,GAAM,WAAW,CAAA,EAAC;AAAA,EAAG,CACzE;AACD,MAAI,CAACC,EAAI,IAAI;AACX,QAAIC,IAAS,GAAGD,EAAI,MAAM;AAC1B,QAAI;AACF,YAAME,IAAQ,MAAMF,EAAI,KAAA;AACxB,MAAAC,IAASC,EAAK,UAAU,GAAGA,EAAK,KAAK,KAAKA,EAAK,OAAO,KAAMA,EAAK,SAASD;AAAA,IAC5E,QAAQ;AAAA,IAER;AACA,UAAM,IAAIV,EAAgBU,GAAQD,EAAI,MAAM;AAAA,EAC9C;AACA,SAAQ,MAAMA,EAAI,KAAA;AACpB;AAEO,SAASG,KAAsE;AACpF,SAAON,EAAI,SAAS;AACtB;AAEO,SAASO,GAAUC,GAAqD;AAC7E,SAAOR,EAAI,WAAW,mBAAmBQ,EAAM,EAAE,CAAC,IAAI;AAAA,IACpD,QAAQ;AAAA,IACR,MAAM,KAAK,UAAUA,CAAK;AAAA,EAAA,CAC3B;AACH;AAEO,SAASC,GAAYC,GAAoD;AAC9E,SAAOV,EAAI,WAAW,mBAAmBU,CAAE,CAAC,IAAI,EAAE,QAAQ,UAAU;AACtE;AAMO,SAASC,GAAaD,GAAYE,GAA+C;AACtF,SAAOZ,EAAI,aAAa,mBAAmBU,CAAE,CAAC,IAAI;AAAA,IAChD,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,MAAAE,GAAM;AAAA,EAAA,CAC9B;AACH;AC5EA,MAAMC,KAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAcO,SAASC,EAAU;AAAA,EACxB,OAAAN;AAAA,EACA,UAAAO;AAAA,EACA,aAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,YAAAC;AACF,GAAU;AACR,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAsBjB,CAAK,GAC/C,CAACkB,GAAUC,CAAW,IAAIF,EAASjB,EAAM,KAAK,KAAK,GAAG,CAAC,GACvD,CAACoB,GAAQC,CAAS,IAAIJ,EAAS,EAAK,GACpC,CAACK,GAAWC,CAAY,IAAIN,EAAwB,IAAI,GACxD,CAACO,GAAQC,CAAS,IAAIR,EAASV,GAAU,QAAQ,EAAE,GACnD,CAACmB,GAAUC,CAAW,IAAIV,EAAS,EAAE,GACrCW,IAAUC,GAAkD,MAAS;AAI3E,EAAAC,EAAU,MAAM;AACd,IAAKrB,MACHO,EAAShB,CAAK,GACdmB,EAAYnB,EAAM,KAAK,KAAK,GAAG,CAAC;AAAA,EAEpC,GAAG,CAACA,GAAOS,CAAK,CAAC;AAEjB,QAAMsB,IACJtB,KAAS,KAAK,UAAU,EAAE,GAAGM,GAAO,MAAMiB,EAAUd,CAAQ,EAAA,CAAG,MAAM,KAAK,UAAUlB,CAAK;AAE3F,WAASgC,EAAU5B,GAAwB;AACzC,WAAO,CAAC,GAAG,IAAI,IAAIA,EAAK,MAAM,QAAQ,EAAE,OAAO,OAAO,CAAC,CAAC;AAAA,EAC1D;AAEA,QAAM6B,IACJxB,MAAU,CAAC,uBAAuB,KAAKM,EAAM,EAAE,KAAKP,EAAY,SAASO,EAAM,EAAE;AAEnF,iBAAemB,IAAa;AAC1B,IAAAb,EAAU,EAAI,GACdE,EAAa,IAAI;AACjB,QAAI;AACF,YAAMb,EAAO,EAAE,GAAGK,GAAO,MAAMiB,EAAUd,CAAQ,GAAG;AAAA,IACtD,SAASiB,GAAK;AACZ,MAAAZ,EAAaY,aAAe,QAAQA,EAAI,UAAU,aAAa;AAAA,IACjE,UAAA;AACE,MAAAd,EAAU,EAAK;AAAA,IACjB;AAAA,EACF;AAEA,iBAAee,IAAe;AAC5B,QAAKzB,KACA,QAAQ,iBAAiBX,EAAM,EAAE,0CAA0C,GAChF;AAAA,MAAAqB,EAAU,EAAI;AACd,UAAI;AACF,cAAMV,EAAA;AAAA,MACR,SAASwB,GAAK;AACZ,QAAAZ,EAAaY,aAAe,QAAQA,EAAI,UAAU,eAAe,GACjEd,EAAU,EAAK;AAAA,MACjB;AAAA;AAAA,EACF;AAEA,WAASgB,EAAWjC,GAAc;AAChC,IAAAqB,EAAUrB,CAAI,GACduB,EAAY,SAAS,GACrB,aAAaC,EAAQ,OAAO,GAC5BA,EAAQ,UAAU,WAAW,MAAM;AACjC,MAAAf,EAAWb,EAAM,IAAII,CAAI,EACtB,KAAK,MAAMuB,EAAYvB,EAAK,KAAA,IAAS,YAAY,EAAE,CAAC,EACpD,MAAM,MAAMuB,EAAY,aAAa,CAAC;AAAA,IAC3C,GAAG,GAAG;AAAA,EACR;AAEA,SACE,gBAAAW;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,WAAW/B,IAAW,4BAA4B,EAAE,GAAGwB,IAAQ,qBAAqB,EAAE;AAAA,MAEjG,UAAA;AAAA,QAAA,gBAAAO,EAAC,OAAA,EAAI,WAAU,iBACZ,UAAA;AAAA,UAAA7B,IACC,gBAAA8B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,aAAY;AAAA,cACZ,OAAOxB,EAAM;AAAA,cACb,UAAU,CAAAyB,MAAKxB,EAAS,EAAE,GAAGD,GAAO,IAAIyB,EAAE,OAAO,MAAA,CAAO;AAAA,YAAA;AAAA,UAAA,IAG1D,gBAAAD,EAAC,QAAA,EAAK,WAAU,gBAAgB,YAAM,IAAG;AAAA,UAE3C,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAOxB,EAAM;AAAA,cACb,UAAU,CAAAyB,MAAKxB,EAAS,EAAE,GAAGD,GAAO,MAAMyB,EAAE,OAAO,OAAoB;AAAA,cAEtE,UAAAnC,GAAY,IAAI,CAAAoC,MACf,gBAAAF,EAAC,YAAe,OAAOE,GACpB,UAAAA,EAAA,GADUA,CAEb,CACD;AAAA,YAAA;AAAA,UAAA;AAAA,UAEH,gBAAAH;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAM;AAAA,cACP,UAAA;AAAA,gBAAA;AAAA,gBAEC,gBAAAC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,KAAK;AAAA,oBACL,KAAK;AAAA,oBACL,OAAOxB,EAAM;AAAA,oBACb,UAAU,CAAAyB,MAAKxB,EAAS,EAAE,GAAGD,GAAO,UAAU,OAAOyB,EAAE,OAAO,KAAK,EAAA,CAAG;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACxE;AAAA,YAAA;AAAA,UAAA;AAAA,QACF,GACF;AAAA,QAEA,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,aAAY;AAAA,YACZ,OAAOxB,EAAM;AAAA,YACb,UAAU,CAAAyB,MAAKxB,EAAS,EAAE,GAAGD,GAAO,OAAOyB,EAAE,OAAO,MAAA,CAAO;AAAA,UAAA;AAAA,QAAA;AAAA,QAG7D,gBAAAD,EAAC,SAAI,WAAU,mBACZ,YAAUrB,CAAQ,EAAE,IAAI,CAAAuB,MACvB,gBAAAF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YAEL,WAAW,kBAAkBG,EAAQD,CAAC,CAAC;AAAA,YACvC,SAAS,MAAM3B,EAAW2B,CAAC;AAAA,YAC3B,OAAM;AAAA,YAEL,UAAAA;AAAA,UAAA;AAAA,UALIA;AAAA,QAAA,CAOR,GACH;AAAA,QACA,gBAAAF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,aAAY;AAAA,YACZ,OAAOrB;AAAA,YACP,UAAU,CAAAsB,MAAKrB,EAAYqB,EAAE,OAAO,KAAK;AAAA,UAAA;AAAA,QAAA;AAAA,QAG3C,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAM;AAAA,YACN,aAAY;AAAA,YACZ,OAAOxB,EAAM;AAAA,YACb,UAAU,CAAAyB,MAAKxB,EAAS,EAAE,GAAGD,GAAO,SAASyB,EAAE,OAAO,MAAA,CAAO;AAAA,UAAA;AAAA,QAAA;AAAA,QAG/D,gBAAAF,EAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,UAAA,gBAAAC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM;AACb,gBAAKL,EAAA;AAAA,cACP;AAAA,cACA,UAAUd,KAAU,CAACW,KAASE;AAAA,cAE7B,UAAAb,IAAS,YAAYX,IAAQ,WAAW;AAAA,YAAA;AAAA,UAAA;AAAA,UAE1CA,IACC,gBAAA8B,EAAC,UAAA,EAAO,MAAK,UAAS,WAAU,mBAAkB,SAAS3B,GAAU,UAAA,SAAA,CAErE,IAEA,gBAAA2B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,MAAM;AACb,gBAAKH,EAAA;AAAA,cACP;AAAA,cACA,UAAUhB;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAIFa,KAAa,gBAAAM,EAAC,QAAA,EAAK,WAAU,kBAAiB,UAAA,gCAA4B;AAAA,UAC1EjB,KAAa,gBAAAiB,EAAC,QAAA,EAAK,WAAU,wCAAwC,UAAAjB,EAAA,CAAU;AAAA,QAAA,GAClF;AAAA,QAEC,CAACb,KACA,gBAAA6B,EAAC,OAAA,EAAI,WAAU,sBACb,UAAA;AAAA,UAAA,gBAAAC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM;AAAA,cACN,aAAY;AAAA,cACZ,OAAOf;AAAA,cACP,UAAU,CAAAgB,MAAKH,EAAWG,EAAE,OAAO,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAE1C,gBAAAD,EAAC,QAAA,EAAK,WAAU,uBAAuB,UAAAb,EAAA,CAAS;AAAA,QAAA,EAAA,CAClD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;ACzNA,IAAIiB,KAAiB,2BA2GjBC,IAAe,QACfC,IAAgB,kBAChBC,KAAuB,SACvBC,KAAc;AAClB,SAASC,EAAYnD,GAAM;AACzB,MAAI,CAACA,KAAQA,EAAK,UAAU;AAC1B,WAAO,EAAE,QAAQ+C,GAAc,UAAU,UAAU,OAAO,OAAM;AAElE,QAAMK,IAAWpD,EAAK,aAAa,WAAWA,EAAK,aAAa,UAAUA,EAAK,aAAa,aAAaA,EAAK,aAAa,YAAYA,EAAK,aAAa,YAAYA,EAAK,aAAa,WAAWA,EAAK,WAAW,UAC5MqD,IAAO,OAAOrD,EAAK,QAAS,WAAWA,EAAK,OAAO;AACzD,SAAI,OAAOA,EAAK,UAAW,YAAYA,EAAK,SACnC,EAAE,QAAQA,EAAK,QAAQ,UAAAoD,GAAU,MAAAC,GAAM,OAAO,OAAM,IAEzD,OAAOrD,EAAK,aAAc,YAAYA,EAAK,YACtC;AAAA,IACL,QAAQ,GAAGiD,EAAoB,GAAGjD,EAAK,SAAS;AAAA,IAChD,UAAAoD;AAAA,IACA,MAAAC;AAAA,IACA,OAAO;AAAA,EACb,IAES,EAAE,QAAQH,IAAa,UAAAE,GAAU,MAAAC,GAAM,OAAO,OAAM;AAC7D;AACA,eAAeC,EAAe5D,GAAK6D,GAAS;AAC1C,QAAMC,IAAU,CAAA;AAChB,EAAID,MACFC,EAAQ,YAAY,IAAID;AAE1B,MAAI;AACF,UAAME,IAAO,MAAM,MAAM/D,GAAK;AAAA,MAC5B,QAAQ;AAAA,MACR,SAAA8D;AAAA,MACA,aAAa;AAAA,MACb,OAAO;AAAA,IACb,CAAK;AACD,WAAKC,EAAK,KACH,MAAMA,EAAK,KAAI,IADD;AAAA,EAEvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AACA,SAASC,KAAmB;AAC1B,QAAMC,IAAM,WAAW;AACvB,SAAIA,MAAQA,EAAI,aAAa,WAAWA,EAAI,aAAa,YAAkB,oBACpE,GAAGb,GAAe,QAAQ,YAAY,EAAE,CAAC;AAClD;AACA,eAAec,GAAOC,IAAO,IAAI;AAC/B,QAAMnE,IAAMmE,EAAK,aAAaH,GAAgB;AAC9C,MAAIG,EAAK;AACP,WAAOV,EAAY,MAAMG,EAAe5D,GAAKmE,EAAK,OAAO,CAAC;AAE5D,QAAMC,IAAI;AACV,MAAIC,IAASD,EAAEd,CAAa;AAC5B,EAAKe,MACHA,IAAST,EAAe5D,CAAG,GAC3BoE,EAAEd,CAAa,IAAIe;AAErB,MAAI;AACF,WAAOZ,EAAY,MAAMY,CAAM;AAAA,EACjC,QAAQ;AACN,WAAO,EAAE,QAAQhB,GAAc,UAAU,UAAU,OAAO,OAAM;AAAA,EAClE;AACF;AC/JO,SAASiB,IAAuB;AACrC,MAAI,OAAO,SAAW,IAAa;AACnC,QAAMC,IAAM,mBAAmB,OAAO,SAAS,WAAW,OAAO,SAAS,MAAM;AAChF,SAAO,SAAS,QAAQ,gBAAgBA,CAAG,EAAE;AAC/C;AAUO,SAASC,KAA8B;AAC5C,QAAM,CAAC3E,GAAQ4E,CAAS,IAAI/C,EAAqB,UAAU,GACrD,CAACiC,GAAMe,CAAO,IAAIhD,EAAwB,IAAI;AAEpD,SAAAa,EAAU,MAAM;AACd,QAAIoC,IAAY;AAChB,WAAAT,GAAA,EACG,KAAK,CAAAU,MAAO;AACX,UAAI,CAAAD,GACJ;AAAA,YAAIC,EAAI,aAAa,SAAS;AAC5B,UAAAF,EAAQE,EAAI,QAAQ,IAAI,GACxBH,EAAU,YAAY;AACtB;AAAA,QACF;AACA,QAAAI,EAAO,KAAK,+CAA+C,EAAE,UAAUD,EAAI,UAAU,GACrFH,EAAU,aAAa,GACvBH,EAAA;AAAA;AAAA,IACF,CAAC,EACA,MAAM,CAAC1B,MAAiB;AAGvB,MAAI+B,MACJE,EAAO,MAAM,2BAA2B;AAAA,QACtC,OAAOjC,aAAe,QAAQA,EAAI,UAAU,OAAOA,CAAG;AAAA,MAAA,CACvD,GACD6B,EAAU,aAAa,GACvBH,EAAA;AAAA,IACF,CAAC,GACI,MAAM;AACX,MAAAK,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAA,CAAE,GAEE,EAAE,QAAA9E,GAAQ,MAAA8D,EAAA;AACnB;AC5CA,MAAM7C,KAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAASqC,EAAQ2B,GAAmD;AACzE,SAAIA,EAAI,WAAW,OAAO,IAAU,SAChCA,EAAI,WAAW,QAAQ,IAAU,UACjCA,EAAI,WAAW,QAAQ,IAAU,UAC9B;AACT;AAIA,SAASC,KAA0B;AACjC,SAAO,EAAE,IAAI,IAAI,MAAM,cAAc,MAAM,IAAI,OAAO,IAAI,SAAS,IAAI,UAAU,EAAA;AACnF;AAEO,SAASC,KAAa;AAC3B,QAAM,EAAE,QAAQC,GAAY,MAAMC,EAAA,IAAcV,GAAA,GAC1C,CAACW,GAAQC,CAAS,IAAI1D,EAAwB,CAAA,CAAE,GAChD,CAACV,GAAUqE,CAAW,IAAI3D,EAAmB,CAAA,CAAE,GAC/C,CAAC4D,GAASC,CAAU,IAAI7D,EAAS,EAAI,GACrC,CAAC8D,GAAOC,CAAQ,IAAI/D,EAAwB,IAAI,GAGhD,CAACgE,GAAQC,CAAS,IAAIjE,EAAS,EAAE,GACjC,CAACkE,GAAYC,CAAa,IAAInE,EAAyB,EAAE,GACzD,CAACoE,GAAYC,CAAa,IAAIrE,EAAsB,oBAAI,KAAK,GAC7D,CAACsE,GAASC,CAAU,IAAIvE,EAAS,EAAI,GACrC,CAACwE,GAAMC,CAAO,IAAIzE,EAAmB,OAAO,GAE5C,CAAC0E,GAAUC,CAAW,IAAI3E,EAA6B,IAAI;AAEjE,EAAAa,EAAU,MAAM;AACd,QAAI0C,MAAe,aAAc;AACjC,QAAIN,IAAY;AAChB,WAAApE,GAAA,EACG,KAAK,CAAAH,MAAO;AACX,MAAIuE,MACJS,EAAUhF,EAAI,MAAM,GACpBiF,EAAYjF,EAAI,QAAQ;AAAA,IAC1B,CAAC,EACA,MAAM,CAACwC,MAAiB;AACvB,UAAI+B,EAAW;AAGf,UAAI/B,aAAejD,MAAoBiD,EAAI,WAAW,OAAOA,EAAI,WAAW,MAAM;AAChF,QAAA0B,EAAA;AACA;AAAA,MACF;AACA,YAAMgC,IAAM1D,aAAe,QAAQA,EAAI,UAAU;AACjD,MAAA6C,EAASa,CAAG,GACZzB,EAAO,MAAM,yBAAyB,EAAE,OAAOyB,GAAK;AAAA,IACtD,CAAC,EACA,QAAQ,MAAM;AACb,MAAK3B,KAAWY,EAAW,EAAK;AAAA,IAClC,CAAC,GACI,MAAM;AACX,MAAAZ,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACM,CAAU,CAAC;AAEf,QAAMsB,IAAYC,EAAQ,MAAM;AAC9B,UAAMC,wBAAa,IAAA;AACnB,eAAWC,KAAKvB,EAAQ,YAAWjC,KAAKwD,EAAE,KAAM,CAAAD,EAAO,IAAIvD,IAAIuD,EAAO,IAAIvD,CAAC,KAAK,KAAK,CAAC;AACtF,WAAOuD;AAAA,EACT,GAAG,CAACtB,CAAM,CAAC,GAELwB,IAAaH;AAAA,IACjB,MACE,CAAC,GAAGD,EAAU,KAAA,CAAM,EAAE;AAAA,MACpB,CAACK,GAAGF,MAAMvD,EAAQyD,CAAC,EAAE,cAAczD,EAAQuD,CAAC,CAAC,KAAKE,EAAE,cAAcF,CAAC;AAAA,IAAA;AAAA,IAEvE,CAACH,CAAS;AAAA,EAAA,GAGNM,IAAUL,EAAQ,MAAM;AAC5B,UAAMM,IAAIpB,EAAO,KAAA,EAAO,YAAA;AACxB,QAAIqB,IAAI5B,EAAO,OAAO,CAAAuB,MAAK;AAEzB,UADId,KAAcc,EAAE,SAASd,KACzBkB,KAAK,EAAEJ,EAAE,KAAKA,EAAE,QAAQA,EAAE,SAAS,YAAA,EAAc,SAASI,CAAC,EAAG,QAAO;AACzE,UAAIhB,EAAW,MAAM;AACnB,cAAMkB,IAAO,CAAC,GAAGlB,CAAU,EAAE,OAAO,CAAA5C,MAAKwD,EAAE,KAAK,SAASxD,CAAC,CAAC,EAAE;AAC7D,YAAI8C,IAAUgB,MAASlB,EAAW,OAAOkB,MAAS,EAAG,QAAO;AAAA,MAC9D;AACA,aAAO;AAAA,IACT,CAAC;AACD,WAAId,MAAS,aAAYa,IAAI,CAAC,GAAGA,CAAC,EAAE,KAAK,CAACH,GAAGF,MAAMA,EAAE,WAAWE,EAAE,QAAQ,IACjEV,MAAS,SAAQa,IAAI,CAAC,GAAGA,CAAC,EAAE,KAAK,CAACH,GAAGF,MAAME,EAAE,KAAK,cAAcF,EAAE,IAAI,CAAC,IACvER,MAAS,eAChBa,IAAI,CAAC,GAAGA,CAAC,EAAE,KAAK,CAACH,GAAGF,OAAO1F,EAAS0F,EAAE,EAAE,IAAI,IAAI,MAAM1F,EAAS4F,EAAE,EAAE,IAAI,IAAI,EAAE,IACxEG;AAAA,EACT,GAAG,CAAC5B,GAAQO,GAAQE,GAAYE,GAAYE,GAASE,GAAMlF,CAAQ,CAAC;AAEpE,WAASiG,EAAUnC,GAAa;AAC9B,IAAAiB,EAAc,CAAAmB,MAAQ;AACpB,YAAMC,IAAO,IAAI,IAAID,CAAI;AACzB,aAAIC,EAAK,IAAIrC,CAAG,IAAGqC,EAAK,OAAOrC,CAAG,IAC7BqC,EAAK,IAAIrC,CAAG,GACVqC;AAAA,IACT,CAAC;AAAA,EACH;AAEA,iBAAexE,EAAWlC,GAAoBS,GAA+B;AAC3E,UAAM,EAAE,OAAOkG,EAAA,IAAU,MAAM5G,GAAUC,CAAK;AAC9C,IAAA2E,EAAU,CAAA8B,MAAQ;AAChB,YAAMG,IAAMH,EAAK,UAAU,OAAKR,EAAE,OAAOU,EAAM,EAAE;AACjD,UAAIC,MAAQ,GAAI,QAAO,CAAC,GAAGH,GAAME,CAAK;AACtC,YAAME,IAAO,CAAC,GAAGJ,CAAI;AACrB,aAAAI,EAAKD,CAAG,IAAID,GACLE;AAAA,IACT,CAAC,GACGpG,OAAmB,IAAI;AAAA,EAC7B;AAEA,iBAAe2B,EAAalC,GAA2B;AACrD,UAAM4G,GAAe5G,CAAE,GACvByE,EAAU,OAAQ8B,EAAK,OAAO,OAAKR,EAAE,OAAO/F,CAAE,CAAC;AAAA,EACjD;AAEA,iBAAe6G,EAAe7G,GAAYE,GAA6B;AACrE,UAAMT,IAAM,MAAMQ,GAAaD,GAAIE,CAAI;AACvC,IAAAwE,EAAYjF,EAAI,QAAQ;AAAA,EAC1B;AAEA,WAASqH,IAAa;AACpB,UAAMC,IAAO,IAAI,KAAK,CAAC,KAAK,UAAUvC,GAAQ,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,oBAAoB,GAC/EnF,IAAM,IAAI,gBAAgB0H,CAAI,GAC9Bd,IAAI,SAAS,cAAc,GAAG;AACpC,IAAAA,EAAE,OAAO5G,GACT4G,EAAE,WAAW,eACbA,EAAE,MAAA,GACF,IAAI,gBAAgB5G,CAAG;AAAA,EACzB;AAEA,SAAIiF,MAAe,+BAAoB,KAAA,EAAE,WAAU,sBAAqB,UAAA,oBAAgB,IACpFA,MAAe,gBACV,gBAAAjC,EAAC,KAAA,EAAE,WAAU,sBAAqB,UAAA,2BAAuB,IAC9DsC,IAAgB,gBAAAtC,EAAC,KAAA,EAAE,WAAU,sBAAqB,UAAA,mBAAe,IACjEwC,IAAc,gBAAAxC,EAAC,KAAA,EAAE,WAAU,gDAAgD,UAAAwC,GAAM,IAGnF,gBAAAzC,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,UAAA,EAAO,WAAU,sBAChB,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAG,UAAA,iBAAA,CAAc;AAAA,QAClB,gBAAAD,EAAC,OAAA,EAAI,WAAU,qBACZ,UAAA;AAAA,UAAA8D,EAAQ;AAAA,UAAO;AAAA,UAAI1B,EAAO;AAAA,UAAO;AAAA,QAAA,GACpC;AAAA,QACCD,KACC,gBAAAnC,EAAC,OAAA,EAAI,WAAU,sBAAqB,UAAA;AAAA,UAAA;AAAA,UACrB,gBAAAC,EAAC,QAAA,EAAK,WAAU,2BAA2B,UAAAkC,EAAA,CAAU;AAAA,QAAA,GACpE;AAAA,QAEF,gBAAAnC,EAAC,OAAA,EAAI,WAAU,8BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,YAAO,MAAK,UAAS,SAASyE,GAAY,WAAU,mBAAkB,UAAA,qBAAA,CAEvE;AAAA,UACA,gBAAAzE;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAMqD,EAAYtB,IAAY;AAAA,cACvC,WAAU;AAAA,cACV,UAAUqB,MAAa;AAAA,cACxB,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MAEA,gBAAArD,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,QAAA,gBAAAC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,aAAY;AAAA,YACZ,OAAO0C;AAAA,YACP,UAAU,CAAAzC,MAAK0C,EAAU1C,EAAE,OAAO,KAAK;AAAA,YACvC,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEZ,gBAAAF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO6C;AAAA,YACP,UAAU,CAAA3C,MAAK4C,EAAc5C,EAAE,OAAO,KAAuB;AAAA,YAC7D,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAD,EAAC,UAAA,EAAO,OAAM,IAAG,UAAA,aAAS;AAAA,cACzBlC,GAAY,IAAI,CAAAoC,MACf,gBAAAF,EAAC,YAAe,OAAOE,GACpB,UAAAA,EAAA,GADUA,CAEb,CACD;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEH,gBAAAH;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAOmD;AAAA,YACP,UAAU,CAAAjD,MAAKkD,EAAQlD,EAAE,OAAO,KAAiB;AAAA,YACjD,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAD,EAAC,UAAA,EAAO,OAAM,SAAQ,UAAA,gBAAY;AAAA,cAClC,gBAAAA,EAAC,UAAA,EAAO,OAAM,YAAW,UAAA,cAAU;AAAA,cACnC,gBAAAA,EAAC,UAAA,EAAO,OAAM,QAAO,UAAA,QAAI;AAAA,cACzB,gBAAAA,EAAC,UAAA,EAAO,OAAM,YAAW,UAAA,eAAA,CAAY;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEvC,gBAAAD,EAAC,SAAA,EAAM,WAAU,uBACf,UAAA;AAAA,UAAA,gBAAAC,EAAC,SAAA,EAAM,MAAK,YAAW,SAASgD,GAAS,UAAU,CAAA/C,MAAKgD,EAAWhD,EAAE,OAAO,OAAO,EAAA,CAAG;AAAA,UAAE;AAAA,QAAA,EAAA,CAE1F;AAAA,MAAA,GACF;AAAA,MAEA,gBAAAF,EAAC,OAAA,EAAI,WAAU,sBACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,sDAAA,CAAsD;AAAA,UAAE;AAAA,QAAA,GAE1E;AAAA,QACA,gBAAAD,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,uDAAA,CAAuD;AAAA,UAAE;AAAA,QAAA,GAE3E;AAAA,QACA,gBAAAD,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,uDAAA,CAAuD;AAAA,UAAE;AAAA,QAAA,GAE3E;AAAA,QACA,gBAAAD,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,uDAAA,CAAuD;AAAA,UAAE;AAAA,QAAA,GAE3E;AAAA,QACA,gBAAAD,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAC,EAAC,YAAO,UAAA,OAAA,CAAI;AAAA,UAAS;AAAA,QAAA,EAAA,CACvB;AAAA,MAAA,GACF;AAAA,wBAEC,OAAA,EAAI,WAAU,sBACZ,UAAA2D,EAAW,IAAI,CAAAzD,MACd,gBAAAH;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UAEL,SAAS,MAAMkE,EAAU/D,CAAC;AAAA,UAC1B,WAAW,kBAAkBC,EAAQD,CAAC,CAAC,GAAG4C,EAAW,IAAI5C,CAAC,IAAI,oBAAoB,EAAE;AAAA,UAEnF,UAAA;AAAA,YAAAA;AAAA,8BACA,QAAA,EAAK,WAAU,aAAa,UAAAqD,EAAU,IAAIrD,CAAC,EAAA,CAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QALzCA;AAAA,MAAA,CAOR,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAEA,gBAAAH,EAAC,OAAA,EAAI,WAAU,oBACZ,UAAA;AAAA,MAAAqD,KACC,gBAAApD;AAAA,QAACjC;AAAA,QAAA;AAAA,UAEC,OAAOqF;AAAA,UACP,UAAU;AAAA,UACV,OAAK;AAAA,UACL,aAAajB,EAAO,IAAI,CAAAuB,MAAKA,EAAE,EAAE;AAAA,UACjC,QAAQ,CAAAA,MAAK/D,EAAW+D,GAAG,EAAI;AAAA,UAC/B,UAAU,MAAML,EAAY,IAAI;AAAA,UAChC,YAAYmB;AAAA,UACZ,YAAYP;AAAA,QAAA;AAAA,QARR;AAAA,MAAA;AAAA,MAWPJ,EAAQ,IAAI,CAAAH,MACX,gBAAA1D;AAAA,QAACjC;AAAA,QAAA;AAAA,UAEC,OAAO2F;AAAA,UACP,UAAU1F,EAAS0F,EAAE,EAAE;AAAA,UACvB,aAAavB,EAAO,IAAI,CAAAwC,MAAKA,EAAE,EAAE;AAAA,UACjC,QAAQ,CAAAlH,MAASkC,EAAWlC,GAAO,EAAK;AAAA,UACxC,UAAU,MAAMoC,EAAa6D,EAAE,EAAE;AAAA,UACjC,YAAYc;AAAA,UACZ,YAAYP;AAAA,QAAA;AAAA,QAPPP,EAAE;AAAA,MAAA,CASV;AAAA,IAAA,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;;ACzRA,SAASkB,KAAe;AACtB,MAAI,SAAS,eAAe,mBAAmB,EAAG;AAClD,QAAMC,IAAQ,SAAS,cAAc,OAAO;AAC5C,EAAAA,EAAM,KAAK,qBACXA,EAAM,cAAcC,IACpB,SAAS,KAAK,YAAYD,CAAK;AACjC;AAYO,SAASE,GAAMC,GAAiBC,GAA2B;AAChE,EAAAL,GAAA,GACA7H,GAAqBkI,EAAM,UAAU;AACrC,QAAMC,IAAOC,EAAWH,CAAE;AAC1B,EAAAE,EAAK,OAAO,gBAAAlF,EAACgC,IAAA,CAAA,CAAW,CAAE,GACxBgD,EAAsB,SAASE,GACjCrD,EAAO,KAAK,4BAA4B,EAAE,YAAYoD,EAAM,YAAY;AAC1E;AAEO,SAASG,GAAQJ,GAAiB;AACrC,EAAAA,EAAsB,QAAQ,QAAA,GAChCnD,EAAO,KAAK,4BAA4B;AAC1C;","x_google_ignoreList":[2]}
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@property --advanced-gradient{syntax: "*"; inherits: false;}:root,[data-theme=light]{color-scheme:light;--color-primary: #2563eb;--color-primary-dark: #1d4ed8;--color-primary-bg: #eff6ff;--color-primary-hover: rgba(37, 99, 235, .06);--color-on-primary: white;--color-on-primary-bg: #2563eb;--color-success: #0ea5e9;--color-success-dark: #0284c7;--color-success-bg: rgba(14, 165, 233, .1);--color-success-hover: rgba(14, 165, 233, .06);--color-on-success: black;--color-on-success-bg: #0067a7;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-hover: rgba(245, 158, 11, .06);--color-on-warning: black;--color-on-warning-bg: #9e4d00;--color-danger: #f97316;--color-danger-dark: #ea580c;--color-danger-bg: #ffedd5;--color-danger-hover: rgba(249, 115, 22, .06);--color-on-danger: black;--color-on-danger-bg: #c13e00;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #e2e8f0;--color-neutral-hover: rgba(100, 116, 139, .06);--color-on-neutral: white;--color-on-neutral-bg: #58677d;--color-text: #0f172a;--color-text-secondary: #475569;--color-text-tertiary: #64748b;--color-text-muted: #94a3b8;--color-border: #cdd4db;--color-border-light: #dfe5ed;--color-bg: #e7eef5;--color-bg-card: #ffffff;--color-bg-alt: #e7eef5;--color-bg-hover: #e2e9f0;--color-bg-overlay: rgba(15, 23, 42, .5);--hdk-space-xs: 2px;--hdk-space-sm: 4px;--hdk-space-md: 8px;--hdk-space-lg: 12px;--hdk-space-xl: 16px;--hdk-space-2xl: 20px;--hdk-space-3xl: 24px;--hdk-space-4xl: 40px;--hdk-space-5xl: 60px;--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--hdk-text-xs: 12px;--hdk-text-sm: 14px;--hdk-text-md: 15px;--hdk-text-base: 16px;--hdk-text-lg: 24px;--font-weight-normal: 400;--font-weight-semibold: 500;--font-weight-bold: 600;--line-height-normal: 1.4;--line-height-relaxed: 1.5;--hdk-radius-sm: 4px;--hdk-radius: 6px;--hdk-radius-lg: 8px;--hdk-shadow-sm: 0 1px 2px rgba(15, 23, 42, .04);--hdk-shadow-md: 0 2px 4px rgba(15, 23, 42, .08);--hdk-shadow-lg: 0 4px 12px rgba(15, 23, 42, .15);--hdk-shadow-focus: 0 0 0 3px rgba(37, 99, 235, .2);--hdk-shadow-focus-sm: 0 0 0 2px rgba(37, 99, 235, .2);--hdk-shadow-focus-alt: 0 0 0 2px rgba(37, 99, 235, .1);--transition-fast: .15s ease;--transition-smooth: .2s ease}[data-theme=light]{--advanced-stop-1-l: .82;--advanced-stop-1-c: .18;--advanced-stop-1-h: 55;--advanced-stop-2-l: .78;--advanced-stop-2-c: .2;--advanced-stop-2-h: 40;--advanced-stop-3-l: .72;--advanced-stop-3-c: .22;--advanced-stop-3-h: 25;--advanced-stop-4-l: .7;--advanced-stop-4-c: .18;--advanced-stop-4-h: 10;--advanced-stop-5-l: .72;--advanced-stop-5-c: .16;--advanced-stop-5-h: 355;--advanced-stop-6-l: .68;--advanced-stop-6-c: .14;--advanced-stop-6-h: 190;--advanced-stop-7-l: .6;--advanced-stop-7-c: .16;--advanced-stop-7-h: 200;--advanced-stop-8-l: .5;--advanced-stop-8-c: .18;--advanced-stop-8-h: 210;--advanced-gradient: linear-gradient( 135deg, oklch(var(--advanced-stop-1-l) var(--advanced-stop-1-c) var(--advanced-stop-1-h)) 0%, oklch(var(--advanced-stop-2-l) var(--advanced-stop-2-c) var(--advanced-stop-2-h)) 15%, oklch(var(--advanced-stop-3-l) var(--advanced-stop-3-c) var(--advanced-stop-3-h)) 30%, oklch(var(--advanced-stop-4-l) var(--advanced-stop-4-c) var(--advanced-stop-4-h)) 45%, oklch(var(--advanced-stop-5-l) var(--advanced-stop-5-c) var(--advanced-stop-5-h)) 55%, oklch(var(--advanced-stop-6-l) var(--advanced-stop-6-c) var(--advanced-stop-6-h)) 70%, oklch(var(--advanced-stop-7-l) var(--advanced-stop-7-c) var(--advanced-stop-7-h)) 85%, oklch(var(--advanced-stop-8-l) var(--advanced-stop-8-c) var(--advanced-stop-8-h)) 100% )}[data-theme=dark]{color-scheme:dark only;--color-primary: #b793ff;--color-primary-dark: #a17de7;--color-primary-bg: rgba(183, 147, 255, .16);--color-primary-hover: rgba(183, 147, 255, .12);--color-on-primary: black;--color-on-primary-bg: #b793ff;--color-success: #fcde3d;--color-success-dark: #e5c70e;--color-success-bg: rgba(252, 222, 61, .15);--color-success-hover: rgba(252, 222, 61, .1);--color-on-success: black;--color-on-success-bg: #fcde3d;--color-warning: #ffb848;--color-warning-dark: #e7a22b;--color-warning-bg: rgba(255, 184, 72, .15);--color-warning-hover: rgba(255, 184, 72, .1);--color-on-warning: black;--color-on-warning-bg: #ffb848;--color-danger: #f46a82;--color-danger-dark: #db536d;--color-danger-bg: rgba(244, 106, 130, .15);--color-danger-hover: rgba(244, 106, 130, .1);--color-on-danger: black;--color-on-danger-bg: #fb7088;--color-neutral: #9d9ea6;--color-neutral-dark: #888991;--color-neutral-bg: #2f3038;--color-neutral-hover: rgba(157, 158, 166, .1);--color-on-neutral: black;--color-on-neutral-bg: #9d9ea6;--color-text: #f4f2f9;--color-text-secondary: #dcd9e3;--color-text-tertiary: #c0bbcb;--color-text-muted: #948f9e;--color-border: #3c3d40;--color-border-light: #525256;--color-bg: #151618;--color-bg-card: #222325;--color-bg-alt: #101013;--color-bg-hover: #2c2c30;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(183, 147, 255, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(183, 147, 255, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(183, 147, 255, .2)}[data-theme=strawberry-light]{color-scheme:light;--color-primary: #ff6b9d;--color-primary-dark: #ff477a;--color-primary-bg: #fff5f8;--color-primary-hover: rgba(255, 107, 157, .1);--color-on-primary: black;--color-on-primary-bg: #c6356d;--color-success: #22c55e;--color-success-dark: #16a34a;--color-success-bg: rgba(34, 197, 94, .1);--color-success-hover: rgba(34, 197, 94, .06);--color-on-success: black;--color-on-success-bg: #006d00;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-hover: rgba(245, 158, 11, .06);--color-on-warning: black;--color-on-warning-bg: #984700;--color-danger: #ec4899;--color-danger-dark: #db2777;--color-danger-bg: #ffe4e9;--color-danger-hover: rgba(236, 72, 153, .06);--color-on-danger: black;--color-on-danger-bg: #c51a78;--color-neutral: #94a3b8;--color-neutral-dark: #728094;--color-neutral-bg: #fdd5e0;--color-neutral-hover: rgba(148, 163, 184, .06);--color-on-neutral: black;--color-on-neutral-bg: #546275;--color-text: #1f1c1e;--color-text-secondary: #6b5a5e;--color-text-tertiary: #a78b92;--color-text-muted: #c4a4ab;--color-border: #f3becf;--color-border-light: #f6d7e0;--color-bg: #f0e6e9;--color-bg-card: #fff9fc;--color-bg-alt: #ecdde1;--color-bg-hover: #eccdd6;--color-bg-overlay: rgba(255, 107, 157, .3);--hdk-shadow-sm: 0 1px 2px rgba(255, 107, 157, .08);--hdk-shadow-md: 0 2px 4px rgba(255, 107, 157, .12);--hdk-shadow-lg: 0 8px 24px rgba(255, 107, 157, .2);--hdk-shadow-focus: 0 0 0 3px rgba(255, 107, 157, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(255, 107, 157, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(255, 107, 157, .15)}[data-theme=strawberry-dark]{color-scheme:dark only;--color-primary: #f6526f;--color-primary-dark: #dd395b;--color-primary-bg: rgba(246, 82, 111, .16);--color-primary-hover: rgba(246, 82, 111, .12);--color-on-primary: black;--color-on-primary-bg: #ff6781;--color-success: #6fda75;--color-success-dark: #57c35f;--color-success-bg: rgba(111, 218, 117, .15);--color-success-hover: rgba(111, 218, 117, .1);--color-on-success: black;--color-on-success-bg: #6fda75;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #f2823b;--color-danger-dark: #da6c1f;--color-danger-bg: rgba(242, 130, 59, .15);--color-danger-hover: rgba(242, 130, 59, .1);--color-on-danger: black;--color-on-danger-bg: #f2823b;--color-neutral: #889e94;--color-neutral-dark: #73897f;--color-neutral-bg: #20362c;--color-neutral-hover: rgba(136, 158, 148, .1);--color-on-neutral: black;--color-on-neutral-bg: #8ba197;--color-text: #ffefef;--color-text-secondary: #edd4d6;--color-text-tertiary: #dbb2b7;--color-text-muted: #ab888c;--color-border: #2f5838;--color-border-light: #3f704a;--color-bg: #0a1a13;--color-bg-card: #16271f;--color-bg-alt: #05140e;--color-bg-hover: #1e3129;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(246, 82, 111, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(246, 82, 111, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(246, 82, 111, .2)}[data-theme=ocean-light]{color-scheme:light;--color-primary: #06b6d4;--color-primary-dark: #0891b2;--color-primary-bg: #ecfeff;--color-primary-hover: rgba(6, 182, 212, .08);--color-on-primary: black;--color-on-primary-bg: #007b97;--color-success: #f97316;--color-success-dark: #ea580c;--color-success-bg: rgba(249, 115, 22, .1);--color-success-hover: rgba(249, 115, 22, .06);--color-on-success: black;--color-on-success-bg: #af2c00;--color-warning: #eab308;--color-warning-dark: #c48e00;--color-warning-bg: rgba(234, 179, 8, .1);--color-warning-hover: rgba(234, 179, 8, .06);--color-on-warning: black;--color-on-warning-bg: #8a5600;--color-danger: #ec4899;--color-danger-dark: #db2777;--color-danger-bg: #fce7f3;--color-danger-hover: rgba(236, 72, 153, .06);--color-on-danger: black;--color-on-danger-bg: #c51a78;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #e0f2fe;--color-neutral-hover: rgba(100, 116, 139, .06);--color-on-neutral: white;--color-on-neutral-bg: #5b6a80;--color-text: #0c4a6e;--color-text-secondary: #075985;--color-text-tertiary: #0ea5e9;--color-text-muted: #38bdf8;--color-border: #95e2eb;--color-border-light: #c4eef2;--color-bg: #e6eff5;--color-bg-card: #ffffff;--color-bg-alt: #d6e8f4;--color-bg-hover: #c5f0f4;--color-bg-overlay: rgba(8, 47, 73, .3);--hdk-shadow-sm: 0 1px 2px rgba(6, 182, 212, .08);--hdk-shadow-md: 0 2px 4px rgba(6, 182, 212, .12);--hdk-shadow-lg: 0 8px 24px rgba(6, 182, 212, .2);--hdk-shadow-focus: 0 0 0 3px rgba(6, 182, 212, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(6, 182, 212, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(6, 182, 212, .15)}[data-theme=ocean-dark]{color-scheme:dark only;--color-primary: #06b6d4;--color-primary-dark: #0891b2;--color-primary-bg: #0c4a6e;--color-primary-hover: rgba(6, 182, 212, .15);--color-on-primary: black;--color-on-primary-bg: #30c6e5;--color-success: #f97316;--color-success-dark: #ea580c;--color-success-bg: rgba(249, 115, 22, .15);--color-success-hover: rgba(249, 115, 22, .1);--color-on-success: black;--color-on-success-bg: #ffb568;--color-warning: #fbbf24;--color-warning-dark: #d59a00;--color-warning-bg: rgba(251, 191, 36, .15);--color-warning-hover: rgba(251, 191, 36, .1);--color-on-warning: black;--color-on-warning-bg: #ffc935;--color-danger: #ec4899;--color-danger-dark: #db2777;--color-danger-bg: #500724;--color-danger-hover: rgba(236, 72, 153, .1);--color-on-danger: black;--color-on-danger-bg: #f34f9f;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #1e3a52;--color-neutral-hover: rgba(100, 116, 139, .1);--color-on-neutral: white;--color-on-neutral-bg: #95a6be;--color-text: #e0f2fe;--color-text-secondary: #bae6fd;--color-text-tertiary: #7dd3fc;--color-text-muted: #0ea5e9;--color-border: #34697f;--color-border-light: #0e7490;--color-bg: #082f49;--color-bg-card: #0c4a6e;--color-bg-alt: #164e63;--color-bg-hover: #0e7490;--color-bg-overlay: rgba(0, 0, 0, .7);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .6);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(6, 182, 212, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(6, 182, 212, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(6, 182, 212, .2)}[data-theme=cyberpunk-light]{color-scheme:light;--color-primary: #ff006e;--color-primary-dark: #ea005e;--color-primary-bg: #fff0f7;--color-primary-hover: rgba(255, 0, 110, .08);--color-on-primary: black;--color-on-primary-bg: #d90052;--color-success: #00f5d4;--color-success-dark: #00d9c0;--color-success-bg: rgba(0, 245, 212, .1);--color-success-hover: rgba(0, 245, 212, .06);--color-on-success: black;--color-on-success-bg: #007158;--color-warning: #ff9f1c;--color-warning-dark: #d77b00;--color-warning-bg: rgba(255, 159, 28, .1);--color-warning-hover: rgba(255, 159, 28, .06);--color-on-warning: black;--color-on-warning-bg: #a04800;--color-danger: #fb5607;--color-danger-dark: #e04f06;--color-danger-bg: #ffe8dc;--color-danger-hover: rgba(251, 86, 7, .06);--color-on-danger: black;--color-on-danger-bg: #cc2200;--color-neutral: #9849d8;--color-neutral-dark: #761eb1;--color-neutral-bg: #e9d5ff;--color-neutral-hover: rgba(157, 78, 221, .06);--color-on-neutral: white;--color-on-neutral-bg: #8634c4;--color-text: #1a1a2e;--color-text-secondary: #3d3d5c;--color-text-tertiary: #6b6b8a;--color-text-muted: #9999b3;--color-border: #dacaf8;--color-border-light: #eadff9;--color-bg: #ececf5;--color-bg-card: #ffffff;--color-bg-alt: #e8e6f2;--color-bg-hover: #e3d8f2;--color-bg-overlay: rgba(26, 26, 46, .4);--hdk-shadow-sm: 0 1px 3px rgba(255, 0, 110, .12);--hdk-shadow-md: 0 2px 6px rgba(255, 0, 110, .18);--hdk-shadow-lg: 0 8px 24px rgba(255, 0, 110, .25);--hdk-shadow-focus: 0 0 0 3px rgba(255, 0, 110, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(255, 0, 110, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(255, 0, 110, .2)}[data-theme=cyberpunk-dark]{color-scheme:dark only;--color-primary: #22d3ee;--color-primary-dark: #06b6d4;--color-primary-bg: #0a1929;--color-primary-hover: rgba(34, 211, 238, .15);--color-on-primary: black;--color-on-primary-bg: #22d3ee;--color-success: #39ff14;--color-success-dark: #00ff00;--color-success-bg: rgba(57, 255, 20, .15);--color-success-hover: rgba(57, 255, 20, .1);--color-on-success: black;--color-on-success-bg: #39ff14;--color-warning: #ffbe0b;--color-warning-dark: #d89900;--color-warning-bg: rgba(255, 190, 11, .15);--color-warning-hover: rgba(255, 190, 11, .1);--color-on-warning: black;--color-on-warning-bg: #ffbe0b;--color-danger: #ff10f0;--color-danger-dark: #ff00ff;--color-danger-bg: #800080;--color-danger-hover: rgba(255, 16, 240, .1);--color-on-danger: black;--color-on-danger-bg: #ff89ff;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #1e293b;--color-neutral-hover: rgba(100, 116, 139, .1);--color-on-neutral: white;--color-on-neutral-bg: #8394ab;--color-text: #e0f2fe;--color-text-secondary: #67e8f9;--color-text-tertiary: #22d3ee;--color-text-muted: #0891b2;--color-border: #164e63;--color-border-light: #0e7490;--color-bg: #020617;--color-bg-card: #0c1929;--color-bg-alt: #1e293b;--color-bg-hover: #0f172a;--color-bg-overlay: rgba(0, 0, 0, .8);--hdk-shadow-sm: 0 1px 2px rgba(34, 211, 238, .2);--hdk-shadow-md: 0 2px 4px rgba(34, 211, 238, .3);--hdk-shadow-lg: 0 8px 24px rgba(34, 211, 238, .4);--hdk-shadow-focus: 0 0 0 3px rgba(34, 211, 238, .4);--hdk-shadow-focus-sm: 0 0 0 2px rgba(34, 211, 238, .4);--hdk-shadow-focus-alt: 0 0 0 2px rgba(34, 211, 238, .3);--advanced-stop-1-l: .32;--advanced-stop-1-c: .12;--advanced-stop-1-h: 220;--advanced-stop-2-l: .42;--advanced-stop-2-c: .18;--advanced-stop-2-h: 200;--advanced-stop-3-l: .5;--advanced-stop-3-c: .2;--advanced-stop-3-h: 195;--advanced-stop-4-l: .45;--advanced-stop-4-c: .22;--advanced-stop-4-h: 280;--advanced-stop-5-l: .4;--advanced-stop-5-c: .26;--advanced-stop-5-h: 320;--advanced-stop-6-l: .46;--advanced-stop-6-c: .28;--advanced-stop-6-h: 340;--advanced-stop-7-l: .38;--advanced-stop-7-c: .22;--advanced-stop-7-h: 290;--advanced-stop-8-l: .28;--advanced-stop-8-c: .16;--advanced-stop-8-h: 250;--advanced-gradient: linear-gradient( 135deg, oklch(var(--advanced-stop-1-l) var(--advanced-stop-1-c) var(--advanced-stop-1-h)) 0%, oklch(var(--advanced-stop-2-l) var(--advanced-stop-2-c) var(--advanced-stop-2-h)) 15%, oklch(var(--advanced-stop-3-l) var(--advanced-stop-3-c) var(--advanced-stop-3-h)) 30%, oklch(var(--advanced-stop-4-l) var(--advanced-stop-4-c) var(--advanced-stop-4-h)) 45%, oklch(var(--advanced-stop-5-l) var(--advanced-stop-5-c) var(--advanced-stop-5-h)) 60%, oklch(var(--advanced-stop-6-l) var(--advanced-stop-6-c) var(--advanced-stop-6-h)) 75%, oklch(var(--advanced-stop-7-l) var(--advanced-stop-7-c) var(--advanced-stop-7-h)) 88%, oklch(var(--advanced-stop-8-l) var(--advanced-stop-8-c) var(--advanced-stop-8-h)) 100% )}[data-theme=coffee-light]{color-scheme:light;--color-primary: #ea580c;--color-primary-dark: #d54300;--color-primary-bg: #fffbeb;--color-primary-hover: rgba(234, 88, 12, .08);--color-on-primary: black;--color-on-primary-bg: #cd3c00;--color-success: #eab308;--color-success-dark: #ca8a04;--color-success-bg: rgba(234, 179, 8, .1);--color-success-hover: rgba(234, 179, 8, .06);--color-on-success: black;--color-on-success-bg: #8a5600;--color-warning: #d97706;--color-warning-dark: #bb5b00;--color-warning-bg: rgba(217, 119, 6, .1);--color-warning-hover: rgba(217, 119, 6, .06);--color-on-warning: black;--color-on-warning-bg: #a04300;--color-danger: #78350f;--color-danger-dark: #92400e;--color-danger-bg: #fef3c7;--color-danger-hover: rgba(120, 53, 15, .06);--color-on-danger: white;--color-on-danger-bg: #78350f;--color-neutral: #77706b;--color-neutral-dark: #56504b;--color-neutral-bg: #fde68a;--color-neutral-hover: rgba(120, 113, 108, .06);--color-on-neutral: white;--color-on-neutral-bg: #6b6560;--color-text: #1c1917;--color-text-secondary: #44403c;--color-text-tertiary: #78716c;--color-text-muted: #a8a29e;--color-border: #ead377;--color-border-light: #f0e5ba;--color-bg: #f1edde;--color-bg-card: #ffffff;--color-bg-alt: #f0e5ba;--color-bg-hover: #f0ca9d;--color-bg-overlay: rgba(28, 25, 23, .3);--hdk-shadow-sm: 0 1px 2px rgba(234, 88, 12, .08);--hdk-shadow-md: 0 2px 4px rgba(234, 88, 12, .12);--hdk-shadow-lg: 0 8px 24px rgba(234, 88, 12, .2);--hdk-shadow-focus: 0 0 0 3px rgba(234, 88, 12, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(234, 88, 12, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(234, 88, 12, .15)}[data-theme=coffee-dark]{color-scheme:dark only;--color-primary: #ea580c;--color-primary-dark: #d54300;--color-primary-bg: #292524;--color-primary-hover: rgba(234, 88, 12, .15);--color-on-primary: black;--color-on-primary-bg: #f15f1a;--color-success: #facc15;--color-success-dark: #eab308;--color-success-bg: rgba(250, 204, 21, .15);--color-success-hover: rgba(250, 204, 21, .1);--color-on-success: black;--color-on-success-bg: #facc15;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .15);--color-warning-hover: rgba(245, 158, 11, .1);--color-on-warning: black;--color-on-warning-bg: #ffab29;--color-danger: #57534e;--color-danger-dark: #44403c;--color-danger-bg: #1c1917;--color-danger-hover: rgba(87, 83, 78, .1);--color-on-danger: white;--color-on-danger-bg: #88847e;--color-neutral: #77706b;--color-neutral-dark: #56504b;--color-neutral-bg: #3e3933;--color-neutral-hover: rgba(120, 113, 108, .1);--color-on-neutral: white;--color-on-neutral-bg: #aea6a1;--color-text: #fef3c7;--color-text-secondary: #fde68a;--color-text-tertiary: #fbbf24;--color-text-muted: #d97706;--color-border: #44403c;--color-border-light: #57534e;--color-bg: #1c1917;--color-bg-card: #292524;--color-bg-alt: #3e3933;--color-bg-hover: #44403c;--color-bg-overlay: rgba(0, 0, 0, .75);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .6);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .7);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .8);--hdk-shadow-focus: 0 0 0 3px rgba(234, 88, 12, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(234, 88, 12, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(234, 88, 12, .2)}[data-theme=lavender-light]{color-scheme:light;--color-primary: #c084fc;--color-primary-dark: #a855f7;--color-primary-bg: #faf5ff;--color-primary-hover: rgba(192, 132, 252, .08);--color-on-primary: black;--color-on-primary-bg: #8e52c6;--color-success: #84cc16;--color-success-dark: #65a30d;--color-success-bg: rgba(132, 204, 22, .1);--color-success-hover: rgba(132, 204, 22, .06);--color-on-success: black;--color-on-success-bg: #256700;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-hover: rgba(245, 158, 11, .06);--color-on-warning: black;--color-on-warning-bg: #914100;--color-danger: #5e60ea;--color-danger-dark: #4f46e5;--color-danger-bg: #e0e7ff;--color-danger-hover: rgba(99, 102, 241, .06);--color-on-danger: white;--color-on-danger-bg: #5453dc;--color-neutral: #71717a;--color-neutral-dark: #515159;--color-neutral-bg: #e4e4e7;--color-neutral-hover: rgba(113, 113, 122, .06);--color-on-neutral: white;--color-on-neutral-bg: #63636b;--color-text: #1f1f29;--color-text-secondary: #52525b;--color-text-tertiary: #71717a;--color-text-muted: #a1a1aa;--color-border: #d8c4ee;--color-border-light: #e6dbf1;--color-bg: #eae6ef;--color-bg-card: #fdf8ff;--color-bg-alt: #e1d6ed;--color-bg-hover: #d7c3ed;--color-bg-overlay: rgba(192, 132, 252, .25);--hdk-shadow-sm: 0 1px 2px rgba(192, 132, 252, .06);--hdk-shadow-md: 0 2px 4px rgba(192, 132, 252, .1);--hdk-shadow-lg: 0 8px 24px rgba(192, 132, 252, .15);--hdk-shadow-focus: 0 0 0 3px rgba(192, 132, 252, .2);--hdk-shadow-focus-sm: 0 0 0 2px rgba(192, 132, 252, .2);--hdk-shadow-focus-alt: 0 0 0 2px rgba(192, 132, 252, .15)}[data-theme=lavender-dark]{color-scheme:dark only;--color-primary: #cba1fa;--color-primary-dark: #b58be2;--color-primary-bg: rgba(203, 161, 250, .16);--color-primary-hover: rgba(203, 161, 250, .12);--color-on-primary: black;--color-on-primary-bg: #d1a7ff;--color-success: #b3e14d;--color-success-dark: #9dca30;--color-success-bg: rgba(179, 225, 77, .15);--color-success-hover: rgba(179, 225, 77, .1);--color-on-success: black;--color-on-success-bg: #b3e14d;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #f06f84;--color-danger-dark: #d7596f;--color-danger-bg: rgba(240, 111, 132, .15);--color-danger-hover: rgba(240, 111, 132, .1);--color-on-danger: black;--color-on-danger-bg: #ff8c9f;--color-neutral: #9098ab;--color-neutral-dark: #7b8395;--color-neutral-bg: #253154;--color-neutral-hover: rgba(144, 152, 171, .1);--color-on-neutral: black;--color-on-neutral-bg: #969eb1;--color-text: #f3f2fd;--color-text-secondary: #dad9e8;--color-text-tertiary: #bdbad4;--color-text-muted: #918fa6;--color-border: #333e5b;--color-border-light: #3b496e;--color-bg: #0e172f;--color-bg-card: #192341;--color-bg-alt: #27324e;--color-bg-hover: #222d4d;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(203, 161, 250, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(203, 161, 250, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(203, 161, 250, .2)}[data-theme=pink-light]{color-scheme:light;--color-primary: #ff69b4;--color-primary-dark: #ff1493;--color-primary-bg: #fff0f5;--color-primary-hover: rgba(255, 105, 180, .08);--color-on-primary: black;--color-on-primary-bg: #c32e80;--color-success: #ffb3d9;--color-success-dark: #ff8fcc;--color-success-bg: rgba(255, 179, 217, .15);--color-success-hover: rgba(255, 179, 217, .06);--color-on-success: black;--color-on-success-bg: #8f4c70;--color-warning: #fbbf24;--color-warning-dark: #d59a00;--color-warning-bg: rgba(251, 191, 36, .1);--color-warning-hover: rgba(251, 191, 36, .06);--color-on-warning: black;--color-on-warning-bg: #8d5500;--color-danger: #9856b3;--color-danger-dark: #8e44ad;--color-danger-bg: #e8daef;--color-danger-hover: rgba(155, 89, 182, .06);--color-on-danger: white;--color-on-danger-bg: #8644a0;--color-neutral: #d4a5a5;--color-neutral-dark: #af8282;--color-neutral-bg: #ffd9e0;--color-neutral-hover: rgba(212, 165, 165, .06);--color-on-neutral: black;--color-on-neutral-bg: #825858;--color-text: #4a2a3a;--color-text-secondary: #88576c;--color-text-tertiary: #c48ca0;--color-text-muted: #e5b3c8;--color-border: #ffc0cb;--color-border-light: #ffd9e0;--color-bg: #f4eaee;--color-bg-card: #ffffff;--color-bg-alt: #f0e2e7;--color-bg-hover: #f0cbd2;--color-bg-overlay: rgba(255, 105, 180, .2);--hdk-shadow-sm: 0 1px 2px rgba(255, 105, 180, .08);--hdk-shadow-md: 0 2px 4px rgba(255, 105, 180, .12);--hdk-shadow-lg: 0 8px 24px rgba(255, 105, 180, .15);--hdk-shadow-focus: 0 0 0 3px rgba(255, 105, 180, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(255, 105, 180, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(255, 105, 180, .15)}[data-theme=pink-dark]{color-scheme:dark only;--color-primary: #f799be;--color-primary-dark: #df83a8;--color-primary-bg: rgba(247, 153, 190, .16);--color-primary-hover: rgba(247, 153, 190, .12);--color-on-primary: black;--color-on-primary-bg: #f799be;--color-success: #63e6be;--color-success-dark: #48cfa8;--color-success-bg: rgba(99, 230, 190, .15);--color-success-hover: rgba(99, 230, 190, .1);--color-on-success: black;--color-on-success-bg: #63e6be;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #ae7ee2;--color-danger-dark: #9869cb;--color-danger-bg: rgba(174, 126, 226, .15);--color-danger-hover: rgba(174, 126, 226, .1);--color-on-danger: black;--color-on-danger-bg: #b787ec;--color-neutral: #a5929a;--color-neutral-dark: #907d85;--color-neutral-bg: #3b2b32;--color-neutral-hover: rgba(165, 146, 154, .1);--color-on-neutral: black;--color-on-neutral-bg: #a8959d;--color-text: #ffeef5;--color-text-secondary: #ead4dd;--color-text-tertiary: #d7b2c2;--color-text-muted: #a88896;--color-border: #4a373f;--color-border-light: #624b55;--color-bg: #1d1217;--color-bg-card: #2c1e24;--color-bg-alt: #170d12;--color-bg-hover: #36282e;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(247, 153, 190, .4);--hdk-shadow-focus-sm: 0 0 0 2px rgba(247, 153, 190, .4);--hdk-shadow-focus-alt: 0 0 0 2px rgba(247, 153, 190, .3)}[data-theme=nature-light]{color-scheme:light;--color-primary: #6bbe4e;--color-primary-dark: #5aa942;--color-primary-bg: #f4faf1;--color-primary-hover: rgba(107, 190, 78, .08);--color-on-primary: black;--color-on-primary-bg: #2c7f00;--color-success: #a7d88f;--color-success-dark: #8dc473;--color-success-bg: rgba(167, 216, 143, .15);--color-success-hover: rgba(167, 216, 143, .06);--color-on-success: black;--color-on-success-bg: #426e29;--color-warning: #ca8a04;--color-warning-dark: #a66800;--color-warning-bg: rgba(202, 138, 4, .1);--color-warning-hover: rgba(202, 138, 4, .06);--color-on-warning: black;--color-on-warning-bg: #8d5100;--color-danger: #c8643b;--color-danger-dark: #bc5930;--color-danger-bg: #f9e8e1;--color-danger-hover: rgba(200, 100, 59, .06);--color-on-danger: black;--color-on-danger-bg: #ad4c21;--color-neutral: #cfc6b0;--color-neutral-dark: #aaa28c;--color-neutral-bg: #ebe7dc;--color-neutral-hover: rgba(207, 198, 176, .06);--color-on-neutral: black;--color-on-neutral-bg: #6d6551;--color-text: #2c2c2c;--color-text-secondary: #5a5a5a;--color-text-tertiary: #8a8a8a;--color-text-muted: #acacac;--color-border: #dad3bf;--color-border-light: #e9e5da;--color-bg: #efede4;--color-bg-card: #ffffff;--color-bg-alt: #ebe8de;--color-bg-hover: #e1ddd2;--color-bg-overlay: rgba(44, 44, 44, .5);--hdk-shadow-sm: 0 1px 2px rgba(107, 190, 78, .08);--hdk-shadow-md: 0 2px 4px rgba(107, 190, 78, .12);--hdk-shadow-lg: 0 8px 24px rgba(107, 190, 78, .2);--hdk-shadow-focus: 0 0 0 3px rgba(107, 190, 78, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(107, 190, 78, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(107, 190, 78, .15)}[data-theme=nature-dark]{color-scheme:dark only;--color-primary: #5ac041;--color-primary-dark: #42a926;--color-primary-bg: rgba(90, 192, 65, .16);--color-primary-hover: rgba(90, 192, 65, .12);--color-on-primary: black;--color-on-primary-bg: #5ac041;--color-success: #52db9c;--color-success-dark: #34c487;--color-success-bg: rgba(82, 219, 156, .15);--color-success-hover: rgba(82, 219, 156, .1);--color-on-success: black;--color-on-success-bg: #52db9c;--color-warning: #f7c243;--color-warning-dark: #e0ab22;--color-warning-bg: rgba(247, 194, 67, .15);--color-warning-hover: rgba(247, 194, 67, .1);--color-on-warning: black;--color-on-warning-bg: #f7c243;--color-danger: #bc4f2b;--color-danger-dark: #a63b14;--color-danger-bg: rgba(190, 81, 45, .15);--color-danger-hover: rgba(190, 81, 45, .1);--color-on-danger: white;--color-on-danger-bg: #ec7b56;--color-neutral: #8f8476;--color-neutral-dark: #807568;--color-neutral-bg: #3b3229;--color-neutral-hover: rgba(143, 132, 118, .1);--color-on-neutral: black;--color-on-neutral-bg: #a89c8e;--color-text: #f8f4e1;--color-text-secondary: #e2dbc1;--color-text-tertiary: #cabe92;--color-text-muted: #9d926c;--color-border: #604734;--color-border-light: #795c45;--color-bg: #1e1811;--color-bg-card: #2c251d;--color-bg-alt: #18130c;--color-bg-hover: #372f26;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .6);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .8);--hdk-shadow-focus: 0 0 0 3px rgba(90, 192, 65, .35);--hdk-shadow-focus-sm: 0 0 0 2px rgba(90, 192, 65, .35);--hdk-shadow-focus-alt: 0 0 0 2px rgba(90, 192, 65, .25)}[data-theme=izakaya-light]{color-scheme:light;--color-primary: #41baae;--color-primary-dark: #369c92;--color-primary-bg: rgba(65, 186, 174, .05);--color-primary-hover: rgba(65, 186, 174, .08);--color-on-primary: black;--color-on-primary-bg: #00534a;--color-success: #a6d8ad;--color-success-dark: #8ccb94;--color-success-bg: rgba(166, 216, 173, .15);--color-success-hover: rgba(166, 216, 173, .06);--color-on-success: black;--color-on-success-bg: #275530;--color-warning: #d4a574;--color-warning-dark: #af8252;--color-warning-bg: rgba(212, 165, 116, .15);--color-warning-hover: rgba(212, 165, 116, .06);--color-on-warning: black;--color-on-warning-bg: #673e07;--color-danger: #c04731;--color-danger-dark: #a23b29;--color-danger-bg: #f97a6f;--color-danger-hover: rgba(192, 71, 49, .06);--color-on-danger: white;--color-on-danger-bg: #720000;--color-neutral: #a8999e;--color-neutral-dark: #85777b;--color-neutral-bg: #d8c8b0;--color-neutral-hover: rgba(168, 153, 158, .06);--color-on-neutral: black;--color-on-neutral-bg: #5e5055;--color-text: #2a2a2a;--color-text-secondary: rgba(42, 42, 42, .8);--color-text-tertiary: rgba(42, 42, 42, .6);--color-text-muted: rgba(42, 42, 42, .4);--color-border: #bfa1a0;--color-border-light: #ceaecb;--color-bg: #f2e6cd;--color-bg-card: #f1c8c8;--color-bg-alt: #d8b888;--color-bg-hover: #d1b1ce;--color-bg-overlay: rgba(42, 42, 42, .45);--hdk-shadow-sm: 0 1px 2px rgba(65, 186, 174, .08);--hdk-shadow-md: 0 2px 4px rgba(65, 186, 174, .12);--hdk-shadow-lg: 0 8px 24px rgba(65, 186, 174, .2);--hdk-shadow-focus: 0 0 0 3px rgba(65, 186, 174, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(65, 186, 174, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(65, 186, 174, .15)}[data-theme=izakaya-dark]{color-scheme:dark only;--color-primary: #04c5b5;--color-primary-dark: #00ac9e;--color-primary-bg: rgba(4, 197, 181, .16);--color-primary-hover: rgba(4, 197, 181, .12);--color-on-primary: black;--color-on-primary-bg: #04c5b5;--color-success: #61d19a;--color-success-dark: #48ba85;--color-success-bg: rgba(97, 209, 154, .15);--color-success-hover: rgba(97, 209, 154, .1);--color-on-success: black;--color-on-success-bg: #61d19a;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #c13e2e;--color-danger-dark: #a92517;--color-danger-bg: rgba(193, 62, 46, .15);--color-danger-hover: rgba(193, 62, 46, .1);--color-on-danger: white;--color-on-danger-bg: #f66f5b;--color-neutral: #7f7f87;--color-neutral-dark: #76767e;--color-neutral-bg: #2d343b;--color-neutral-hover: rgba(127, 127, 135, .1);--color-on-neutral: black;--color-on-neutral-bg: #9d9da5;--color-text: #f5f2f5;--color-text-secondary: #ddd9dd;--color-text-tertiary: #c1bcc1;--color-text-muted: #959095;--color-border: #71574b;--color-border-light: #8c6c5e;--color-bg: #14191e;--color-bg-card: #20262c;--color-bg-alt: #0f1318;--color-bg-hover: #2a3036;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .55);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(4, 197, 181, .32);--hdk-shadow-focus-sm: 0 0 0 2px rgba(4, 197, 181, .32);--hdk-shadow-focus-alt: 0 0 0 2px rgba(4, 197, 181, .18)}.app-header__icon-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;width:32px;height:32px;min-width:32px;min-height:32px;padding:0;margin:0;border:none;border-radius:50%;background:none;color:var(--color-text);font:inherit;font-size:var(--hdk-text-lg);line-height:1;text-decoration:none;cursor:pointer;opacity:.7;transition:background-color var(--transition-fast),opacity var(--transition-fast)}.app-header__icon-btn:link,.app-header__icon-btn:visited,.app-header__icon-btn:hover,.app-header__icon-btn:active{color:var(--color-text);text-decoration:none}.app-header__icon-btn:hover{background-color:var(--color-primary-hover);opacity:1}.app-header__icon-btn:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 2px var(--color-primary)}.theme-picker{position:relative}.theme-picker__overlay{position:fixed;inset:0;z-index:99;background:transparent}.theme-picker__dropdown{position:absolute;top:0;left:calc(100% + var(--hdk-space-md));z-index:100;display:flex;flex-direction:column;align-items:flex-start;gap:var(--hdk-space-sm)}.theme-picker__main{display:flex;align-items:flex-start;gap:var(--hdk-space-md)}.theme-picker--open-left .theme-picker__dropdown{left:auto;right:calc(100% + var(--hdk-space-md))}.theme-picker--open-left .theme-picker__main{flex-direction:row-reverse}.theme-picker__pills{display:flex;flex-direction:column;gap:0;border-radius:12px;overflow:hidden;box-shadow:var(--hdk-shadow-lg)}.theme-pill{display:flex;gap:0;background:transparent;border:none;transition:all var(--transition-fast, .15s ease)}.theme-pill:not(:last-child){border-bottom:1px solid rgba(0,0,0,.08)}.theme-pill__btn{flex:1;display:flex;align-items:center;justify-content:center;padding:calc(var(--hdk-space-lg) * 1.2);border:none;background:transparent;cursor:pointer;transition:all var(--transition-fast, .15s ease);position:relative;overflow:visible}.theme-pill__btn--light{background:linear-gradient(135deg,#f8fafc,#f1f5f9);color:#1e293b;border-right:1px solid rgba(0,0,0,.1)}.theme-pill__btn--dark{background:linear-gradient(135deg,#0f172a,#020617);color:#64748b;border-left:1px solid rgba(100,116,139,.1)}.theme-pill:first-child .theme-pill__btn--light{border-top-left-radius:12px}.theme-pill:first-child .theme-pill__btn--dark{border-top-right-radius:12px}.theme-pill:last-child .theme-pill__btn--light{border-bottom-left-radius:12px}.theme-pill:last-child .theme-pill__btn--dark{border-bottom-right-radius:12px}.theme-pill__btn--light:hover{background:linear-gradient(135deg,#fff,#f8fafc);color:var(--color-primary)}.theme-pill__btn--dark:hover{background:linear-gradient(135deg,#1e293b,#0f172a);color:#cbd5e1}.theme-pill__btn--light.active{background:linear-gradient(135deg,#fff,#f0f9ff);color:var(--color-primary);box-shadow:inset 0 0 0 2.2px var(--color-primary);font-weight:var(--font-weight-semibold, 600)}.theme-pill__btn--dark.active{background:linear-gradient(135deg,#020617,#000);color:var(--color-primary);box-shadow:inset 0 0 0 2.2px var(--color-primary);font-weight:var(--font-weight-semibold, 600);filter:brightness(1.1)}.theme-pill__icon{display:flex;align-items:center;justify-content:center;width:20px;height:20px}.theme-pill__icon svg{width:100%;height:100%}.theme-picker__settings-icon{display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:none;background:var(--color-bg-card);color:var(--color-text-secondary);cursor:pointer;transition:all var(--transition-fast, .15s ease);border-radius:50%;box-shadow:var(--hdk-shadow-md);flex-shrink:0}.theme-picker__settings-icon:hover{background:var(--color-primary-bg);color:var(--color-on-primary-bg);transform:rotate(45deg);box-shadow:var(--hdk-shadow-lg)}.theme-picker__settings-icon svg{width:20px;height:20px}.app-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding-bottom:1rem;margin-bottom:1.5rem;border-bottom:1px solid var(--color-border)}.app-header__title{margin:0;color:var(--color-text);font-size:var(--hdk-text-lg);font-weight:700;line-height:1.2;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-header__actions{display:flex;align-items:center;flex-shrink:0;gap:.5rem}.app-header .theme-picker__dropdown,.app-header .theme-picker--open-left .theme-picker__dropdown{top:calc(100% + 8px);left:auto;right:0}.settings-popout{position:relative;display:inline-flex}.settings-popout__overlay{position:fixed;inset:0;z-index:99;background:transparent}.settings-popout__panel{position:absolute;top:calc(100% + 8px);right:0;z-index:100;box-sizing:border-box;width:300px;max-width:calc(100vw - 32px);max-height:calc(100vh - 80px);overflow-y:auto;display:flex;flex-direction:column;gap:14px;padding:16px;border-radius:12px;background:var(--color-bg-card);border:1px solid var(--color-border);box-shadow:0 8px 28px #0000002e;color:var(--color-text)}.settings-popout__app{border-top:1px solid var(--color-border);padding-top:12px}.settings-popout__header{font-weight:600;font-size:.95rem;color:var(--color-text)}.settings-popout__row{display:flex;align-items:center;justify-content:space-between;gap:10px}.settings-popout__row--stack{flex-direction:column;align-items:stretch;gap:8px}.settings-popout__label{font-size:.8rem;color:var(--color-text-secondary)}.settings-popout__value{font-size:.85rem;font-weight:500;color:var(--color-text)}.settings-popout__value--editable{background:transparent;border:1px solid transparent;border-radius:7px;padding:4px 8px;margin-right:-8px;font-family:inherit;cursor:text;transition:border-color .15s ease}.settings-popout__value--editable:hover,.settings-popout__value--editable:focus-visible{border-color:var(--color-border);outline:none}.settings-popout__label--grow{margin-right:auto}.settings-popout__inline{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex:1 1 auto;min-width:0;flex-wrap:wrap}.settings-popout__inline>.settings-popout__error{flex-basis:100%}.settings-popout__tier{font-size:.78rem;font-weight:600;padding:2px 10px;border-radius:999px;background:var(--color-bg-alt);color:var(--color-text);border:1px solid var(--color-border)}.settings-popout__tier--admin{background:var(--color-primary-bg);color:var(--color-on-primary-bg);border-color:var(--color-primary)}.settings-popout__input{flex:1 1 0;width:0;min-width:0;box-sizing:border-box;font-size:.85rem;padding:5px 8px;border-radius:7px;border:1px solid var(--color-border);background:var(--color-bg);color:var(--color-text)}.settings-popout__input:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 2px var(--color-primary-bg)}.settings-popout__btn{font-size:.78rem;padding:4px 10px;border-radius:7px;border:1px solid var(--color-border);background:var(--color-bg);color:var(--color-text);cursor:pointer;white-space:nowrap;text-decoration:none;transition:background-color .15s ease,border-color .15s ease}.settings-popout__btn:hover:not(:disabled){background:var(--color-bg-alt)}.settings-popout__btn--primary{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.settings-popout__btn--primary:hover:not(:disabled){background:var(--color-primary-dark)}.settings-popout__btn:disabled{opacity:.6;cursor:default}.settings-popout__pill{display:flex;gap:3px;width:100%}.settings-popout__seg{flex:1 1 0;padding:7px 0;font-size:.8rem;font-weight:600;border:1px solid var(--color-border);background:var(--color-bg-alt);color:var(--color-text-secondary);cursor:pointer;transition:background-color .12s ease,color .12s ease}.settings-popout__seg:first-child{border-radius:8px 0 0 8px}.settings-popout__seg:last-child{border-radius:0 8px 8px 0}.settings-popout__seg--filled{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.settings-popout__seg:disabled{cursor:default}.settings-popout__key-form{display:flex;flex-direction:column;gap:6px;width:100%}.settings-popout__error{font-size:.75rem;line-height:1.35;padding:4px 8px;border-radius:6px;background:var(--color-danger-bg);color:var(--color-on-danger-bg)}.settings-popout__hint{font-size:.72rem;line-height:1.35;color:var(--color-text-tertiary)}.resume-bot-container[data-theme=light],.resume-bot-container[data-theme=coffee-light],.resume-bot-container[data-theme=nature-light],.resume-bot-container[data-theme=lavender-light],.resume-bot-container[data-theme=strawberry-light],.resume-bot-container[data-theme=ocean-light],.resume-bot-container[data-theme=cyberpunk-light],.resume-bot-container[data-theme=pink-light]{color-scheme:light}.resume-bot-container[data-theme=dark],.resume-bot-container[data-theme=coffee-dark],.resume-bot-container[data-theme=nature-dark],.resume-bot-container[data-theme=lavender-dark],.resume-bot-container[data-theme=strawberry-dark],.resume-bot-container[data-theme=ocean-dark],.resume-bot-container[data-theme=cyberpunk-dark],.resume-bot-container[data-theme=pink-dark]{color-scheme:dark only}.resume-bot-container[data-dark-theme=true]{--is-dark-theme: 1}.resume-bot-container{min-height:100vh;background-color:var(--color-bg);color:var(--color-text);font-family:var(--font-family);transition:background-color .3s ease,color .3s ease}.resume-bot{max-width:1600px;margin:0 auto;padding:2rem;display:flex;flex-direction:column;height:100vh;box-sizing:border-box}.resume-bot__content{display:flex;gap:1.5rem;flex:1;overflow:hidden}.resume-bot__resume-section{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden;background-color:var(--color-bg-alt);border-radius:var(--hdk-radius);box-shadow:var(--hdk-shadow-sm)}.resume-bot__chat-section{width:400px;flex-shrink:0;background-color:var(--color-bg-card);border-radius:var(--hdk-radius);box-shadow:var(--hdk-shadow-sm)}.resume-bot__chat-fab,.resume-bot__chat-scrim{display:none}.chat-interface{display:flex;flex-direction:column;height:100%}.chat-interface__header{display:flex;justify-content:space-between;align-items:center;padding:1rem;border-bottom:1px solid var(--color-border)}.chat-interface__header h3{margin:0;font-size:var(--hdk-text-md);color:var(--color-text)}.chat-interface__clear-button{padding:.5rem 1rem;background-color:var(--color-bg-card);border:1px solid var(--color-border);border-radius:var(--hdk-radius);color:var(--color-text-secondary);font-size:var(--hdk-text-sm);cursor:pointer;transition:all .2s ease}.chat-interface__clear-button:hover{background-color:var(--color-border);color:var(--color-text)}.chat-interface__messages{flex:1;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:1rem}.chat-interface__welcome{padding:2rem;text-align:center;color:var(--color-text-secondary);font-size:var(--hdk-text-base)}.chat-message{display:flex;flex-direction:column;gap:.25rem;max-width:80%}.chat-message--user{align-self:flex-end}.chat-message--assistant{align-self:flex-start;max-width:95%}.chat-message__role{font-size:var(--hdk-text-xs);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);padding:0 .75rem}.chat-message__content{padding:.5rem .75rem;border-radius:var(--hdk-radius);line-height:var(--line-height-normal);white-space:pre-wrap;word-wrap:break-word}.chat-message--assistant .chat-message__content>*{margin:0}.chat-message--user .chat-message__content{background-color:var(--color-danger);color:var(--color-bg)}.chat-message--assistant .chat-message__content{background-color:var(--color-primary);border:1px solid var(--color-border);color:var(--color-bg)}.chat-message--loading .chat-message__content{opacity:.7;font-style:italic}.chat-message--assistant .chat-message__content p,.chat-message--assistant .chat-message__content li{line-height:var(--line-height-normal)}.chat-message--assistant .chat-message__content li strong{font-weight:var(--font-weight-normal)}.chat-message--assistant .chat-message__content em{font-style:italic}.chat-message--assistant .chat-message__content code{padding:.125rem .25rem;background-color:var(--color-neutral-bg);border-radius:3px;font-family:monospace;font-size:.9em}.chat-message--assistant .chat-message__content pre{background-color:var(--color-bg-alt);padding:.75rem;border-radius:4px;overflow-x:auto;margin:.5rem 0}.chat-message--assistant .chat-message__content pre code{background-color:transparent;padding:0}.chat-message--assistant .chat-message__content a{color:var(--color-text);text-decoration:underline}.chat-message--assistant .chat-message__content a:hover{text-decoration-thickness:2px}.chat-message--assistant .chat-message__content h1,.chat-message--assistant .chat-message__content h2,.chat-message--assistant .chat-message__content h3,.chat-message--assistant .chat-message__content h4{margin:.5rem 0 .25rem;font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal)}.chat-message--assistant .chat-message__content h1:first-child,.chat-message--assistant .chat-message__content h2:first-child,.chat-message--assistant .chat-message__content h3:first-child,.chat-message--assistant .chat-message__content h4:first-child{margin-top:0}.chat-message--assistant .chat-message__content h1:last-child,.chat-message--assistant .chat-message__content h2:last-child,.chat-message--assistant .chat-message__content h3:last-child,.chat-message--assistant .chat-message__content h4:last-child{margin-bottom:0}.chat-interface__error{padding:.75rem 1rem;margin:0 1rem;background-color:var(--color-danger-bg);border:1px solid var(--color-danger);border-radius:var(--hdk-radius);color:var(--color-on-danger-bg);font-size:var(--hdk-text-sm)}.chat-interface__input-form{display:flex;gap:.5rem;padding:1rem;border-top:1px solid var(--color-border)}.chat-interface__input{flex:1;padding:.75rem 1rem;border:1px solid var(--color-border);border-radius:var(--hdk-radius);background-color:var(--color-bg);color:var(--color-text);font-size:var(--hdk-text-base);transition:border-color .2s ease}.chat-interface__input:focus{outline:none;border-color:var(--color-primary)}.chat-interface__input:disabled{opacity:.5;cursor:not-allowed}.chat-interface__send-button{padding:.75rem 1.5rem;background-color:var(--color-success);border:none;border-radius:var(--hdk-radius);color:var(--color-bg);font-size:var(--hdk-text-base);font-weight:var(--font-weight-semibold);cursor:pointer;transition:opacity .2s ease}.chat-interface__send-button:hover:not(:disabled){opacity:.9}.chat-interface__send-button:disabled{opacity:.5;cursor:not-allowed}.resume-viewer{display:flex;flex-direction:column;flex:1;min-height:0;color:var(--color-text);user-select:text}.resume-viewer__toolbar{flex:none;display:flex;gap:.5rem;align-items:center;justify-content:flex-start;padding:.625rem 1rem;background-color:var(--color-bg-card);border-bottom:1px solid var(--color-border)}.resume-viewer__scroll{flex:1;min-height:0;overflow-y:auto;padding:1.5rem 1rem 2.5rem}.resume-viewer__toggle{display:flex;gap:.25rem;margin-right:.5rem}.resume-viewer__downloads{display:flex;align-items:center;gap:.5rem}.resume-viewer__downloads-label{font-size:.85rem;color:var(--color-text-secondary)}.resume-viewer__toggle-btn{padding:.25rem .75rem;background-color:var(--color-bg);color:var(--color-text-secondary);border:1px solid var(--color-border);border-radius:var(--hdk-radius);font-size:var(--hdk-text-sm);cursor:pointer;transition:background-color .15s ease,color .15s ease}.resume-viewer__toggle-btn--active{background-color:var(--color-primary);color:var(--color-bg);border-color:var(--color-primary)}.resume-viewer__print{display:none}.resume-viewer__download-button{display:inline-block;line-height:1.4;text-decoration:none;padding:.25rem .75rem;background-color:var(--color-bg);color:var(--color-text-secondary);border:1px solid var(--color-border);border-radius:var(--hdk-radius);font-size:var(--hdk-text-sm);cursor:pointer;transition:background-color .15s ease,color .15s ease}.resume-viewer__download-button:hover{background-color:var(--color-primary);color:var(--color-bg)}.resume-viewer__schedule-button{margin-left:auto;display:inline-block;line-height:1.4;text-decoration:none;padding:.25rem .75rem;background-color:var(--color-primary);color:var(--color-bg);border:1px solid var(--color-primary);border-radius:var(--hdk-radius);font-size:var(--hdk-text-sm);cursor:pointer;transition:background-color .15s ease,color .15s ease}.resume-viewer__schedule-button:hover{background-color:var(--color-bg);color:var(--color-primary)}.context-menu{background-color:var(--color-bg-card);border:1px solid var(--color-border);border-radius:var(--hdk-radius);box-shadow:var(--hdk-shadow-md);padding:.25rem;min-width:150px}.context-menu__item{width:100%;padding:.5rem 1rem;background:none;border:none;text-align:left;color:var(--color-text);font-size:var(--hdk-text-sm);cursor:pointer;border-radius:var(--hdk-radius-sm);transition:background-color .2s ease}.context-menu__item:hover{background-color:var(--color-bg-hover)}.resume-viewer--loading,.resume-viewer--error{display:block;text-align:center;padding:4rem 2rem}.resume-viewer__error-message{border-left:3px solid var(--color-danger);padding-left:.5rem;color:var(--color-text);margin-bottom:1rem}.resume-viewer__retry-button{padding:.5rem 1rem;background-color:var(--color-primary);border:none;border-radius:var(--hdk-radius);color:var(--color-bg);font-size:var(--hdk-text-base);cursor:pointer;transition:opacity .2s ease}.resume-viewer__retry-button:hover{opacity:.9}.resume-doc__sheet{max-width:52rem;margin:0 auto 1.25rem;padding:2.5rem 3rem 2.75rem;background-color:var(--color-bg-card);border:1px solid var(--color-border);border-radius:var(--hdk-radius-lg);box-shadow:var(--hdk-shadow-sm)}.resume-doc__sheet:last-child{margin-bottom:0}.resume-doc__name{margin:0 0 .35rem;font-size:2rem;font-weight:var(--font-weight-bold);line-height:1.15;letter-spacing:-.02em;color:var(--color-text)}.resume-doc p.resume-doc__contact{margin:0;font-size:var(--hdk-text-sm);line-height:1.6;color:var(--color-text-secondary)}.resume-doc--resume .resume-doc__section--masthead{padding-bottom:1.25rem;border-bottom:2px solid var(--color-border)}.resume-doc__section-title{display:flex;align-items:center;gap:.6rem;margin:2.25rem 0 1rem;font-size:var(--hdk-text-xs);font-weight:var(--font-weight-bold);letter-spacing:.14em;text-transform:uppercase;color:var(--color-text)}.resume-doc__section-title:after{content:"";flex:1;height:1px;background-color:var(--color-border)}.resume-doc__section:first-child .resume-doc__section-title{margin-top:0}.resume-doc__section--masthead+.resume-doc__section .resume-doc__section-title{margin-top:1.5rem}.resume-doc p{margin:0 0 .9rem;font-size:var(--hdk-text-base);line-height:1.65;color:var(--color-text)}.resume-doc p:last-child{margin-bottom:0}.resume-doc h3{margin:1.75rem 0 .2rem;font-size:1.0625rem;font-weight:var(--font-weight-bold);line-height:1.35;letter-spacing:-.01em;color:var(--color-text)}.resume-doc h3:first-child{margin-top:0}.resume-doc p.resume-doc__meta{margin:0 0 .75rem;font-size:var(--hdk-text-xs);letter-spacing:.04em;color:var(--color-text-secondary)}.resume-doc p.resume-doc__meta em{font-style:normal}.resume-doc ul,.resume-doc ol{margin:0 0 1rem;padding-left:1.35rem}.resume-doc ul{list-style:none}.resume-doc ol{list-style:decimal}.resume-doc li{margin-bottom:.55rem;font-size:var(--hdk-text-base);line-height:1.65;color:var(--color-text)}.resume-doc ul>li{position:relative}.resume-doc ul>li:before{content:"";position:absolute;left:-.95rem;top:.68em;width:5px;height:5px;border-radius:50%;background-color:var(--color-primary)}.resume-doc li:last-child{margin-bottom:0}.resume-doc a{color:var(--color-text);text-decoration:underline;text-decoration-color:var(--color-border);text-decoration-thickness:1px;text-underline-offset:.18em;transition:text-decoration-color .2s ease}.resume-doc a:hover{text-decoration-color:var(--color-text);text-decoration-thickness:2px}.resume-doc strong{font-weight:var(--font-weight-semibold);color:var(--color-text)}.resume-doc em{font-style:italic}.resume-doc code{padding:.1rem .3rem;background-color:var(--color-bg-alt);border:1px solid var(--color-border);border-radius:var(--hdk-radius-sm);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.875em}.resume-doc p.resume-doc__lede{margin:0 0 1.5rem;padding:.85rem 1.1rem;background-color:var(--color-primary-bg);border-left:3px solid var(--color-primary);border-radius:0 var(--hdk-radius) var(--hdk-radius) 0;font-size:var(--hdk-text-sm);line-height:1.65;color:var(--color-text)}.resume-doc__section--projects h3{display:inline-block;margin:1.6rem 0 .85rem;padding:.2rem .6rem;background-color:var(--color-primary-bg);border-radius:var(--hdk-radius-sm);font-size:var(--hdk-text-xs);font-weight:var(--font-weight-bold);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-primary-bg)}.resume-doc__section--projects .resume-doc__entry{margin:0 0 .5rem;padding:.15rem 0 .65rem .95rem;border-left:2px solid var(--color-border);font-size:var(--hdk-text-sm);line-height:1.7;color:var(--color-text-secondary);transition:border-color .2s ease}.resume-doc__section--projects .resume-doc__entry:hover{border-left-color:var(--color-primary)}.resume-doc__section--projects .resume-doc__entry>strong:first-child{display:block;margin-bottom:.15rem;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--hdk-text-base);font-weight:var(--font-weight-semibold);letter-spacing:-.01em;color:var(--color-text)}.resume-doc__links{display:block;margin-top:.45rem}.resume-doc__section--projects .resume-doc__entry a{display:inline-block;margin:0 .35rem 0 0;padding:.1rem .6rem;background-color:var(--color-bg-alt);border:1px solid var(--color-border);border-radius:999px;font-size:var(--hdk-text-xs);font-weight:var(--font-weight-semibold);letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-secondary);text-decoration:none;transition:background-color .15s ease,border-color .15s ease,color .15s ease}.resume-doc__section--projects .resume-doc__entry a:hover{background-color:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.resume-doc__section--technical-skills .resume-doc__entry{margin:0 0 .9rem;padding-left:.85rem;border-left:2px solid var(--color-border);font-size:var(--hdk-text-sm);line-height:1.7;color:var(--color-text-secondary)}.resume-doc__section--technical-skills .resume-doc__entry>strong:first-child{display:block;margin-bottom:.1rem;font-size:var(--hdk-text-xs);font-weight:var(--font-weight-bold);letter-spacing:.1em;text-transform:uppercase;color:var(--color-text)}.resume-doc--letter .resume-doc__sheet{max-width:44rem}.resume-doc--letter p{margin-bottom:1.1rem}@media(max-width:1024px){.resume-bot__content{flex-direction:column}.resume-bot__chat-section{width:100%;height:400px}.resume-bot__resume-section{flex:1;min-height:500px}}@media(max-width:720px){.resume-bot{padding:1rem}.resume-bot__resume-section{min-height:0}.resume-bot__chat-section{position:fixed;z-index:1100;top:.75rem;right:.75rem;bottom:5rem;width:min(calc(100% - 1.5rem),26rem);height:auto;box-shadow:var(--hdk-shadow-md);transform:translate(calc(100% + 1.5rem));visibility:hidden;transition:transform .25s ease,visibility 0s linear .25s}.resume-bot__chat-section--open{transform:translate(0);visibility:visible;transition:transform .25s ease}.resume-bot__chat-scrim--open{display:block;position:fixed;inset:0;z-index:1050;padding:0;border:none;background-color:#00000059}.resume-bot__chat-fab{display:flex;position:fixed;z-index:1200;right:1rem;bottom:1rem;align-items:center;justify-content:center;width:3.5rem;height:3.5rem;padding:0;border:none;border-radius:50%;background-color:var(--color-primary);color:var(--color-bg);box-shadow:var(--hdk-shadow-md);cursor:pointer;transition:transform .15s ease}.resume-bot__chat-fab:active{transform:scale(.94)}.resume-viewer__scroll{padding:1rem .5rem 2rem}.resume-doc__sheet{padding:1.5rem 1.25rem 1.75rem}.resume-doc__name{font-size:1.5rem}.resume-viewer__toolbar{flex-wrap:wrap;row-gap:.5rem}}@media print{.app-header,.resume-bot__chat-section,.resume-bot__chat-fab,.resume-bot__chat-scrim,.resume-viewer__toolbar,.context-menu{display:none!important}.resume-bot,.resume-bot-container{height:auto;min-height:0;padding:0}.resume-bot__content,.resume-bot__resume-section{overflow:visible;display:block;box-shadow:none;background-color:transparent}.resume-viewer{display:block;padding:0}.resume-viewer__scroll{overflow:visible;padding:0}.resume-doc__sheet{max-width:none;margin:0;padding:0;background-color:transparent;border:0;border-radius:0;box-shadow:none}.resume-viewer__screen{display:none!important}.resume-viewer__print{display:block}.resume-viewer__pagebreak{break-before:page}}
|
|
1
|
+
@property --advanced-gradient{syntax: "*"; inherits: false;}:root,[data-theme=light]{color-scheme:light;--color-primary: #2563eb;--color-primary-dark: #1d4ed8;--color-primary-bg: #eff6ff;--color-primary-hover: rgba(37, 99, 235, .06);--color-on-primary: white;--color-on-primary-bg: #2563eb;--color-success: #0ea5e9;--color-success-dark: #0284c7;--color-success-bg: rgba(14, 165, 233, .1);--color-success-hover: rgba(14, 165, 233, .06);--color-on-success: black;--color-on-success-bg: #0067a7;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-hover: rgba(245, 158, 11, .06);--color-on-warning: black;--color-on-warning-bg: #9e4d00;--color-danger: #f97316;--color-danger-dark: #ea580c;--color-danger-bg: #ffedd5;--color-danger-hover: rgba(249, 115, 22, .06);--color-on-danger: black;--color-on-danger-bg: #c13e00;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #e2e8f0;--color-neutral-hover: rgba(100, 116, 139, .06);--color-on-neutral: white;--color-on-neutral-bg: #58677d;--color-text: #0f172a;--color-text-secondary: #475569;--color-text-tertiary: #64748b;--color-text-muted: #94a3b8;--color-border: #cdd4db;--color-border-light: #dfe5ed;--color-bg: #e7eef5;--color-bg-card: #ffffff;--color-bg-alt: #e7eef5;--color-bg-hover: #e2e9f0;--color-bg-overlay: rgba(15, 23, 42, .5);--hdk-space-xs: 2px;--hdk-space-sm: 4px;--hdk-space-md: 8px;--hdk-space-lg: 12px;--hdk-space-xl: 16px;--hdk-space-2xl: 20px;--hdk-space-3xl: 24px;--hdk-space-4xl: 40px;--hdk-space-5xl: 60px;--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--hdk-text-xs: 12px;--hdk-text-sm: 14px;--hdk-text-md: 15px;--hdk-text-base: 16px;--hdk-text-lg: 24px;--font-weight-normal: 400;--font-weight-semibold: 500;--font-weight-bold: 600;--line-height-normal: 1.4;--line-height-relaxed: 1.5;--hdk-radius-sm: 4px;--hdk-radius: 6px;--hdk-radius-lg: 8px;--hdk-shadow-sm: 0 1px 2px rgba(15, 23, 42, .04);--hdk-shadow-md: 0 2px 4px rgba(15, 23, 42, .08);--hdk-shadow-lg: 0 4px 12px rgba(15, 23, 42, .15);--hdk-shadow-focus: 0 0 0 3px rgba(37, 99, 235, .2);--hdk-shadow-focus-sm: 0 0 0 2px rgba(37, 99, 235, .2);--hdk-shadow-focus-alt: 0 0 0 2px rgba(37, 99, 235, .1);--transition-fast: .15s ease;--transition-smooth: .2s ease}[data-theme=light]{--advanced-stop-1-l: .82;--advanced-stop-1-c: .18;--advanced-stop-1-h: 55;--advanced-stop-2-l: .78;--advanced-stop-2-c: .2;--advanced-stop-2-h: 40;--advanced-stop-3-l: .72;--advanced-stop-3-c: .22;--advanced-stop-3-h: 25;--advanced-stop-4-l: .7;--advanced-stop-4-c: .18;--advanced-stop-4-h: 10;--advanced-stop-5-l: .72;--advanced-stop-5-c: .16;--advanced-stop-5-h: 355;--advanced-stop-6-l: .68;--advanced-stop-6-c: .14;--advanced-stop-6-h: 190;--advanced-stop-7-l: .6;--advanced-stop-7-c: .16;--advanced-stop-7-h: 200;--advanced-stop-8-l: .5;--advanced-stop-8-c: .18;--advanced-stop-8-h: 210;--advanced-gradient: linear-gradient( 135deg, oklch(var(--advanced-stop-1-l) var(--advanced-stop-1-c) var(--advanced-stop-1-h)) 0%, oklch(var(--advanced-stop-2-l) var(--advanced-stop-2-c) var(--advanced-stop-2-h)) 15%, oklch(var(--advanced-stop-3-l) var(--advanced-stop-3-c) var(--advanced-stop-3-h)) 30%, oklch(var(--advanced-stop-4-l) var(--advanced-stop-4-c) var(--advanced-stop-4-h)) 45%, oklch(var(--advanced-stop-5-l) var(--advanced-stop-5-c) var(--advanced-stop-5-h)) 55%, oklch(var(--advanced-stop-6-l) var(--advanced-stop-6-c) var(--advanced-stop-6-h)) 70%, oklch(var(--advanced-stop-7-l) var(--advanced-stop-7-c) var(--advanced-stop-7-h)) 85%, oklch(var(--advanced-stop-8-l) var(--advanced-stop-8-c) var(--advanced-stop-8-h)) 100% )}[data-theme=dark]{color-scheme:dark only;--color-primary: #b793ff;--color-primary-dark: #a17de7;--color-primary-bg: rgba(183, 147, 255, .16);--color-primary-hover: rgba(183, 147, 255, .12);--color-on-primary: black;--color-on-primary-bg: #b793ff;--color-success: #fcde3d;--color-success-dark: #e5c70e;--color-success-bg: rgba(252, 222, 61, .15);--color-success-hover: rgba(252, 222, 61, .1);--color-on-success: black;--color-on-success-bg: #fcde3d;--color-warning: #ffb848;--color-warning-dark: #e7a22b;--color-warning-bg: rgba(255, 184, 72, .15);--color-warning-hover: rgba(255, 184, 72, .1);--color-on-warning: black;--color-on-warning-bg: #ffb848;--color-danger: #f46a82;--color-danger-dark: #db536d;--color-danger-bg: rgba(244, 106, 130, .15);--color-danger-hover: rgba(244, 106, 130, .1);--color-on-danger: black;--color-on-danger-bg: #fb7088;--color-neutral: #9d9ea6;--color-neutral-dark: #888991;--color-neutral-bg: #2f3038;--color-neutral-hover: rgba(157, 158, 166, .1);--color-on-neutral: black;--color-on-neutral-bg: #9d9ea6;--color-text: #f4f2f9;--color-text-secondary: #dcd9e3;--color-text-tertiary: #c0bbcb;--color-text-muted: #948f9e;--color-border: #3c3d40;--color-border-light: #525256;--color-bg: #151618;--color-bg-card: #222325;--color-bg-alt: #101013;--color-bg-hover: #2c2c30;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(183, 147, 255, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(183, 147, 255, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(183, 147, 255, .2)}[data-theme=strawberry-light]{color-scheme:light;--color-primary: #ff6b9d;--color-primary-dark: #ff477a;--color-primary-bg: #fff5f8;--color-primary-hover: rgba(255, 107, 157, .1);--color-on-primary: black;--color-on-primary-bg: #c6356d;--color-success: #22c55e;--color-success-dark: #16a34a;--color-success-bg: rgba(34, 197, 94, .1);--color-success-hover: rgba(34, 197, 94, .06);--color-on-success: black;--color-on-success-bg: #006d00;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-hover: rgba(245, 158, 11, .06);--color-on-warning: black;--color-on-warning-bg: #984700;--color-danger: #ec4899;--color-danger-dark: #db2777;--color-danger-bg: #ffe4e9;--color-danger-hover: rgba(236, 72, 153, .06);--color-on-danger: black;--color-on-danger-bg: #c51a78;--color-neutral: #94a3b8;--color-neutral-dark: #728094;--color-neutral-bg: #fdd5e0;--color-neutral-hover: rgba(148, 163, 184, .06);--color-on-neutral: black;--color-on-neutral-bg: #546275;--color-text: #1f1c1e;--color-text-secondary: #6b5a5e;--color-text-tertiary: #a78b92;--color-text-muted: #c4a4ab;--color-border: #f3becf;--color-border-light: #f6d7e0;--color-bg: #f0e6e9;--color-bg-card: #fff9fc;--color-bg-alt: #ecdde1;--color-bg-hover: #eccdd6;--color-bg-overlay: rgba(255, 107, 157, .3);--hdk-shadow-sm: 0 1px 2px rgba(255, 107, 157, .08);--hdk-shadow-md: 0 2px 4px rgba(255, 107, 157, .12);--hdk-shadow-lg: 0 8px 24px rgba(255, 107, 157, .2);--hdk-shadow-focus: 0 0 0 3px rgba(255, 107, 157, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(255, 107, 157, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(255, 107, 157, .15)}[data-theme=strawberry-dark]{color-scheme:dark only;--color-primary: #f6526f;--color-primary-dark: #dd395b;--color-primary-bg: rgba(246, 82, 111, .16);--color-primary-hover: rgba(246, 82, 111, .12);--color-on-primary: black;--color-on-primary-bg: #ff6781;--color-success: #6fda75;--color-success-dark: #57c35f;--color-success-bg: rgba(111, 218, 117, .15);--color-success-hover: rgba(111, 218, 117, .1);--color-on-success: black;--color-on-success-bg: #6fda75;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #f2823b;--color-danger-dark: #da6c1f;--color-danger-bg: rgba(242, 130, 59, .15);--color-danger-hover: rgba(242, 130, 59, .1);--color-on-danger: black;--color-on-danger-bg: #f2823b;--color-neutral: #889e94;--color-neutral-dark: #73897f;--color-neutral-bg: #20362c;--color-neutral-hover: rgba(136, 158, 148, .1);--color-on-neutral: black;--color-on-neutral-bg: #8ba197;--color-text: #ffefef;--color-text-secondary: #edd4d6;--color-text-tertiary: #dbb2b7;--color-text-muted: #ab888c;--color-border: #2f5838;--color-border-light: #3f704a;--color-bg: #0a1a13;--color-bg-card: #16271f;--color-bg-alt: #05140e;--color-bg-hover: #1e3129;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(246, 82, 111, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(246, 82, 111, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(246, 82, 111, .2)}[data-theme=ocean-light]{color-scheme:light;--color-primary: #06b6d4;--color-primary-dark: #0891b2;--color-primary-bg: #ecfeff;--color-primary-hover: rgba(6, 182, 212, .08);--color-on-primary: black;--color-on-primary-bg: #007b97;--color-success: #f97316;--color-success-dark: #ea580c;--color-success-bg: rgba(249, 115, 22, .1);--color-success-hover: rgba(249, 115, 22, .06);--color-on-success: black;--color-on-success-bg: #af2c00;--color-warning: #eab308;--color-warning-dark: #c48e00;--color-warning-bg: rgba(234, 179, 8, .1);--color-warning-hover: rgba(234, 179, 8, .06);--color-on-warning: black;--color-on-warning-bg: #8a5600;--color-danger: #ec4899;--color-danger-dark: #db2777;--color-danger-bg: #fce7f3;--color-danger-hover: rgba(236, 72, 153, .06);--color-on-danger: black;--color-on-danger-bg: #c51a78;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #e0f2fe;--color-neutral-hover: rgba(100, 116, 139, .06);--color-on-neutral: white;--color-on-neutral-bg: #5b6a80;--color-text: #0c4a6e;--color-text-secondary: #075985;--color-text-tertiary: #0ea5e9;--color-text-muted: #38bdf8;--color-border: #95e2eb;--color-border-light: #c4eef2;--color-bg: #e6eff5;--color-bg-card: #ffffff;--color-bg-alt: #d6e8f4;--color-bg-hover: #c5f0f4;--color-bg-overlay: rgba(8, 47, 73, .3);--hdk-shadow-sm: 0 1px 2px rgba(6, 182, 212, .08);--hdk-shadow-md: 0 2px 4px rgba(6, 182, 212, .12);--hdk-shadow-lg: 0 8px 24px rgba(6, 182, 212, .2);--hdk-shadow-focus: 0 0 0 3px rgba(6, 182, 212, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(6, 182, 212, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(6, 182, 212, .15)}[data-theme=ocean-dark]{color-scheme:dark only;--color-primary: #06b6d4;--color-primary-dark: #0891b2;--color-primary-bg: #0c4a6e;--color-primary-hover: rgba(6, 182, 212, .15);--color-on-primary: black;--color-on-primary-bg: #30c6e5;--color-success: #f97316;--color-success-dark: #ea580c;--color-success-bg: rgba(249, 115, 22, .15);--color-success-hover: rgba(249, 115, 22, .1);--color-on-success: black;--color-on-success-bg: #ffb568;--color-warning: #fbbf24;--color-warning-dark: #d59a00;--color-warning-bg: rgba(251, 191, 36, .15);--color-warning-hover: rgba(251, 191, 36, .1);--color-on-warning: black;--color-on-warning-bg: #ffc935;--color-danger: #ec4899;--color-danger-dark: #db2777;--color-danger-bg: #500724;--color-danger-hover: rgba(236, 72, 153, .1);--color-on-danger: black;--color-on-danger-bg: #f34f9f;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #1e3a52;--color-neutral-hover: rgba(100, 116, 139, .1);--color-on-neutral: white;--color-on-neutral-bg: #95a6be;--color-text: #e0f2fe;--color-text-secondary: #bae6fd;--color-text-tertiary: #7dd3fc;--color-text-muted: #0ea5e9;--color-border: #34697f;--color-border-light: #0e7490;--color-bg: #082f49;--color-bg-card: #0c4a6e;--color-bg-alt: #164e63;--color-bg-hover: #0e7490;--color-bg-overlay: rgba(0, 0, 0, .7);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .6);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(6, 182, 212, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(6, 182, 212, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(6, 182, 212, .2)}[data-theme=cyberpunk-light]{color-scheme:light;--color-primary: #ff006e;--color-primary-dark: #ea005e;--color-primary-bg: #fff0f7;--color-primary-hover: rgba(255, 0, 110, .08);--color-on-primary: black;--color-on-primary-bg: #d90052;--color-success: #00f5d4;--color-success-dark: #00d9c0;--color-success-bg: rgba(0, 245, 212, .1);--color-success-hover: rgba(0, 245, 212, .06);--color-on-success: black;--color-on-success-bg: #007158;--color-warning: #ff9f1c;--color-warning-dark: #d77b00;--color-warning-bg: rgba(255, 159, 28, .1);--color-warning-hover: rgba(255, 159, 28, .06);--color-on-warning: black;--color-on-warning-bg: #a04800;--color-danger: #fb5607;--color-danger-dark: #e04f06;--color-danger-bg: #ffe8dc;--color-danger-hover: rgba(251, 86, 7, .06);--color-on-danger: black;--color-on-danger-bg: #cc2200;--color-neutral: #9849d8;--color-neutral-dark: #761eb1;--color-neutral-bg: #e9d5ff;--color-neutral-hover: rgba(157, 78, 221, .06);--color-on-neutral: white;--color-on-neutral-bg: #8634c4;--color-text: #1a1a2e;--color-text-secondary: #3d3d5c;--color-text-tertiary: #6b6b8a;--color-text-muted: #9999b3;--color-border: #dacaf8;--color-border-light: #eadff9;--color-bg: #ececf5;--color-bg-card: #ffffff;--color-bg-alt: #e8e6f2;--color-bg-hover: #e3d8f2;--color-bg-overlay: rgba(26, 26, 46, .4);--hdk-shadow-sm: 0 1px 3px rgba(255, 0, 110, .12);--hdk-shadow-md: 0 2px 6px rgba(255, 0, 110, .18);--hdk-shadow-lg: 0 8px 24px rgba(255, 0, 110, .25);--hdk-shadow-focus: 0 0 0 3px rgba(255, 0, 110, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(255, 0, 110, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(255, 0, 110, .2)}[data-theme=cyberpunk-dark]{color-scheme:dark only;--color-primary: #22d3ee;--color-primary-dark: #06b6d4;--color-primary-bg: #0a1929;--color-primary-hover: rgba(34, 211, 238, .15);--color-on-primary: black;--color-on-primary-bg: #22d3ee;--color-success: #39ff14;--color-success-dark: #00ff00;--color-success-bg: rgba(57, 255, 20, .15);--color-success-hover: rgba(57, 255, 20, .1);--color-on-success: black;--color-on-success-bg: #39ff14;--color-warning: #ffbe0b;--color-warning-dark: #d89900;--color-warning-bg: rgba(255, 190, 11, .15);--color-warning-hover: rgba(255, 190, 11, .1);--color-on-warning: black;--color-on-warning-bg: #ffbe0b;--color-danger: #ff10f0;--color-danger-dark: #ff00ff;--color-danger-bg: #800080;--color-danger-hover: rgba(255, 16, 240, .1);--color-on-danger: black;--color-on-danger-bg: #ff89ff;--color-neutral: #637389;--color-neutral-dark: #435267;--color-neutral-bg: #1e293b;--color-neutral-hover: rgba(100, 116, 139, .1);--color-on-neutral: white;--color-on-neutral-bg: #8394ab;--color-text: #e0f2fe;--color-text-secondary: #67e8f9;--color-text-tertiary: #22d3ee;--color-text-muted: #0891b2;--color-border: #164e63;--color-border-light: #0e7490;--color-bg: #020617;--color-bg-card: #0c1929;--color-bg-alt: #1e293b;--color-bg-hover: #0f172a;--color-bg-overlay: rgba(0, 0, 0, .8);--hdk-shadow-sm: 0 1px 2px rgba(34, 211, 238, .2);--hdk-shadow-md: 0 2px 4px rgba(34, 211, 238, .3);--hdk-shadow-lg: 0 8px 24px rgba(34, 211, 238, .4);--hdk-shadow-focus: 0 0 0 3px rgba(34, 211, 238, .4);--hdk-shadow-focus-sm: 0 0 0 2px rgba(34, 211, 238, .4);--hdk-shadow-focus-alt: 0 0 0 2px rgba(34, 211, 238, .3);--advanced-stop-1-l: .32;--advanced-stop-1-c: .12;--advanced-stop-1-h: 220;--advanced-stop-2-l: .42;--advanced-stop-2-c: .18;--advanced-stop-2-h: 200;--advanced-stop-3-l: .5;--advanced-stop-3-c: .2;--advanced-stop-3-h: 195;--advanced-stop-4-l: .45;--advanced-stop-4-c: .22;--advanced-stop-4-h: 280;--advanced-stop-5-l: .4;--advanced-stop-5-c: .26;--advanced-stop-5-h: 320;--advanced-stop-6-l: .46;--advanced-stop-6-c: .28;--advanced-stop-6-h: 340;--advanced-stop-7-l: .38;--advanced-stop-7-c: .22;--advanced-stop-7-h: 290;--advanced-stop-8-l: .28;--advanced-stop-8-c: .16;--advanced-stop-8-h: 250;--advanced-gradient: linear-gradient( 135deg, oklch(var(--advanced-stop-1-l) var(--advanced-stop-1-c) var(--advanced-stop-1-h)) 0%, oklch(var(--advanced-stop-2-l) var(--advanced-stop-2-c) var(--advanced-stop-2-h)) 15%, oklch(var(--advanced-stop-3-l) var(--advanced-stop-3-c) var(--advanced-stop-3-h)) 30%, oklch(var(--advanced-stop-4-l) var(--advanced-stop-4-c) var(--advanced-stop-4-h)) 45%, oklch(var(--advanced-stop-5-l) var(--advanced-stop-5-c) var(--advanced-stop-5-h)) 60%, oklch(var(--advanced-stop-6-l) var(--advanced-stop-6-c) var(--advanced-stop-6-h)) 75%, oklch(var(--advanced-stop-7-l) var(--advanced-stop-7-c) var(--advanced-stop-7-h)) 88%, oklch(var(--advanced-stop-8-l) var(--advanced-stop-8-c) var(--advanced-stop-8-h)) 100% )}[data-theme=coffee-light]{color-scheme:light;--color-primary: #ea580c;--color-primary-dark: #d54300;--color-primary-bg: #fffbeb;--color-primary-hover: rgba(234, 88, 12, .08);--color-on-primary: black;--color-on-primary-bg: #cd3c00;--color-success: #eab308;--color-success-dark: #ca8a04;--color-success-bg: rgba(234, 179, 8, .1);--color-success-hover: rgba(234, 179, 8, .06);--color-on-success: black;--color-on-success-bg: #8a5600;--color-warning: #d97706;--color-warning-dark: #bb5b00;--color-warning-bg: rgba(217, 119, 6, .1);--color-warning-hover: rgba(217, 119, 6, .06);--color-on-warning: black;--color-on-warning-bg: #a04300;--color-danger: #78350f;--color-danger-dark: #92400e;--color-danger-bg: #fef3c7;--color-danger-hover: rgba(120, 53, 15, .06);--color-on-danger: white;--color-on-danger-bg: #78350f;--color-neutral: #77706b;--color-neutral-dark: #56504b;--color-neutral-bg: #fde68a;--color-neutral-hover: rgba(120, 113, 108, .06);--color-on-neutral: white;--color-on-neutral-bg: #6b6560;--color-text: #1c1917;--color-text-secondary: #44403c;--color-text-tertiary: #78716c;--color-text-muted: #a8a29e;--color-border: #ead377;--color-border-light: #f0e5ba;--color-bg: #f1edde;--color-bg-card: #ffffff;--color-bg-alt: #f0e5ba;--color-bg-hover: #f0ca9d;--color-bg-overlay: rgba(28, 25, 23, .3);--hdk-shadow-sm: 0 1px 2px rgba(234, 88, 12, .08);--hdk-shadow-md: 0 2px 4px rgba(234, 88, 12, .12);--hdk-shadow-lg: 0 8px 24px rgba(234, 88, 12, .2);--hdk-shadow-focus: 0 0 0 3px rgba(234, 88, 12, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(234, 88, 12, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(234, 88, 12, .15)}[data-theme=coffee-dark]{color-scheme:dark only;--color-primary: #ea580c;--color-primary-dark: #d54300;--color-primary-bg: #292524;--color-primary-hover: rgba(234, 88, 12, .15);--color-on-primary: black;--color-on-primary-bg: #f15f1a;--color-success: #facc15;--color-success-dark: #eab308;--color-success-bg: rgba(250, 204, 21, .15);--color-success-hover: rgba(250, 204, 21, .1);--color-on-success: black;--color-on-success-bg: #facc15;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .15);--color-warning-hover: rgba(245, 158, 11, .1);--color-on-warning: black;--color-on-warning-bg: #ffab29;--color-danger: #57534e;--color-danger-dark: #44403c;--color-danger-bg: #1c1917;--color-danger-hover: rgba(87, 83, 78, .1);--color-on-danger: white;--color-on-danger-bg: #88847e;--color-neutral: #77706b;--color-neutral-dark: #56504b;--color-neutral-bg: #3e3933;--color-neutral-hover: rgba(120, 113, 108, .1);--color-on-neutral: white;--color-on-neutral-bg: #aea6a1;--color-text: #fef3c7;--color-text-secondary: #fde68a;--color-text-tertiary: #fbbf24;--color-text-muted: #d97706;--color-border: #44403c;--color-border-light: #57534e;--color-bg: #1c1917;--color-bg-card: #292524;--color-bg-alt: #3e3933;--color-bg-hover: #44403c;--color-bg-overlay: rgba(0, 0, 0, .75);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .6);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .7);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .8);--hdk-shadow-focus: 0 0 0 3px rgba(234, 88, 12, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(234, 88, 12, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(234, 88, 12, .2)}[data-theme=lavender-light]{color-scheme:light;--color-primary: #c084fc;--color-primary-dark: #a855f7;--color-primary-bg: #faf5ff;--color-primary-hover: rgba(192, 132, 252, .08);--color-on-primary: black;--color-on-primary-bg: #8e52c6;--color-success: #84cc16;--color-success-dark: #65a30d;--color-success-bg: rgba(132, 204, 22, .1);--color-success-hover: rgba(132, 204, 22, .06);--color-on-success: black;--color-on-success-bg: #256700;--color-warning: #f59e0b;--color-warning-dark: #ce7a00;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-hover: rgba(245, 158, 11, .06);--color-on-warning: black;--color-on-warning-bg: #914100;--color-danger: #5e60ea;--color-danger-dark: #4f46e5;--color-danger-bg: #e0e7ff;--color-danger-hover: rgba(99, 102, 241, .06);--color-on-danger: white;--color-on-danger-bg: #5453dc;--color-neutral: #71717a;--color-neutral-dark: #515159;--color-neutral-bg: #e4e4e7;--color-neutral-hover: rgba(113, 113, 122, .06);--color-on-neutral: white;--color-on-neutral-bg: #63636b;--color-text: #1f1f29;--color-text-secondary: #52525b;--color-text-tertiary: #71717a;--color-text-muted: #a1a1aa;--color-border: #d8c4ee;--color-border-light: #e6dbf1;--color-bg: #eae6ef;--color-bg-card: #fdf8ff;--color-bg-alt: #e1d6ed;--color-bg-hover: #d7c3ed;--color-bg-overlay: rgba(192, 132, 252, .25);--hdk-shadow-sm: 0 1px 2px rgba(192, 132, 252, .06);--hdk-shadow-md: 0 2px 4px rgba(192, 132, 252, .1);--hdk-shadow-lg: 0 8px 24px rgba(192, 132, 252, .15);--hdk-shadow-focus: 0 0 0 3px rgba(192, 132, 252, .2);--hdk-shadow-focus-sm: 0 0 0 2px rgba(192, 132, 252, .2);--hdk-shadow-focus-alt: 0 0 0 2px rgba(192, 132, 252, .15)}[data-theme=lavender-dark]{color-scheme:dark only;--color-primary: #cba1fa;--color-primary-dark: #b58be2;--color-primary-bg: rgba(203, 161, 250, .16);--color-primary-hover: rgba(203, 161, 250, .12);--color-on-primary: black;--color-on-primary-bg: #d1a7ff;--color-success: #b3e14d;--color-success-dark: #9dca30;--color-success-bg: rgba(179, 225, 77, .15);--color-success-hover: rgba(179, 225, 77, .1);--color-on-success: black;--color-on-success-bg: #b3e14d;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #f06f84;--color-danger-dark: #d7596f;--color-danger-bg: rgba(240, 111, 132, .15);--color-danger-hover: rgba(240, 111, 132, .1);--color-on-danger: black;--color-on-danger-bg: #ff8c9f;--color-neutral: #9098ab;--color-neutral-dark: #7b8395;--color-neutral-bg: #253154;--color-neutral-hover: rgba(144, 152, 171, .1);--color-on-neutral: black;--color-on-neutral-bg: #969eb1;--color-text: #f3f2fd;--color-text-secondary: #dad9e8;--color-text-tertiary: #bdbad4;--color-text-muted: #918fa6;--color-border: #333e5b;--color-border-light: #3b496e;--color-bg: #0e172f;--color-bg-card: #192341;--color-bg-alt: #27324e;--color-bg-hover: #222d4d;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(203, 161, 250, .3);--hdk-shadow-focus-sm: 0 0 0 2px rgba(203, 161, 250, .3);--hdk-shadow-focus-alt: 0 0 0 2px rgba(203, 161, 250, .2)}[data-theme=pink-light]{color-scheme:light;--color-primary: #ff69b4;--color-primary-dark: #ff1493;--color-primary-bg: #fff0f5;--color-primary-hover: rgba(255, 105, 180, .08);--color-on-primary: black;--color-on-primary-bg: #c32e80;--color-success: #ffb3d9;--color-success-dark: #ff8fcc;--color-success-bg: rgba(255, 179, 217, .15);--color-success-hover: rgba(255, 179, 217, .06);--color-on-success: black;--color-on-success-bg: #8f4c70;--color-warning: #fbbf24;--color-warning-dark: #d59a00;--color-warning-bg: rgba(251, 191, 36, .1);--color-warning-hover: rgba(251, 191, 36, .06);--color-on-warning: black;--color-on-warning-bg: #8d5500;--color-danger: #9856b3;--color-danger-dark: #8e44ad;--color-danger-bg: #e8daef;--color-danger-hover: rgba(155, 89, 182, .06);--color-on-danger: white;--color-on-danger-bg: #8644a0;--color-neutral: #d4a5a5;--color-neutral-dark: #af8282;--color-neutral-bg: #ffd9e0;--color-neutral-hover: rgba(212, 165, 165, .06);--color-on-neutral: black;--color-on-neutral-bg: #825858;--color-text: #4a2a3a;--color-text-secondary: #88576c;--color-text-tertiary: #c48ca0;--color-text-muted: #e5b3c8;--color-border: #ffc0cb;--color-border-light: #ffd9e0;--color-bg: #f4eaee;--color-bg-card: #ffffff;--color-bg-alt: #f0e2e7;--color-bg-hover: #f0cbd2;--color-bg-overlay: rgba(255, 105, 180, .2);--hdk-shadow-sm: 0 1px 2px rgba(255, 105, 180, .08);--hdk-shadow-md: 0 2px 4px rgba(255, 105, 180, .12);--hdk-shadow-lg: 0 8px 24px rgba(255, 105, 180, .15);--hdk-shadow-focus: 0 0 0 3px rgba(255, 105, 180, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(255, 105, 180, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(255, 105, 180, .15)}[data-theme=pink-dark]{color-scheme:dark only;--color-primary: #f799be;--color-primary-dark: #df83a8;--color-primary-bg: rgba(247, 153, 190, .16);--color-primary-hover: rgba(247, 153, 190, .12);--color-on-primary: black;--color-on-primary-bg: #f799be;--color-success: #63e6be;--color-success-dark: #48cfa8;--color-success-bg: rgba(99, 230, 190, .15);--color-success-hover: rgba(99, 230, 190, .1);--color-on-success: black;--color-on-success-bg: #63e6be;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #ae7ee2;--color-danger-dark: #9869cb;--color-danger-bg: rgba(174, 126, 226, .15);--color-danger-hover: rgba(174, 126, 226, .1);--color-on-danger: black;--color-on-danger-bg: #b787ec;--color-neutral: #a5929a;--color-neutral-dark: #907d85;--color-neutral-bg: #3b2b32;--color-neutral-hover: rgba(165, 146, 154, .1);--color-on-neutral: black;--color-on-neutral-bg: #a8959d;--color-text: #ffeef5;--color-text-secondary: #ead4dd;--color-text-tertiary: #d7b2c2;--color-text-muted: #a88896;--color-border: #4a373f;--color-border-light: #624b55;--color-bg: #1d1217;--color-bg-card: #2c1e24;--color-bg-alt: #170d12;--color-bg-hover: #36282e;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .5);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(247, 153, 190, .4);--hdk-shadow-focus-sm: 0 0 0 2px rgba(247, 153, 190, .4);--hdk-shadow-focus-alt: 0 0 0 2px rgba(247, 153, 190, .3)}[data-theme=nature-light]{color-scheme:light;--color-primary: #6bbe4e;--color-primary-dark: #5aa942;--color-primary-bg: #f4faf1;--color-primary-hover: rgba(107, 190, 78, .08);--color-on-primary: black;--color-on-primary-bg: #2c7f00;--color-success: #a7d88f;--color-success-dark: #8dc473;--color-success-bg: rgba(167, 216, 143, .15);--color-success-hover: rgba(167, 216, 143, .06);--color-on-success: black;--color-on-success-bg: #426e29;--color-warning: #ca8a04;--color-warning-dark: #a66800;--color-warning-bg: rgba(202, 138, 4, .1);--color-warning-hover: rgba(202, 138, 4, .06);--color-on-warning: black;--color-on-warning-bg: #8d5100;--color-danger: #c8643b;--color-danger-dark: #bc5930;--color-danger-bg: #f9e8e1;--color-danger-hover: rgba(200, 100, 59, .06);--color-on-danger: black;--color-on-danger-bg: #ad4c21;--color-neutral: #cfc6b0;--color-neutral-dark: #aaa28c;--color-neutral-bg: #ebe7dc;--color-neutral-hover: rgba(207, 198, 176, .06);--color-on-neutral: black;--color-on-neutral-bg: #6d6551;--color-text: #2c2c2c;--color-text-secondary: #5a5a5a;--color-text-tertiary: #8a8a8a;--color-text-muted: #acacac;--color-border: #dad3bf;--color-border-light: #e9e5da;--color-bg: #efede4;--color-bg-card: #ffffff;--color-bg-alt: #ebe8de;--color-bg-hover: #e1ddd2;--color-bg-overlay: rgba(44, 44, 44, .5);--hdk-shadow-sm: 0 1px 2px rgba(107, 190, 78, .08);--hdk-shadow-md: 0 2px 4px rgba(107, 190, 78, .12);--hdk-shadow-lg: 0 8px 24px rgba(107, 190, 78, .2);--hdk-shadow-focus: 0 0 0 3px rgba(107, 190, 78, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(107, 190, 78, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(107, 190, 78, .15)}[data-theme=nature-dark]{color-scheme:dark only;--color-primary: #5ac041;--color-primary-dark: #42a926;--color-primary-bg: rgba(90, 192, 65, .16);--color-primary-hover: rgba(90, 192, 65, .12);--color-on-primary: black;--color-on-primary-bg: #5ac041;--color-success: #52db9c;--color-success-dark: #34c487;--color-success-bg: rgba(82, 219, 156, .15);--color-success-hover: rgba(82, 219, 156, .1);--color-on-success: black;--color-on-success-bg: #52db9c;--color-warning: #f7c243;--color-warning-dark: #e0ab22;--color-warning-bg: rgba(247, 194, 67, .15);--color-warning-hover: rgba(247, 194, 67, .1);--color-on-warning: black;--color-on-warning-bg: #f7c243;--color-danger: #bc4f2b;--color-danger-dark: #a63b14;--color-danger-bg: rgba(190, 81, 45, .15);--color-danger-hover: rgba(190, 81, 45, .1);--color-on-danger: white;--color-on-danger-bg: #ec7b56;--color-neutral: #8f8476;--color-neutral-dark: #807568;--color-neutral-bg: #3b3229;--color-neutral-hover: rgba(143, 132, 118, .1);--color-on-neutral: black;--color-on-neutral-bg: #a89c8e;--color-text: #f8f4e1;--color-text-secondary: #e2dbc1;--color-text-tertiary: #cabe92;--color-text-muted: #9d926c;--color-border: #604734;--color-border-light: #795c45;--color-bg: #1e1811;--color-bg-card: #2c251d;--color-bg-alt: #18130c;--color-bg-hover: #372f26;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .6);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .8);--hdk-shadow-focus: 0 0 0 3px rgba(90, 192, 65, .35);--hdk-shadow-focus-sm: 0 0 0 2px rgba(90, 192, 65, .35);--hdk-shadow-focus-alt: 0 0 0 2px rgba(90, 192, 65, .25)}[data-theme=izakaya-light]{color-scheme:light;--color-primary: #41baae;--color-primary-dark: #369c92;--color-primary-bg: rgba(65, 186, 174, .05);--color-primary-hover: rgba(65, 186, 174, .08);--color-on-primary: black;--color-on-primary-bg: #00534a;--color-success: #a6d8ad;--color-success-dark: #8ccb94;--color-success-bg: rgba(166, 216, 173, .15);--color-success-hover: rgba(166, 216, 173, .06);--color-on-success: black;--color-on-success-bg: #275530;--color-warning: #d4a574;--color-warning-dark: #af8252;--color-warning-bg: rgba(212, 165, 116, .15);--color-warning-hover: rgba(212, 165, 116, .06);--color-on-warning: black;--color-on-warning-bg: #673e07;--color-danger: #c04731;--color-danger-dark: #a23b29;--color-danger-bg: #f97a6f;--color-danger-hover: rgba(192, 71, 49, .06);--color-on-danger: white;--color-on-danger-bg: #720000;--color-neutral: #a8999e;--color-neutral-dark: #85777b;--color-neutral-bg: #d8c8b0;--color-neutral-hover: rgba(168, 153, 158, .06);--color-on-neutral: black;--color-on-neutral-bg: #5e5055;--color-text: #2a2a2a;--color-text-secondary: rgba(42, 42, 42, .8);--color-text-tertiary: rgba(42, 42, 42, .6);--color-text-muted: rgba(42, 42, 42, .4);--color-border: #bfa1a0;--color-border-light: #ceaecb;--color-bg: #f2e6cd;--color-bg-card: #f1c8c8;--color-bg-alt: #d8b888;--color-bg-hover: #d1b1ce;--color-bg-overlay: rgba(42, 42, 42, .45);--hdk-shadow-sm: 0 1px 2px rgba(65, 186, 174, .08);--hdk-shadow-md: 0 2px 4px rgba(65, 186, 174, .12);--hdk-shadow-lg: 0 8px 24px rgba(65, 186, 174, .2);--hdk-shadow-focus: 0 0 0 3px rgba(65, 186, 174, .25);--hdk-shadow-focus-sm: 0 0 0 2px rgba(65, 186, 174, .25);--hdk-shadow-focus-alt: 0 0 0 2px rgba(65, 186, 174, .15)}[data-theme=izakaya-dark]{color-scheme:dark only;--color-primary: #04c5b5;--color-primary-dark: #00ac9e;--color-primary-bg: rgba(4, 197, 181, .16);--color-primary-hover: rgba(4, 197, 181, .12);--color-on-primary: black;--color-on-primary-bg: #04c5b5;--color-success: #61d19a;--color-success-dark: #48ba85;--color-success-bg: rgba(97, 209, 154, .15);--color-success-hover: rgba(97, 209, 154, .1);--color-on-success: black;--color-on-success-bg: #61d19a;--color-warning: #fdbe45;--color-warning-dark: #e5a725;--color-warning-bg: rgba(253, 190, 69, .15);--color-warning-hover: rgba(253, 190, 69, .1);--color-on-warning: black;--color-on-warning-bg: #fdbe45;--color-danger: #c13e2e;--color-danger-dark: #a92517;--color-danger-bg: rgba(193, 62, 46, .15);--color-danger-hover: rgba(193, 62, 46, .1);--color-on-danger: white;--color-on-danger-bg: #f66f5b;--color-neutral: #7f7f87;--color-neutral-dark: #76767e;--color-neutral-bg: #2d343b;--color-neutral-hover: rgba(127, 127, 135, .1);--color-on-neutral: black;--color-on-neutral-bg: #9d9da5;--color-text: #f5f2f5;--color-text-secondary: #ddd9dd;--color-text-tertiary: #c1bcc1;--color-text-muted: #959095;--color-border: #71574b;--color-border-light: #8c6c5e;--color-bg: #14191e;--color-bg-card: #20262c;--color-bg-alt: #0f1318;--color-bg-hover: #2a3036;--color-bg-overlay: rgba(0, 0, 0, .72);--hdk-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);--hdk-shadow-md: 0 2px 4px rgba(0, 0, 0, .55);--hdk-shadow-lg: 0 8px 24px rgba(0, 0, 0, .7);--hdk-shadow-focus: 0 0 0 3px rgba(4, 197, 181, .32);--hdk-shadow-focus-sm: 0 0 0 2px rgba(4, 197, 181, .32);--hdk-shadow-focus-alt: 0 0 0 2px rgba(4, 197, 181, .18)}.app-header__icon-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;width:32px;height:32px;min-width:32px;min-height:32px;padding:0;margin:0;border:none;border-radius:50%;background:none;color:var(--color-text);font:inherit;font-size:var(--hdk-text-lg);line-height:1;text-decoration:none;cursor:pointer;opacity:.7;transition:background-color var(--transition-fast),opacity var(--transition-fast)}.app-header__icon-btn:link,.app-header__icon-btn:visited,.app-header__icon-btn:hover,.app-header__icon-btn:active{color:var(--color-text);text-decoration:none}.app-header__icon-btn:hover{background-color:var(--color-primary-hover);opacity:1}.app-header__icon-btn:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 2px var(--color-primary)}.theme-picker{position:relative}.theme-picker__overlay{position:fixed;inset:0;z-index:99;background:transparent}.theme-picker__dropdown{position:absolute;top:0;left:calc(100% + var(--hdk-space-md));z-index:100;display:flex;flex-direction:column;align-items:flex-start;gap:var(--hdk-space-sm)}.theme-picker__main{display:flex;align-items:flex-start;gap:var(--hdk-space-md)}.theme-picker--open-left .theme-picker__dropdown{left:auto;right:calc(100% + var(--hdk-space-md))}.theme-picker--open-left .theme-picker__main{flex-direction:row-reverse}.theme-picker__pills{display:flex;flex-direction:column;gap:0;border-radius:12px;overflow:hidden;box-shadow:var(--hdk-shadow-lg)}.theme-pill{display:flex;gap:0;background:transparent;border:none;transition:all var(--transition-fast, .15s ease)}.theme-pill:not(:last-child){border-bottom:1px solid rgba(0,0,0,.08)}.theme-pill__btn{flex:1;display:flex;align-items:center;justify-content:center;padding:calc(var(--hdk-space-lg) * 1.2);border:none;background:transparent;cursor:pointer;transition:all var(--transition-fast, .15s ease);position:relative;overflow:visible}.theme-pill__btn--light{background:linear-gradient(135deg,#f8fafc,#f1f5f9);color:#1e293b;border-right:1px solid rgba(0,0,0,.1)}.theme-pill__btn--dark{background:linear-gradient(135deg,#0f172a,#020617);color:#64748b;border-left:1px solid rgba(100,116,139,.1)}.theme-pill:first-child .theme-pill__btn--light{border-top-left-radius:12px}.theme-pill:first-child .theme-pill__btn--dark{border-top-right-radius:12px}.theme-pill:last-child .theme-pill__btn--light{border-bottom-left-radius:12px}.theme-pill:last-child .theme-pill__btn--dark{border-bottom-right-radius:12px}.theme-pill__btn--light:hover{background:linear-gradient(135deg,#fff,#f8fafc);color:var(--color-primary)}.theme-pill__btn--dark:hover{background:linear-gradient(135deg,#1e293b,#0f172a);color:#cbd5e1}.theme-pill__btn--light.active{background:linear-gradient(135deg,#fff,#f0f9ff);color:var(--color-primary);box-shadow:inset 0 0 0 2.2px var(--color-primary);font-weight:var(--font-weight-semibold, 600)}.theme-pill__btn--dark.active{background:linear-gradient(135deg,#020617,#000);color:var(--color-primary);box-shadow:inset 0 0 0 2.2px var(--color-primary);font-weight:var(--font-weight-semibold, 600);filter:brightness(1.1)}.theme-pill__icon{display:flex;align-items:center;justify-content:center;width:20px;height:20px}.theme-pill__icon svg{width:100%;height:100%}.theme-picker__settings-icon{display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:none;background:var(--color-bg-card);color:var(--color-text-secondary);cursor:pointer;transition:all var(--transition-fast, .15s ease);border-radius:50%;box-shadow:var(--hdk-shadow-md);flex-shrink:0}.theme-picker__settings-icon:hover{background:var(--color-primary-bg);color:var(--color-on-primary-bg);transform:rotate(45deg);box-shadow:var(--hdk-shadow-lg)}.theme-picker__settings-icon svg{width:20px;height:20px}.app-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding-bottom:1rem;margin-bottom:1.5rem;border-bottom:1px solid var(--color-border)}.app-header__title{margin:0;color:var(--color-text);font-size:var(--hdk-text-lg);font-weight:700;line-height:1.2;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-header__actions{display:flex;align-items:center;flex-shrink:0;gap:.5rem}.app-header .theme-picker__dropdown,.app-header .theme-picker--open-left .theme-picker__dropdown{top:calc(100% + 8px);left:auto;right:0}.settings-popout{position:relative;display:inline-flex}.settings-popout__overlay{position:fixed;inset:0;z-index:99;background:transparent}.settings-popout__panel{position:absolute;top:calc(100% + 8px);right:0;z-index:100;box-sizing:border-box;width:300px;max-width:calc(100vw - 32px);max-height:calc(100vh - 80px);overflow-y:auto;display:flex;flex-direction:column;gap:14px;padding:16px;border-radius:12px;background:var(--color-bg-card);border:1px solid var(--color-border);box-shadow:0 8px 28px #0000002e;color:var(--color-text)}.settings-popout__header{font-weight:600;font-size:.95rem;color:var(--color-text)}.settings-popout__row{display:flex;align-items:center;justify-content:space-between;gap:10px}.settings-popout__row--stack{flex-direction:column;align-items:stretch;gap:8px}.settings-popout__label{font-size:.8rem;color:var(--color-text-secondary)}.settings-popout__value{font-size:.85rem;font-weight:500;color:var(--color-text)}.settings-popout__value--editable{background:transparent;border:1px solid transparent;border-radius:7px;padding:4px 8px;margin-right:-8px;font-family:inherit;cursor:text;transition:border-color .15s ease}.settings-popout__value--editable:hover,.settings-popout__value--editable:focus-visible{border-color:var(--color-border);outline:none}.settings-popout__label--grow{margin-right:auto}.settings-popout__inline{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex:1 1 auto;min-width:0;flex-wrap:wrap}.settings-popout__inline>.settings-popout__error{flex-basis:100%}.settings-popout__tier{font-size:.78rem;font-weight:600;padding:2px 10px;border-radius:999px;background:var(--color-bg-alt);color:var(--color-text);border:1px solid var(--color-border)}.settings-popout__tier--admin{background:var(--color-primary-bg);color:var(--color-on-primary-bg);border-color:var(--color-primary)}.settings-popout__input{flex:1 1 0;width:0;min-width:0;box-sizing:border-box;font-size:.85rem;padding:5px 8px;border-radius:7px;border:1px solid var(--color-border);background:var(--color-bg);color:var(--color-text)}.settings-popout__input:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 2px var(--color-primary-bg)}.settings-popout__btn{font-size:.78rem;padding:4px 10px;border-radius:7px;border:1px solid var(--color-border);background:var(--color-bg);color:var(--color-text);cursor:pointer;white-space:nowrap;text-decoration:none;transition:background-color .15s ease,border-color .15s ease}.settings-popout__btn:hover:not(:disabled){background:var(--color-bg-alt)}.settings-popout__btn--primary{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.settings-popout__btn--primary:hover:not(:disabled){background:var(--color-primary-dark)}.settings-popout__btn:disabled{opacity:.6;cursor:default}.settings-popout__pill{display:flex;gap:3px;width:100%}.settings-popout__seg{flex:1 1 0;padding:7px 0;font-size:.8rem;font-weight:600;border:1px solid var(--color-border);background:var(--color-bg-alt);color:var(--color-text-secondary);cursor:pointer;transition:background-color .12s ease,color .12s ease}.settings-popout__seg:first-child{border-radius:8px 0 0 8px}.settings-popout__seg:last-child{border-radius:0 8px 8px 0}.settings-popout__seg--filled{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.settings-popout__seg:disabled{cursor:default}.settings-popout__key-form{display:flex;flex-direction:column;gap:6px;width:100%}.settings-popout__error{font-size:.75rem;line-height:1.35;padding:4px 8px;border-radius:6px;background:var(--color-danger-bg);color:var(--color-on-danger-bg)}.settings-popout__hint{font-size:.72rem;line-height:1.35;color:var(--color-text-tertiary)}.resume-bot-container[data-theme=light],.resume-bot-container[data-theme=coffee-light],.resume-bot-container[data-theme=nature-light],.resume-bot-container[data-theme=lavender-light],.resume-bot-container[data-theme=strawberry-light],.resume-bot-container[data-theme=ocean-light],.resume-bot-container[data-theme=cyberpunk-light],.resume-bot-container[data-theme=pink-light]{color-scheme:light}.resume-bot-container[data-theme=dark],.resume-bot-container[data-theme=coffee-dark],.resume-bot-container[data-theme=nature-dark],.resume-bot-container[data-theme=lavender-dark],.resume-bot-container[data-theme=strawberry-dark],.resume-bot-container[data-theme=ocean-dark],.resume-bot-container[data-theme=cyberpunk-dark],.resume-bot-container[data-theme=pink-dark]{color-scheme:dark only}.resume-bot-container[data-dark-theme=true]{--is-dark-theme: 1}.resume-bot-container{min-height:100vh;background-color:var(--color-bg);color:var(--color-text);font-family:var(--font-family);transition:background-color .3s ease,color .3s ease}.resume-bot{max-width:1600px;margin:0 auto;padding:2rem;display:flex;flex-direction:column;height:100vh;box-sizing:border-box}.resume-bot__content{display:flex;gap:1.5rem;flex:1;overflow:hidden}.resume-bot__resume-section{flex:1;min-width:0;display:flex;flex-direction:column;overflow:hidden;background-color:var(--color-bg-alt);border-radius:var(--hdk-radius);box-shadow:var(--hdk-shadow-sm)}.resume-bot__chat-section{width:400px;flex-shrink:0;background-color:var(--color-bg-card);border-radius:var(--hdk-radius);box-shadow:var(--hdk-shadow-sm)}.resume-bot__chat-fab,.resume-bot__chat-scrim{display:none}.chat-interface{display:flex;flex-direction:column;height:100%}.chat-interface__header{display:flex;justify-content:space-between;align-items:center;padding:1rem;border-bottom:1px solid var(--color-border)}.chat-interface__header h3{margin:0;font-size:var(--hdk-text-md);color:var(--color-text)}.chat-interface__clear-button{padding:.5rem 1rem;background-color:var(--color-bg-card);border:1px solid var(--color-border);border-radius:var(--hdk-radius);color:var(--color-text-secondary);font-size:var(--hdk-text-sm);cursor:pointer;transition:all .2s ease}.chat-interface__clear-button:hover{background-color:var(--color-border);color:var(--color-text)}.chat-interface__messages{flex:1;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:1rem}.chat-interface__welcome{padding:2rem;text-align:center;color:var(--color-text-secondary);font-size:var(--hdk-text-base)}.chat-message{display:flex;flex-direction:column;gap:.25rem;max-width:80%}.chat-message--user{align-self:flex-end}.chat-message--assistant{align-self:flex-start;max-width:95%}.chat-message__role{font-size:var(--hdk-text-xs);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);padding:0 .75rem}.chat-message__content{padding:.5rem .75rem;border-radius:var(--hdk-radius);line-height:var(--line-height-normal);white-space:pre-wrap;word-wrap:break-word}.chat-message--assistant .chat-message__content>*{margin:0}.chat-message--user .chat-message__content{background-color:var(--color-danger);color:var(--color-bg)}.chat-message--assistant .chat-message__content{background-color:var(--color-primary);border:1px solid var(--color-border);color:var(--color-bg)}.chat-message--loading .chat-message__content{opacity:.7;font-style:italic}.chat-message--assistant .chat-message__content p,.chat-message--assistant .chat-message__content li{line-height:var(--line-height-normal)}.chat-message--assistant .chat-message__content li strong{font-weight:var(--font-weight-normal)}.chat-message--assistant .chat-message__content em{font-style:italic}.chat-message--assistant .chat-message__content code{padding:.125rem .25rem;background-color:var(--color-neutral-bg);border-radius:3px;font-family:monospace;font-size:.9em}.chat-message--assistant .chat-message__content pre{background-color:var(--color-bg-alt);padding:.75rem;border-radius:4px;overflow-x:auto;margin:.5rem 0}.chat-message--assistant .chat-message__content pre code{background-color:transparent;padding:0}.chat-message--assistant .chat-message__content a{color:var(--color-text);text-decoration:underline}.chat-message--assistant .chat-message__content a:hover{text-decoration-thickness:2px}.chat-message--assistant .chat-message__content h1,.chat-message--assistant .chat-message__content h2,.chat-message--assistant .chat-message__content h3,.chat-message--assistant .chat-message__content h4{margin:.5rem 0 .25rem;font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal)}.chat-message--assistant .chat-message__content h1:first-child,.chat-message--assistant .chat-message__content h2:first-child,.chat-message--assistant .chat-message__content h3:first-child,.chat-message--assistant .chat-message__content h4:first-child{margin-top:0}.chat-message--assistant .chat-message__content h1:last-child,.chat-message--assistant .chat-message__content h2:last-child,.chat-message--assistant .chat-message__content h3:last-child,.chat-message--assistant .chat-message__content h4:last-child{margin-bottom:0}.chat-interface__error{padding:.75rem 1rem;margin:0 1rem;background-color:var(--color-danger-bg);border:1px solid var(--color-danger);border-radius:var(--hdk-radius);color:var(--color-on-danger-bg);font-size:var(--hdk-text-sm)}.chat-interface__input-form{display:flex;gap:.5rem;padding:1rem;border-top:1px solid var(--color-border)}.chat-interface__input{flex:1;padding:.75rem 1rem;border:1px solid var(--color-border);border-radius:var(--hdk-radius);background-color:var(--color-bg);color:var(--color-text);font-size:var(--hdk-text-base);transition:border-color .2s ease}.chat-interface__input:focus{outline:none;border-color:var(--color-primary)}.chat-interface__input:disabled{opacity:.5;cursor:not-allowed}.chat-interface__send-button{padding:.75rem 1.5rem;background-color:var(--color-success);border:none;border-radius:var(--hdk-radius);color:var(--color-bg);font-size:var(--hdk-text-base);font-weight:var(--font-weight-semibold);cursor:pointer;transition:opacity .2s ease}.chat-interface__send-button:hover:not(:disabled){opacity:.9}.chat-interface__send-button:disabled{opacity:.5;cursor:not-allowed}.resume-viewer{display:flex;flex-direction:column;flex:1;min-height:0;color:var(--color-text);user-select:text}.resume-viewer__toolbar{flex:none;display:flex;gap:.5rem;align-items:center;justify-content:flex-start;padding:.625rem 1rem;background-color:var(--color-bg-card);border-bottom:1px solid var(--color-border)}.resume-viewer__scroll{flex:1;min-height:0;overflow-y:auto;padding:1.5rem 1rem 2.5rem}.resume-viewer__toggle{display:flex;gap:.25rem;margin-right:.5rem}.resume-viewer__downloads{display:flex;align-items:center;gap:.5rem}.resume-viewer__downloads-label{font-size:.85rem;color:var(--color-text-secondary)}.resume-viewer__toggle-btn{padding:.25rem .75rem;background-color:var(--color-bg);color:var(--color-text-secondary);border:1px solid var(--color-border);border-radius:var(--hdk-radius);font-size:var(--hdk-text-sm);cursor:pointer;transition:background-color .15s ease,color .15s ease}.resume-viewer__toggle-btn--active{background-color:var(--color-primary);color:var(--color-bg);border-color:var(--color-primary)}.resume-viewer__print{display:none}.resume-viewer__download-button{display:inline-block;line-height:1.4;text-decoration:none;padding:.25rem .75rem;background-color:var(--color-bg);color:var(--color-text-secondary);border:1px solid var(--color-border);border-radius:var(--hdk-radius);font-size:var(--hdk-text-sm);cursor:pointer;transition:background-color .15s ease,color .15s ease}.resume-viewer__download-button:hover{background-color:var(--color-primary);color:var(--color-bg)}.resume-viewer__schedule-button{margin-left:auto;display:inline-block;line-height:1.4;text-decoration:none;padding:.25rem .75rem;background-color:var(--color-primary);color:var(--color-bg);border:1px solid var(--color-primary);border-radius:var(--hdk-radius);font-size:var(--hdk-text-sm);cursor:pointer;transition:background-color .15s ease,color .15s ease}.resume-viewer__schedule-button:hover{background-color:var(--color-bg);color:var(--color-primary)}.context-menu{background-color:var(--color-bg-card);border:1px solid var(--color-border);border-radius:var(--hdk-radius);box-shadow:var(--hdk-shadow-md);padding:.25rem;min-width:150px}.context-menu__item{width:100%;padding:.5rem 1rem;background:none;border:none;text-align:left;color:var(--color-text);font-size:var(--hdk-text-sm);cursor:pointer;border-radius:var(--hdk-radius-sm);transition:background-color .2s ease}.context-menu__item:hover{background-color:var(--color-bg-hover)}.resume-viewer--loading,.resume-viewer--error{display:block;text-align:center;padding:4rem 2rem}.resume-viewer__error-message{border-left:3px solid var(--color-danger);padding-left:.5rem;color:var(--color-text);margin-bottom:1rem}.resume-viewer__retry-button{padding:.5rem 1rem;background-color:var(--color-primary);border:none;border-radius:var(--hdk-radius);color:var(--color-bg);font-size:var(--hdk-text-base);cursor:pointer;transition:opacity .2s ease}.resume-viewer__retry-button:hover{opacity:.9}.resume-doc__sheet{max-width:52rem;margin:0 auto 1.25rem;padding:2.5rem 3rem 2.75rem;background-color:var(--color-bg-card);border:1px solid var(--color-border);border-radius:var(--hdk-radius-lg);box-shadow:var(--hdk-shadow-sm)}.resume-doc__sheet:last-child{margin-bottom:0}.resume-doc__name{margin:0 0 .35rem;font-size:2rem;font-weight:var(--font-weight-bold);line-height:1.15;letter-spacing:-.02em;color:var(--color-text)}.resume-doc p.resume-doc__contact{margin:0;font-size:var(--hdk-text-sm);line-height:1.6;color:var(--color-text-secondary)}.resume-doc--resume .resume-doc__section--masthead{padding-bottom:1.25rem;border-bottom:2px solid var(--color-border)}.resume-doc__section-title{display:flex;align-items:center;gap:.6rem;margin:2.25rem 0 1rem;font-size:var(--hdk-text-xs);font-weight:var(--font-weight-bold);letter-spacing:.14em;text-transform:uppercase;color:var(--color-text)}.resume-doc__section-title:after{content:"";flex:1;height:1px;background-color:var(--color-border)}.resume-doc__section:first-child .resume-doc__section-title{margin-top:0}.resume-doc__section--masthead+.resume-doc__section .resume-doc__section-title{margin-top:1.5rem}.resume-doc p{margin:0 0 .9rem;font-size:var(--hdk-text-base);line-height:1.65;color:var(--color-text)}.resume-doc p:last-child{margin-bottom:0}.resume-doc h3{margin:1.75rem 0 .2rem;font-size:1.0625rem;font-weight:var(--font-weight-bold);line-height:1.35;letter-spacing:-.01em;color:var(--color-text)}.resume-doc h3:first-child{margin-top:0}.resume-doc p.resume-doc__meta{margin:0 0 .75rem;font-size:var(--hdk-text-xs);letter-spacing:.04em;color:var(--color-text-secondary)}.resume-doc p.resume-doc__meta em{font-style:normal}.resume-doc ul,.resume-doc ol{margin:0 0 1rem;padding-left:1.35rem}.resume-doc ul{list-style:none}.resume-doc ol{list-style:decimal}.resume-doc li{margin-bottom:.55rem;font-size:var(--hdk-text-base);line-height:1.65;color:var(--color-text)}.resume-doc ul>li{position:relative}.resume-doc ul>li:before{content:"";position:absolute;left:-.95rem;top:.68em;width:5px;height:5px;border-radius:50%;background-color:var(--color-primary)}.resume-doc li:last-child{margin-bottom:0}.resume-doc a{color:var(--color-text);text-decoration:underline;text-decoration-color:var(--color-border);text-decoration-thickness:1px;text-underline-offset:.18em;transition:text-decoration-color .2s ease}.resume-doc a:hover{text-decoration-color:var(--color-text);text-decoration-thickness:2px}.resume-doc strong{font-weight:var(--font-weight-semibold);color:var(--color-text)}.resume-doc em{font-style:italic}.resume-doc code{padding:.1rem .3rem;background-color:var(--color-bg-alt);border:1px solid var(--color-border);border-radius:var(--hdk-radius-sm);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.875em}.resume-doc p.resume-doc__lede{margin:0 0 1.5rem;padding:.85rem 1.1rem;background-color:var(--color-primary-bg);border-left:3px solid var(--color-primary);border-radius:0 var(--hdk-radius) var(--hdk-radius) 0;font-size:var(--hdk-text-sm);line-height:1.65;color:var(--color-text)}.resume-doc__section--projects h3{display:inline-block;margin:1.6rem 0 .85rem;padding:.2rem .6rem;background-color:var(--color-primary-bg);border-radius:var(--hdk-radius-sm);font-size:var(--hdk-text-xs);font-weight:var(--font-weight-bold);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-primary-bg)}.resume-doc__section--projects .resume-doc__entry{margin:0 0 .5rem;padding:.15rem 0 .65rem .95rem;border-left:2px solid var(--color-border);font-size:var(--hdk-text-sm);line-height:1.7;color:var(--color-text-secondary);transition:border-color .2s ease}.resume-doc__section--projects .resume-doc__entry:hover{border-left-color:var(--color-primary)}.resume-doc__section--projects .resume-doc__entry>strong:first-child{display:block;margin-bottom:.15rem;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--hdk-text-base);font-weight:var(--font-weight-semibold);letter-spacing:-.01em;color:var(--color-text)}.resume-doc__links{display:block;margin-top:.45rem}.resume-doc__section--projects .resume-doc__entry a{display:inline-block;margin:0 .35rem 0 0;padding:.1rem .6rem;background-color:var(--color-bg-alt);border:1px solid var(--color-border);border-radius:999px;font-size:var(--hdk-text-xs);font-weight:var(--font-weight-semibold);letter-spacing:.05em;text-transform:uppercase;color:var(--color-text-secondary);text-decoration:none;transition:background-color .15s ease,border-color .15s ease,color .15s ease}.resume-doc__section--projects .resume-doc__entry a:hover{background-color:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.resume-doc__section--technical-skills .resume-doc__entry{margin:0 0 .9rem;padding-left:.85rem;border-left:2px solid var(--color-border);font-size:var(--hdk-text-sm);line-height:1.7;color:var(--color-text-secondary)}.resume-doc__section--technical-skills .resume-doc__entry>strong:first-child{display:block;margin-bottom:.1rem;font-size:var(--hdk-text-xs);font-weight:var(--font-weight-bold);letter-spacing:.1em;text-transform:uppercase;color:var(--color-text)}.resume-doc--letter .resume-doc__sheet{max-width:44rem}.resume-doc--letter p{margin-bottom:1.1rem}@media(max-width:1024px){.resume-bot__content{flex-direction:column}.resume-bot__chat-section{width:100%;height:400px}.resume-bot__resume-section{flex:1;min-height:500px}}@media(max-width:720px){.resume-bot{padding:1rem}.resume-bot__resume-section{min-height:0}.resume-bot__chat-section{position:fixed;z-index:1100;top:.75rem;right:.75rem;bottom:5rem;width:min(calc(100% - 1.5rem),26rem);height:auto;box-shadow:var(--hdk-shadow-md);transform:translate(calc(100% + 1.5rem));visibility:hidden;transition:transform .25s ease,visibility 0s linear .25s}.resume-bot__chat-section--open{transform:translate(0);visibility:visible;transition:transform .25s ease}.resume-bot__chat-scrim--open{display:block;position:fixed;inset:0;z-index:1050;padding:0;border:none;background-color:#00000059}.resume-bot__chat-fab{display:flex;position:fixed;z-index:1200;right:1rem;bottom:1rem;align-items:center;justify-content:center;width:3.5rem;height:3.5rem;padding:0;border:none;border-radius:50%;background-color:var(--color-primary);color:var(--color-bg);box-shadow:var(--hdk-shadow-md);cursor:pointer;transition:transform .15s ease}.resume-bot__chat-fab:active{transform:scale(.94)}.resume-viewer__scroll{padding:1rem .5rem 2rem}.resume-doc__sheet{padding:1.5rem 1.25rem 1.75rem}.resume-doc__name{font-size:1.5rem}.resume-viewer__toolbar{flex-wrap:wrap;row-gap:.5rem}}@media print{.app-header,.resume-bot__chat-section,.resume-bot__chat-fab,.resume-bot__chat-scrim,.resume-viewer__toolbar,.context-menu{display:none!important}.resume-bot,.resume-bot-container{height:auto;min-height:0;padding:0}.resume-bot__content,.resume-bot__resume-section{overflow:visible;display:block;box-shadow:none;background-color:transparent}.resume-viewer{display:block;padding:0}.resume-viewer__scroll{overflow:visible;padding:0}.resume-doc__sheet{max-width:none;margin:0;padding:0;background-color:transparent;border:0;border-radius:0;box-shadow:none}.resume-viewer__screen{display:none!important}.resume-viewer__print{display:block}.resume-viewer__pagebreak{break-before:page}}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hadoku/resume-bot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.2",
|
|
4
4
|
"description": "AI-powered conversational interface for interactive resume exploration",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"repository": {
|
|
7
8
|
"type": "git",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"react-dom": "^19.0.0"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@wolffm/prefs-client": "npm:@hadoku/prefs-client@^1.1.
|
|
36
|
+
"@wolffm/prefs-client": "npm:@hadoku/prefs-client@^1.1.7",
|
|
36
37
|
"@wolffm/worker-utils": "npm:@hadoku/worker-utils@^1.6.19",
|
|
37
38
|
"hono": "^4.11.4",
|
|
38
39
|
"openai": "^6.21.0",
|