@hadoku/resume-bot 0.0.0-stage → 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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -3
  3. package/dist/App.d.ts +9 -0
  4. package/dist/App.d.ts.map +1 -0
  5. package/dist/ChatInterface-mHtxUGpp.js +128 -0
  6. package/dist/ChatInterface-mHtxUGpp.js.map +1 -0
  7. package/dist/ResumeViewer-C-uxZ-7E.js +296 -0
  8. package/dist/ResumeViewer-C-uxZ-7E.js.map +1 -0
  9. package/dist/builder/BlockCard.d.ts +15 -0
  10. package/dist/builder/BlockCard.d.ts.map +1 -0
  11. package/dist/builder/BuilderApp.d.ts +3 -0
  12. package/dist/builder/BuilderApp.d.ts.map +1 -0
  13. package/dist/builder/api.d.ts +37 -0
  14. package/dist/builder/api.d.ts.map +1 -0
  15. package/dist/builder/entry.d.ts +8 -0
  16. package/dist/builder/entry.d.ts.map +1 -0
  17. package/dist/builder/useBuilderAuth.d.ts +10 -0
  18. package/dist/builder/useBuilderAuth.d.ts.map +1 -0
  19. package/dist/builder.js +537 -0
  20. package/dist/builder.js.map +1 -0
  21. package/dist/components/ChatInterface.d.ts +10 -0
  22. package/dist/components/ChatInterface.d.ts.map +1 -0
  23. package/dist/components/ResumeDocument.d.ts +30 -0
  24. package/dist/components/ResumeDocument.d.ts.map +1 -0
  25. package/dist/components/ResumeViewer.d.ts +12 -0
  26. package/dist/components/ResumeViewer.d.ts.map +1 -0
  27. package/dist/entry-BTJjyohQ.js +154 -0
  28. package/dist/entry-BTJjyohQ.js.map +1 -0
  29. package/dist/entry.d.ts +22 -0
  30. package/dist/entry.d.ts.map +1 -0
  31. package/dist/index.js +9 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/markdown-vendor-61sRGACd.js +10510 -0
  34. package/dist/markdown-vendor-61sRGACd.js.map +1 -0
  35. package/dist/rehype-vendor-C_Q-vwLE.js +5647 -0
  36. package/dist/rehype-vendor-C_Q-vwLE.js.map +1 -0
  37. package/dist/services/api.d.ts +62 -0
  38. package/dist/services/api.d.ts.map +1 -0
  39. package/dist/style.css +1 -0
  40. package/dist/worker/application-extras.d.ts +56 -0
  41. package/dist/worker/application-extras.d.ts.map +1 -0
  42. package/dist/worker/blocks.d.ts +12 -0
  43. package/dist/worker/blocks.d.ts.map +1 -0
  44. package/dist/worker/builder.d.ts +33 -0
  45. package/dist/worker/builder.d.ts.map +1 -0
  46. package/dist/worker/constants.d.ts +39 -0
  47. package/dist/worker/constants.d.ts.map +1 -0
  48. package/dist/worker/contact.d.ts +34 -0
  49. package/dist/worker/contact.d.ts.map +1 -0
  50. package/dist/worker/cover-letter.d.ts +16 -0
  51. package/dist/worker/cover-letter.d.ts.map +1 -0
  52. package/dist/worker/index.d.ts +38 -0
  53. package/dist/worker/index.d.ts.map +1 -0
  54. package/dist/worker/llm.d.ts +77 -0
  55. package/dist/worker/llm.d.ts.map +1 -0
  56. package/dist/worker/pdf.d.ts +46 -0
  57. package/dist/worker/pdf.d.ts.map +1 -0
  58. package/dist/worker/rate-limit.d.ts +10 -0
  59. package/dist/worker/rate-limit.d.ts.map +1 -0
  60. package/dist/worker/resume.d.ts +33 -0
  61. package/dist/worker/resume.d.ts.map +1 -0
  62. package/dist/worker/skeleton.d.ts +73 -0
  63. package/dist/worker/skeleton.d.ts.map +1 -0
  64. package/dist/worker/tailored-resume.d.ts +31 -0
  65. package/dist/worker/tailored-resume.d.ts.map +1 -0
  66. package/dist/worker/typography.d.ts +12 -0
  67. package/dist/worker/typography.d.ts.map +1 -0
  68. package/dist/worker/variants.d.ts +51 -0
  69. package/dist/worker/variants.d.ts.map +1 -0
  70. package/dist/worker.js +42508 -0
  71. package/package.json +44 -4
