@dataimago/interview 0.2.0-alpha.3 → 0.2.0-alpha.4

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/dist/index.cjs CHANGED
@@ -748,27 +748,30 @@ function ReviewSummary({ questions, answers, onGenerate, onEdit, generating }) {
748
748
  const answered = isAnswered(answer);
749
749
  const display = answered ? summarizeLong(q, answer) : "";
750
750
  return (
751
- // Grid so the index + Edit button sit beside the dt/dd group while
752
- // <dt>/<dd> remain DIRECT children of this div (a direct child of
753
- // <dl>) required for valid definition-list semantics (axe
754
- // definition-list / dlitem).
751
+ // A <div> child of <dl> may contain ONLY dt/dd groups (HTML spec;
752
+ // axe definition-list), so the index + Edit button live INSIDE
753
+ // <dt>. Subgrid keeps all three columns aligned across dt and dd
754
+ // without extra wrappers.
755
755
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
756
756
  "div",
757
757
  {
758
758
  className: "grid grid-cols-[auto_1fr_auto] gap-x-4 border-b border-stone-200 pb-6",
759
759
  children: [
760
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "row-span-2 pt-1 font-mono text-sm text-stone-600", children: String(i + 1).padStart(2, "0") }),
761
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dt", { className: "text-sm font-medium text-stone-900", children: q.prompt }),
762
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
763
- "button",
764
- {
765
- type: "button",
766
- onClick: () => onEdit(i),
767
- className: "btn-ghost row-span-2 self-start text-sm",
768
- children: "Edit"
769
- }
770
- ),
771
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dd", { className: "col-start-2 mt-2 whitespace-pre-wrap text-stone-900", children: answered ? display : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "italic text-stone-600", children: "Not answered" }) })
760
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("dt", { className: "col-span-3 grid grid-cols-subgrid", children: [
761
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", className: "pt-1 font-mono text-sm text-stone-600", children: String(i + 1).padStart(2, "0") }),
762
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-medium text-stone-900", children: q.prompt }),
763
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
764
+ "button",
765
+ {
766
+ type: "button",
767
+ onClick: () => onEdit(i),
768
+ "aria-label": `Edit: ${q.prompt}`,
769
+ className: "btn-ghost self-start text-sm",
770
+ children: "Edit"
771
+ }
772
+ )
773
+ ] }),
774
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dd", { className: "col-span-3 mt-2 grid grid-cols-subgrid", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "col-start-2 whitespace-pre-wrap text-stone-900", children: answered ? display : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "italic text-stone-600", children: "Not answered" }) }) })
772
775
  ]
773
776
  },
774
777
  q.id
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/ProgressBar.tsx","../src/QuestionCard.tsx","../src/summarize.ts","../src/AnswerSidebar.tsx","../src/ReviewSummary.tsx"],"sourcesContent":["/**\n * @dataimago/interview — public surface barrel.\n *\n * Components (named exports — note the original apps/hub components\n * were default exports; the package exposes them as named exports for\n * tree-shaking and to make the import surface symmetric with @dataimago/ui):\n */\nexport { ProgressBar } from './ProgressBar';\nexport { QuestionCard } from './QuestionCard';\nexport { AnswerSidebar } from './AnswerSidebar';\nexport { ReviewSummary } from './ReviewSummary';\n\n/**\n * Schema contract — the public type surface that consumers populate with\n * their domain-specific question content.\n */\nexport type {\n QuestionInputType,\n InterviewQuestion,\n InterviewAnswers,\n AnswerValue,\n AnswerComposite,\n AnswerRepeater,\n AnswerFileUpload,\n FileEntry,\n} from './types';\n\n/**\n * Answer-rendering helpers — useful for consumers who want to display\n * answer previews outside the package's sidebar/review components.\n */\nexport { isAnswered, summarizeShort, summarizeLong } from './summarize';\n","'use client';\n\ninterface Props {\n current: number;\n total: number;\n estimatedMinutesRemaining: number;\n}\n\n/**\n * Linear progress indicator for the interview flow. Renders the\n * \"Question N of M\" caption, the estimated minutes remaining, and a\n * forest-700 fill bar at `(current / total) * 100%`.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * stone-100 surface with stone-200 border; forest-700 fill bar; stone-700\n * caption text. Pure-render component — no state-management dependency.\n *\n * Extracted from `apps/hub/src/components/interview/ProgressBar.tsx`\n * during iteration-3-B.1 (2026-05-07). No prop API change.\n */\nexport function ProgressBar({ current, total, estimatedMinutesRemaining }: Props) {\n const percent = Math.round((current / total) * 100);\n\n return (\n <div className=\"border-b border-stone-200 bg-stone-100 py-3 px-6\">\n <div className=\"mx-auto max-w-3xl\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Question {current} of {total}\n </span>\n <span className=\"font-mono text-xs text-stone-700\">\n ~{estimatedMinutesRemaining} min remaining\n </span>\n </div>\n <div\n className=\"mt-2 h-1 w-full overflow-hidden rounded-full bg-stone-200\"\n role=\"progressbar\"\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`Interview progress: ${percent}% complete`}\n >\n <div\n className=\"h-full bg-forest-700 transition-all duration-300 ease-out\"\n style={{ width: `${percent}%` }}\n />\n </div>\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport type {\n InterviewQuestion,\n AnswerValue,\n AnswerComposite,\n AnswerRepeater,\n AnswerFileUpload,\n FileEntry,\n} from './types';\n\ninterface Props {\n question: InterviewQuestion;\n /**\n * The currently-saved answer for this question (from the consumer's\n * state container). The component initializes its local form state\n * from this value and re-syncs when the question id changes.\n */\n existingAnswer?: AnswerValue;\n /**\n * Called when the user submits an answer. The consumer is expected to\n * persist the answer into its state container and then advance via\n * `onNext`.\n */\n onAnswerSubmit: (questionId: string, value: AnswerValue) => void;\n /** Called after `onAnswerSubmit` to advance to the next question. */\n onNext: () => void;\n /** Called when the user clicks the Back button. */\n onBack: () => void;\n isFirst: boolean;\n isLast: boolean;\n}\n\n/**\n * Default value to use when no `existingAnswer` is supplied. Depends on\n * the question's `inputType`.\n */\nfunction defaultValueFor(question: InterviewQuestion): AnswerValue {\n switch (question.inputType) {\n case 'multi-select':\n case 'list':\n return [];\n case 'composite':\n return {} as AnswerComposite;\n case 'repeater':\n case 'file-upload':\n return [];\n default:\n return '';\n }\n}\n\n/**\n * Whether the user's current local value satisfies the required check\n * for the question.\n */\nfunction canAdvanceWith(question: InterviewQuestion, value: AnswerValue): boolean {\n if (!question.required) return true;\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * Single question renderer. Handles all input types: short-text, long-text,\n * single-select, multi-select, scale, list, date, composite, repeater,\n * file-upload. Keyboard-navigable and screen-reader safe.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * existing answer + change handler as props.\n *\n * Iteration-1 visual identity: form input fields use stone-50 elevated\n * surface + stone-200 default border + forest-700 focus border. Selected\n * radio/checkbox option states use forest-700 border + forest-50 background.\n * The examples disclosure has border-l-2 frame in border-copper-200 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n */\nexport function QuestionCard({\n question,\n existingAnswer,\n onAnswerSubmit,\n onNext,\n onBack,\n isFirst,\n isLast,\n}: Props) {\n const [localValue, setLocalValue] = useState<AnswerValue>(\n existingAnswer ?? defaultValueFor(question),\n );\n\n // Sync when question changes (consumer flipped to a different question;\n // local form state should reflect that question's existing answer).\n useEffect(() => {\n setLocalValue(existingAnswer ?? defaultValueFor(question));\n }, [question.id, existingAnswer, question.inputType]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onAnswerSubmit(question.id, localValue);\n onNext();\n };\n\n const canAdvance = canAdvanceWith(question, localValue);\n\n return (\n <form onSubmit={handleSubmit} className=\"animate-slide-up\">\n {/* Prompt */}\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n {question.prompt}\n </h2>\n {question.subprompt && (\n <p className=\"mt-4 text-lg text-stone-700\">{question.subprompt}</p>\n )}\n\n {/* Input — dispatched per type */}\n <div className=\"mt-8\">\n <InputForType\n question={question}\n value={localValue}\n onChange={setLocalValue}\n />\n </div>\n\n {/* Examples */}\n {question.examples && question.examples.length > 0 && (\n <details className=\"mt-8\">\n <summary className=\"cursor-pointer text-sm font-medium text-forest-700 hover:text-forest-800\">\n Show examples from different fields\n </summary>\n {/* border-copper-200 PRESERVED: decorative-emphasis frame around\n illustrative content, same role as HeroSection's etymology box. */}\n <ul className=\"mt-4 space-y-3 border-l-2 border-copper-200 pl-5\">\n {question.examples.map((ex, i) => (\n <li key={i} className=\"text-sm italic text-stone-700\">\n “{ex}”\n </li>\n ))}\n </ul>\n </details>\n )}\n\n {/* Skip consequence (if applicable) */}\n {!question.required && question.skipConsequence && (\n <p className=\"mt-6 text-sm text-stone-700\">\n <span className=\"font-medium\">If you skip this:</span> {question.skipConsequence}\n </p>\n )}\n\n {/* Nav */}\n <div className=\"mt-10 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={onBack}\n disabled={isFirst}\n className=\"btn-ghost disabled:opacity-40\"\n >\n ← Back\n </button>\n <div className=\"flex gap-3\">\n {!question.required && (\n <button type=\"button\" onClick={onNext} className=\"btn-ghost\">\n Skip\n </button>\n )}\n <button type=\"submit\" disabled={!canAdvance} className=\"btn-primary\">\n {isLast ? 'Review answers' : 'Continue →'}\n </button>\n </div>\n </div>\n </form>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Per-input-type renderers\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface InputProps {\n question: InterviewQuestion;\n value: AnswerValue;\n onChange: (next: AnswerValue) => void;\n}\n\nfunction InputForType({ question, value, onChange }: InputProps) {\n switch (question.inputType) {\n case 'short-text':\n return <ShortTextInput value={value as string} onChange={onChange} />;\n case 'long-text':\n return <LongTextInput value={value as string} onChange={onChange} />;\n case 'single-select':\n return <SingleSelectInput question={question} value={value as string} onChange={onChange} />;\n case 'multi-select':\n return <MultiSelectInput question={question} value={(value as string[]) ?? []} onChange={onChange} />;\n case 'list':\n return <ListInput value={(value as string[]) ?? []} onChange={onChange} listRange={question.listRange} />;\n case 'scale':\n return <ScaleInput question={question} value={value as string} onChange={onChange} />;\n case 'date':\n return <DateInput value={value as string} onChange={onChange} ariaLabel={question.prompt} />;\n case 'composite':\n return <CompositeInput question={question} value={(value as AnswerComposite) ?? {}} onChange={onChange} />;\n case 'repeater':\n return <RepeaterInput question={question} value={(value as AnswerRepeater) ?? []} onChange={onChange} />;\n case 'file-upload':\n return <FileUploadInput question={question} value={(value as AnswerFileUpload) ?? []} onChange={onChange} />;\n default: {\n const _exhaustive: never = question.inputType;\n return <UnknownTypeFallback inputType={_exhaustive} />;\n }\n }\n}\n\nfunction ShortTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <input\n type=\"text\"\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction LongTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <textarea\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n rows={5}\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction SingleSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n ))}\n </div>\n );\n}\n\nfunction MultiSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string[];\n onChange: (v: string[]) => void;\n}) {\n return (\n <div className=\"space-y-2\" role=\"group\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => {\n const checked = value.includes(opt.value);\n return (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n checked\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"checkbox\"\n value={opt.value}\n checked={checked}\n onChange={(e) => {\n if (e.target.checked) onChange([...value, opt.value]);\n else onChange(value.filter((v) => v !== opt.value));\n }}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n );\n })}\n </div>\n );\n}\n\nfunction ScaleInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n const options = question.options ?? [];\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {options.map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-center gap-3 rounded-lg border-2 p-3 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-4 w-4 text-forest-700\"\n />\n <span className=\"font-mono text-sm text-stone-700\">{opt.value}</span>\n <span className=\"text-stone-900\">{opt.label}</span>\n </label>\n ))}\n </div>\n );\n}\n\nfunction DateInput({\n value,\n onChange,\n ariaLabel,\n}: {\n value: string;\n onChange: (v: string) => void;\n ariaLabel: string;\n}) {\n return (\n <input\n type=\"date\"\n aria-label={ariaLabel}\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n />\n );\n}\n\nfunction ListInput({\n value,\n onChange,\n listRange,\n}: {\n value: string[];\n onChange: (v: string[]) => void;\n listRange?: { min: number; max: number };\n}) {\n const items = value.length > 0 ? value : [''];\n const min = listRange?.min ?? 0;\n const max = listRange?.max ?? Infinity;\n\n const setItem = (i: number, v: string) => {\n const next = [...items];\n next[i] = v;\n onChange(next);\n };\n const addItem = () => {\n if (items.length < max) onChange([...items, '']);\n };\n const removeItem = (i: number) => {\n if (items.length <= 1) return;\n onChange(items.filter((_, idx) => idx !== i));\n };\n const validCount = items.filter((v) => v.trim().length > 0).length;\n\n return (\n <div>\n <ul className=\"space-y-2\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-center gap-2\">\n <span className=\"w-6 text-right font-mono text-xs text-stone-600\">{i + 1}.</span>\n <input\n type=\"text\"\n value={item}\n onChange={(e) => setItem(i, e.target.value)}\n className=\"flex-grow rounded-lg border-2 border-stone-200 bg-stone-50 px-3 py-2 text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder={`Item ${i + 1}`}\n />\n <button\n type=\"button\"\n onClick={() => removeItem(i)}\n disabled={items.length <= 1}\n className=\"btn-ghost text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n ×\n </button>\n </li>\n ))}\n </ul>\n <div className=\"mt-3 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={addItem}\n disabled={items.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add item\n </button>\n {listRange && (\n <span className=\"font-mono text-xs text-stone-700\">\n {validCount} / {min}–{max === Infinity ? '∞' : max}\n </span>\n )}\n </div>\n </div>\n );\n}\n\nfunction CompositeInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerComposite;\n onChange: (v: AnswerComposite) => void;\n}) {\n const subQuestions = question.subQuestions ?? [];\n return (\n <div className=\"space-y-6 rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n {subQuestions.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={value[sub.id]}\n onChange={(next) => onChange({ ...value, [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction RepeaterInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerRepeater;\n onChange: (v: AnswerRepeater) => void;\n}) {\n const rows = value.length > 0 ? value : [{} as Record<string, AnswerValue>];\n const itemSchema = question.itemSchema ?? [];\n const min = question.listRange?.min ?? 1;\n const max = question.listRange?.max ?? Infinity;\n\n const updateRow = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...rows];\n next[i] = { ...next[i], ...patch };\n onChange(next);\n };\n const addRow = () => {\n if (rows.length < max) onChange([...rows, {} as Record<string, AnswerValue>]);\n };\n const removeRow = (i: number) => {\n if (rows.length <= 1) return;\n onChange(rows.filter((_, idx) => idx !== i));\n };\n\n return (\n <div className=\"space-y-4\">\n {rows.map((row, i) => (\n <div key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Item {i + 1}\n </span>\n <button\n type=\"button\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= min}\n className=\"btn-ghost text-xs text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n Remove\n </button>\n </div>\n <div className=\"space-y-4\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && (\n <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>\n )}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={row[sub.id]}\n onChange={(next) => updateRow(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={addRow}\n disabled={rows.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add another\n </button>\n </div>\n );\n}\n\nfunction FileUploadInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerFileUpload;\n onChange: (v: AnswerFileUpload) => void;\n}) {\n const itemSchema = question.itemSchema ?? [];\n\n const onFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return;\n const entries: FileEntry[] = Array.from(files).map((f) => ({\n file: f,\n metadata: {},\n }));\n onChange([...value, ...entries]);\n };\n\n const updateMetadata = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...value];\n next[i] = { ...next[i], metadata: { ...next[i].metadata, ...patch } };\n onChange(next);\n };\n const removeEntry = (i: number) => onChange(value.filter((_, idx) => idx !== i));\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n onFiles(e.dataTransfer.files);\n };\n const onDragOver = (e: React.DragEvent<HTMLDivElement>) => e.preventDefault();\n\n return (\n <div className=\"space-y-4\">\n <div\n onDrop={onDrop}\n onDragOver={onDragOver}\n className=\"rounded-lg border-2 border-dashed border-stone-300 bg-stone-50 p-6 text-center\"\n >\n <p className=\"text-sm text-stone-700\">\n Drag PDFs or other files here, or{' '}\n <label className=\"cursor-pointer font-medium text-forest-700 hover:text-forest-800\">\n browse\n <input\n type=\"file\"\n multiple\n className=\"sr-only\"\n onChange={(e) => onFiles(e.target.files)}\n />\n </label>\n </p>\n <p className=\"mt-1 text-xs text-stone-700\">\n You'll add a title, author, and description for each file below.\n </p>\n </div>\n\n {value.length > 0 && (\n <ul className=\"space-y-4\">\n {value.map((entry, i) => {\n const name = entry.file.name;\n const size = 'size' in entry.file ? entry.file.size : undefined;\n return (\n <li key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"font-medium text-stone-900\">{name}</div>\n {typeof size === 'number' && (\n <div className=\"font-mono text-xs text-stone-700\">\n {(size / 1024).toFixed(1)} KB\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => removeEntry(i)}\n className=\"btn-ghost text-xs text-stone-700\"\n aria-label={`Remove ${name}`}\n >\n Remove\n </button>\n </div>\n {itemSchema.length > 0 && (\n <div className=\"mt-4 space-y-3\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-xs font-medium text-stone-900\">{sub.prompt}</div>\n <div className=\"mt-1\">\n <InputForType\n question={sub}\n value={entry.metadata[sub.id]}\n onChange={(next) => updateMetadata(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n\nfunction UnknownTypeFallback({ inputType }: { inputType: never }) {\n // Render-time defensive guard for runtime values that bypass TS (e.g.,\n // YAML-loaded interview schemas with typos). Visible to dev; user sees a\n // muted \"unsupported\" notice.\n return (\n <div className=\"rounded-lg border-2 border-stone-300 bg-stone-50 p-4 text-sm text-stone-700\">\n Unsupported question input type:{' '}\n <code className=\"font-mono\">{String(inputType)}</code>\n </div>\n );\n}\n","/**\n * Helpers for rendering one-line / summary previews of answer values in\n * `AnswerSidebar` and `ReviewSummary`. Centralized so the two components\n * stay consistent when new answer shapes are added.\n */\nimport type { AnswerValue, FileEntry, InterviewQuestion } from './types';\n\nexport function isAnswered(value: AnswerValue): boolean {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * A short, single-line preview suitable for sidebar items. Truncates\n * long content. Returns the empty string for unanswered values.\n */\nexport function summarizeShort(question: InterviewQuestion, value: AnswerValue, maxLen = 80): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return truncate(String(value), maxLen);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return truncate(label ?? v, maxLen);\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => {\n const found = question.options?.find((o) => o.value === v)?.label;\n return found ?? v;\n });\n return truncate(labels.join(', '), maxLen);\n }\n case 'composite': {\n // Show the first sub-answer's preview if any.\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n return truncate(summarizeShort(sub, subVal, maxLen), maxLen);\n }\n }\n return '';\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n return `${rows.length} item${rows.length === 1 ? '' : 's'}`;\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return `${files.length} file${files.length === 1 ? '' : 's'}`;\n }\n default:\n return '';\n }\n}\n\n/**\n * A richer multi-line summary suitable for the ReviewSummary list. May\n * contain newlines; consumers should render in a `whitespace-pre-wrap`\n * container.\n */\nexport function summarizeLong(question: InterviewQuestion, value: AnswerValue): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return String(value);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return label ?? v;\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => question.options?.find((o) => o.value === v)?.label ?? v);\n return labels.join('\\n• ').replace(/^/, '• ');\n }\n case 'composite': {\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n const lines: string[] = [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n lines.push(`${sub.prompt}: ${summarizeShort(sub, subVal, 200)}`);\n }\n }\n return lines.join('\\n');\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n const itemSchema = question.itemSchema ?? [];\n const summary = rows.map((row, i) => {\n const parts: string[] = [`Item ${i + 1}:`];\n for (const sub of itemSchema) {\n const subVal = row[sub.id];\n if (isAnswered(subVal)) {\n parts.push(` ${sub.prompt}: ${summarizeShort(sub, subVal, 100)}`);\n }\n }\n return parts.join('\\n');\n });\n return summary.join('\\n');\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return files\n .map((f, i) => `${i + 1}. ${f.file.name}`)\n .join('\\n');\n }\n default:\n return '';\n }\n}\n\nfunction truncate(s: string, maxLen: number): string {\n return s.length > maxLen ? s.slice(0, maxLen - 1) + '…' : s;\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeShort } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n currentIndex: number;\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n /** Called when the user clicks a sidebar item to jump to that question. */\n onSelectQuestion: (index: number) => void;\n}\n\n/**\n * Sidebar showing all answered questions. Clicking any returns to edit that\n * question without losing later answers. Implements the wiki's pattern:\n * \"Edit any prior answer — a sidebar shows all answered questions.\"\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answers + jump handler as props.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Three item states with distinct token tiers:\n * - current → forest-700 border + forest-50 bg (interactive primary)\n * - answered → stone-200 border + stone-50 bg (default, hover stone-400)\n * - unanswered → stone-200/50 + stone-50/50 (muted via opacity preservation)\n *\n * D.2.1.b extension: previews for composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all eight scalar + three compound types\n * render consistently.\n */\nexport function AnswerSidebar({ questions, currentIndex, answers, onSelectQuestion }: Props) {\n return (\n <aside\n className=\"sticky top-24 hidden max-h-[calc(100vh-6rem)] overflow-y-auto lg:block\"\n aria-label=\"Completed answers\"\n >\n <h3 className=\"mb-3 font-mono text-xs uppercase tracking-wider text-stone-700\">\n Your answers\n </h3>\n <ol className=\"space-y-3\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const isCurrent = i === currentIndex;\n const preview = answered ? summarizeShort(q, answer) : '';\n\n return (\n <li key={q.id}>\n <button\n type=\"button\"\n onClick={() => onSelectQuestion(i)}\n className={`w-full rounded-lg border p-3 text-left transition-colors ${\n isCurrent\n ? 'border-forest-700 bg-forest-50'\n : answered\n ? 'border-stone-200 bg-stone-50 hover:border-stone-400'\n : 'border-stone-200/50 bg-stone-50/50 hover:border-stone-300'\n }`}\n >\n <div className=\"flex items-start gap-2\">\n <span\n className={`mt-0.5 font-mono text-xs ${\n isCurrent\n ? 'text-forest-700'\n : answered\n ? 'text-stone-700'\n : 'text-stone-600'\n }`}\n >\n {String(i + 1).padStart(2, '0')}.\n </span>\n <div className=\"flex-grow\">\n <div\n className={`text-xs font-medium ${\n answered ? 'text-stone-900' : 'text-stone-700'\n }`}\n >\n {q.prompt.length > 50 ? q.prompt.slice(0, 50) + '…' : q.prompt}\n </div>\n {answered && (\n <div className=\"mt-1 text-xs italic text-stone-700 line-clamp-1\">\n {preview}\n </div>\n )}\n </div>\n </div>\n </button>\n </li>\n );\n })}\n </ol>\n </aside>\n );\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeLong } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n onGenerate: () => void;\n onEdit: (questionIndex: number) => void;\n generating: boolean;\n}\n\n/**\n * Final review screen — the penultimate step before generation.\n * Shows all answers so the user can confirm ownership of the output before\n * committing.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answer record as a prop.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Editorial Josefin display family on the heading and the \"What happens next\"\n * callout title. Stone-tier surfaces and content text throughout. The\n * \"What happens next\" callout box preserves border-copper-300 + bg-copper-50 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n *\n * D.2.1.b extension: rendering of composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all answer types display consistently.\n */\nexport function ReviewSummary({ questions, answers, onGenerate, onEdit, generating }: Props) {\n return (\n <div className=\"animate-slide-up\">\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n Review your answers\n </h2>\n <p className=\"mt-4 text-lg text-stone-700\">\n These become the seed content of your project. You can edit anything now, or continue and\n edit later through the platform.\n </p>\n\n <dl className=\"mt-10 space-y-6 border-t border-stone-200 pt-6\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const display = answered ? summarizeLong(q, answer) : '';\n\n return (\n // Grid so the index + Edit button sit beside the dt/dd group while\n // <dt>/<dd> remain DIRECT children of this div (a direct child of\n // <dl>) — required for valid definition-list semantics (axe\n // definition-list / dlitem).\n <div\n key={q.id}\n className=\"grid grid-cols-[auto_1fr_auto] gap-x-4 border-b border-stone-200 pb-6\"\n >\n <span className=\"row-span-2 pt-1 font-mono text-sm text-stone-600\">\n {String(i + 1).padStart(2, '0')}\n </span>\n <dt className=\"text-sm font-medium text-stone-900\">{q.prompt}</dt>\n <button\n type=\"button\"\n onClick={() => onEdit(i)}\n className=\"btn-ghost row-span-2 self-start text-sm\"\n >\n Edit\n </button>\n <dd className=\"col-start-2 mt-2 whitespace-pre-wrap text-stone-900\">\n {answered ? (\n display\n ) : (\n <span className=\"italic text-stone-600\">Not answered</span>\n )}\n </dd>\n </div>\n );\n })}\n </dl>\n\n {/* \"What happens next\" callout — copper PRESERVED as decorative\n informational frame, same role as HeroSection's etymology box.\n Per iteration-1 §5.2's preserved-decorative-copper governance. */}\n <div className=\"mt-10 rounded-lg border border-copper-300 bg-copper-50 p-6\">\n <h3 className=\"font-display text-xl text-stone-900\">What happens next</h3>\n <p className=\"mt-2 text-stone-900\">\n When you click Generate, the platform will create a GitHub repository in your account,\n populate it with your personalized CLAUDE.md, KNOWLEDGE.md, and wiki, and give you the\n URL. This takes about 30–90 seconds. You can edit everything afterward through the\n platform or through your repo.\n </p>\n <p className=\"mt-3 text-sm text-stone-700\">\n <span className=\"font-medium\">MVP note:</span> In this phase, GitHub repo creation is\n mocked for demonstration. Once OAuth credentials are configured, real repos will be\n created on your behalf.\n </p>\n </div>\n\n <div className=\"mt-8 flex justify-end\">\n <button\n type=\"button\"\n onClick={onGenerate}\n disabled={generating}\n className=\"btn-primary text-lg\"\n >\n {generating ? 'Generating your project…' : 'Generate my platform'}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/ProgressBar.tsx","../src/QuestionCard.tsx","../src/summarize.ts","../src/AnswerSidebar.tsx","../src/ReviewSummary.tsx"],"sourcesContent":["/**\n * @dataimago/interview — public surface barrel.\n *\n * Components (named exports — note the original apps/hub components\n * were default exports; the package exposes them as named exports for\n * tree-shaking and to make the import surface symmetric with @dataimago/ui):\n */\nexport { ProgressBar } from './ProgressBar';\nexport { QuestionCard } from './QuestionCard';\nexport { AnswerSidebar } from './AnswerSidebar';\nexport { ReviewSummary } from './ReviewSummary';\n\n/**\n * Schema contract — the public type surface that consumers populate with\n * their domain-specific question content.\n */\nexport type {\n QuestionInputType,\n InterviewQuestion,\n InterviewAnswers,\n AnswerValue,\n AnswerComposite,\n AnswerRepeater,\n AnswerFileUpload,\n FileEntry,\n} from './types';\n\n/**\n * Answer-rendering helpers — useful for consumers who want to display\n * answer previews outside the package's sidebar/review components.\n */\nexport { isAnswered, summarizeShort, summarizeLong } from './summarize';\n","'use client';\n\ninterface Props {\n current: number;\n total: number;\n estimatedMinutesRemaining: number;\n}\n\n/**\n * Linear progress indicator for the interview flow. Renders the\n * \"Question N of M\" caption, the estimated minutes remaining, and a\n * forest-700 fill bar at `(current / total) * 100%`.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * stone-100 surface with stone-200 border; forest-700 fill bar; stone-700\n * caption text. Pure-render component — no state-management dependency.\n *\n * Extracted from `apps/hub/src/components/interview/ProgressBar.tsx`\n * during iteration-3-B.1 (2026-05-07). No prop API change.\n */\nexport function ProgressBar({ current, total, estimatedMinutesRemaining }: Props) {\n const percent = Math.round((current / total) * 100);\n\n return (\n <div className=\"border-b border-stone-200 bg-stone-100 py-3 px-6\">\n <div className=\"mx-auto max-w-3xl\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Question {current} of {total}\n </span>\n <span className=\"font-mono text-xs text-stone-700\">\n ~{estimatedMinutesRemaining} min remaining\n </span>\n </div>\n <div\n className=\"mt-2 h-1 w-full overflow-hidden rounded-full bg-stone-200\"\n role=\"progressbar\"\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`Interview progress: ${percent}% complete`}\n >\n <div\n className=\"h-full bg-forest-700 transition-all duration-300 ease-out\"\n style={{ width: `${percent}%` }}\n />\n </div>\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport type {\n InterviewQuestion,\n AnswerValue,\n AnswerComposite,\n AnswerRepeater,\n AnswerFileUpload,\n FileEntry,\n} from './types';\n\ninterface Props {\n question: InterviewQuestion;\n /**\n * The currently-saved answer for this question (from the consumer's\n * state container). The component initializes its local form state\n * from this value and re-syncs when the question id changes.\n */\n existingAnswer?: AnswerValue;\n /**\n * Called when the user submits an answer. The consumer is expected to\n * persist the answer into its state container and then advance via\n * `onNext`.\n */\n onAnswerSubmit: (questionId: string, value: AnswerValue) => void;\n /** Called after `onAnswerSubmit` to advance to the next question. */\n onNext: () => void;\n /** Called when the user clicks the Back button. */\n onBack: () => void;\n isFirst: boolean;\n isLast: boolean;\n}\n\n/**\n * Default value to use when no `existingAnswer` is supplied. Depends on\n * the question's `inputType`.\n */\nfunction defaultValueFor(question: InterviewQuestion): AnswerValue {\n switch (question.inputType) {\n case 'multi-select':\n case 'list':\n return [];\n case 'composite':\n return {} as AnswerComposite;\n case 'repeater':\n case 'file-upload':\n return [];\n default:\n return '';\n }\n}\n\n/**\n * Whether the user's current local value satisfies the required check\n * for the question.\n */\nfunction canAdvanceWith(question: InterviewQuestion, value: AnswerValue): boolean {\n if (!question.required) return true;\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * Single question renderer. Handles all input types: short-text, long-text,\n * single-select, multi-select, scale, list, date, composite, repeater,\n * file-upload. Keyboard-navigable and screen-reader safe.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * existing answer + change handler as props.\n *\n * Iteration-1 visual identity: form input fields use stone-50 elevated\n * surface + stone-200 default border + forest-700 focus border. Selected\n * radio/checkbox option states use forest-700 border + forest-50 background.\n * The examples disclosure has border-l-2 frame in border-copper-200 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n */\nexport function QuestionCard({\n question,\n existingAnswer,\n onAnswerSubmit,\n onNext,\n onBack,\n isFirst,\n isLast,\n}: Props) {\n const [localValue, setLocalValue] = useState<AnswerValue>(\n existingAnswer ?? defaultValueFor(question),\n );\n\n // Sync when question changes (consumer flipped to a different question;\n // local form state should reflect that question's existing answer).\n useEffect(() => {\n setLocalValue(existingAnswer ?? defaultValueFor(question));\n }, [question.id, existingAnswer, question.inputType]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onAnswerSubmit(question.id, localValue);\n onNext();\n };\n\n const canAdvance = canAdvanceWith(question, localValue);\n\n return (\n <form onSubmit={handleSubmit} className=\"animate-slide-up\">\n {/* Prompt */}\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n {question.prompt}\n </h2>\n {question.subprompt && (\n <p className=\"mt-4 text-lg text-stone-700\">{question.subprompt}</p>\n )}\n\n {/* Input — dispatched per type */}\n <div className=\"mt-8\">\n <InputForType\n question={question}\n value={localValue}\n onChange={setLocalValue}\n />\n </div>\n\n {/* Examples */}\n {question.examples && question.examples.length > 0 && (\n <details className=\"mt-8\">\n <summary className=\"cursor-pointer text-sm font-medium text-forest-700 hover:text-forest-800\">\n Show examples from different fields\n </summary>\n {/* border-copper-200 PRESERVED: decorative-emphasis frame around\n illustrative content, same role as HeroSection's etymology box. */}\n <ul className=\"mt-4 space-y-3 border-l-2 border-copper-200 pl-5\">\n {question.examples.map((ex, i) => (\n <li key={i} className=\"text-sm italic text-stone-700\">\n “{ex}”\n </li>\n ))}\n </ul>\n </details>\n )}\n\n {/* Skip consequence (if applicable) */}\n {!question.required && question.skipConsequence && (\n <p className=\"mt-6 text-sm text-stone-700\">\n <span className=\"font-medium\">If you skip this:</span> {question.skipConsequence}\n </p>\n )}\n\n {/* Nav */}\n <div className=\"mt-10 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={onBack}\n disabled={isFirst}\n className=\"btn-ghost disabled:opacity-40\"\n >\n ← Back\n </button>\n <div className=\"flex gap-3\">\n {!question.required && (\n <button type=\"button\" onClick={onNext} className=\"btn-ghost\">\n Skip\n </button>\n )}\n <button type=\"submit\" disabled={!canAdvance} className=\"btn-primary\">\n {isLast ? 'Review answers' : 'Continue →'}\n </button>\n </div>\n </div>\n </form>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Per-input-type renderers\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface InputProps {\n question: InterviewQuestion;\n value: AnswerValue;\n onChange: (next: AnswerValue) => void;\n}\n\nfunction InputForType({ question, value, onChange }: InputProps) {\n switch (question.inputType) {\n case 'short-text':\n return <ShortTextInput value={value as string} onChange={onChange} />;\n case 'long-text':\n return <LongTextInput value={value as string} onChange={onChange} />;\n case 'single-select':\n return <SingleSelectInput question={question} value={value as string} onChange={onChange} />;\n case 'multi-select':\n return <MultiSelectInput question={question} value={(value as string[]) ?? []} onChange={onChange} />;\n case 'list':\n return <ListInput value={(value as string[]) ?? []} onChange={onChange} listRange={question.listRange} />;\n case 'scale':\n return <ScaleInput question={question} value={value as string} onChange={onChange} />;\n case 'date':\n return <DateInput value={value as string} onChange={onChange} ariaLabel={question.prompt} />;\n case 'composite':\n return <CompositeInput question={question} value={(value as AnswerComposite) ?? {}} onChange={onChange} />;\n case 'repeater':\n return <RepeaterInput question={question} value={(value as AnswerRepeater) ?? []} onChange={onChange} />;\n case 'file-upload':\n return <FileUploadInput question={question} value={(value as AnswerFileUpload) ?? []} onChange={onChange} />;\n default: {\n const _exhaustive: never = question.inputType;\n return <UnknownTypeFallback inputType={_exhaustive} />;\n }\n }\n}\n\nfunction ShortTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <input\n type=\"text\"\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction LongTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <textarea\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n rows={5}\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction SingleSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n ))}\n </div>\n );\n}\n\nfunction MultiSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string[];\n onChange: (v: string[]) => void;\n}) {\n return (\n <div className=\"space-y-2\" role=\"group\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => {\n const checked = value.includes(opt.value);\n return (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n checked\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"checkbox\"\n value={opt.value}\n checked={checked}\n onChange={(e) => {\n if (e.target.checked) onChange([...value, opt.value]);\n else onChange(value.filter((v) => v !== opt.value));\n }}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n );\n })}\n </div>\n );\n}\n\nfunction ScaleInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n const options = question.options ?? [];\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {options.map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-center gap-3 rounded-lg border-2 p-3 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-4 w-4 text-forest-700\"\n />\n <span className=\"font-mono text-sm text-stone-700\">{opt.value}</span>\n <span className=\"text-stone-900\">{opt.label}</span>\n </label>\n ))}\n </div>\n );\n}\n\nfunction DateInput({\n value,\n onChange,\n ariaLabel,\n}: {\n value: string;\n onChange: (v: string) => void;\n ariaLabel: string;\n}) {\n return (\n <input\n type=\"date\"\n aria-label={ariaLabel}\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n />\n );\n}\n\nfunction ListInput({\n value,\n onChange,\n listRange,\n}: {\n value: string[];\n onChange: (v: string[]) => void;\n listRange?: { min: number; max: number };\n}) {\n const items = value.length > 0 ? value : [''];\n const min = listRange?.min ?? 0;\n const max = listRange?.max ?? Infinity;\n\n const setItem = (i: number, v: string) => {\n const next = [...items];\n next[i] = v;\n onChange(next);\n };\n const addItem = () => {\n if (items.length < max) onChange([...items, '']);\n };\n const removeItem = (i: number) => {\n if (items.length <= 1) return;\n onChange(items.filter((_, idx) => idx !== i));\n };\n const validCount = items.filter((v) => v.trim().length > 0).length;\n\n return (\n <div>\n <ul className=\"space-y-2\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-center gap-2\">\n <span className=\"w-6 text-right font-mono text-xs text-stone-600\">{i + 1}.</span>\n <input\n type=\"text\"\n value={item}\n onChange={(e) => setItem(i, e.target.value)}\n className=\"flex-grow rounded-lg border-2 border-stone-200 bg-stone-50 px-3 py-2 text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder={`Item ${i + 1}`}\n />\n <button\n type=\"button\"\n onClick={() => removeItem(i)}\n disabled={items.length <= 1}\n className=\"btn-ghost text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n ×\n </button>\n </li>\n ))}\n </ul>\n <div className=\"mt-3 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={addItem}\n disabled={items.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add item\n </button>\n {listRange && (\n <span className=\"font-mono text-xs text-stone-700\">\n {validCount} / {min}–{max === Infinity ? '∞' : max}\n </span>\n )}\n </div>\n </div>\n );\n}\n\nfunction CompositeInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerComposite;\n onChange: (v: AnswerComposite) => void;\n}) {\n const subQuestions = question.subQuestions ?? [];\n return (\n <div className=\"space-y-6 rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n {subQuestions.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={value[sub.id]}\n onChange={(next) => onChange({ ...value, [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction RepeaterInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerRepeater;\n onChange: (v: AnswerRepeater) => void;\n}) {\n const rows = value.length > 0 ? value : [{} as Record<string, AnswerValue>];\n const itemSchema = question.itemSchema ?? [];\n const min = question.listRange?.min ?? 1;\n const max = question.listRange?.max ?? Infinity;\n\n const updateRow = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...rows];\n next[i] = { ...next[i], ...patch };\n onChange(next);\n };\n const addRow = () => {\n if (rows.length < max) onChange([...rows, {} as Record<string, AnswerValue>]);\n };\n const removeRow = (i: number) => {\n if (rows.length <= 1) return;\n onChange(rows.filter((_, idx) => idx !== i));\n };\n\n return (\n <div className=\"space-y-4\">\n {rows.map((row, i) => (\n <div key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Item {i + 1}\n </span>\n <button\n type=\"button\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= min}\n className=\"btn-ghost text-xs text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n Remove\n </button>\n </div>\n <div className=\"space-y-4\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && (\n <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>\n )}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={row[sub.id]}\n onChange={(next) => updateRow(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={addRow}\n disabled={rows.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add another\n </button>\n </div>\n );\n}\n\nfunction FileUploadInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerFileUpload;\n onChange: (v: AnswerFileUpload) => void;\n}) {\n const itemSchema = question.itemSchema ?? [];\n\n const onFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return;\n const entries: FileEntry[] = Array.from(files).map((f) => ({\n file: f,\n metadata: {},\n }));\n onChange([...value, ...entries]);\n };\n\n const updateMetadata = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...value];\n next[i] = { ...next[i], metadata: { ...next[i].metadata, ...patch } };\n onChange(next);\n };\n const removeEntry = (i: number) => onChange(value.filter((_, idx) => idx !== i));\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n onFiles(e.dataTransfer.files);\n };\n const onDragOver = (e: React.DragEvent<HTMLDivElement>) => e.preventDefault();\n\n return (\n <div className=\"space-y-4\">\n <div\n onDrop={onDrop}\n onDragOver={onDragOver}\n className=\"rounded-lg border-2 border-dashed border-stone-300 bg-stone-50 p-6 text-center\"\n >\n <p className=\"text-sm text-stone-700\">\n Drag PDFs or other files here, or{' '}\n <label className=\"cursor-pointer font-medium text-forest-700 hover:text-forest-800\">\n browse\n <input\n type=\"file\"\n multiple\n className=\"sr-only\"\n onChange={(e) => onFiles(e.target.files)}\n />\n </label>\n </p>\n <p className=\"mt-1 text-xs text-stone-700\">\n You'll add a title, author, and description for each file below.\n </p>\n </div>\n\n {value.length > 0 && (\n <ul className=\"space-y-4\">\n {value.map((entry, i) => {\n const name = entry.file.name;\n const size = 'size' in entry.file ? entry.file.size : undefined;\n return (\n <li key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"font-medium text-stone-900\">{name}</div>\n {typeof size === 'number' && (\n <div className=\"font-mono text-xs text-stone-700\">\n {(size / 1024).toFixed(1)} KB\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => removeEntry(i)}\n className=\"btn-ghost text-xs text-stone-700\"\n aria-label={`Remove ${name}`}\n >\n Remove\n </button>\n </div>\n {itemSchema.length > 0 && (\n <div className=\"mt-4 space-y-3\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-xs font-medium text-stone-900\">{sub.prompt}</div>\n <div className=\"mt-1\">\n <InputForType\n question={sub}\n value={entry.metadata[sub.id]}\n onChange={(next) => updateMetadata(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n\nfunction UnknownTypeFallback({ inputType }: { inputType: never }) {\n // Render-time defensive guard for runtime values that bypass TS (e.g.,\n // YAML-loaded interview schemas with typos). Visible to dev; user sees a\n // muted \"unsupported\" notice.\n return (\n <div className=\"rounded-lg border-2 border-stone-300 bg-stone-50 p-4 text-sm text-stone-700\">\n Unsupported question input type:{' '}\n <code className=\"font-mono\">{String(inputType)}</code>\n </div>\n );\n}\n","/**\n * Helpers for rendering one-line / summary previews of answer values in\n * `AnswerSidebar` and `ReviewSummary`. Centralized so the two components\n * stay consistent when new answer shapes are added.\n */\nimport type { AnswerValue, FileEntry, InterviewQuestion } from './types';\n\nexport function isAnswered(value: AnswerValue): boolean {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * A short, single-line preview suitable for sidebar items. Truncates\n * long content. Returns the empty string for unanswered values.\n */\nexport function summarizeShort(question: InterviewQuestion, value: AnswerValue, maxLen = 80): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return truncate(String(value), maxLen);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return truncate(label ?? v, maxLen);\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => {\n const found = question.options?.find((o) => o.value === v)?.label;\n return found ?? v;\n });\n return truncate(labels.join(', '), maxLen);\n }\n case 'composite': {\n // Show the first sub-answer's preview if any.\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n return truncate(summarizeShort(sub, subVal, maxLen), maxLen);\n }\n }\n return '';\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n return `${rows.length} item${rows.length === 1 ? '' : 's'}`;\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return `${files.length} file${files.length === 1 ? '' : 's'}`;\n }\n default:\n return '';\n }\n}\n\n/**\n * A richer multi-line summary suitable for the ReviewSummary list. May\n * contain newlines; consumers should render in a `whitespace-pre-wrap`\n * container.\n */\nexport function summarizeLong(question: InterviewQuestion, value: AnswerValue): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return String(value);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return label ?? v;\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => question.options?.find((o) => o.value === v)?.label ?? v);\n return labels.join('\\n• ').replace(/^/, '• ');\n }\n case 'composite': {\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n const lines: string[] = [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n lines.push(`${sub.prompt}: ${summarizeShort(sub, subVal, 200)}`);\n }\n }\n return lines.join('\\n');\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n const itemSchema = question.itemSchema ?? [];\n const summary = rows.map((row, i) => {\n const parts: string[] = [`Item ${i + 1}:`];\n for (const sub of itemSchema) {\n const subVal = row[sub.id];\n if (isAnswered(subVal)) {\n parts.push(` ${sub.prompt}: ${summarizeShort(sub, subVal, 100)}`);\n }\n }\n return parts.join('\\n');\n });\n return summary.join('\\n');\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return files\n .map((f, i) => `${i + 1}. ${f.file.name}`)\n .join('\\n');\n }\n default:\n return '';\n }\n}\n\nfunction truncate(s: string, maxLen: number): string {\n return s.length > maxLen ? s.slice(0, maxLen - 1) + '…' : s;\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeShort } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n currentIndex: number;\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n /** Called when the user clicks a sidebar item to jump to that question. */\n onSelectQuestion: (index: number) => void;\n}\n\n/**\n * Sidebar showing all answered questions. Clicking any returns to edit that\n * question without losing later answers. Implements the wiki's pattern:\n * \"Edit any prior answer — a sidebar shows all answered questions.\"\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answers + jump handler as props.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Three item states with distinct token tiers:\n * - current → forest-700 border + forest-50 bg (interactive primary)\n * - answered → stone-200 border + stone-50 bg (default, hover stone-400)\n * - unanswered → stone-200/50 + stone-50/50 (muted via opacity preservation)\n *\n * D.2.1.b extension: previews for composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all eight scalar + three compound types\n * render consistently.\n */\nexport function AnswerSidebar({ questions, currentIndex, answers, onSelectQuestion }: Props) {\n return (\n <aside\n className=\"sticky top-24 hidden max-h-[calc(100vh-6rem)] overflow-y-auto lg:block\"\n aria-label=\"Completed answers\"\n >\n <h3 className=\"mb-3 font-mono text-xs uppercase tracking-wider text-stone-700\">\n Your answers\n </h3>\n <ol className=\"space-y-3\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const isCurrent = i === currentIndex;\n const preview = answered ? summarizeShort(q, answer) : '';\n\n return (\n <li key={q.id}>\n <button\n type=\"button\"\n onClick={() => onSelectQuestion(i)}\n className={`w-full rounded-lg border p-3 text-left transition-colors ${\n isCurrent\n ? 'border-forest-700 bg-forest-50'\n : answered\n ? 'border-stone-200 bg-stone-50 hover:border-stone-400'\n : 'border-stone-200/50 bg-stone-50/50 hover:border-stone-300'\n }`}\n >\n <div className=\"flex items-start gap-2\">\n <span\n className={`mt-0.5 font-mono text-xs ${\n isCurrent\n ? 'text-forest-700'\n : answered\n ? 'text-stone-700'\n : 'text-stone-600'\n }`}\n >\n {String(i + 1).padStart(2, '0')}.\n </span>\n <div className=\"flex-grow\">\n <div\n className={`text-xs font-medium ${\n answered ? 'text-stone-900' : 'text-stone-700'\n }`}\n >\n {q.prompt.length > 50 ? q.prompt.slice(0, 50) + '…' : q.prompt}\n </div>\n {answered && (\n <div className=\"mt-1 text-xs italic text-stone-700 line-clamp-1\">\n {preview}\n </div>\n )}\n </div>\n </div>\n </button>\n </li>\n );\n })}\n </ol>\n </aside>\n );\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeLong } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n onGenerate: () => void;\n onEdit: (questionIndex: number) => void;\n generating: boolean;\n}\n\n/**\n * Final review screen — the penultimate step before generation.\n * Shows all answers so the user can confirm ownership of the output before\n * committing.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answer record as a prop.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Editorial Josefin display family on the heading and the \"What happens next\"\n * callout title. Stone-tier surfaces and content text throughout. The\n * \"What happens next\" callout box preserves border-copper-300 + bg-copper-50 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n *\n * D.2.1.b extension: rendering of composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all answer types display consistently.\n */\nexport function ReviewSummary({ questions, answers, onGenerate, onEdit, generating }: Props) {\n return (\n <div className=\"animate-slide-up\">\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n Review your answers\n </h2>\n <p className=\"mt-4 text-lg text-stone-700\">\n These become the seed content of your project. You can edit anything now, or continue and\n edit later through the platform.\n </p>\n\n <dl className=\"mt-10 space-y-6 border-t border-stone-200 pt-6\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const display = answered ? summarizeLong(q, answer) : '';\n\n return (\n // A <div> child of <dl> may contain ONLY dt/dd groups (HTML spec;\n // axe definition-list), so the index + Edit button live INSIDE\n // <dt>. Subgrid keeps all three columns aligned across dt and dd\n // without extra wrappers.\n <div\n key={q.id}\n className=\"grid grid-cols-[auto_1fr_auto] gap-x-4 border-b border-stone-200 pb-6\"\n >\n <dt className=\"col-span-3 grid grid-cols-subgrid\">\n <span aria-hidden=\"true\" className=\"pt-1 font-mono text-sm text-stone-600\">\n {String(i + 1).padStart(2, '0')}\n </span>\n <span className=\"text-sm font-medium text-stone-900\">{q.prompt}</span>\n <button\n type=\"button\"\n onClick={() => onEdit(i)}\n aria-label={`Edit: ${q.prompt}`}\n className=\"btn-ghost self-start text-sm\"\n >\n Edit\n </button>\n </dt>\n <dd className=\"col-span-3 mt-2 grid grid-cols-subgrid\">\n <span className=\"col-start-2 whitespace-pre-wrap text-stone-900\">\n {answered ? (\n display\n ) : (\n <span className=\"italic text-stone-600\">Not answered</span>\n )}\n </span>\n </dd>\n </div>\n );\n })}\n </dl>\n\n {/* \"What happens next\" callout — copper PRESERVED as decorative\n informational frame, same role as HeroSection's etymology box.\n Per iteration-1 §5.2's preserved-decorative-copper governance. */}\n <div className=\"mt-10 rounded-lg border border-copper-300 bg-copper-50 p-6\">\n <h3 className=\"font-display text-xl text-stone-900\">What happens next</h3>\n <p className=\"mt-2 text-stone-900\">\n When you click Generate, the platform will create a GitHub repository in your account,\n populate it with your personalized CLAUDE.md, KNOWLEDGE.md, and wiki, and give you the\n URL. This takes about 30–90 seconds. You can edit everything afterward through the\n platform or through your repo.\n </p>\n <p className=\"mt-3 text-sm text-stone-700\">\n <span className=\"font-medium\">MVP note:</span> In this phase, GitHub repo creation is\n mocked for demonstration. Once OAuth credentials are configured, real repos will be\n created on your behalf.\n </p>\n </div>\n\n <div className=\"mt-8 flex justify-end\">\n <button\n type=\"button\"\n onClick={onGenerate}\n disabled={generating}\n className=\"btn-primary text-lg\"\n >\n {generating ? 'Generating your project…' : 'Generate my platform'}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.js CHANGED
@@ -716,27 +716,30 @@ function ReviewSummary({ questions, answers, onGenerate, onEdit, generating }) {
716
716
  const answered = isAnswered(answer);
717
717
  const display = answered ? summarizeLong(q, answer) : "";
718
718
  return (
719
- // Grid so the index + Edit button sit beside the dt/dd group while
720
- // <dt>/<dd> remain DIRECT children of this div (a direct child of
721
- // <dl>) required for valid definition-list semantics (axe
722
- // definition-list / dlitem).
719
+ // A <div> child of <dl> may contain ONLY dt/dd groups (HTML spec;
720
+ // axe definition-list), so the index + Edit button live INSIDE
721
+ // <dt>. Subgrid keeps all three columns aligned across dt and dd
722
+ // without extra wrappers.
723
723
  /* @__PURE__ */ jsxs4(
724
724
  "div",
725
725
  {
726
726
  className: "grid grid-cols-[auto_1fr_auto] gap-x-4 border-b border-stone-200 pb-6",
727
727
  children: [
728
- /* @__PURE__ */ jsx4("span", { className: "row-span-2 pt-1 font-mono text-sm text-stone-600", children: String(i + 1).padStart(2, "0") }),
729
- /* @__PURE__ */ jsx4("dt", { className: "text-sm font-medium text-stone-900", children: q.prompt }),
730
- /* @__PURE__ */ jsx4(
731
- "button",
732
- {
733
- type: "button",
734
- onClick: () => onEdit(i),
735
- className: "btn-ghost row-span-2 self-start text-sm",
736
- children: "Edit"
737
- }
738
- ),
739
- /* @__PURE__ */ jsx4("dd", { className: "col-start-2 mt-2 whitespace-pre-wrap text-stone-900", children: answered ? display : /* @__PURE__ */ jsx4("span", { className: "italic text-stone-600", children: "Not answered" }) })
728
+ /* @__PURE__ */ jsxs4("dt", { className: "col-span-3 grid grid-cols-subgrid", children: [
729
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: "pt-1 font-mono text-sm text-stone-600", children: String(i + 1).padStart(2, "0") }),
730
+ /* @__PURE__ */ jsx4("span", { className: "text-sm font-medium text-stone-900", children: q.prompt }),
731
+ /* @__PURE__ */ jsx4(
732
+ "button",
733
+ {
734
+ type: "button",
735
+ onClick: () => onEdit(i),
736
+ "aria-label": `Edit: ${q.prompt}`,
737
+ className: "btn-ghost self-start text-sm",
738
+ children: "Edit"
739
+ }
740
+ )
741
+ ] }),
742
+ /* @__PURE__ */ jsx4("dd", { className: "col-span-3 mt-2 grid grid-cols-subgrid", children: /* @__PURE__ */ jsx4("span", { className: "col-start-2 whitespace-pre-wrap text-stone-900", children: answered ? display : /* @__PURE__ */ jsx4("span", { className: "italic text-stone-600", children: "Not answered" }) }) })
740
743
  ]
741
744
  },
742
745
  q.id
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ProgressBar.tsx","../src/QuestionCard.tsx","../src/summarize.ts","../src/AnswerSidebar.tsx","../src/ReviewSummary.tsx"],"sourcesContent":["'use client';\n\ninterface Props {\n current: number;\n total: number;\n estimatedMinutesRemaining: number;\n}\n\n/**\n * Linear progress indicator for the interview flow. Renders the\n * \"Question N of M\" caption, the estimated minutes remaining, and a\n * forest-700 fill bar at `(current / total) * 100%`.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * stone-100 surface with stone-200 border; forest-700 fill bar; stone-700\n * caption text. Pure-render component — no state-management dependency.\n *\n * Extracted from `apps/hub/src/components/interview/ProgressBar.tsx`\n * during iteration-3-B.1 (2026-05-07). No prop API change.\n */\nexport function ProgressBar({ current, total, estimatedMinutesRemaining }: Props) {\n const percent = Math.round((current / total) * 100);\n\n return (\n <div className=\"border-b border-stone-200 bg-stone-100 py-3 px-6\">\n <div className=\"mx-auto max-w-3xl\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Question {current} of {total}\n </span>\n <span className=\"font-mono text-xs text-stone-700\">\n ~{estimatedMinutesRemaining} min remaining\n </span>\n </div>\n <div\n className=\"mt-2 h-1 w-full overflow-hidden rounded-full bg-stone-200\"\n role=\"progressbar\"\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`Interview progress: ${percent}% complete`}\n >\n <div\n className=\"h-full bg-forest-700 transition-all duration-300 ease-out\"\n style={{ width: `${percent}%` }}\n />\n </div>\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport type {\n InterviewQuestion,\n AnswerValue,\n AnswerComposite,\n AnswerRepeater,\n AnswerFileUpload,\n FileEntry,\n} from './types';\n\ninterface Props {\n question: InterviewQuestion;\n /**\n * The currently-saved answer for this question (from the consumer's\n * state container). The component initializes its local form state\n * from this value and re-syncs when the question id changes.\n */\n existingAnswer?: AnswerValue;\n /**\n * Called when the user submits an answer. The consumer is expected to\n * persist the answer into its state container and then advance via\n * `onNext`.\n */\n onAnswerSubmit: (questionId: string, value: AnswerValue) => void;\n /** Called after `onAnswerSubmit` to advance to the next question. */\n onNext: () => void;\n /** Called when the user clicks the Back button. */\n onBack: () => void;\n isFirst: boolean;\n isLast: boolean;\n}\n\n/**\n * Default value to use when no `existingAnswer` is supplied. Depends on\n * the question's `inputType`.\n */\nfunction defaultValueFor(question: InterviewQuestion): AnswerValue {\n switch (question.inputType) {\n case 'multi-select':\n case 'list':\n return [];\n case 'composite':\n return {} as AnswerComposite;\n case 'repeater':\n case 'file-upload':\n return [];\n default:\n return '';\n }\n}\n\n/**\n * Whether the user's current local value satisfies the required check\n * for the question.\n */\nfunction canAdvanceWith(question: InterviewQuestion, value: AnswerValue): boolean {\n if (!question.required) return true;\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * Single question renderer. Handles all input types: short-text, long-text,\n * single-select, multi-select, scale, list, date, composite, repeater,\n * file-upload. Keyboard-navigable and screen-reader safe.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * existing answer + change handler as props.\n *\n * Iteration-1 visual identity: form input fields use stone-50 elevated\n * surface + stone-200 default border + forest-700 focus border. Selected\n * radio/checkbox option states use forest-700 border + forest-50 background.\n * The examples disclosure has border-l-2 frame in border-copper-200 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n */\nexport function QuestionCard({\n question,\n existingAnswer,\n onAnswerSubmit,\n onNext,\n onBack,\n isFirst,\n isLast,\n}: Props) {\n const [localValue, setLocalValue] = useState<AnswerValue>(\n existingAnswer ?? defaultValueFor(question),\n );\n\n // Sync when question changes (consumer flipped to a different question;\n // local form state should reflect that question's existing answer).\n useEffect(() => {\n setLocalValue(existingAnswer ?? defaultValueFor(question));\n }, [question.id, existingAnswer, question.inputType]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onAnswerSubmit(question.id, localValue);\n onNext();\n };\n\n const canAdvance = canAdvanceWith(question, localValue);\n\n return (\n <form onSubmit={handleSubmit} className=\"animate-slide-up\">\n {/* Prompt */}\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n {question.prompt}\n </h2>\n {question.subprompt && (\n <p className=\"mt-4 text-lg text-stone-700\">{question.subprompt}</p>\n )}\n\n {/* Input — dispatched per type */}\n <div className=\"mt-8\">\n <InputForType\n question={question}\n value={localValue}\n onChange={setLocalValue}\n />\n </div>\n\n {/* Examples */}\n {question.examples && question.examples.length > 0 && (\n <details className=\"mt-8\">\n <summary className=\"cursor-pointer text-sm font-medium text-forest-700 hover:text-forest-800\">\n Show examples from different fields\n </summary>\n {/* border-copper-200 PRESERVED: decorative-emphasis frame around\n illustrative content, same role as HeroSection's etymology box. */}\n <ul className=\"mt-4 space-y-3 border-l-2 border-copper-200 pl-5\">\n {question.examples.map((ex, i) => (\n <li key={i} className=\"text-sm italic text-stone-700\">\n “{ex}”\n </li>\n ))}\n </ul>\n </details>\n )}\n\n {/* Skip consequence (if applicable) */}\n {!question.required && question.skipConsequence && (\n <p className=\"mt-6 text-sm text-stone-700\">\n <span className=\"font-medium\">If you skip this:</span> {question.skipConsequence}\n </p>\n )}\n\n {/* Nav */}\n <div className=\"mt-10 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={onBack}\n disabled={isFirst}\n className=\"btn-ghost disabled:opacity-40\"\n >\n ← Back\n </button>\n <div className=\"flex gap-3\">\n {!question.required && (\n <button type=\"button\" onClick={onNext} className=\"btn-ghost\">\n Skip\n </button>\n )}\n <button type=\"submit\" disabled={!canAdvance} className=\"btn-primary\">\n {isLast ? 'Review answers' : 'Continue →'}\n </button>\n </div>\n </div>\n </form>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Per-input-type renderers\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface InputProps {\n question: InterviewQuestion;\n value: AnswerValue;\n onChange: (next: AnswerValue) => void;\n}\n\nfunction InputForType({ question, value, onChange }: InputProps) {\n switch (question.inputType) {\n case 'short-text':\n return <ShortTextInput value={value as string} onChange={onChange} />;\n case 'long-text':\n return <LongTextInput value={value as string} onChange={onChange} />;\n case 'single-select':\n return <SingleSelectInput question={question} value={value as string} onChange={onChange} />;\n case 'multi-select':\n return <MultiSelectInput question={question} value={(value as string[]) ?? []} onChange={onChange} />;\n case 'list':\n return <ListInput value={(value as string[]) ?? []} onChange={onChange} listRange={question.listRange} />;\n case 'scale':\n return <ScaleInput question={question} value={value as string} onChange={onChange} />;\n case 'date':\n return <DateInput value={value as string} onChange={onChange} ariaLabel={question.prompt} />;\n case 'composite':\n return <CompositeInput question={question} value={(value as AnswerComposite) ?? {}} onChange={onChange} />;\n case 'repeater':\n return <RepeaterInput question={question} value={(value as AnswerRepeater) ?? []} onChange={onChange} />;\n case 'file-upload':\n return <FileUploadInput question={question} value={(value as AnswerFileUpload) ?? []} onChange={onChange} />;\n default: {\n const _exhaustive: never = question.inputType;\n return <UnknownTypeFallback inputType={_exhaustive} />;\n }\n }\n}\n\nfunction ShortTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <input\n type=\"text\"\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction LongTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <textarea\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n rows={5}\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction SingleSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n ))}\n </div>\n );\n}\n\nfunction MultiSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string[];\n onChange: (v: string[]) => void;\n}) {\n return (\n <div className=\"space-y-2\" role=\"group\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => {\n const checked = value.includes(opt.value);\n return (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n checked\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"checkbox\"\n value={opt.value}\n checked={checked}\n onChange={(e) => {\n if (e.target.checked) onChange([...value, opt.value]);\n else onChange(value.filter((v) => v !== opt.value));\n }}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n );\n })}\n </div>\n );\n}\n\nfunction ScaleInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n const options = question.options ?? [];\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {options.map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-center gap-3 rounded-lg border-2 p-3 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-4 w-4 text-forest-700\"\n />\n <span className=\"font-mono text-sm text-stone-700\">{opt.value}</span>\n <span className=\"text-stone-900\">{opt.label}</span>\n </label>\n ))}\n </div>\n );\n}\n\nfunction DateInput({\n value,\n onChange,\n ariaLabel,\n}: {\n value: string;\n onChange: (v: string) => void;\n ariaLabel: string;\n}) {\n return (\n <input\n type=\"date\"\n aria-label={ariaLabel}\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n />\n );\n}\n\nfunction ListInput({\n value,\n onChange,\n listRange,\n}: {\n value: string[];\n onChange: (v: string[]) => void;\n listRange?: { min: number; max: number };\n}) {\n const items = value.length > 0 ? value : [''];\n const min = listRange?.min ?? 0;\n const max = listRange?.max ?? Infinity;\n\n const setItem = (i: number, v: string) => {\n const next = [...items];\n next[i] = v;\n onChange(next);\n };\n const addItem = () => {\n if (items.length < max) onChange([...items, '']);\n };\n const removeItem = (i: number) => {\n if (items.length <= 1) return;\n onChange(items.filter((_, idx) => idx !== i));\n };\n const validCount = items.filter((v) => v.trim().length > 0).length;\n\n return (\n <div>\n <ul className=\"space-y-2\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-center gap-2\">\n <span className=\"w-6 text-right font-mono text-xs text-stone-600\">{i + 1}.</span>\n <input\n type=\"text\"\n value={item}\n onChange={(e) => setItem(i, e.target.value)}\n className=\"flex-grow rounded-lg border-2 border-stone-200 bg-stone-50 px-3 py-2 text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder={`Item ${i + 1}`}\n />\n <button\n type=\"button\"\n onClick={() => removeItem(i)}\n disabled={items.length <= 1}\n className=\"btn-ghost text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n ×\n </button>\n </li>\n ))}\n </ul>\n <div className=\"mt-3 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={addItem}\n disabled={items.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add item\n </button>\n {listRange && (\n <span className=\"font-mono text-xs text-stone-700\">\n {validCount} / {min}–{max === Infinity ? '∞' : max}\n </span>\n )}\n </div>\n </div>\n );\n}\n\nfunction CompositeInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerComposite;\n onChange: (v: AnswerComposite) => void;\n}) {\n const subQuestions = question.subQuestions ?? [];\n return (\n <div className=\"space-y-6 rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n {subQuestions.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={value[sub.id]}\n onChange={(next) => onChange({ ...value, [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction RepeaterInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerRepeater;\n onChange: (v: AnswerRepeater) => void;\n}) {\n const rows = value.length > 0 ? value : [{} as Record<string, AnswerValue>];\n const itemSchema = question.itemSchema ?? [];\n const min = question.listRange?.min ?? 1;\n const max = question.listRange?.max ?? Infinity;\n\n const updateRow = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...rows];\n next[i] = { ...next[i], ...patch };\n onChange(next);\n };\n const addRow = () => {\n if (rows.length < max) onChange([...rows, {} as Record<string, AnswerValue>]);\n };\n const removeRow = (i: number) => {\n if (rows.length <= 1) return;\n onChange(rows.filter((_, idx) => idx !== i));\n };\n\n return (\n <div className=\"space-y-4\">\n {rows.map((row, i) => (\n <div key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Item {i + 1}\n </span>\n <button\n type=\"button\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= min}\n className=\"btn-ghost text-xs text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n Remove\n </button>\n </div>\n <div className=\"space-y-4\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && (\n <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>\n )}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={row[sub.id]}\n onChange={(next) => updateRow(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={addRow}\n disabled={rows.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add another\n </button>\n </div>\n );\n}\n\nfunction FileUploadInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerFileUpload;\n onChange: (v: AnswerFileUpload) => void;\n}) {\n const itemSchema = question.itemSchema ?? [];\n\n const onFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return;\n const entries: FileEntry[] = Array.from(files).map((f) => ({\n file: f,\n metadata: {},\n }));\n onChange([...value, ...entries]);\n };\n\n const updateMetadata = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...value];\n next[i] = { ...next[i], metadata: { ...next[i].metadata, ...patch } };\n onChange(next);\n };\n const removeEntry = (i: number) => onChange(value.filter((_, idx) => idx !== i));\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n onFiles(e.dataTransfer.files);\n };\n const onDragOver = (e: React.DragEvent<HTMLDivElement>) => e.preventDefault();\n\n return (\n <div className=\"space-y-4\">\n <div\n onDrop={onDrop}\n onDragOver={onDragOver}\n className=\"rounded-lg border-2 border-dashed border-stone-300 bg-stone-50 p-6 text-center\"\n >\n <p className=\"text-sm text-stone-700\">\n Drag PDFs or other files here, or{' '}\n <label className=\"cursor-pointer font-medium text-forest-700 hover:text-forest-800\">\n browse\n <input\n type=\"file\"\n multiple\n className=\"sr-only\"\n onChange={(e) => onFiles(e.target.files)}\n />\n </label>\n </p>\n <p className=\"mt-1 text-xs text-stone-700\">\n You'll add a title, author, and description for each file below.\n </p>\n </div>\n\n {value.length > 0 && (\n <ul className=\"space-y-4\">\n {value.map((entry, i) => {\n const name = entry.file.name;\n const size = 'size' in entry.file ? entry.file.size : undefined;\n return (\n <li key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"font-medium text-stone-900\">{name}</div>\n {typeof size === 'number' && (\n <div className=\"font-mono text-xs text-stone-700\">\n {(size / 1024).toFixed(1)} KB\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => removeEntry(i)}\n className=\"btn-ghost text-xs text-stone-700\"\n aria-label={`Remove ${name}`}\n >\n Remove\n </button>\n </div>\n {itemSchema.length > 0 && (\n <div className=\"mt-4 space-y-3\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-xs font-medium text-stone-900\">{sub.prompt}</div>\n <div className=\"mt-1\">\n <InputForType\n question={sub}\n value={entry.metadata[sub.id]}\n onChange={(next) => updateMetadata(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n\nfunction UnknownTypeFallback({ inputType }: { inputType: never }) {\n // Render-time defensive guard for runtime values that bypass TS (e.g.,\n // YAML-loaded interview schemas with typos). Visible to dev; user sees a\n // muted \"unsupported\" notice.\n return (\n <div className=\"rounded-lg border-2 border-stone-300 bg-stone-50 p-4 text-sm text-stone-700\">\n Unsupported question input type:{' '}\n <code className=\"font-mono\">{String(inputType)}</code>\n </div>\n );\n}\n","/**\n * Helpers for rendering one-line / summary previews of answer values in\n * `AnswerSidebar` and `ReviewSummary`. Centralized so the two components\n * stay consistent when new answer shapes are added.\n */\nimport type { AnswerValue, FileEntry, InterviewQuestion } from './types';\n\nexport function isAnswered(value: AnswerValue): boolean {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * A short, single-line preview suitable for sidebar items. Truncates\n * long content. Returns the empty string for unanswered values.\n */\nexport function summarizeShort(question: InterviewQuestion, value: AnswerValue, maxLen = 80): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return truncate(String(value), maxLen);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return truncate(label ?? v, maxLen);\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => {\n const found = question.options?.find((o) => o.value === v)?.label;\n return found ?? v;\n });\n return truncate(labels.join(', '), maxLen);\n }\n case 'composite': {\n // Show the first sub-answer's preview if any.\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n return truncate(summarizeShort(sub, subVal, maxLen), maxLen);\n }\n }\n return '';\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n return `${rows.length} item${rows.length === 1 ? '' : 's'}`;\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return `${files.length} file${files.length === 1 ? '' : 's'}`;\n }\n default:\n return '';\n }\n}\n\n/**\n * A richer multi-line summary suitable for the ReviewSummary list. May\n * contain newlines; consumers should render in a `whitespace-pre-wrap`\n * container.\n */\nexport function summarizeLong(question: InterviewQuestion, value: AnswerValue): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return String(value);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return label ?? v;\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => question.options?.find((o) => o.value === v)?.label ?? v);\n return labels.join('\\n• ').replace(/^/, '• ');\n }\n case 'composite': {\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n const lines: string[] = [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n lines.push(`${sub.prompt}: ${summarizeShort(sub, subVal, 200)}`);\n }\n }\n return lines.join('\\n');\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n const itemSchema = question.itemSchema ?? [];\n const summary = rows.map((row, i) => {\n const parts: string[] = [`Item ${i + 1}:`];\n for (const sub of itemSchema) {\n const subVal = row[sub.id];\n if (isAnswered(subVal)) {\n parts.push(` ${sub.prompt}: ${summarizeShort(sub, subVal, 100)}`);\n }\n }\n return parts.join('\\n');\n });\n return summary.join('\\n');\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return files\n .map((f, i) => `${i + 1}. ${f.file.name}`)\n .join('\\n');\n }\n default:\n return '';\n }\n}\n\nfunction truncate(s: string, maxLen: number): string {\n return s.length > maxLen ? s.slice(0, maxLen - 1) + '…' : s;\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeShort } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n currentIndex: number;\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n /** Called when the user clicks a sidebar item to jump to that question. */\n onSelectQuestion: (index: number) => void;\n}\n\n/**\n * Sidebar showing all answered questions. Clicking any returns to edit that\n * question without losing later answers. Implements the wiki's pattern:\n * \"Edit any prior answer — a sidebar shows all answered questions.\"\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answers + jump handler as props.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Three item states with distinct token tiers:\n * - current → forest-700 border + forest-50 bg (interactive primary)\n * - answered → stone-200 border + stone-50 bg (default, hover stone-400)\n * - unanswered → stone-200/50 + stone-50/50 (muted via opacity preservation)\n *\n * D.2.1.b extension: previews for composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all eight scalar + three compound types\n * render consistently.\n */\nexport function AnswerSidebar({ questions, currentIndex, answers, onSelectQuestion }: Props) {\n return (\n <aside\n className=\"sticky top-24 hidden max-h-[calc(100vh-6rem)] overflow-y-auto lg:block\"\n aria-label=\"Completed answers\"\n >\n <h3 className=\"mb-3 font-mono text-xs uppercase tracking-wider text-stone-700\">\n Your answers\n </h3>\n <ol className=\"space-y-3\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const isCurrent = i === currentIndex;\n const preview = answered ? summarizeShort(q, answer) : '';\n\n return (\n <li key={q.id}>\n <button\n type=\"button\"\n onClick={() => onSelectQuestion(i)}\n className={`w-full rounded-lg border p-3 text-left transition-colors ${\n isCurrent\n ? 'border-forest-700 bg-forest-50'\n : answered\n ? 'border-stone-200 bg-stone-50 hover:border-stone-400'\n : 'border-stone-200/50 bg-stone-50/50 hover:border-stone-300'\n }`}\n >\n <div className=\"flex items-start gap-2\">\n <span\n className={`mt-0.5 font-mono text-xs ${\n isCurrent\n ? 'text-forest-700'\n : answered\n ? 'text-stone-700'\n : 'text-stone-600'\n }`}\n >\n {String(i + 1).padStart(2, '0')}.\n </span>\n <div className=\"flex-grow\">\n <div\n className={`text-xs font-medium ${\n answered ? 'text-stone-900' : 'text-stone-700'\n }`}\n >\n {q.prompt.length > 50 ? q.prompt.slice(0, 50) + '…' : q.prompt}\n </div>\n {answered && (\n <div className=\"mt-1 text-xs italic text-stone-700 line-clamp-1\">\n {preview}\n </div>\n )}\n </div>\n </div>\n </button>\n </li>\n );\n })}\n </ol>\n </aside>\n );\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeLong } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n onGenerate: () => void;\n onEdit: (questionIndex: number) => void;\n generating: boolean;\n}\n\n/**\n * Final review screen — the penultimate step before generation.\n * Shows all answers so the user can confirm ownership of the output before\n * committing.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answer record as a prop.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Editorial Josefin display family on the heading and the \"What happens next\"\n * callout title. Stone-tier surfaces and content text throughout. The\n * \"What happens next\" callout box preserves border-copper-300 + bg-copper-50 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n *\n * D.2.1.b extension: rendering of composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all answer types display consistently.\n */\nexport function ReviewSummary({ questions, answers, onGenerate, onEdit, generating }: Props) {\n return (\n <div className=\"animate-slide-up\">\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n Review your answers\n </h2>\n <p className=\"mt-4 text-lg text-stone-700\">\n These become the seed content of your project. You can edit anything now, or continue and\n edit later through the platform.\n </p>\n\n <dl className=\"mt-10 space-y-6 border-t border-stone-200 pt-6\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const display = answered ? summarizeLong(q, answer) : '';\n\n return (\n // Grid so the index + Edit button sit beside the dt/dd group while\n // <dt>/<dd> remain DIRECT children of this div (a direct child of\n // <dl>) — required for valid definition-list semantics (axe\n // definition-list / dlitem).\n <div\n key={q.id}\n className=\"grid grid-cols-[auto_1fr_auto] gap-x-4 border-b border-stone-200 pb-6\"\n >\n <span className=\"row-span-2 pt-1 font-mono text-sm text-stone-600\">\n {String(i + 1).padStart(2, '0')}\n </span>\n <dt className=\"text-sm font-medium text-stone-900\">{q.prompt}</dt>\n <button\n type=\"button\"\n onClick={() => onEdit(i)}\n className=\"btn-ghost row-span-2 self-start text-sm\"\n >\n Edit\n </button>\n <dd className=\"col-start-2 mt-2 whitespace-pre-wrap text-stone-900\">\n {answered ? (\n display\n ) : (\n <span className=\"italic text-stone-600\">Not answered</span>\n )}\n </dd>\n </div>\n );\n })}\n </dl>\n\n {/* \"What happens next\" callout — copper PRESERVED as decorative\n informational frame, same role as HeroSection's etymology box.\n Per iteration-1 §5.2's preserved-decorative-copper governance. */}\n <div className=\"mt-10 rounded-lg border border-copper-300 bg-copper-50 p-6\">\n <h3 className=\"font-display text-xl text-stone-900\">What happens next</h3>\n <p className=\"mt-2 text-stone-900\">\n When you click Generate, the platform will create a GitHub repository in your account,\n populate it with your personalized CLAUDE.md, KNOWLEDGE.md, and wiki, and give you the\n URL. This takes about 30–90 seconds. You can edit everything afterward through the\n platform or through your repo.\n </p>\n <p className=\"mt-3 text-sm text-stone-700\">\n <span className=\"font-medium\">MVP note:</span> In this phase, GitHub repo creation is\n mocked for demonstration. Once OAuth credentials are configured, real repos will be\n created on your behalf.\n </p>\n </div>\n\n <div className=\"mt-8 flex justify-end\">\n <button\n type=\"button\"\n onClick={onGenerate}\n disabled={generating}\n className=\"btn-primary text-lg\"\n >\n {generating ? 'Generating your project…' : 'Generate my platform'}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":";AA2BU,SAeA,KAfA;AAPH,SAAS,YAAY,EAAE,SAAS,OAAO,0BAA0B,GAAU;AAChF,QAAM,UAAU,KAAK,MAAO,UAAU,QAAS,GAAG;AAElD,SACE,oBAAC,SAAI,WAAU,oDACb,+BAAC,SAAI,WAAU,qBACb;AAAA,yBAAC,SAAI,WAAU,6CACb;AAAA,2BAAC,UAAK,WAAU,6DAA4D;AAAA;AAAA,QAChE;AAAA,QAAQ;AAAA,QAAK;AAAA,SACzB;AAAA,MACA,qBAAC,UAAK,WAAU,oCAAmC;AAAA;AAAA,QAC/C;AAAA,QAA0B;AAAA,SAC9B;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,MAAK;AAAA,QACL,iBAAe;AAAA,QACf,iBAAe;AAAA,QACf,iBAAe;AAAA,QACf,cAAY,uBAAuB,OAAO;AAAA,QAE1C;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI;AAAA;AAAA,QAChC;AAAA;AAAA,IACF;AAAA,KACF,GACF;AAEJ;;;AChDA,SAAS,UAAU,iBAAiB;AA4G9B,gBAAAA,MA0BQ,QAAAC,aA1BR;AAxEN,SAAS,gBAAgB,UAA0C;AACjE,UAAQ,SAAS,WAAW;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC;AAAA,IACV,KAAK;AACH,aAAO,CAAC;AAAA,IACV,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC;AAAA,IACV;AACE,aAAO;AAAA,EACX;AACF;AAMA,SAAS,eAAe,UAA6B,OAA6B;AAChF,MAAI,CAAC,SAAS,SAAU,QAAO;AAC/B,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,KAAK,EAAE,SAAS;AAC5D,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,SAAS;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAK,EAAE,SAAS;AAClE,SAAO;AACT;AAgBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAU;AACR,QAAM,CAAC,YAAY,aAAa,IAAI;AAAA,IAClC,kBAAkB,gBAAgB,QAAQ;AAAA,EAC5C;AAIA,YAAU,MAAM;AACd,kBAAc,kBAAkB,gBAAgB,QAAQ,CAAC;AAAA,EAC3D,GAAG,CAAC,SAAS,IAAI,gBAAgB,SAAS,SAAS,CAAC;AAEpD,QAAM,eAAe,CAAC,MAAuB;AAC3C,MAAE,eAAe;AACjB,mBAAe,SAAS,IAAI,UAAU;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,eAAe,UAAU,UAAU;AAEtD,SACE,gBAAAA,MAAC,UAAK,UAAU,cAAc,WAAU,oBAEtC;AAAA,oBAAAD,KAAC,QAAG,WAAU,gEACX,mBAAS,QACZ;AAAA,IACC,SAAS,aACR,gBAAAA,KAAC,OAAE,WAAU,+BAA+B,mBAAS,WAAU;AAAA,IAIjE,gBAAAA,KAAC,SAAI,WAAU,QACb,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA;AAAA,IACZ,GACF;AAAA,IAGC,SAAS,YAAY,SAAS,SAAS,SAAS,KAC/C,gBAAAC,MAAC,aAAQ,WAAU,QACjB;AAAA,sBAAAD,KAAC,aAAQ,WAAU,4EAA2E,iDAE9F;AAAA,MAGA,gBAAAA,KAAC,QAAG,WAAU,oDACX,mBAAS,SAAS,IAAI,CAAC,IAAI,MAC1B,gBAAAC,MAAC,QAAW,WAAU,iCAAgC;AAAA;AAAA,QAClD;AAAA,QAAG;AAAA,WADE,CAET,CACD,GACH;AAAA,OACF;AAAA,IAID,CAAC,SAAS,YAAY,SAAS,mBAC9B,gBAAAA,MAAC,OAAE,WAAU,+BACX;AAAA,sBAAAD,KAAC,UAAK,WAAU,eAAc,+BAAiB;AAAA,MAAO;AAAA,MAAE,SAAS;AAAA,OACnE;AAAA,IAIF,gBAAAC,MAAC,SAAI,WAAU,2CACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU;AAAA,UACV,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACA,gBAAAC,MAAC,SAAI,WAAU,cACZ;AAAA,SAAC,SAAS,YACT,gBAAAD,KAAC,YAAO,MAAK,UAAS,SAAS,QAAQ,WAAU,aAAY,kBAE7D;AAAA,QAEF,gBAAAA,KAAC,YAAO,MAAK,UAAS,UAAU,CAAC,YAAY,WAAU,eACpD,mBAAS,mBAAmB,mBAC/B;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEJ;AAYA,SAAS,aAAa,EAAE,UAAU,OAAO,SAAS,GAAe;AAC/D,UAAQ,SAAS,WAAW;AAAA,IAC1B,KAAK;AACH,aAAO,gBAAAA,KAAC,kBAAe,OAAwB,UAAoB;AAAA,IACrE,KAAK;AACH,aAAO,gBAAAA,KAAC,iBAAc,OAAwB,UAAoB;AAAA,IACpE,KAAK;AACH,aAAO,gBAAAA,KAAC,qBAAkB,UAAoB,OAAwB,UAAoB;AAAA,IAC5F,KAAK;AACH,aAAO,gBAAAA,KAAC,oBAAiB,UAAoB,OAAQ,SAAsB,CAAC,GAAG,UAAoB;AAAA,IACrG,KAAK;AACH,aAAO,gBAAAA,KAAC,aAAU,OAAQ,SAAsB,CAAC,GAAG,UAAoB,WAAW,SAAS,WAAW;AAAA,IACzG,KAAK;AACH,aAAO,gBAAAA,KAAC,cAAW,UAAoB,OAAwB,UAAoB;AAAA,IACrF,KAAK;AACH,aAAO,gBAAAA,KAAC,aAAU,OAAwB,UAAoB,WAAW,SAAS,QAAQ;AAAA,IAC5F,KAAK;AACH,aAAO,gBAAAA,KAAC,kBAAe,UAAoB,OAAQ,SAA6B,CAAC,GAAG,UAAoB;AAAA,IAC1G,KAAK;AACH,aAAO,gBAAAA,KAAC,iBAAc,UAAoB,OAAQ,SAA4B,CAAC,GAAG,UAAoB;AAAA,IACxG,KAAK;AACH,aAAO,gBAAAA,KAAC,mBAAgB,UAAoB,OAAQ,SAA8B,CAAC,GAAG,UAAoB;AAAA,IAC5G,SAAS;AACP,YAAM,cAAqB,SAAS;AACpC,aAAO,gBAAAA,KAAC,uBAAoB,WAAW,aAAa;AAAA,IACtD;AAAA,EACF;AACF;AAEA,SAAS,eAAe,EAAE,OAAO,SAAS,GAAqD;AAC7F,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,OAAO,SAAS;AAAA,MAChB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,MACxC,WAAS;AAAA,MACT,WAAU;AAAA,MACV,aAAY;AAAA;AAAA,EACd;AAEJ;AAEA,SAAS,cAAc,EAAE,OAAO,SAAS,GAAqD;AAC5F,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,SAAS;AAAA,MAChB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,MACxC,WAAS;AAAA,MACT,MAAM;AAAA,MACN,WAAU;AAAA,MACV,aAAY;AAAA;AAAA,EACd;AAEJ;AAEA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAA,KAAC,SAAI,WAAU,aAAY,MAAK,cAAa,mBAAiB,KAAK,SAAS,EAAE,IAC1E,oBAAS,WAAW,CAAC,GAAG,IAAI,CAAC,QAC7B,gBAAAC;AAAA,IAAC;AAAA;AAAA,MAEC,WAAW,mFACT,UAAU,IAAI,QACV,mCACA,qDACN;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAM,SAAS;AAAA,YACf,OAAO,IAAI;AAAA,YACX,SAAS,UAAU,IAAI;AAAA,YACvB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,YACxC,WAAU;AAAA;AAAA,QACZ;AAAA,QACA,gBAAAC,MAAC,SACC;AAAA,0BAAAD,KAAC,SAAI,WAAU,8BAA8B,cAAI,OAAM;AAAA,UACtD,IAAI,eACH,gBAAAA,KAAC,SAAI,WAAU,+BAA+B,cAAI,aAAY;AAAA,WAElE;AAAA;AAAA;AAAA,IApBK,IAAI;AAAA,EAqBX,CACD,GACH;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAA,KAAC,SAAI,WAAU,aAAY,MAAK,SAAQ,mBAAiB,KAAK,SAAS,EAAE,IACrE,oBAAS,WAAW,CAAC,GAAG,IAAI,CAAC,QAAQ;AACrC,UAAM,UAAU,MAAM,SAAS,IAAI,KAAK;AACxC,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW,mFACT,UACI,mCACA,qDACN;AAAA,QAEA;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO,IAAI;AAAA,cACX;AAAA,cACA,UAAU,CAAC,MAAM;AACf,oBAAI,EAAE,OAAO,QAAS,UAAS,CAAC,GAAG,OAAO,IAAI,KAAK,CAAC;AAAA,oBAC/C,UAAS,MAAM,OAAO,CAAC,MAAM,MAAM,IAAI,KAAK,CAAC;AAAA,cACpD;AAAA,cACA,WAAU;AAAA;AAAA,UACZ;AAAA,UACA,gBAAAC,MAAC,SACC;AAAA,4BAAAD,KAAC,SAAI,WAAU,8BAA8B,cAAI,OAAM;AAAA,YACtD,IAAI,eACH,gBAAAA,KAAC,SAAI,WAAU,+BAA+B,cAAI,aAAY;AAAA,aAElE;AAAA;AAAA;AAAA,MAtBK,IAAI;AAAA,IAuBX;AAAA,EAEJ,CAAC,GACH;AAEJ;AAEA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,UAAU,SAAS,WAAW,CAAC;AACrC,SACE,gBAAAA,KAAC,SAAI,WAAU,aAAY,MAAK,cAAa,mBAAiB,KAAK,SAAS,EAAE,IAC3E,kBAAQ,IAAI,CAAC,QACZ,gBAAAC;AAAA,IAAC;AAAA;AAAA,MAEC,WAAW,oFACT,UAAU,IAAI,QACV,mCACA,qDACN;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAM,SAAS;AAAA,YACf,OAAO,IAAI;AAAA,YACX,SAAS,UAAU,IAAI;AAAA,YACvB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,YACxC,WAAU;AAAA;AAAA,QACZ;AAAA,QACA,gBAAAA,KAAC,UAAK,WAAU,oCAAoC,cAAI,OAAM;AAAA,QAC9D,gBAAAA,KAAC,UAAK,WAAU,kBAAkB,cAAI,OAAM;AAAA;AAAA;AAAA,IAhBvC,IAAI;AAAA,EAiBX,CACD,GACH;AAEJ;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,OAAO,SAAS;AAAA,MAChB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,MACxC,WAAS;AAAA,MACT,WAAU;AAAA;AAAA,EACZ;AAEJ;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,QAAQ,MAAM,SAAS,IAAI,QAAQ,CAAC,EAAE;AAC5C,QAAM,MAAM,WAAW,OAAO;AAC9B,QAAM,MAAM,WAAW,OAAO;AAE9B,QAAM,UAAU,CAAC,GAAW,MAAc;AACxC,UAAM,OAAO,CAAC,GAAG,KAAK;AACtB,SAAK,CAAC,IAAI;AACV,aAAS,IAAI;AAAA,EACf;AACA,QAAM,UAAU,MAAM;AACpB,QAAI,MAAM,SAAS,IAAK,UAAS,CAAC,GAAG,OAAO,EAAE,CAAC;AAAA,EACjD;AACA,QAAM,aAAa,CAAC,MAAc;AAChC,QAAI,MAAM,UAAU,EAAG;AACvB,aAAS,MAAM,OAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAC9C;AACA,QAAM,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE;AAE5D,SACE,gBAAAC,MAAC,SACC;AAAA,oBAAAD,KAAC,QAAG,WAAU,aACX,gBAAM,IAAI,CAAC,MAAM,MAChB,gBAAAC,MAAC,QAAW,WAAU,2BACpB;AAAA,sBAAAA,MAAC,UAAK,WAAU,mDAAmD;AAAA,YAAI;AAAA,QAAE;AAAA,SAAC;AAAA,MAC1E,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,QAAQ,GAAG,EAAE,OAAO,KAAK;AAAA,UAC1C,WAAU;AAAA,UACV,aAAa,QAAQ,IAAI,CAAC;AAAA;AAAA,MAC5B;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,WAAW,CAAC;AAAA,UAC3B,UAAU,MAAM,UAAU;AAAA,UAC1B,WAAU;AAAA,UACV,cAAY,eAAe,IAAI,CAAC;AAAA,UACjC;AAAA;AAAA,MAED;AAAA,SAjBO,CAkBT,CACD,GACH;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,0CACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU,MAAM,UAAU;AAAA,UAC1B,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACC,aACC,gBAAAC,MAAC,UAAK,WAAU,oCACb;AAAA;AAAA,QAAW;AAAA,QAAI;AAAA,QAAI;AAAA,QAAE,QAAQ,WAAW,WAAM;AAAA,SACjD;AAAA,OAEJ;AAAA,KACF;AAEJ;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,eAAe,SAAS,gBAAgB,CAAC;AAC/C,SACE,gBAAAD,KAAC,SAAI,WAAU,kEACZ,uBAAa,IAAI,CAAC,QACjB,gBAAAC,MAAC,SACC;AAAA,oBAAAD,KAAC,SAAI,WAAU,sCAAsC,cAAI,QAAO;AAAA,IAC/D,IAAI,aAAa,gBAAAA,KAAC,SAAI,WAAU,+BAA+B,cAAI,WAAU;AAAA,IAC9E,gBAAAA,KAAC,SAAI,WAAU,QACb,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU;AAAA,QACV,OAAO,MAAM,IAAI,EAAE;AAAA,QACnB,UAAU,CAAC,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC;AAAA;AAAA,IAC3D,GACF;AAAA,OATQ,IAAI,EAUd,CACD,GACH;AAEJ;AAEA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,OAAO,MAAM,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAgC;AAC1E,QAAM,aAAa,SAAS,cAAc,CAAC;AAC3C,QAAM,MAAM,SAAS,WAAW,OAAO;AACvC,QAAM,MAAM,SAAS,WAAW,OAAO;AAEvC,QAAM,YAAY,CAAC,GAAW,UAAuC;AACnE,UAAM,OAAO,CAAC,GAAG,IAAI;AACrB,SAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,GAAG,MAAM;AACjC,aAAS,IAAI;AAAA,EACf;AACA,QAAM,SAAS,MAAM;AACnB,QAAI,KAAK,SAAS,IAAK,UAAS,CAAC,GAAG,MAAM,CAAC,CAAgC,CAAC;AAAA,EAC9E;AACA,QAAM,YAAY,CAAC,MAAc;AAC/B,QAAI,KAAK,UAAU,EAAG;AACtB,aAAS,KAAK,OAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAC7C;AAEA,SACE,gBAAAC,MAAC,SAAI,WAAU,aACZ;AAAA,SAAK,IAAI,CAAC,KAAK,MACd,gBAAAA,MAAC,SAAY,WAAU,wDACrB;AAAA,sBAAAA,MAAC,SAAI,WAAU,0CACb;AAAA,wBAAAA,MAAC,UAAK,WAAU,6DAA4D;AAAA;AAAA,UACpE,IAAI;AAAA,WACZ;AAAA,QACA,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM,UAAU,CAAC;AAAA,YAC1B,UAAU,KAAK,UAAU;AAAA,YACzB,WAAU;AAAA,YACV,cAAY,eAAe,IAAI,CAAC;AAAA,YACjC;AAAA;AAAA,QAED;AAAA,SACF;AAAA,MACA,gBAAAA,KAAC,SAAI,WAAU,aACZ,qBAAW,IAAI,CAAC,QACf,gBAAAC,MAAC,SACC;AAAA,wBAAAD,KAAC,SAAI,WAAU,sCAAsC,cAAI,QAAO;AAAA,QAC/D,IAAI,aACH,gBAAAA,KAAC,SAAI,WAAU,+BAA+B,cAAI,WAAU;AAAA,QAE9D,gBAAAA,KAAC,SAAI,WAAU,QACb,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,OAAO,IAAI,IAAI,EAAE;AAAA,YACjB,UAAU,CAAC,SAAS,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC;AAAA;AAAA,QACrD,GACF;AAAA,WAXQ,IAAI,EAYd,CACD,GACH;AAAA,SA/BQ,CAgCV,CACD;AAAA,IACD,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,UAAU,KAAK,UAAU;AAAA,QACzB,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;AAEA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,aAAa,SAAS,cAAc,CAAC;AAE3C,QAAM,UAAU,CAAC,UAA2B;AAC1C,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAClC,UAAM,UAAuB,MAAM,KAAK,KAAK,EAAE,IAAI,CAAC,OAAO;AAAA,MACzD,MAAM;AAAA,MACN,UAAU,CAAC;AAAA,IACb,EAAE;AACF,aAAS,CAAC,GAAG,OAAO,GAAG,OAAO,CAAC;AAAA,EACjC;AAEA,QAAM,iBAAiB,CAAC,GAAW,UAAuC;AACxE,UAAM,OAAO,CAAC,GAAG,KAAK;AACtB,SAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,UAAU,EAAE,GAAG,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE;AACpE,aAAS,IAAI;AAAA,EACf;AACA,QAAM,cAAc,CAAC,MAAc,SAAS,MAAM,OAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC;AAE/E,QAAM,SAAS,CAAC,MAAuC;AACrD,MAAE,eAAe;AACjB,YAAQ,EAAE,aAAa,KAAK;AAAA,EAC9B;AACA,QAAM,aAAa,CAAC,MAAuC,EAAE,eAAe;AAE5E,SACE,gBAAAC,MAAC,SAAI,WAAU,aACb;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAU;AAAA,QAEV;AAAA,0BAAAA,MAAC,OAAE,WAAU,0BAAyB;AAAA;AAAA,YACF;AAAA,YAClC,gBAAAA,MAAC,WAAM,WAAU,oEAAmE;AAAA;AAAA,cAElF,gBAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,UAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,UAAU,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK;AAAA;AAAA,cACzC;AAAA,eACF;AAAA,aACF;AAAA,UACA,gBAAAA,KAAC,OAAE,WAAU,+BAA8B,8EAE3C;AAAA;AAAA;AAAA,IACF;AAAA,IAEC,MAAM,SAAS,KACd,gBAAAA,KAAC,QAAG,WAAU,aACX,gBAAM,IAAI,CAAC,OAAO,MAAM;AACvB,YAAM,OAAO,MAAM,KAAK;AACxB,YAAM,OAAO,UAAU,MAAM,OAAO,MAAM,KAAK,OAAO;AACtD,aACE,gBAAAC,MAAC,QAAW,WAAU,wDACpB;AAAA,wBAAAA,MAAC,SAAI,WAAU,qCACb;AAAA,0BAAAA,MAAC,SACC;AAAA,4BAAAD,KAAC,SAAI,WAAU,8BAA8B,gBAAK;AAAA,YACjD,OAAO,SAAS,YACf,gBAAAC,MAAC,SAAI,WAAU,oCACX;AAAA,sBAAO,MAAM,QAAQ,CAAC;AAAA,cAAE;AAAA,eAC5B;AAAA,aAEJ;AAAA,UACA,gBAAAD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAM,YAAY,CAAC;AAAA,cAC5B,WAAU;AAAA,cACV,cAAY,UAAU,IAAI;AAAA,cAC3B;AAAA;AAAA,UAED;AAAA,WACF;AAAA,QACC,WAAW,SAAS,KACnB,gBAAAA,KAAC,SAAI,WAAU,kBACZ,qBAAW,IAAI,CAAC,QACf,gBAAAC,MAAC,SACC;AAAA,0BAAAD,KAAC,SAAI,WAAU,sCAAsC,cAAI,QAAO;AAAA,UAChE,gBAAAA,KAAC,SAAI,WAAU,QACb,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,UAAU;AAAA,cACV,OAAO,MAAM,SAAS,IAAI,EAAE;AAAA,cAC5B,UAAU,CAAC,SAAS,eAAe,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC;AAAA;AAAA,UAC1D,GACF;AAAA,aARQ,IAAI,EASd,CACD,GACH;AAAA,WAjCK,CAmCT;AAAA,IAEJ,CAAC,GACH;AAAA,KAEJ;AAEJ;AAEA,SAAS,oBAAoB,EAAE,UAAU,GAAyB;AAIhE,SACE,gBAAAC,MAAC,SAAI,WAAU,+EAA8E;AAAA;AAAA,IAC1D;AAAA,IACjC,gBAAAD,KAAC,UAAK,WAAU,aAAa,iBAAO,SAAS,GAAE;AAAA,KACjD;AAEJ;;;AC9pBO,SAAS,WAAW,OAA6B;AACtD,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,KAAK,EAAE,SAAS;AAC5D,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,SAAS;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAK,EAAE,SAAS;AAClE,SAAO;AACT;AAMO,SAAS,eAAe,UAA6B,OAAoB,SAAS,IAAY;AACnG,MAAI,CAAC,WAAW,KAAK,EAAG,QAAO;AAC/B,UAAQ,SAAS,WAAW;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,SAAS,OAAO,KAAK,GAAG,MAAM;AAAA,IACvC,KAAK,iBAAiB;AACpB,YAAM,IAAI,OAAO,KAAK;AACtB,YAAM,QAAQ,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;AAC5D,aAAO,SAAS,SAAS,GAAG,MAAM;AAAA,IACpC;AAAA,IACA,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,YAAM,MAAM;AACZ,YAAM,SAAS,IAAI,IAAI,CAAC,MAAM;AAC5B,cAAM,QAAQ,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;AAC5D,eAAO,SAAS;AAAA,MAClB,CAAC;AACD,aAAO,SAAS,OAAO,KAAK,IAAI,GAAG,MAAM;AAAA,IAC3C;AAAA,IACA,KAAK,aAAa;AAEhB,YAAM,MAAM;AACZ,YAAM,OAAO,SAAS,gBAAgB,CAAC;AACvC,iBAAW,OAAO,MAAM;AACtB,cAAM,SAAS,IAAI,IAAI,EAAE;AACzB,YAAI,WAAW,MAAM,GAAG;AACtB,iBAAO,SAAS,eAAe,KAAK,QAAQ,MAAM,GAAG,MAAM;AAAA,QAC7D;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,YAAY;AACf,YAAM,OAAO;AACb,aAAO,GAAG,KAAK,MAAM,QAAQ,KAAK,WAAW,IAAI,KAAK,GAAG;AAAA,IAC3D;AAAA,IACA,KAAK,eAAe;AAClB,YAAM,QAAQ;AACd,aAAO,GAAG,MAAM,MAAM,QAAQ,MAAM,WAAW,IAAI,KAAK,GAAG;AAAA,IAC7D;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,cAAc,UAA6B,OAA4B;AACrF,MAAI,CAAC,WAAW,KAAK,EAAG,QAAO;AAC/B,UAAQ,SAAS,WAAW;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO,KAAK;AAAA,IACrB,KAAK,iBAAiB;AACpB,YAAM,IAAI,OAAO,KAAK;AACtB,YAAM,QAAQ,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;AAC5D,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,YAAM,MAAM;AACZ,YAAM,SAAS,IAAI,IAAI,CAAC,MAAM,SAAS,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS,CAAC;AACtF,aAAO,OAAO,KAAK,WAAM,EAAE,QAAQ,KAAK,SAAI;AAAA,IAC9C;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,MAAM;AACZ,YAAM,OAAO,SAAS,gBAAgB,CAAC;AACvC,YAAM,QAAkB,CAAC;AACzB,iBAAW,OAAO,MAAM;AACtB,cAAM,SAAS,IAAI,IAAI,EAAE;AACzB,YAAI,WAAW,MAAM,GAAG;AACtB,gBAAM,KAAK,GAAG,IAAI,MAAM,KAAK,eAAe,KAAK,QAAQ,GAAG,CAAC,EAAE;AAAA,QACjE;AAAA,MACF;AACA,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAAA,IACA,KAAK,YAAY;AACf,YAAM,OAAO;AACb,YAAM,aAAa,SAAS,cAAc,CAAC;AAC3C,YAAM,UAAU,KAAK,IAAI,CAAC,KAAK,MAAM;AACnC,cAAM,QAAkB,CAAC,QAAQ,IAAI,CAAC,GAAG;AACzC,mBAAW,OAAO,YAAY;AAC5B,gBAAM,SAAS,IAAI,IAAI,EAAE;AACzB,cAAI,WAAW,MAAM,GAAG;AACtB,kBAAM,KAAK,KAAK,IAAI,MAAM,KAAK,eAAe,KAAK,QAAQ,GAAG,CAAC,EAAE;AAAA,UACnE;AAAA,QACF;AACA,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB,CAAC;AACD,aAAO,QAAQ,KAAK,IAAI;AAAA,IAC1B;AAAA,IACA,KAAK,eAAe;AAClB,YAAM,QAAQ;AACd,aAAO,MACJ,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,EACxC,KAAK,IAAI;AAAA,IACd;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,SAAS,GAAW,QAAwB;AACnD,SAAO,EAAE,SAAS,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC,IAAI,WAAM;AAC5D;;;AC5FM,gBAAAE,MAwBY,QAAAC,aAxBZ;AANC,SAAS,cAAc,EAAE,WAAW,cAAc,SAAS,iBAAiB,GAAU;AAC3F,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,cAAW;AAAA,MAEX;AAAA,wBAAAD,KAAC,QAAG,WAAU,kEAAiE,0BAE/E;AAAA,QACA,gBAAAA,KAAC,QAAG,WAAU,aACX,oBAAU,IAAI,CAAC,GAAG,MAAM;AACvB,gBAAM,SAAS,QAAQ,EAAE,EAAE;AAC3B,gBAAM,WAAW,WAAW,MAAM;AAClC,gBAAM,YAAY,MAAM;AACxB,gBAAM,UAAU,WAAW,eAAe,GAAG,MAAM,IAAI;AAEvD,iBACE,gBAAAA,KAAC,QACC,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAM,iBAAiB,CAAC;AAAA,cACjC,WAAW,4DACT,YACI,mCACA,WACA,wDACA,2DACN;AAAA,cAEA,0BAAAC,MAAC,SAAI,WAAU,0BACb;AAAA,gCAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAW,4BACT,YACI,oBACA,WACA,mBACA,gBACN;AAAA,oBAEC;AAAA,6BAAO,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AAAA,sBAAE;AAAA;AAAA;AAAA,gBAClC;AAAA,gBACA,gBAAAA,MAAC,SAAI,WAAU,aACb;AAAA,kCAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAW,uBACT,WAAW,mBAAmB,gBAChC;AAAA,sBAEC,YAAE,OAAO,SAAS,KAAK,EAAE,OAAO,MAAM,GAAG,EAAE,IAAI,WAAM,EAAE;AAAA;AAAA,kBAC1D;AAAA,kBACC,YACC,gBAAAA,KAAC,SAAI,WAAU,mDACZ,mBACH;AAAA,mBAEJ;AAAA,iBACF;AAAA;AAAA,UACF,KAvCO,EAAE,EAwCX;AAAA,QAEJ,CAAC,GACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC7DM,gBAAAE,MAmBM,QAAAC,aAnBN;AAHC,SAAS,cAAc,EAAE,WAAW,SAAS,YAAY,QAAQ,WAAW,GAAU;AAC3F,SACE,gBAAAA,MAAC,SAAI,WAAU,oBACb;AAAA,oBAAAD,KAAC,QAAG,WAAU,gEAA+D,iCAE7E;AAAA,IACA,gBAAAA,KAAC,OAAE,WAAU,+BAA8B,wIAG3C;AAAA,IAEA,gBAAAA,KAAC,QAAG,WAAU,kDACX,oBAAU,IAAI,CAAC,GAAG,MAAM;AACvB,YAAM,SAAS,QAAQ,EAAE,EAAE;AAC3B,YAAM,WAAW,WAAW,MAAM;AAClC,YAAM,UAAU,WAAW,cAAc,GAAG,MAAM,IAAI;AAEtD;AAAA;AAAA;AAAA;AAAA;AAAA,QAKE,gBAAAC;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV;AAAA,8BAAAD,KAAC,UAAK,WAAU,oDACb,iBAAO,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG,GAChC;AAAA,cACA,gBAAAA,KAAC,QAAG,WAAU,sCAAsC,YAAE,QAAO;AAAA,cAC7D,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,OAAO,CAAC;AAAA,kBACvB,WAAU;AAAA,kBACX;AAAA;AAAA,cAED;AAAA,cACA,gBAAAA,KAAC,QAAG,WAAU,uDACX,qBACC,UAEA,gBAAAA,KAAC,UAAK,WAAU,yBAAwB,0BAAY,GAExD;AAAA;AAAA;AAAA,UApBK,EAAE;AAAA,QAqBT;AAAA;AAAA,IAEJ,CAAC,GACH;AAAA,IAKA,gBAAAC,MAAC,SAAI,WAAU,8DACb;AAAA,sBAAAD,KAAC,QAAG,WAAU,uCAAsC,+BAAiB;AAAA,MACrE,gBAAAA,KAAC,OAAE,WAAU,uBAAsB,kTAKnC;AAAA,MACA,gBAAAC,MAAC,OAAE,WAAU,+BACX;AAAA,wBAAAD,KAAC,UAAK,WAAU,eAAc,uBAAS;AAAA,QAAO;AAAA,SAGhD;AAAA,OACF;AAAA,IAEA,gBAAAA,KAAC,SAAI,WAAU,yBACb,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,WAAU;AAAA,QAET,uBAAa,kCAA6B;AAAA;AAAA,IAC7C,GACF;AAAA,KACF;AAEJ;","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/ProgressBar.tsx","../src/QuestionCard.tsx","../src/summarize.ts","../src/AnswerSidebar.tsx","../src/ReviewSummary.tsx"],"sourcesContent":["'use client';\n\ninterface Props {\n current: number;\n total: number;\n estimatedMinutesRemaining: number;\n}\n\n/**\n * Linear progress indicator for the interview flow. Renders the\n * \"Question N of M\" caption, the estimated minutes remaining, and a\n * forest-700 fill bar at `(current / total) * 100%`.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * stone-100 surface with stone-200 border; forest-700 fill bar; stone-700\n * caption text. Pure-render component — no state-management dependency.\n *\n * Extracted from `apps/hub/src/components/interview/ProgressBar.tsx`\n * during iteration-3-B.1 (2026-05-07). No prop API change.\n */\nexport function ProgressBar({ current, total, estimatedMinutesRemaining }: Props) {\n const percent = Math.round((current / total) * 100);\n\n return (\n <div className=\"border-b border-stone-200 bg-stone-100 py-3 px-6\">\n <div className=\"mx-auto max-w-3xl\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Question {current} of {total}\n </span>\n <span className=\"font-mono text-xs text-stone-700\">\n ~{estimatedMinutesRemaining} min remaining\n </span>\n </div>\n <div\n className=\"mt-2 h-1 w-full overflow-hidden rounded-full bg-stone-200\"\n role=\"progressbar\"\n aria-valuenow={percent}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`Interview progress: ${percent}% complete`}\n >\n <div\n className=\"h-full bg-forest-700 transition-all duration-300 ease-out\"\n style={{ width: `${percent}%` }}\n />\n </div>\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport type {\n InterviewQuestion,\n AnswerValue,\n AnswerComposite,\n AnswerRepeater,\n AnswerFileUpload,\n FileEntry,\n} from './types';\n\ninterface Props {\n question: InterviewQuestion;\n /**\n * The currently-saved answer for this question (from the consumer's\n * state container). The component initializes its local form state\n * from this value and re-syncs when the question id changes.\n */\n existingAnswer?: AnswerValue;\n /**\n * Called when the user submits an answer. The consumer is expected to\n * persist the answer into its state container and then advance via\n * `onNext`.\n */\n onAnswerSubmit: (questionId: string, value: AnswerValue) => void;\n /** Called after `onAnswerSubmit` to advance to the next question. */\n onNext: () => void;\n /** Called when the user clicks the Back button. */\n onBack: () => void;\n isFirst: boolean;\n isLast: boolean;\n}\n\n/**\n * Default value to use when no `existingAnswer` is supplied. Depends on\n * the question's `inputType`.\n */\nfunction defaultValueFor(question: InterviewQuestion): AnswerValue {\n switch (question.inputType) {\n case 'multi-select':\n case 'list':\n return [];\n case 'composite':\n return {} as AnswerComposite;\n case 'repeater':\n case 'file-upload':\n return [];\n default:\n return '';\n }\n}\n\n/**\n * Whether the user's current local value satisfies the required check\n * for the question.\n */\nfunction canAdvanceWith(question: InterviewQuestion, value: AnswerValue): boolean {\n if (!question.required) return true;\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * Single question renderer. Handles all input types: short-text, long-text,\n * single-select, multi-select, scale, list, date, composite, repeater,\n * file-upload. Keyboard-navigable and screen-reader safe.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * existing answer + change handler as props.\n *\n * Iteration-1 visual identity: form input fields use stone-50 elevated\n * surface + stone-200 default border + forest-700 focus border. Selected\n * radio/checkbox option states use forest-700 border + forest-50 background.\n * The examples disclosure has border-l-2 frame in border-copper-200 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n */\nexport function QuestionCard({\n question,\n existingAnswer,\n onAnswerSubmit,\n onNext,\n onBack,\n isFirst,\n isLast,\n}: Props) {\n const [localValue, setLocalValue] = useState<AnswerValue>(\n existingAnswer ?? defaultValueFor(question),\n );\n\n // Sync when question changes (consumer flipped to a different question;\n // local form state should reflect that question's existing answer).\n useEffect(() => {\n setLocalValue(existingAnswer ?? defaultValueFor(question));\n }, [question.id, existingAnswer, question.inputType]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onAnswerSubmit(question.id, localValue);\n onNext();\n };\n\n const canAdvance = canAdvanceWith(question, localValue);\n\n return (\n <form onSubmit={handleSubmit} className=\"animate-slide-up\">\n {/* Prompt */}\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n {question.prompt}\n </h2>\n {question.subprompt && (\n <p className=\"mt-4 text-lg text-stone-700\">{question.subprompt}</p>\n )}\n\n {/* Input — dispatched per type */}\n <div className=\"mt-8\">\n <InputForType\n question={question}\n value={localValue}\n onChange={setLocalValue}\n />\n </div>\n\n {/* Examples */}\n {question.examples && question.examples.length > 0 && (\n <details className=\"mt-8\">\n <summary className=\"cursor-pointer text-sm font-medium text-forest-700 hover:text-forest-800\">\n Show examples from different fields\n </summary>\n {/* border-copper-200 PRESERVED: decorative-emphasis frame around\n illustrative content, same role as HeroSection's etymology box. */}\n <ul className=\"mt-4 space-y-3 border-l-2 border-copper-200 pl-5\">\n {question.examples.map((ex, i) => (\n <li key={i} className=\"text-sm italic text-stone-700\">\n “{ex}”\n </li>\n ))}\n </ul>\n </details>\n )}\n\n {/* Skip consequence (if applicable) */}\n {!question.required && question.skipConsequence && (\n <p className=\"mt-6 text-sm text-stone-700\">\n <span className=\"font-medium\">If you skip this:</span> {question.skipConsequence}\n </p>\n )}\n\n {/* Nav */}\n <div className=\"mt-10 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={onBack}\n disabled={isFirst}\n className=\"btn-ghost disabled:opacity-40\"\n >\n ← Back\n </button>\n <div className=\"flex gap-3\">\n {!question.required && (\n <button type=\"button\" onClick={onNext} className=\"btn-ghost\">\n Skip\n </button>\n )}\n <button type=\"submit\" disabled={!canAdvance} className=\"btn-primary\">\n {isLast ? 'Review answers' : 'Continue →'}\n </button>\n </div>\n </div>\n </form>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Per-input-type renderers\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface InputProps {\n question: InterviewQuestion;\n value: AnswerValue;\n onChange: (next: AnswerValue) => void;\n}\n\nfunction InputForType({ question, value, onChange }: InputProps) {\n switch (question.inputType) {\n case 'short-text':\n return <ShortTextInput value={value as string} onChange={onChange} />;\n case 'long-text':\n return <LongTextInput value={value as string} onChange={onChange} />;\n case 'single-select':\n return <SingleSelectInput question={question} value={value as string} onChange={onChange} />;\n case 'multi-select':\n return <MultiSelectInput question={question} value={(value as string[]) ?? []} onChange={onChange} />;\n case 'list':\n return <ListInput value={(value as string[]) ?? []} onChange={onChange} listRange={question.listRange} />;\n case 'scale':\n return <ScaleInput question={question} value={value as string} onChange={onChange} />;\n case 'date':\n return <DateInput value={value as string} onChange={onChange} ariaLabel={question.prompt} />;\n case 'composite':\n return <CompositeInput question={question} value={(value as AnswerComposite) ?? {}} onChange={onChange} />;\n case 'repeater':\n return <RepeaterInput question={question} value={(value as AnswerRepeater) ?? []} onChange={onChange} />;\n case 'file-upload':\n return <FileUploadInput question={question} value={(value as AnswerFileUpload) ?? []} onChange={onChange} />;\n default: {\n const _exhaustive: never = question.inputType;\n return <UnknownTypeFallback inputType={_exhaustive} />;\n }\n }\n}\n\nfunction ShortTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <input\n type=\"text\"\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction LongTextInput({ value, onChange }: { value: string; onChange: (v: string) => void }) {\n return (\n <textarea\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n rows={5}\n className=\"w-full rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder=\"Type your answer…\"\n />\n );\n}\n\nfunction SingleSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n ))}\n </div>\n );\n}\n\nfunction MultiSelectInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string[];\n onChange: (v: string[]) => void;\n}) {\n return (\n <div className=\"space-y-2\" role=\"group\" aria-labelledby={`q-${question.id}`}>\n {(question.options ?? []).map((opt) => {\n const checked = value.includes(opt.value);\n return (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-start gap-3 rounded-lg border-2 p-4 transition-colors ${\n checked\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"checkbox\"\n value={opt.value}\n checked={checked}\n onChange={(e) => {\n if (e.target.checked) onChange([...value, opt.value]);\n else onChange(value.filter((v) => v !== opt.value));\n }}\n className=\"mt-1 h-4 w-4 text-forest-700\"\n />\n <div>\n <div className=\"font-medium text-stone-900\">{opt.label}</div>\n {opt.description && (\n <div className=\"mt-1 text-sm text-stone-700\">{opt.description}</div>\n )}\n </div>\n </label>\n );\n })}\n </div>\n );\n}\n\nfunction ScaleInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: string;\n onChange: (v: string) => void;\n}) {\n const options = question.options ?? [];\n return (\n <div className=\"space-y-3\" role=\"radiogroup\" aria-labelledby={`q-${question.id}`}>\n {options.map((opt) => (\n <label\n key={opt.value}\n className={`flex cursor-pointer items-center gap-3 rounded-lg border-2 p-3 transition-colors ${\n value === opt.value\n ? 'border-forest-700 bg-forest-50'\n : 'border-stone-200 bg-stone-50 hover:border-stone-400'\n }`}\n >\n <input\n type=\"radio\"\n name={question.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-4 w-4 text-forest-700\"\n />\n <span className=\"font-mono text-sm text-stone-700\">{opt.value}</span>\n <span className=\"text-stone-900\">{opt.label}</span>\n </label>\n ))}\n </div>\n );\n}\n\nfunction DateInput({\n value,\n onChange,\n ariaLabel,\n}: {\n value: string;\n onChange: (v: string) => void;\n ariaLabel: string;\n}) {\n return (\n <input\n type=\"date\"\n aria-label={ariaLabel}\n value={value ?? ''}\n onChange={(e) => onChange(e.target.value)}\n autoFocus\n className=\"rounded-lg border-2 border-stone-200 bg-stone-50 px-4 py-3 text-lg text-stone-900 focus:border-forest-700 focus:outline-none\"\n />\n );\n}\n\nfunction ListInput({\n value,\n onChange,\n listRange,\n}: {\n value: string[];\n onChange: (v: string[]) => void;\n listRange?: { min: number; max: number };\n}) {\n const items = value.length > 0 ? value : [''];\n const min = listRange?.min ?? 0;\n const max = listRange?.max ?? Infinity;\n\n const setItem = (i: number, v: string) => {\n const next = [...items];\n next[i] = v;\n onChange(next);\n };\n const addItem = () => {\n if (items.length < max) onChange([...items, '']);\n };\n const removeItem = (i: number) => {\n if (items.length <= 1) return;\n onChange(items.filter((_, idx) => idx !== i));\n };\n const validCount = items.filter((v) => v.trim().length > 0).length;\n\n return (\n <div>\n <ul className=\"space-y-2\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-center gap-2\">\n <span className=\"w-6 text-right font-mono text-xs text-stone-600\">{i + 1}.</span>\n <input\n type=\"text\"\n value={item}\n onChange={(e) => setItem(i, e.target.value)}\n className=\"flex-grow rounded-lg border-2 border-stone-200 bg-stone-50 px-3 py-2 text-stone-900 focus:border-forest-700 focus:outline-none\"\n placeholder={`Item ${i + 1}`}\n />\n <button\n type=\"button\"\n onClick={() => removeItem(i)}\n disabled={items.length <= 1}\n className=\"btn-ghost text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n ×\n </button>\n </li>\n ))}\n </ul>\n <div className=\"mt-3 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={addItem}\n disabled={items.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add item\n </button>\n {listRange && (\n <span className=\"font-mono text-xs text-stone-700\">\n {validCount} / {min}–{max === Infinity ? '∞' : max}\n </span>\n )}\n </div>\n </div>\n );\n}\n\nfunction CompositeInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerComposite;\n onChange: (v: AnswerComposite) => void;\n}) {\n const subQuestions = question.subQuestions ?? [];\n return (\n <div className=\"space-y-6 rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n {subQuestions.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={value[sub.id]}\n onChange={(next) => onChange({ ...value, [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction RepeaterInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerRepeater;\n onChange: (v: AnswerRepeater) => void;\n}) {\n const rows = value.length > 0 ? value : [{} as Record<string, AnswerValue>];\n const itemSchema = question.itemSchema ?? [];\n const min = question.listRange?.min ?? 1;\n const max = question.listRange?.max ?? Infinity;\n\n const updateRow = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...rows];\n next[i] = { ...next[i], ...patch };\n onChange(next);\n };\n const addRow = () => {\n if (rows.length < max) onChange([...rows, {} as Record<string, AnswerValue>]);\n };\n const removeRow = (i: number) => {\n if (rows.length <= 1) return;\n onChange(rows.filter((_, idx) => idx !== i));\n };\n\n return (\n <div className=\"space-y-4\">\n {rows.map((row, i) => (\n <div key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <span className=\"font-mono text-xs uppercase tracking-wider text-stone-700\">\n Item {i + 1}\n </span>\n <button\n type=\"button\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= min}\n className=\"btn-ghost text-xs text-stone-700 disabled:opacity-30\"\n aria-label={`Remove item ${i + 1}`}\n >\n Remove\n </button>\n </div>\n <div className=\"space-y-4\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-sm font-medium text-stone-900\">{sub.prompt}</div>\n {sub.subprompt && (\n <div className=\"mt-1 text-xs text-stone-700\">{sub.subprompt}</div>\n )}\n <div className=\"mt-2\">\n <InputForType\n question={sub}\n value={row[sub.id]}\n onChange={(next) => updateRow(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={addRow}\n disabled={rows.length >= max}\n className=\"text-sm font-medium text-forest-700 hover:text-forest-800 disabled:opacity-40\"\n >\n + Add another\n </button>\n </div>\n );\n}\n\nfunction FileUploadInput({\n question,\n value,\n onChange,\n}: {\n question: InterviewQuestion;\n value: AnswerFileUpload;\n onChange: (v: AnswerFileUpload) => void;\n}) {\n const itemSchema = question.itemSchema ?? [];\n\n const onFiles = (files: FileList | null) => {\n if (!files || files.length === 0) return;\n const entries: FileEntry[] = Array.from(files).map((f) => ({\n file: f,\n metadata: {},\n }));\n onChange([...value, ...entries]);\n };\n\n const updateMetadata = (i: number, patch: Record<string, AnswerValue>) => {\n const next = [...value];\n next[i] = { ...next[i], metadata: { ...next[i].metadata, ...patch } };\n onChange(next);\n };\n const removeEntry = (i: number) => onChange(value.filter((_, idx) => idx !== i));\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n onFiles(e.dataTransfer.files);\n };\n const onDragOver = (e: React.DragEvent<HTMLDivElement>) => e.preventDefault();\n\n return (\n <div className=\"space-y-4\">\n <div\n onDrop={onDrop}\n onDragOver={onDragOver}\n className=\"rounded-lg border-2 border-dashed border-stone-300 bg-stone-50 p-6 text-center\"\n >\n <p className=\"text-sm text-stone-700\">\n Drag PDFs or other files here, or{' '}\n <label className=\"cursor-pointer font-medium text-forest-700 hover:text-forest-800\">\n browse\n <input\n type=\"file\"\n multiple\n className=\"sr-only\"\n onChange={(e) => onFiles(e.target.files)}\n />\n </label>\n </p>\n <p className=\"mt-1 text-xs text-stone-700\">\n You'll add a title, author, and description for each file below.\n </p>\n </div>\n\n {value.length > 0 && (\n <ul className=\"space-y-4\">\n {value.map((entry, i) => {\n const name = entry.file.name;\n const size = 'size' in entry.file ? entry.file.size : undefined;\n return (\n <li key={i} className=\"rounded-lg border-2 border-stone-200 bg-stone-50 p-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <div className=\"font-medium text-stone-900\">{name}</div>\n {typeof size === 'number' && (\n <div className=\"font-mono text-xs text-stone-700\">\n {(size / 1024).toFixed(1)} KB\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => removeEntry(i)}\n className=\"btn-ghost text-xs text-stone-700\"\n aria-label={`Remove ${name}`}\n >\n Remove\n </button>\n </div>\n {itemSchema.length > 0 && (\n <div className=\"mt-4 space-y-3\">\n {itemSchema.map((sub) => (\n <div key={sub.id}>\n <div className=\"text-xs font-medium text-stone-900\">{sub.prompt}</div>\n <div className=\"mt-1\">\n <InputForType\n question={sub}\n value={entry.metadata[sub.id]}\n onChange={(next) => updateMetadata(i, { [sub.id]: next })}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n\nfunction UnknownTypeFallback({ inputType }: { inputType: never }) {\n // Render-time defensive guard for runtime values that bypass TS (e.g.,\n // YAML-loaded interview schemas with typos). Visible to dev; user sees a\n // muted \"unsupported\" notice.\n return (\n <div className=\"rounded-lg border-2 border-stone-300 bg-stone-50 p-4 text-sm text-stone-700\">\n Unsupported question input type:{' '}\n <code className=\"font-mono\">{String(inputType)}</code>\n </div>\n );\n}\n","/**\n * Helpers for rendering one-line / summary previews of answer values in\n * `AnswerSidebar` and `ReviewSummary`. Centralized so the two components\n * stay consistent when new answer shapes are added.\n */\nimport type { AnswerValue, FileEntry, InterviewQuestion } from './types';\n\nexport function isAnswered(value: AnswerValue): boolean {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return true;\n}\n\n/**\n * A short, single-line preview suitable for sidebar items. Truncates\n * long content. Returns the empty string for unanswered values.\n */\nexport function summarizeShort(question: InterviewQuestion, value: AnswerValue, maxLen = 80): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return truncate(String(value), maxLen);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return truncate(label ?? v, maxLen);\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => {\n const found = question.options?.find((o) => o.value === v)?.label;\n return found ?? v;\n });\n return truncate(labels.join(', '), maxLen);\n }\n case 'composite': {\n // Show the first sub-answer's preview if any.\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n return truncate(summarizeShort(sub, subVal, maxLen), maxLen);\n }\n }\n return '';\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n return `${rows.length} item${rows.length === 1 ? '' : 's'}`;\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return `${files.length} file${files.length === 1 ? '' : 's'}`;\n }\n default:\n return '';\n }\n}\n\n/**\n * A richer multi-line summary suitable for the ReviewSummary list. May\n * contain newlines; consumers should render in a `whitespace-pre-wrap`\n * container.\n */\nexport function summarizeLong(question: InterviewQuestion, value: AnswerValue): string {\n if (!isAnswered(value)) return '';\n switch (question.inputType) {\n case 'short-text':\n case 'long-text':\n case 'date':\n case 'scale':\n return String(value);\n case 'single-select': {\n const v = String(value);\n const label = question.options?.find((o) => o.value === v)?.label;\n return label ?? v;\n }\n case 'multi-select':\n case 'list': {\n const arr = value as string[];\n const labels = arr.map((v) => question.options?.find((o) => o.value === v)?.label ?? v);\n return labels.join('\\n• ').replace(/^/, '• ');\n }\n case 'composite': {\n const obj = value as { [k: string]: AnswerValue };\n const subs = question.subQuestions ?? [];\n const lines: string[] = [];\n for (const sub of subs) {\n const subVal = obj[sub.id];\n if (isAnswered(subVal)) {\n lines.push(`${sub.prompt}: ${summarizeShort(sub, subVal, 200)}`);\n }\n }\n return lines.join('\\n');\n }\n case 'repeater': {\n const rows = value as Array<{ [k: string]: AnswerValue }>;\n const itemSchema = question.itemSchema ?? [];\n const summary = rows.map((row, i) => {\n const parts: string[] = [`Item ${i + 1}:`];\n for (const sub of itemSchema) {\n const subVal = row[sub.id];\n if (isAnswered(subVal)) {\n parts.push(` ${sub.prompt}: ${summarizeShort(sub, subVal, 100)}`);\n }\n }\n return parts.join('\\n');\n });\n return summary.join('\\n');\n }\n case 'file-upload': {\n const files = value as FileEntry[];\n return files\n .map((f, i) => `${i + 1}. ${f.file.name}`)\n .join('\\n');\n }\n default:\n return '';\n }\n}\n\nfunction truncate(s: string, maxLen: number): string {\n return s.length > maxLen ? s.slice(0, maxLen - 1) + '…' : s;\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeShort } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n currentIndex: number;\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n /** Called when the user clicks a sidebar item to jump to that question. */\n onSelectQuestion: (index: number) => void;\n}\n\n/**\n * Sidebar showing all answered questions. Clicking any returns to edit that\n * question without losing later answers. Implements the wiki's pattern:\n * \"Edit any prior answer — a sidebar shows all answered questions.\"\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answers + jump handler as props.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Three item states with distinct token tiers:\n * - current → forest-700 border + forest-50 bg (interactive primary)\n * - answered → stone-200 border + stone-50 bg (default, hover stone-400)\n * - unanswered → stone-200/50 + stone-50/50 (muted via opacity preservation)\n *\n * D.2.1.b extension: previews for composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all eight scalar + three compound types\n * render consistently.\n */\nexport function AnswerSidebar({ questions, currentIndex, answers, onSelectQuestion }: Props) {\n return (\n <aside\n className=\"sticky top-24 hidden max-h-[calc(100vh-6rem)] overflow-y-auto lg:block\"\n aria-label=\"Completed answers\"\n >\n <h3 className=\"mb-3 font-mono text-xs uppercase tracking-wider text-stone-700\">\n Your answers\n </h3>\n <ol className=\"space-y-3\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const isCurrent = i === currentIndex;\n const preview = answered ? summarizeShort(q, answer) : '';\n\n return (\n <li key={q.id}>\n <button\n type=\"button\"\n onClick={() => onSelectQuestion(i)}\n className={`w-full rounded-lg border p-3 text-left transition-colors ${\n isCurrent\n ? 'border-forest-700 bg-forest-50'\n : answered\n ? 'border-stone-200 bg-stone-50 hover:border-stone-400'\n : 'border-stone-200/50 bg-stone-50/50 hover:border-stone-300'\n }`}\n >\n <div className=\"flex items-start gap-2\">\n <span\n className={`mt-0.5 font-mono text-xs ${\n isCurrent\n ? 'text-forest-700'\n : answered\n ? 'text-stone-700'\n : 'text-stone-600'\n }`}\n >\n {String(i + 1).padStart(2, '0')}.\n </span>\n <div className=\"flex-grow\">\n <div\n className={`text-xs font-medium ${\n answered ? 'text-stone-900' : 'text-stone-700'\n }`}\n >\n {q.prompt.length > 50 ? q.prompt.slice(0, 50) + '…' : q.prompt}\n </div>\n {answered && (\n <div className=\"mt-1 text-xs italic text-stone-700 line-clamp-1\">\n {preview}\n </div>\n )}\n </div>\n </div>\n </button>\n </li>\n );\n })}\n </ol>\n </aside>\n );\n}\n","'use client';\n\nimport type { InterviewAnswers, InterviewQuestion } from './types';\nimport { isAnswered, summarizeLong } from './summarize';\n\ninterface Props {\n questions: InterviewQuestion[];\n /** Consumer's current answer record (read-only — engine doesn't write). */\n answers: InterviewAnswers;\n onGenerate: () => void;\n onEdit: (questionIndex: number) => void;\n generating: boolean;\n}\n\n/**\n * Final review screen — the penultimate step before generation.\n * Shows all answers so the user can confirm ownership of the output before\n * committing.\n *\n * **Decoupled from any state-management library.** Consumers receive the\n * answer record as a prop.\n *\n * Iteration-1 visual identity (Phase B.2, 2026-05-06):\n * Editorial Josefin display family on the heading and the \"What happens next\"\n * callout title. Stone-tier surfaces and content text throughout. The\n * \"What happens next\" callout box preserves border-copper-300 + bg-copper-50 —\n * preserved-decorative-copper role per iteration-2-blue-accent.md.\n *\n * D.2.1.b extension: rendering of composite/repeater/file-upload answers\n * delegated to `summarize.ts` so all answer types display consistently.\n */\nexport function ReviewSummary({ questions, answers, onGenerate, onEdit, generating }: Props) {\n return (\n <div className=\"animate-slide-up\">\n <h2 className=\"font-display text-3xl font-medium text-stone-900 sm:text-4xl\">\n Review your answers\n </h2>\n <p className=\"mt-4 text-lg text-stone-700\">\n These become the seed content of your project. You can edit anything now, or continue and\n edit later through the platform.\n </p>\n\n <dl className=\"mt-10 space-y-6 border-t border-stone-200 pt-6\">\n {questions.map((q, i) => {\n const answer = answers[q.id];\n const answered = isAnswered(answer);\n const display = answered ? summarizeLong(q, answer) : '';\n\n return (\n // A <div> child of <dl> may contain ONLY dt/dd groups (HTML spec;\n // axe definition-list), so the index + Edit button live INSIDE\n // <dt>. Subgrid keeps all three columns aligned across dt and dd\n // without extra wrappers.\n <div\n key={q.id}\n className=\"grid grid-cols-[auto_1fr_auto] gap-x-4 border-b border-stone-200 pb-6\"\n >\n <dt className=\"col-span-3 grid grid-cols-subgrid\">\n <span aria-hidden=\"true\" className=\"pt-1 font-mono text-sm text-stone-600\">\n {String(i + 1).padStart(2, '0')}\n </span>\n <span className=\"text-sm font-medium text-stone-900\">{q.prompt}</span>\n <button\n type=\"button\"\n onClick={() => onEdit(i)}\n aria-label={`Edit: ${q.prompt}`}\n className=\"btn-ghost self-start text-sm\"\n >\n Edit\n </button>\n </dt>\n <dd className=\"col-span-3 mt-2 grid grid-cols-subgrid\">\n <span className=\"col-start-2 whitespace-pre-wrap text-stone-900\">\n {answered ? (\n display\n ) : (\n <span className=\"italic text-stone-600\">Not answered</span>\n )}\n </span>\n </dd>\n </div>\n );\n })}\n </dl>\n\n {/* \"What happens next\" callout — copper PRESERVED as decorative\n informational frame, same role as HeroSection's etymology box.\n Per iteration-1 §5.2's preserved-decorative-copper governance. */}\n <div className=\"mt-10 rounded-lg border border-copper-300 bg-copper-50 p-6\">\n <h3 className=\"font-display text-xl text-stone-900\">What happens next</h3>\n <p className=\"mt-2 text-stone-900\">\n When you click Generate, the platform will create a GitHub repository in your account,\n populate it with your personalized CLAUDE.md, KNOWLEDGE.md, and wiki, and give you the\n URL. This takes about 30–90 seconds. You can edit everything afterward through the\n platform or through your repo.\n </p>\n <p className=\"mt-3 text-sm text-stone-700\">\n <span className=\"font-medium\">MVP note:</span> In this phase, GitHub repo creation is\n mocked for demonstration. Once OAuth credentials are configured, real repos will be\n created on your behalf.\n </p>\n </div>\n\n <div className=\"mt-8 flex justify-end\">\n <button\n type=\"button\"\n onClick={onGenerate}\n disabled={generating}\n className=\"btn-primary text-lg\"\n >\n {generating ? 'Generating your project…' : 'Generate my platform'}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataimago/interview",
3
- "version": "0.2.0-alpha.3",
3
+ "version": "0.2.0-alpha.4",
4
4
  "description": "Domain-agnostic interview engine — React components + schema contract for AI-native onboarding flows. Extracted from dataimago-ai/apps/hub during iteration-3-B.1 (2026-05-07).",
5
5
  "license": "MIT",
6
6
  "repository": {