@@ -0,0 +1,62 @@
1
+ export interface ChatMessage {
2
+ role: 'user' | 'assistant' | 'system';
3
+ content: string;
4
+ }
5
+ export interface ChatResponse {
6
+ message: string;
7
+ usage?: {
8
+ prompt_tokens: number;
9
+ completion_tokens: number;
10
+ total_tokens: number;
11
+ };
12
+ }
13
+ export interface ResumeResponse {
14
+ content: string;
15
+ variant?: string;
16
+ label?: string;
17
+ cover_letter?: string | null;
18
+ company?: string | null;
19
+ job_title?: string | null;
20
+ }
21
+ /** The delivered application packet: résumé + optional tailored cover letter. */
22
+ export interface ResumePacket {
23
+ content: string;
24
+ coverLetter: string | null;
25
+ variant: string | null;
26
+ label: string | null;
27
+ company: string | null;
28
+ jobTitle: string | null;
29
+ }
30
+ export interface ApiError {
31
+ error: string;
32
+ message?: string;
33
+ retryAfter?: number;
34
+ }
35
+ /**
36
+ * Set the API root at runtime.
37
+ * Called by the mount function with the apiBaseUrl prop, which is the API root
38
+ * ('/resume/api') — endpoints are appended to it directly.
39
+ */
40
+ export declare function setApiBaseUrl(url: string): void;
41
+ /**
42
+ * Send a chat message to the backend
43
+ */
44
+ export declare function sendChatMessage(messages: ChatMessage[]): Promise<ChatResponse>;
45
+ /**
46
+ * Fetch the resume content from the backend.
47
+ * Pass a variant slug to fetch a link-tailored resume; the API falls back to
48
+ * the full resume for unknown or expired slugs.
49
+ */
50
+ export declare function fetchResume(variant?: string): Promise<ResumePacket>;
51
+ /**
52
+ * URL of the server-rendered resume PDF (the packet, when the variant carries a
53
+ * cover letter). Same variant fall-back semantics as fetchResume.
54
+ *
55
+ * Returned as a URL rather than a fetched Blob on purpose: the endpoint already
56
+ * sends `Content-Disposition: attachment` with the owner's filename, so linking
57
+ * straight at it downloads the file with no object URL in the middle — and an
58
+ * attachment cannot be hijacked by a browser's "open PDFs in Firefox" handler
59
+ * the way a `blob:` URL can.
60
+ */
61
+ export declare function resumePdfUrl(variant?: string): string;
62
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/services/api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;IACrC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAA;QACrB,iBAAiB,EAAE,MAAM,CAAA;QACzB,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAQD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAepF;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAIrD"}
package/dist/style.css ADDED
@@ -0,0 +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__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}}
@@ -0,0 +1,56 @@
1
+ import type { KVNamespace } from '@cloudflare/workers-types';
2
+ import { type LLMChain } from './llm.js';
3
+ import { type ContactProfile } from './contact.js';
4
+ export interface ApplicationExtrasRequest {
5
+ job_title: string;
6
+ company: string;
7
+ description: string;
8
+ /** The tailored résumé for this job — grounds the extras in what was actually sent. */
9
+ resume_markdown: string;
10
+ /** The JOB's location (city/region as posted) — without it the kit answers
11
+ * location questions from the candidate's own location and reads tone-deaf
12
+ * on hybrid/onsite roles elsewhere. Optional for caller compatibility. */
13
+ job_location?: string;
14
+ /** The job's workplace type as posted: remote | hybrid | onsite | unknown. */
15
+ workplace_type?: string;
16
+ }
17
+ export interface ScreeningAnswer {
18
+ q: string;
19
+ a: string;
20
+ }
21
+ export interface ApplicationExtras {
22
+ /**
23
+ * The cover letter, produced in the same call as the rest of the kit. Folding
24
+ * it in here (rather than a separate /cover-letter request) removes one LLM
25
+ * call from a cold packet, so the extras can't fail independently after the
26
+ * cover letter has already succeeded — the two share one call and one retry.
27
+ */
28
+ cover_letter_markdown: string;
29
+ /** Short outreach note to a recruiter or hiring manager. */
30
+ intro_email: string;
31
+ /** 2-3 sentences on why this company/role — reused in the email and form fields. */
32
+ why_hook: string;
33
+ /** Pre-drafted answers to the questions applications ask over and over. */
34
+ screening_answers: ScreeningAnswer[];
35
+ /** Expected-comp line for the salary field. */
36
+ salary_line: string;
37
+ /** LinkedIn connection note, ≤300 chars. */
38
+ linkedin_note: string;
39
+ /** 3-5 bullets for the recruiter phone screen. */
40
+ talking_points: string[];
41
+ }
42
+ export interface ApplicationExtrasResponse extends ApplicationExtras {
43
+ /** Deterministic copy-paste block for the boring repeated form fields. */
44
+ standard_fields: string;
45
+ /** Raw contact profile, so the UI can offer any single field on its own. */
46
+ contact: ContactProfile;
47
+ cached: boolean;
48
+ }
49
+ /**
50
+ * One LLM call → the full non-résumé half of an application kit. Grounded in the
51
+ * owner's contact profile (for truthful salary/auth/relocation answers) and the
52
+ * tailored résumé (so talking points and screening answers match what was sent).
53
+ * The standard-fields block is assembled deterministically, not generated.
54
+ */
55
+ export declare function generateApplicationExtras(client: LLMChain, kv: KVNamespace, req: ApplicationExtrasRequest): Promise<ApplicationExtrasResponse>;
56
+ //# sourceMappingURL=application-extras.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-extras.d.ts","sourceRoot":"","sources":["../../worker/src/application-extras.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,OAAO,EAAsB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAI5D,OAAO,EAA2C,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAK3F,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,uFAAuF;IACvF,eAAe,EAAE,MAAM,CAAA;IACvB;;+EAE2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,qBAAqB,EAAE,MAAM,CAAA;IAC7B,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAA;IACnB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,iBAAiB,EAAE,eAAe,EAAE,CAAA;IACpC,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAA;IACnB,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAA;IACrB,kDAAkD;IAClD,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,0EAA0E;IAC1E,eAAe,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,OAAO,EAAE,cAAc,CAAA;IACvB,MAAM,EAAE,OAAO,CAAA;CAChB;AAcD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,QAAQ,EAChB,EAAE,EAAE,WAAW,EACf,GAAG,EAAE,wBAAwB,GAC5B,OAAO,CAAC,yBAAyB,CAAC,CAoHpC"}
@@ -0,0 +1,12 @@
1
+ import type { KVNamespace } from '@cloudflare/workers-types';
2
+ export interface ResumeBlock {
3
+ id: string;
4
+ type: 'experience' | 'project' | 'skills' | 'education' | 'summary' | 'header';
5
+ tags: string[];
6
+ title: string;
7
+ content: string;
8
+ priority: number;
9
+ }
10
+ export declare function getAllBlocks(kv: KVNamespace): Promise<ResumeBlock[]>;
11
+ export declare function cacheKey(prefix: string, ...parts: string[]): Promise<string>;
12
+ //# sourceMappingURL=blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../worker/src/blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;IAC9E,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAc1E;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CASlF"}
@@ -0,0 +1,33 @@
1
+ import type { KVNamespace } from '@cloudflare/workers-types';
2
+ import { type ResumeBlock } from './blocks.js';
3
+ export interface BlockFeedbackEntry {
4
+ text: string;
5
+ updated: string;
6
+ }
7
+ export type BlockFeedback = Record<string, BlockFeedbackEntry>;
8
+ /**
9
+ * Strictly validate an untrusted block, mirroring resume_ingest.py: exact field
10
+ * set (no missing, no extra), known type, tags is a string[], priority is an
11
+ * integer, id is a safe non-reserved slug. Throws with a human message on any
12
+ * violation; returns the typed block on success.
13
+ */
14
+ export declare function validateBlock(raw: unknown): ResumeBlock;
15
+ /** Create or update a block. New ids are appended to the render index. */
16
+ export declare function upsertBlock(kv: KVNamespace, block: ResumeBlock): Promise<void>;
17
+ /** Delete a block + drop it from the index. Returns false if it wasn't present. */
18
+ export declare function deleteBlock(kv: KVNamespace, id: string): Promise<boolean>;
19
+ /**
20
+ * Replace the render order. `ids` must be a permutation of the current index.
21
+ *
22
+ * Busts the derived caches like the other two writers: order decides what the
23
+ * résumé actually reads like, so a reorder changes the generated output even
24
+ * though no block's content moved. It did not bust before, which only went
25
+ * unnoticed because the 24h TTL swept everything overnight anyway.
26
+ */
27
+ export declare function reorderBlocks(kv: KVNamespace, ids: string[]): Promise<void>;
28
+ export declare function getFeedback(kv: KVNamespace): Promise<BlockFeedback>;
29
+ /** Upsert (or clear, when text is empty) one block's review note. */
30
+ export declare function setFeedback(kv: KVNamespace, id: string, text: string): Promise<BlockFeedback>;
31
+ /** Blocks in render order — the exact array shape `blocks.json` holds, for git backup. */
32
+ export declare function exportBlocks(kv: KVNamespace): Promise<ResumeBlock[]>;
33
+ //# sourceMappingURL=builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../worker/src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AA6B5D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AACD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;AAE9D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAmCvD;AAuBD,0EAA0E;AAC1E,wBAAsB,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpF;AAED,mFAAmF;AACnF,wBAAsB,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/E;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CASjF;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAGzE;AAED,qEAAqE;AACrE,wBAAsB,WAAW,CAC/B,EAAE,EAAE,WAAW,EACf,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,CAAC,CASxB;AAED,0FAA0F;AAC1F,wBAAsB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAE1E"}
@@ -0,0 +1,39 @@
1
+ export declare const LLM_CONFIG: {
2
+ readonly TEMPERATURE: 0.7;
3
+ readonly MAX_TOKENS: 512;
4
+ };
5
+ /**
6
+ * Every binding a provider entry may name.
7
+ *
8
+ * `LLMEnv` in llm.ts is DERIVED from this, so adding a provider below without
9
+ * widening this union is a compile error rather than a silently skipped
10
+ * provider — which is what happened when CLOUDFLARE_AI_TOKEN and
11
+ * MISTRAL_API_KEY were added against a hardcoded three-name union.
12
+ */
13
+ export type ProviderEnvKey = 'GROQ_API_KEY' | 'GEMINI_API_KEY' | 'GEMINI_API_KEY_2' | 'CLOUDFLARE_AI_TOKEN' | 'MISTRAL_API_KEY';
14
+ export declare const LLM_PROVIDERS: {
15
+ name: string;
16
+ envKey: ProviderEnvKey;
17
+ baseUrl: string;
18
+ model: string;
19
+ authHeader?: string;
20
+ }[];
21
+ export declare const RATE_LIMIT_CONFIG: {
22
+ readonly MAX_REQUESTS_PER_WINDOW: 30;
23
+ readonly WINDOW_DURATION_SECONDS: 60;
24
+ readonly KV_TTL_SECONDS: 120;
25
+ };
26
+ export declare const TAILORED_RESUME_TOKENS: {
27
+ readonly SELECTION: 2048;
28
+ readonly TAILORING: 4096;
29
+ };
30
+ export declare const SELECTION_BUDGET: {
31
+ readonly MAX_REQUEST_TOKENS: 7600;
32
+ readonly CHARS_PER_TOKEN: 3.4;
33
+ readonly LADDER: readonly [readonly [200, 2500], readonly [120, 2000], readonly [80, 1500], readonly [0, 1000]];
34
+ };
35
+ export declare const COVER_LETTER_TOKENS = 2048;
36
+ export declare const APPLICATION_EXTRAS_TOKENS = 3500;
37
+ export declare const OPERATION_BUDGET_MS = 100000;
38
+ export declare const MIN_ATTEMPT_MS = 3000;
39
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../worker/src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;CAGb,CAAA;AA0DV;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,gBAAgB,GAChB,kBAAkB,GAClB,qBAAqB,GACrB,iBAAiB,CAAA;AAErB,eAAO,MAAM,aAAa,EAAE;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,EAuFS,CAAA;AAEV,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAA;AAEV,eAAO,MAAM,sBAAsB;;;CASzB,CAAA;AAUV,eAAO,MAAM,gBAAgB;;;;CAanB,CAAA;AAEV,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAMvC,eAAO,MAAM,yBAAyB,OAAO,CAAA;AAwB7C,eAAO,MAAM,mBAAmB,SAAU,CAAA;AAM1C,eAAO,MAAM,cAAc,OAAQ,CAAA"}
@@ -0,0 +1,34 @@
1
+ import type { KVNamespace } from '@cloudflare/workers-types';
2
+ /**
3
+ * The owner's constant application facts — the boring, repeated form fields plus
4
+ * the context the extras generator needs to answer "why us", salary and
5
+ * sponsorship questions truthfully. Filled once, stored in CONTENT_KV under
6
+ * CONTACT_KEY, never regenerated. The résumé header block carries name/email/
7
+ * phone/linkedin too; this is the single place the standard-fields block and the
8
+ * salary/auth answers read from, so the two never drift.
9
+ */
10
+ export interface ContactProfile {
11
+ name: string;
12
+ email: string;
13
+ phone: string;
14
+ linkedin: string;
15
+ github: string;
16
+ location: string;
17
+ /** e.g. "US citizen — no sponsorship required" */
18
+ work_auth: string;
19
+ /** e.g. "Remote preferred; open to relocation for the right role" */
20
+ relocation: string;
21
+ /**
22
+ * The expected-comp line, phrased as an affirmative signal rather than a hard
23
+ * gate — states the target without reading as an ultimatum.
24
+ */
25
+ salary_line: string;
26
+ }
27
+ export declare const CONTACT_KEY = "resume:profile:contact";
28
+ export declare function getContactProfile(kv: KVNamespace): Promise<ContactProfile | null>;
29
+ /**
30
+ * The copy-paste block for the boring repeated fields on an application form.
31
+ * Deterministic — assembled from the contact profile, no LLM involved.
32
+ */
33
+ export declare function renderStandardFields(p: ContactProfile): string;
34
+ //# sourceMappingURL=contact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact.d.ts","sourceRoot":"","sources":["../../worker/src/contact.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,WAAW,2BAA2B,CAAA;AAEnD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAGvF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAW9D"}
@@ -0,0 +1,16 @@
1
+ import type { KVNamespace } from '@cloudflare/workers-types';
2
+ import { type LLMChain } from './llm.js';
3
+ export interface CoverLetterRequest {
4
+ job_title: string;
5
+ company: string;
6
+ description: string;
7
+ tone?: 'formal' | 'conversational';
8
+ }
9
+ export interface CoverLetterResponse {
10
+ cover_letter_markdown: string;
11
+ cached: boolean;
12
+ }
13
+ export declare function generateCoverLetter(client: LLMChain, kv: KVNamespace, resumeContent: string, req: CoverLetterRequest,
14
+ /** Epoch ms this generation must finish by. See generateTailoredResume. */
15
+ deadline?: number): Promise<CoverLetterResponse>;
16
+ //# sourceMappingURL=cover-letter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cover-letter.d.ts","sourceRoot":"","sources":["../../worker/src/cover-letter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,OAAO,EAAsB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAQ5D,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,gBAAgB,CAAA;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,QAAQ,EAChB,EAAE,EAAE,WAAW,EACf,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,kBAAkB;AACvB,2EAA2E;AAC3E,QAAQ,GAAE,MAAyC,GAClD,OAAO,CAAC,mBAAmB,CAAC,CA6C9B"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Resume Bot Worker Package
3
+ *
4
+ * Exports a factory function for Cloudflare Workers.
5
+ * The host worker in hadoku_site imports this and delegates to it.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // In hadoku_site/workers/resume-api/src/index.ts
10
+ * import { createResumeHandler } from '@wolffm/resume-bot/api';
11
+ * export default createResumeHandler('/resume/api');
12
+ * ```
13
+ */
14
+ import { Hono } from 'hono';
15
+ import type { KVNamespace } from '@cloudflare/workers-types';
16
+ interface ResumeEnv {
17
+ /** Groq API key — the only provider in the chain. See constants.ts. */
18
+ GROQ_API_KEY: string;
19
+ /** Legacy fallback for the system prompt; CONTENT_KV `resume:prompt` wins. */
20
+ RESUME_SYSTEM_PROMPT?: string;
21
+ /**
22
+ * Shared secret proving a request arrived via edge-router. The edge strips any
23
+ * client-supplied X-Edge-Auth/X-Hadoku-Tier and stamps its own, so a valid
24
+ * X-Edge-Auth is proof of provenance and X-Hadoku-Tier can be trusted without
25
+ * re-validating keys here.
26
+ */
27
+ EDGE_AUTH_SECRET: string;
28
+ RATE_LIMIT_KV: KVNamespace;
29
+ CONTENT_KV: KVNamespace;
30
+ }
31
+ export interface ResumeHandlerOptions {
32
+ ownerName?: string;
33
+ }
34
+ export declare function createResumeHandler(basePath: string, options?: ResumeHandlerOptions): Hono<{
35
+ Bindings: ResumeEnv;
36
+ }, import("hono/types").BlankSchema, "/">;
37
+ export type { ResumeEnv };
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../worker/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AA8B5D,UAAU,SAAS;IACjB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAA;IACpB,8EAA8E;IAC9E,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,WAAW,CAAA;IAC1B,UAAU,EAAE,WAAW,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB;cAUrD,SAAS;0CAwZ3C;AAED,YAAY,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,77 @@
1
+ import OpenAI from 'openai';
2
+ import { type ProviderEnvKey } from './constants.js';
3
+ /**
4
+ * Options for one completion. `deadline` is the important one: it is an epoch
5
+ * ms after which no further attempt may START, and it is what keeps a request
6
+ * that fans out across providers and retries inside the edge's 120s patience.
7
+ */
8
+ export interface CompletionOptions {
9
+ maxTokens?: number;
10
+ temperature?: number;
11
+ /** Epoch ms. Attempts stop once there is not a real attempt's worth left. */
12
+ deadline?: number;
13
+ }
14
+ /**
15
+ * Thrown when the budget is spent. Distinct from a provider error on purpose:
16
+ * falling over to the NEXT provider is the right move for a provider failure
17
+ * and exactly the wrong one here, because the clock is shared. sendChatCompletion
18
+ * rethrows this instead of continuing down the chain.
19
+ */
20
+ export declare class DeadlineExceededError extends Error {
21
+ constructor(message: string);
22
+ }
23
+ export interface ChatMessage {
24
+ role: 'system' | 'user' | 'assistant';
25
+ content: string;
26
+ }
27
+ export interface ChatResponse {
28
+ message: string;
29
+ /**
30
+ * Which provider actually answered.
31
+ *
32
+ * The chain falls over on any error, silently and by design, so a generation
33
+ * served by a weaker fallback looks identical to one served by the primary.
34
+ * Without this the first sign of a quality regression is a real job
35
+ * application that reads badly, and no way to attribute it.
36
+ */
37
+ provider: string;
38
+ usage?: {
39
+ prompt_tokens: number;
40
+ completion_tokens: number;
41
+ total_tokens: number;
42
+ };
43
+ }
44
+ /** One free-tier provider in the chain: an OpenAI-compatible client + its model id. */
45
+ export interface LLMProvider {
46
+ name: string;
47
+ client: OpenAI;
48
+ model: string;
49
+ }
50
+ /** A prioritized chain of providers; calls fall over from one to the next. */
51
+ export type LLMChain = LLMProvider[];
52
+ /** Just the key bindings the chain reads — a subset of the worker env. */
53
+ /**
54
+ * The bindings the chain reads. Derived from `ProviderEnvKey` so it cannot fall
55
+ * behind the provider list; the account id is separate because it is not a
56
+ * credential and is substituted into a base URL rather than sent as one.
57
+ */
58
+ export type LLMEnv = Partial<Record<ProviderEnvKey, string>> & {
59
+ /** Substituted into Cloudflare's base URL, which carries it in the path. */
60
+ CLOUDFLARE_ACCOUNT_ID?: string;
61
+ };
62
+ /**
63
+ * Build the provider chain from whatever keys are configured, in LLM_PROVIDERS
64
+ * order. Every provider speaks an OpenAI-compatible API, so a request can fall
65
+ * over from one to the next transparently. A provider is included only when its
66
+ * key binding is present, so a missing key degrades the chain instead of
67
+ * breaking it. Today that list is Groq alone — see constants.ts for why.
68
+ */
69
+ export declare function createLLMClient(env: LLMEnv): LLMChain;
70
+ /**
71
+ * Send a completion through the provider chain: try each in order, falling over
72
+ * to the next free provider on any error (a 429 on Nebius silently rolls to Groq,
73
+ * etc.). Only the final provider retries a rate limit, since there's nothing left
74
+ * to fall back to.
75
+ */
76
+ export declare function sendChatCompletion(chain: LLMChain, messages: ChatMessage[], options?: CompletionOptions): Promise<ChatResponse>;
77
+ //# sourceMappingURL=llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../worker/src/llm.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/F;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAOD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAA;IACrC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;OAOG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAA;QACrB,iBAAiB,EAAE,MAAM,CAAA;QACzB,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;CACF;AAED,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;AAEpC,0EAA0E;AAC1E;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,GAAG;IAC7D,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AA2BD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAyDrD;AA6FD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAoBvB"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Server-side résumé PDF rendering.
3
+ *
4
+ * The download button used to be `window.print()`, which reconstructed the
5
+ * document from the on-screen DOM — fragile (host-page CSS could clip it) and
6
+ * it opened a print dialog instead of downloading a file. This renders the
7
+ * same canonical markdown the viewer displays straight to a paginated PDF, so
8
+ * GET /resume.pdf serves a real file.
9
+ *
10
+ * The résumé markdown is a constrained subset (the builder emits it): `#`
11
+ * headings, paragraphs with hard line breaks, `-` bullet lists, `**bold**`,
12
+ * `*italic*`, `[text](url)` links and `---` rules. This is a purpose-built
13
+ * typesetter for exactly that subset, not a general markdown engine.
14
+ */
15
+ export interface ResumePdfInput {
16
+ /** Résumé markdown (the canonical or variant-rendered content). */
17
+ resume: string;
18
+ /** Optional cover letter markdown — rendered from a fresh page after the résumé. */
19
+ coverLetter?: string | null;
20
+ /** Document metadata: title bar in PDF viewers, and the Author field. */
21
+ ownerName: string;
22
+ }
23
+ interface InlineRun {
24
+ text: string;
25
+ bold: boolean;
26
+ italic: boolean;
27
+ link?: string;
28
+ }
29
+ type Block = {
30
+ kind: 'heading';
31
+ runs: InlineRun[];
32
+ } | {
33
+ kind: 'paragraph';
34
+ lines: InlineRun[][];
35
+ } | {
36
+ kind: 'bullet';
37
+ runs: InlineRun[];
38
+ } | {
39
+ kind: 'rule';
40
+ } | {
41
+ kind: 'page-break';
42
+ };
43
+ export declare function parseBlocks(markdown: string): Block[];
44
+ export declare function renderResumePdf(input: ResumePdfInput): Promise<Uint8Array>;
45
+ export {};
46
+ //# sourceMappingURL=pdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../worker/src/pdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAcH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,KAAK,KAAK,GACN;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,EAAE,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,SAAS,EAAE,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAA;AAoC1B,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,EAAE,CAmCrD;AA+SD,wBAAsB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA0BhF"}
@@ -0,0 +1,10 @@
1
+ import type { KVNamespace } from '@cloudflare/workers-types';
2
+ export interface RateLimitResult {
3
+ allowed: boolean;
4
+ reason: string;
5
+ resetAt: number;
6
+ remaining: number;
7
+ }
8
+ export declare function checkRateLimit(kv: KVNamespace, ip: string): Promise<RateLimitResult>;
9
+ export declare function recordRequest(kv: KVNamespace, ip: string): Promise<void>;
10
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../worker/src/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAG5D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAMD,wBAAsB,cAAc,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAwB1F;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9E"}