@engenty/wizards 0.9.2 → 0.9.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["labelOf","id","listeners","EntryRows","Chips","labelOf","fileName","_Fragment","INK","_Fragment","_Fragment","text","labelOf","cell","_Fragment","Segments","labelOf","_Fragment","DOMPurify","columnBaseSchema","z","numberStyleSchema","numberFormatSchema","val","ctx","dateKindSchema","dateStyleSchema","timePrecisionSchema","dateFormatSchema","durationUnitSchema","durationDisplaySchema","durationFormatSchema","selectOptionSchema","selectFormatSchema","textStyleSchema","textFormatSchema","tableColumnSchema","tableColumnsSchema","seen","i","columns","id","tableColumnWireSchema","MS_HOUR","MS_MINUTE","MS_SECOND","fractionDigits","format","formatNumberCell","value","digits","grouping","locale","formatDateCell","formatClock","date","dateStyle","timePrecision","hours","minutes","seconds","precision","formatDurationCell","ms","toIsoDuration","formatTableCell","column","formatSelectCell","ids","labels","option","acc","readNumber","s","opts","n","formatBytes","bytes","formatMoney","amount","currency","key","named","leaves","LEAF_KINDS","objectAt","deeper","depth","of","list","field","f","objectsOf","out","k","shape","at","refProblem","target","root","to","outputShapeSchema","objects","keys","o","ref","problem","shapeOfFields","one","d","fields","titleKey","labelOf$1","about","base","more","CELL","shapeZod","description","meta","c","shapeJsonSchema","schema","title","CONNECTION_KINDS","cellValue","text","SURFACE_COMPONENTS","id$1","surfaceComponentSchema","surfaceComponentsSchema","isPath","v","pointer","data","part","path","bound","worded","row","raw","map","spec","ENGENTY_KINDS","ENGENTY_COSTUMES","THEME_ID","LANGS","LOCALES","isLang","localeOf","code","FIELD_KINDS","isLocationValue","lat","lng","label","isAudioValue","TOOL_IDS","PLUGIN_ID","PLUGIN_TOOL_NAME","TEXT_CLASSES","EFFORTS","ASSET_KINDS","FORMATS","ASPECT_RATIOS","VIDEO_RESOLUTIONS","itemColumnSchema","conditionSchema","whenSchema","cardsSchema","fieldSchema","fieldGroupSchema","nextRuleSchema","rule","stepBase","outputFieldSchema","pageStepSchema","pluginToolIdSchema","agentStepSchema","generateStepSchema","widgetStepSchema","FILM_FORMATS","filmStepSchema","surfaceCandidateSchema","surfaceStepSchema","step","reviewStepSchema","deliverableSchema","shareOptionSchema","resultStepSchema","stepSchema","declaredShape","stepShape","listSchema","connectionSchema","isEmptyValue","conditionsOf","when","conditionMatches","values","a","b","whenHolds","isDecidedField","shownFields","known","page","SLOT_RE","slotTime","m","iso","y","mo","h","mi","wall","slotDayText","slot","lang","itemsTotals","rows","numeric","withAmount","amountOf","round2","net","r","vatRate","parsed","vat","BUILT_IN_THEMES","hex","themeColorsSchema","themeShapeSchema","themeEffectSchema","fontName","SANS","SERIF","SERIFS","serifFamily","family","shippedLike","fontStack","next","faces","lookColours","own","look","mode","CARD_EFFECTS","RADIUS","wizardLook","colours","options","style","set","name","on","effects","plurals","pluralRules","rules","form","line","count","gapText","item","fillGaps","params","gap","textOf","texts","lineText","NOTES_EN","RUN_NOTES","gapIn","table","noteText","note","RUNNER_TEXTS","version","listeners$1","changed","listener","setRunnerLang","runnerLangCode","eventText","ev","setChoiceLabels","choiceLabel","t","vars","ApiError","message","status","body","safeJson","createApi","request","res","withBase","headers","onServerError","method","file","none","ability","env","configureRunner","runnerEnv","api","asset","runBase","runId","appCan","appCall","args","appTell","appDownload","event","href","filename","standalone","cn","parts","VARIANTS","Button","forwardRef","rest","variant","disabled","busy","size","className","Spinner","children","IconButton","fieldBase","fieldWidth","Input","Swatch","props","Textarea","inner","useRef","resize","el","lh","max","maxRows","minRows","useLayoutEffect","outer","onChange","Select","placeholder","Segmented","selected","multi","x","SLIDE","Tabs","buttons","thumb","setThumb","useState","measure","observer","Switch","checked","Label","required","hint","Card","Dialog","useEffect","open","bare","height","tallest","keep","onClose","wide","LinkedText","WHEEL_EVERY_MS","LiveBrowser","image","controls","setText","hidden","setHidden","error","setError","act","err","driving","pending","timer","onWheel","e","dy","box","onBroken","action","caption","MousePointerClick","ToolButton","CornerDownLeft","ArrowUp","ArrowDown","AskPanel","ask","ConfirmPanel","LoginPanel","remember","setRemember","setBusy","answer","Icon","TriangleAlert","PencilLine","setValues","filled","LockKeyhole","ShieldCheck","isTouch","canUseMedia","useKeyboardInset","vv","reveal","update","covered","opened","useWakeLock","held","setHeld","active","lock","stopped","acquire","taken","NOTIFY_KEY","listeners","audio","wanted","setWanted","hasNotifications","appAllows","notifyState","useNotifyState","useSyncExternalStore","notificationsBlocked","enableNotify","worker","disableNotify","chime","now","freq","osc","gain","signalPerson","registration","canShareFiles","shrinkImage","bitmap","scale","canvas","blob","stamp","cameraError","hasTorch","track","useCameraStream","video","stream","setStream","cameras","setCameras","torchable","setTorchable","torch","setTorchOn","live","picture","facing","readTorch","devices","MediaSheet","SheetButton","SheetBar","X","camera","Flashlight","FlashlightOff","onFlip","SwitchCamera","CameraStage","actions","asking","CLIP_SECONDS","clipType","type","canRecordClips","CameraDialog","allowVideo","setFacing","setMode","setTaken","recording","setRecording","recorder","deliver","onCapture","multiple","shoot","stopClip","startClip","chunks","rec","mime","ext","clock","onNative","SheetAction","Camera","Video","Check","quiet","cellField","isEntry","setIn","head","copy","obj","tableShape","flat","isTable","isRows","titleOf","entry","Words","Value","cell","word","entries","hit","Link2","EntryTable","Entries","EntryRows$1","EntryCards","Chips$1","Form","items","draft","setDraft","j","entriesIn","fresh","cols","RemoveButton","AddButton","main","short","lists","ChevronRight","Field","onClick","Trash2","Plus","what","DataEditor","offered","modes","setOwn","start","onMode","scope","useId","DataMenu","setOpen","outside","onKey","MoreVertical","fileName$1","JsonSchemaDialog","copied","setCopied","jsx","Copy","url","Download","editableData","StudioData","setSchema","saving","setSaving","output","save","menu","Database","Braces","Fragment","header","GOOD_METRES","REFINE_MS","trouble","LocationField","place","locating","setLocating","watch","typed","latest","hasPoint","supported","stop","onBusy","locate","started","best","pos","accuracy","latitude","longitude","setLabel","MapPin","ExternalLink","LocateFixed","reader","codeReader","Native","formats","detector","source","QrScanner","engine","AppScan","found","onResult","close","ScanDialog","WebScan","qrOnly","setQrOnly","miss","setMiss","photo","tick","fromPhoto","ImageUp","INK$1","OUT","draw","pen","stroke","strokes","w","last","Pad","current","all","paint","ratio","ro","done","onStrokes","SignatureField","setStrokes","accept","PenLine","Eraser","CredentialsForm","submit","connectionId","connector","onCancel","ConnectionField","setForm","link","setLink","connection","Unplug","oauth","popup","inputText","CellInput","boxed","onCommit","ListTable","def","call","run","addRow","hasDraft","editable","commitCell","rowId","columnId","storeFileUrl","safe","inline","ANSWER_TONE","ListCheck","fileColumn","statusColumn","answers","openId","statusOf","isOpen","setSelected","onlyOpen","setOnlyOpen","shown","labelled","titleColumn","restColumns","patch","move","tone","FileText","LIST_FORMAT_LABEL","ListDownloads","StoreButton","setData","confirm","setConfirm","empty","l","MAX_SECONDS","recordingType","transcribeOnDevice","result","resolve","reject","VoiceField","setSeconds","level","setLevel","uploading","setUploading","denied","setDenied","local","setLocal","session","picker","canRecord","transcript","length","began","analyser","samples","frame","meter","peak","fileButton","FileAudio","Square","RotateCcw","Mic","ItemsField","totals","col","grid","ci","typingTarget","UploadField","nativeCamera","nativeVideo","names","setNames","setCamera","over","setOver","dragging","setDragging","drag","grab","most","withCamera","clips","room","add","files","free","adding","remove","left","from","sortable","onPaste","tile","index","other","GripVertical","Film","Paperclip","ImagePlus","textHints","ScanInput","ScanLine","SLOT_DAYS","slotDays","days","sorted","day","SlotField","chosenDay","tm","setAll","CardChoice","picked","toggle","src","cards","shut","FieldInput","str","closed","control","view","groupOf","cls","CLASS_GROUP","text$1","sectionLabel","entryShape","kind","long","figures","numbers","leafText","Chips","Leaves","FigureTable","Nested","ordered","Flags","tags","words","tag","EntryRows","flags","metas","EntryCard","longs","JsonView","json","leaf","INK","INK_3","LINK","LINE","TEXT_WIDTH","ENTITIES","plain","untagged","html","runs","token","tokens","blocks","_","cell$1","TABLE_LAYOUT","markdownContent","marked","jsonContent","pdfDocument","written","foot","pages","ROBOTO","loading","pdfMake","lib","fonts","pdf","fileName","writePdf","num","assetUrl","prop","points","labelKey","valueKey","p","Children","kids","Node","TONES","labelOf","grouped","groups","by","rank","order","Metas","metasOf","TabsView","setOn","tabs","tab","child","ChecklistView","detailKey","noteKey","noteFormat","groupKey","ticks","keyOf","indexed","detailOf","noteMap","noteOf","lines","Share2","Bars","Line","min","span","xy","DONUT","Donut","total","Titled","badge","declared","eyebrow","subtitle","flagKey","flag","flagged","textKey","minutesKey","time","Clock","Lightbulb","SurfaceView","state","setState","initial","sheet","setSheet","surface","onState","Markdown","useMemo","HtmlFrame","tall","setTall","listen","msg","wrap","width","setWidth","setHtml","alive","layout","flow","fit","doc","Maximize2","AI_ICONS","AiIcon","art","icon","AiBadge","ai","tones","theme","labelFor","CopyButton","setDone","OutputView","onSurfaceAction","onView","film","poster","onPick","images","onDraft","img","FORMAT_LABEL","downloadName","fallback","saveFile","ShareFileButton","share","make","Share","SHARES_FILES","DownloadButtons","stepId","made","makePdf","savePdf","inBrowser","Printer","Progress","pct","keepView","StepHeading","kicker","initialValues","typedInputs","PageForm","setPending","first","inputs","prev","Footer","ArrowRight","sticky","ArrowLeft","NotifyToggle","BellRing","Bell","Working","setNow","recent","trail","pictures","Mascot","compact","Sparkles","awake","useDoneSignal","running","since","tell","Review","drafts","setDrafts","editing","setEditing","setNote","setTarget","setPicked","prompt","aim","several","send","heading","Pencil","studio","RefreshCw","Result","ShareResultButton","TranslatedOutput","onRestart","Failed","original","setOriginal","translated","Languages","RunnerBody","stickyProgress","STALE_MS","useWizardRun","setView","notFound","setNotFound","fieldErrors","setFieldErrors","retry","es","lastHeard","refresh","watchdog","command","useCallback","prefill","runField","EMPTY_FORM","useMessageRun","streaming","useIsStreaming","getField","useGetFieldValue","setField","useSetFieldValue","setRunId","failed","setFailed","cancelled","kept","WIZARD_COMPONENT","useReport","trigger","useTriggerAction","Dot","configureWizards","config","looks","lookOf","query","useLook","setLook","startRun","resultContext","results","WizardRun","report","seenRunning","Wizard","defineComponent","WIZARD_DESCRIPTION","wizardProps","WizardSpec","addWizard","loadWizards","wizardRules"],"sources":["../../../shared/src/engenty/data-tables/columns.ts","../../../shared/src/engenty/data-tables/columns-format.ts","../../../shared/src/numbers.ts","../../../shared/src/shape.ts","../../../shared/src/store.ts","../../../shared/src/surface.ts","../../../shared/src/definition.ts","../../../shared/src/theme.ts","../../src/openui/look.ts","../../../shared/src/texts.ts","../../../shared/src/run.ts","../../../shared/src/runner-texts.ts","../../../runner/src/i18n.ts","../../../runner/src/api.ts","../../../runner/src/env.ts","../../../runner/src/ui.tsx","../../../runner/src/browser-live.tsx","../../../runner/src/AskPanel.tsx","../../../runner/src/device.ts","../../../runner/src/camera.tsx","../../../runner/src/data.tsx","../../../runner/src/location.tsx","../../../runner/src/scan.tsx","../../../runner/src/signature.tsx","../../../runner/src/store.tsx","../../../runner/src/voice.tsx","../../../runner/src/fields.tsx","../../../runner/src/json-view.tsx","../../../runner/src/pdf.ts","../../../runner/src/surface.tsx","../../../runner/src/outputs.tsx","../../../runner/src/RunnerView.tsx","../../src/openui/run.ts","../../src/openui/message.ts","../../src/openui/Wizard.tsx"],"sourcesContent":["// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\n/**\n * Space-table column definitions.\n *\n * A table is a small database, not a CSV dump: every column has a type and a\n * display format. Agents create the definition; row writes are validated\n * against it.\n */\nimport { z } from \"zod\";\n\nconst COLUMN_ID = /^[a-z][a-z0-9_]*$/;\n\nconst columnBaseSchema = z.object({\n description: z.string().max(1024).optional(),\n /**\n * Where the cell is edited. Omit to use the type default:\n * single-line text and booleans are in-field; everything else is a popout.\n */\n edit: z.enum([\"inline\", \"popout\"]).optional(),\n id: z\n .string()\n .min(1)\n .max(64)\n .regex(COLUMN_ID, \"column id must be a lowercase slug (a-z, 0-9, _)\"),\n name: z.string().min(1).max(128),\n required: z.boolean().optional(),\n});\n\nexport const numberStyleSchema = z.enum([\n \"integer\",\n \"decimal\",\n \"percent\",\n \"currency\",\n]);\nexport type NumberStyle = z.infer<typeof numberStyleSchema>;\n\nexport const numberFormatSchema = z\n .object({\n currency: z\n .string()\n .regex(/^[A-Z]{3}$/, \"currency must be an ISO 4217 code\")\n .optional(),\n fractionDigits: z.number().int().min(0).max(8).optional(),\n grouping: z.boolean().optional(),\n style: numberStyleSchema,\n })\n .superRefine((val, ctx) => {\n if (val.style === \"currency\" && !val.currency) {\n ctx.addIssue({\n code: \"custom\",\n message: \"currency style needs an ISO 4217 code\",\n path: [\"currency\"],\n });\n }\n if (val.style !== \"currency\" && val.currency) {\n ctx.addIssue({\n code: \"custom\",\n message: \"currency is only valid on currency columns\",\n path: [\"currency\"],\n });\n }\n });\nexport type NumberFormat = z.infer<typeof numberFormatSchema>;\n\nexport const dateKindSchema = z.enum([\"date\", \"datetime\", \"time\"]);\nexport type DateKind = z.infer<typeof dateKindSchema>;\n\nexport const dateStyleSchema = z.enum([\"short\", \"medium\", \"long\", \"iso\"]);\nexport type DateStyle = z.infer<typeof dateStyleSchema>;\n\n/** `hours` is clock time with no minutes — `14` or `14:30` both store as `14:00`. */\nexport const timePrecisionSchema = z.enum([\"hours\", \"minutes\", \"seconds\"]);\nexport type TimePrecision = z.infer<typeof timePrecisionSchema>;\n\nexport const dateFormatSchema = z.object({\n dateStyle: dateStyleSchema.optional(),\n kind: dateKindSchema,\n timePrecision: timePrecisionSchema.optional(),\n});\nexport type DateFormat = z.infer<typeof dateFormatSchema>;\n\nexport const durationUnitSchema = z.enum([\n \"milliseconds\",\n \"seconds\",\n \"minutes\",\n \"hours\",\n \"days\",\n]);\nexport type DurationUnit = z.infer<typeof durationUnitSchema>;\n\nexport const durationDisplaySchema = z.enum([\n \"hms\",\n \"hours\",\n \"minutes\",\n \"decimal-hours\",\n \"iso\",\n]);\nexport type DurationDisplay = z.infer<typeof durationDisplaySchema>;\n\nexport const durationFormatSchema = z.object({\n display: durationDisplaySchema,\n /** Unit a writer typically types; stored value is always milliseconds. */\n inputUnit: durationUnitSchema,\n});\nexport type DurationFormat = z.infer<typeof durationFormatSchema>;\n\nexport const selectOptionSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().min(1).max(128),\n});\nexport type SelectOption = z.infer<typeof selectOptionSchema>;\n\nexport const selectFormatSchema = z.object({\n /** Values outside `options` are kept as-is instead of rejected. */\n allowCustom: z.boolean(),\n multiple: z.boolean().optional(),\n options: z.array(selectOptionSchema).max(200),\n});\nexport type SelectFormat = z.infer<typeof selectFormatSchema>;\n\nexport const textStyleSchema = z.enum([\"single\", \"multiline\", \"markdown\"]);\nexport type TextStyle = z.infer<typeof textStyleSchema>;\n\nexport const textFormatSchema = z.object({\n /** `single` is one line; `multiline` is plain wrapping text; `markdown` is inline marks. */\n style: textStyleSchema.default(\"single\"),\n});\nexport type TextFormat = z.infer<typeof textFormatSchema>;\n\nexport const tableColumnSchema = z.discriminatedUnion(\"type\", [\n columnBaseSchema.extend({\n format: textFormatSchema.optional(),\n type: z.literal(\"text\"),\n }),\n columnBaseSchema.extend({\n format: numberFormatSchema,\n type: z.literal(\"number\"),\n }),\n columnBaseSchema.extend({\n format: dateFormatSchema,\n type: z.literal(\"date\"),\n }),\n columnBaseSchema.extend({\n format: durationFormatSchema,\n type: z.literal(\"duration\"),\n }),\n columnBaseSchema.extend({\n format: selectFormatSchema,\n type: z.literal(\"select\"),\n }),\n columnBaseSchema.extend({ type: z.literal(\"boolean\") }),\n]);\nexport type TableColumn = z.infer<typeof tableColumnSchema>;\n\nexport type ColumnEdit = NonNullable<TableColumn[\"edit\"]>;\n\nexport function textColumnStyle(column: TableColumn): TextStyle {\n return column.type === \"text\" ? (column.format?.style ?? \"single\") : \"single\";\n}\n\n/** Where this cell is edited. Explicit `edit` wins; otherwise type defaults. */\nexport function columnEdit(column: TableColumn): ColumnEdit {\n if (column.edit) {\n return column.edit;\n }\n if (column.type === \"boolean\") {\n return \"inline\";\n }\n if (column.type === \"text\" && textColumnStyle(column) === \"single\") {\n return \"inline\";\n }\n return \"popout\";\n}\n\nexport const tableColumnsSchema = z\n .array(tableColumnSchema)\n .min(1)\n .max(64)\n .superRefine((columns, ctx) => {\n const seen = new Set<string>();\n for (let i = 0; i < columns.length; i++) {\n const id = columns[i]?.id;\n if (!id) {\n continue;\n }\n if (seen.has(id)) {\n ctx.addIssue({\n code: \"custom\",\n message: `duplicate column id \"${id}\"`,\n path: [i, \"id\"],\n });\n }\n seen.add(id);\n }\n });\n\n/**\n * The shape a MODEL is shown for `columns`, as opposed to the one we validate.\n *\n * `tableColumnsSchema` is a six-branch discriminated union that repeats the\n * whole column base per branch. As a tool's JSON Schema that came to 14.7 KB —\n * on its own 5% of a copilot prompt, resent on every model call of every run,\n * whether or not a table is in play. The union earns that as a *contract*; it\n * does not earn it as a *hint*.\n *\n * So the wire shape is one flat object with every format key optional, and the\n * tool re-parses the result with `tableColumnsSchema` before doing anything.\n * Validation is unchanged and the error the model gets back is the strict\n * schema's own; only the advertisement shrinks. Per-type rules live in the\n * tool description, which the model reads anyway.\n */\nexport const tableColumnWireSchema = z.object({\n description: z.string().optional(),\n edit: z.enum([\"inline\", \"popout\"]).optional(),\n format: z\n .object({\n allowCustom: z.boolean().optional(),\n currency: z.string().optional(),\n dateStyle: z.enum([\"short\", \"medium\", \"long\", \"iso\"]).optional(),\n display: durationDisplaySchema.optional(),\n fractionDigits: z.number().int().optional(),\n grouping: z.boolean().optional(),\n inputUnit: durationUnitSchema.optional(),\n kind: dateKindSchema.optional(),\n multiple: z.boolean().optional(),\n options: z.array(selectOptionSchema).optional(),\n // `style` spans text and number columns; which values are legal follows\n // from `type`, and the strict schema is what decides.\n style: z\n .enum([\n \"single\",\n \"multiline\",\n \"markdown\",\n \"integer\",\n \"decimal\",\n \"percent\",\n \"currency\",\n ])\n .optional(),\n timePrecision: timePrecisionSchema.optional(),\n })\n .optional(),\n id: z.string(),\n name: z.string(),\n required: z.boolean().optional(),\n type: z.enum([\"text\", \"number\", \"date\", \"duration\", \"select\", \"boolean\"]),\n});\n\nexport const tableColumnsWireSchema = z.array(tableColumnWireSchema);\nexport type TableColumnWire = z.infer<typeof tableColumnWireSchema>;\n\nexport const DATA_TABLE_ARTIFACT_TYPE = \"database\" as const;\nexport const DATA_TABLE_MIME_TYPE = \"application/vnd.engenty.database+json\";\n\nexport const dataTableHandleSchema = z.object({\n table_id: z.string().uuid(),\n});\nexport type DataTableHandle = z.infer<typeof dataTableHandleSchema>;\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport type {\n DateFormat,\n DurationFormat,\n NumberFormat,\n TableColumn,\n} from \"./columns.js\";\n\nconst MS_HOUR = 3_600_000;\nconst MS_MINUTE = 60_000;\nconst MS_SECOND = 1000;\n\nfunction fractionDigits(format: NumberFormat): number {\n if (format.fractionDigits !== undefined) {\n return format.fractionDigits;\n }\n return format.style === \"integer\" ? 0 : 2;\n}\n\nexport function formatNumberCell(\n value: unknown,\n format: NumberFormat,\n locale = \"en\"\n): string {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return \"\";\n }\n const digits = fractionDigits(format);\n const grouping = format.grouping !== false;\n if (format.style === \"percent\") {\n return new Intl.NumberFormat(locale, {\n maximumFractionDigits: digits,\n minimumFractionDigits: digits,\n style: \"percent\",\n useGrouping: grouping,\n }).format(value);\n }\n if (format.style === \"currency\" && format.currency) {\n return new Intl.NumberFormat(locale, {\n currency: format.currency,\n maximumFractionDigits: digits,\n minimumFractionDigits: digits,\n style: \"currency\",\n useGrouping: grouping,\n }).format(value);\n }\n return new Intl.NumberFormat(locale, {\n maximumFractionDigits: digits,\n minimumFractionDigits: digits,\n useGrouping: grouping,\n }).format(value);\n}\n\nexport function formatDateCell(\n value: unknown,\n format: DateFormat,\n locale = \"en\"\n): string {\n if (typeof value !== \"string\" || value.length === 0) {\n return \"\";\n }\n if (format.kind === \"time\") {\n return formatClock(value, format.timePrecision ?? \"minutes\");\n }\n if (format.dateStyle === \"iso\") {\n return format.kind === \"date\" ? value.slice(0, 10) : value;\n }\n const date =\n format.kind === \"date\" ? new Date(`${value}T00:00:00`) : new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const dateStyle = format.dateStyle ?? \"medium\";\n if (format.kind === \"date\") {\n return new Intl.DateTimeFormat(locale, { dateStyle }).format(date);\n }\n const timePrecision = format.timePrecision ?? \"minutes\";\n return new Intl.DateTimeFormat(locale, {\n dateStyle,\n timeStyle: timePrecision === \"hours\" ? \"short\" : \"medium\",\n }).format(date);\n}\n\nfunction formatClock(\n value: string,\n precision: NonNullable<DateFormat[\"timePrecision\"]>\n): string {\n const [hours = \"0\", minutes = \"00\", seconds = \"00\"] = value.split(\":\");\n if (precision === \"hours\") {\n return `${hours.padStart(2, \"0\")}:00`;\n }\n if (precision === \"minutes\") {\n return `${hours.padStart(2, \"0\")}:${minutes.padStart(2, \"0\")}`;\n }\n return `${hours.padStart(2, \"0\")}:${minutes.padStart(2, \"0\")}:${seconds.padStart(2, \"0\")}`;\n}\n\nexport function formatDurationCell(\n value: unknown,\n format: DurationFormat\n): string {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return \"\";\n }\n const ms = Math.max(0, Math.round(value));\n if (format.display === \"iso\") {\n return toIsoDuration(ms);\n }\n if (format.display === \"minutes\") {\n return `${Math.round(ms / MS_MINUTE)} min`;\n }\n if (format.display === \"hours\") {\n return `${(ms / MS_HOUR).toFixed(2)} h`;\n }\n if (format.display === \"decimal-hours\") {\n return (ms / MS_HOUR).toFixed(2);\n }\n const hours = Math.floor(ms / MS_HOUR);\n const minutes = Math.floor((ms % MS_HOUR) / MS_MINUTE);\n const seconds = Math.floor((ms % MS_MINUTE) / MS_SECOND);\n return `${hours}:${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`;\n}\n\nfunction toIsoDuration(ms: number): string {\n const hours = Math.floor(ms / MS_HOUR);\n const minutes = Math.floor((ms % MS_HOUR) / MS_MINUTE);\n const seconds = Math.floor((ms % MS_MINUTE) / MS_SECOND);\n const dayPart = hours >= 24 ? `P${Math.floor(hours / 24)}D` : \"P\";\n const h = hours % 24;\n return `${dayPart}T${h}H${minutes}M${seconds}S`;\n}\n\nexport function formatTableCell(\n column: TableColumn,\n value: unknown,\n locale = \"en\"\n): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n switch (column.type) {\n case \"number\":\n return formatNumberCell(value, column.format, locale);\n case \"date\":\n return formatDateCell(value, column.format, locale);\n case \"duration\":\n return formatDurationCell(value, column.format);\n case \"boolean\":\n return value === true ? \"true\" : value === false ? \"false\" : \"\";\n case \"select\":\n return formatSelectCell(column, value);\n default:\n return String(value);\n }\n}\n\nfunction formatSelectCell(\n column: Extract<TableColumn, { type: \"select\" }>,\n value: unknown\n): string {\n const ids = Array.isArray(value) ? value : [value];\n const labels = column.format.options.reduce<Record<string, string>>(\n (acc, option) => {\n acc[option.id] = option.label;\n return acc;\n },\n {}\n );\n return ids\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .map((id) => labels[id] ?? id)\n .join(\", \");\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\n\n/**\n * Numbers as people write and read them: what a phone's number pad, a table cell or a document\n * gives, and an amount or a file's size as a page shows it. The server, the studio and the runner read and\n * show them the same way.\n */\n\n/**\n * A number as a person types it: digits with at most one decimal mark, a point or a comma\n * alike, as a phone's number pad gives it in either language (`1.5`, `1,5`, `89,90`). There are\n * no thousands separators: `1.234` and `1,234` are 1.234, and anything with two marks\n * (`1.234,50`, `1.234.567`) is no number, since only the writer's language could say which mark\n * is which. Text that is not typed (a document, a website) is read by a model into numbers\n * before it gets here. With `units`, what stands around the number is dropped (`38 h`,\n * `19 %`); without, anything but the number makes it none. Null where there is no number.\n */\nexport function readNumber(value: unknown, opts: { units?: boolean } = {}): number | null {\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? value : null;\n }\n if (typeof value !== \"string\") {\n return null;\n }\n const s = opts.units ? value.replace(/[^\\d,.-]/g, \"\") : value.trim();\n if (!/^-?(\\d+([.,]\\d*)?|[.,]\\d+)$/.test(s)) {\n return null;\n }\n const n = Number(s.replace(\",\", \".\"));\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * A file's size for a list, in decimal units as the operating systems show them: `1 KB` for\n * anything below a kilobyte but nothing (`0 KB`), `340 KB`, `2.4 MB`, `1.2 GB`.\n */\nexport function formatBytes(bytes: number): string {\n if (!(bytes > 0)) {\n return \"0 KB\";\n }\n if (bytes < 999_500) {\n return `${Math.max(1, Math.round(bytes / 1000))} KB`;\n }\n if (bytes < 999_950_000) {\n return `${(bytes / 1_000_000).toFixed(1)} MB`;\n }\n return `${(bytes / 1_000_000_000).toFixed(1)} GB`;\n}\n\n/** An amount in a currency, as the language writes it (`1.234,50 €`); an unknown currency code as `1234.50 XYZ`. */\nexport function formatMoney(amount: number, currency: string, locale: string): string {\n try {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(amount);\n } catch {\n return `${amount.toFixed(2)} ${currency}`;\n }\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { z } from \"zod\";\n\n/**\n * What an agent step's json output holds, in the kinds wizards already use: `output.schema`.\n * Text, numbers, yes/no, a choice, an entry of another list by its id (`ref`), and lists — of\n * these or of objects (entries) with lists of their own — every one with a label. The runtime builds the model's JSON Schema from\n * it, the admin shows and edits the data by it, downloads and views read it.\n *\n * `output.fields`, the short form, compiles to the same shape (`shapeOfFields`); two kinds exist\n * only there: `score` (a decision's levels) and `table` (rows of text or numbers, columns named\n * or picked by the model).\n */\n\n/** Objects nest at most this deep, the step's own object counted. */\nexport const MAX_SHAPE_DEPTH = 4;\n/** At most this many keys in all objects together. */\nexport const MAX_SHAPE_KEYS = 100;\n\ninterface Named {\n /** What people read: a column's head, a part's title, \"add …\". Without one, the key. */\n label?: string;\n /** What the model is to put there. */\n description?: string;\n}\n\nexport type TextShape = Named & { kind: \"text\"; long?: boolean };\nexport type NumberShape = Named & { kind: \"number\"; unit?: string };\nexport type YesNoShape = Named & { kind: \"yesno\"; yes?: string; no?: string };\nexport type ChoiceShape = Named & { kind: \"choice\"; options: string[] };\n/** An entry of a top-level list of the same output, by its `id`. */\nexport type RefShape = Named & { kind: \"ref\"; to: string };\nexport type LeafShape = TextShape | NumberShape | YesNoShape | ChoiceShape | RefShape;\nexport type ListShape = Named & { kind: \"list\"; of: LeafShape | ObjectShape };\nexport interface ObjectShape extends Named {\n kind: \"object\";\n fields: Record<string, FieldShape>;\n}\n/** `fields` only: a decision's levels, lowest first. */\nexport type ScoreShape = Named & { kind: \"score\"; options: string[] };\n/** `fields` only: rows of text or numbers; without columns the model picks them. */\nexport type TableShape = Named & { kind: \"table\"; columns?: string[] };\nexport type FieldShape = LeafShape | ListShape | ScoreShape | TableShape;\n\nconst key = z\n .string()\n .regex(/^[a-zA-Z][a-zA-Z0-9_]{0,40}$/, \"keys are letters, digits and _ and start with a letter\");\n\nconst named = {\n label: z.string().min(1).optional(),\n description: z.string().optional(),\n};\n\nconst leaves = [\n z.object({ kind: z.literal(\"text\"), ...named, long: z.boolean().optional() }),\n z.object({ kind: z.literal(\"number\"), ...named, unit: z.string().optional() }),\n z.object({\n kind: z.literal(\"yesno\"),\n ...named,\n yes: z.string().optional(),\n no: z.string().optional(),\n }),\n z.object({\n kind: z.literal(\"choice\"),\n ...named,\n options: z.array(z.string().min(1)).min(2).max(40),\n }),\n z.object({ kind: z.literal(\"ref\"), ...named, to: key }),\n] as const;\n\nconst LEAF_KINDS = \"text, number, yesno, choice, ref\";\n\n/**\n * The shape of an object `depth` deep, built level by level instead of recursively: JSON Schema\n * of the definition takes no $ref, and the depth is part of the schema. Objects are the entries\n * of lists (and the step's own); a field holding one object would only add a level.\n */\nfunction objectAt(depth: number): z.ZodObject {\n const deeper: z.ZodObject | undefined = depth < MAX_SHAPE_DEPTH ? objectAt(depth + 1) : undefined;\n const of = deeper\n ? z.discriminatedUnion(\"kind\", [...leaves, deeper], {\n error: `A list holds ${LEAF_KINDS} or object.`,\n })\n : z.discriminatedUnion(\"kind\", [...leaves], {\n error: `A list this deep holds ${LEAF_KINDS}: objects nest at most ${MAX_SHAPE_DEPTH} deep.`,\n });\n const list = z.object({ kind: z.literal(\"list\"), ...named, of });\n const field = z.discriminatedUnion(\"kind\", [...leaves, list], {\n error: `\"kind\" is one of ${LEAF_KINDS}, list.`,\n });\n return z.object({\n kind: z.literal(\"object\"),\n ...named,\n fields: z\n .record(key, field)\n .refine((f) => Object.keys(f).length > 0, { message: \"An object has fields.\" }),\n });\n}\n\n/** Every object of a shape with where it sits, the shape's own first. */\nfunction objectsOf(shape: ObjectShape, at: (string | number)[] = []) {\n const out: { shape: ObjectShape; at: (string | number)[] }[] = [{ shape, at }];\n for (const [k, f] of Object.entries(shape.fields)) {\n if (f.kind === \"list\" && f.of.kind === \"object\") {\n out.push(...objectsOf(f.of, [...at, \"fields\", k, \"of\"]));\n }\n }\n return out;\n}\n\n/** The list a `ref` points into: a top-level list of objects with an `id`. Null when it is fine. */\nfunction refProblem(root: ObjectShape, to: string): string | null {\n const target = root.fields[to];\n if (target?.kind !== \"list\" || target.of.kind !== \"object\") {\n return `\"ref\" to \"${to}\": that is no list of objects at the top of the schema.`;\n }\n return target.of.fields.id?.kind === \"text\"\n ? null\n : `\"ref\" to \"${to}\": its entries need an \"id\" text field to be pointed at.`;\n}\n\n/** `output.schema`: what the step returns. */\nexport const outputShapeSchema = (objectAt(1) as unknown as z.ZodType<ObjectShape>).superRefine(\n (shape, ctx) => {\n const objects = objectsOf(shape);\n const keys = objects.reduce((n, o) => n + Object.keys(o.shape.fields).length, 0);\n if (keys > MAX_SHAPE_KEYS) {\n ctx.addIssue({\n code: \"custom\",\n message: `A schema has at most ${MAX_SHAPE_KEYS} keys in all; this one has ${keys}.`,\n });\n }\n for (const o of objects) {\n for (const [k, f] of Object.entries(o.shape.fields)) {\n const ref = f.kind === \"ref\" ? f : f.kind === \"list\" && f.of.kind === \"ref\" ? f.of : null;\n const problem = ref ? refProblem(shape, ref.to) : null;\n if (problem) {\n ctx.addIssue({ code: \"custom\", message: problem, path: [...o.at, \"fields\", k] });\n }\n }\n }\n },\n);\n\n/** An output field as `output.fields` writes it. */\ninterface ShortField {\n id: string;\n kind: string;\n description?: string;\n columns?: string[];\n options?: string[];\n}\n\n/** The short form as a shape: a field per key, a list of text, a table as it is. */\nexport function shapeOfFields(fields: ShortField[]): ObjectShape {\n const one = (f: ShortField): FieldShape => {\n const d = f.description ? { description: f.description } : {};\n switch (f.kind) {\n case \"number\":\n return { kind: \"number\", ...d };\n case \"list\":\n return { kind: \"list\", ...d, of: { kind: \"text\" } };\n case \"yesno\":\n return { kind: \"yesno\", ...d };\n case \"choice\":\n return { kind: \"choice\", ...d, options: f.options ?? [] };\n case \"score\":\n return { kind: \"score\", ...d, options: f.options ?? [] };\n case \"table\":\n return { kind: \"table\", ...d, ...(f.columns?.length ? { columns: f.columns } : {}) };\n default:\n return { kind: \"text\", ...d };\n }\n };\n return { kind: \"object\", fields: Object.fromEntries(fields.map((f) => [f.id, one(f)])) };\n}\n\n/** The key of an entry's title: its first short text other than its `id`. */\nexport function titleKey(shape: ObjectShape): string | undefined {\n return Object.entries(shape.fields).find(\n ([k, f]) => k !== \"id\" && f.kind === \"text\" && !f.long,\n )?.[0];\n}\n\n/** What people read for a key. */\nexport function labelOf(key: string, shape: FieldShape | ListShape[\"of\"]): string {\n return shape.label ?? key;\n}\n\n/**\n * What the model reads about a value beside its title: its description (without label: its key),\n * its unit, a score's order, where a ref points. Undefined where the title says it all.\n */\nfunction about(k: string, s: FieldShape | ListShape[\"of\"]): string | undefined {\n const base = s.description ?? (s.label ? \"\" : k);\n const more =\n s.kind === \"number\" && s.unit\n ? `in ${s.unit}`\n : s.kind === \"score\"\n ? \"lowest to highest\"\n : s.kind === \"ref\"\n ? `the id of an entry of \"${s.to}\"`\n : \"\";\n return (base && more ? `${base} (${more})` : base || more) || undefined;\n}\n\nconst CELL = z.union([z.string(), z.number(), z.null()]);\n\n/** The data a shape describes, as Zod: what a model's answer is checked against. */\nexport function shapeZod(shape: FieldShape | ListShape[\"of\"], k = \"data\"): z.ZodType {\n const description = about(k, shape);\n const meta = {\n ...(shape.label ? { title: shape.label } : {}),\n ...(description ? { description } : {}),\n };\n switch (shape.kind) {\n case \"text\":\n case \"ref\":\n return z.string().meta(meta);\n case \"number\":\n return z.number().meta(meta);\n case \"yesno\":\n return z.boolean().meta(meta);\n case \"choice\":\n case \"score\":\n return z.enum(shape.options as [string, ...string[]]).meta(meta);\n case \"list\":\n return z.array(shapeZod(shape.of, k)).meta(meta);\n case \"object\":\n return z\n .object(\n Object.fromEntries(Object.entries(shape.fields).map(([n, f]) => [n, shapeZod(f, n)])),\n )\n .meta(meta);\n case \"table\":\n return (\n shape.columns?.length\n ? z.array(z.object(Object.fromEntries(shape.columns.map((c) => [c, CELL]))))\n : // Free columns come as columns + rows, which a strict schema takes; stored as records.\n z.object({ columns: z.array(z.string()), rows: z.array(z.array(CELL)) })\n ).meta(meta);\n }\n}\n\n/**\n * The data as JSON Schema (draft 2020-12): every key required, no other keys — what a model's\n * structured output takes, and what developers read.\n */\nexport function shapeJsonSchema(shape: ObjectShape, title?: string): Record<string, unknown> {\n const schema = z.toJSONSchema(shapeZod(shape), { target: \"draft-2020-12\" }) as Record<\n string,\n unknown\n >;\n return title && !shape.label ? { ...schema, title } : schema;\n}\n\n/** A table cell as a table takes it: a list joined by spaces, anything else as text. */\nfunction fitCell(value: unknown): string | number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\" || typeof value === \"number\") {\n return value;\n }\n if (Array.isArray(value) && value.every((v) => typeof v === \"string\" || typeof v === \"number\")) {\n return value.join(\" \");\n }\n return typeof value === \"boolean\" ? String(value) : JSON.stringify(value);\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n Boolean(v) && typeof v === \"object\" && !Array.isArray(v);\n\n/**\n * Data a model wrote itself, fitted to the shape before it is checked: a number where text\n * belongs as text, a number written as text as a number; in a table a cell's list joined and a\n * missing column empty. Lists stay lists everywhere else.\n */\nexport function fitData(shape: FieldShape | ListShape[\"of\"], value: unknown): unknown {\n switch (shape.kind) {\n case \"text\":\n case \"ref\":\n return typeof value === \"number\" ? String(value) : value;\n case \"number\":\n return typeof value === \"string\" && value.trim() && Number.isFinite(Number(value))\n ? Number(value)\n : value;\n case \"list\":\n return Array.isArray(value) ? value.map((v) => fitData(shape.of, v)) : value;\n case \"object\":\n if (!isRecord(value)) {\n return value;\n }\n return {\n ...value,\n ...Object.fromEntries(\n Object.entries(shape.fields)\n .filter(([k]) => k in value)\n .map(([k, f]) => [k, fitData(f, value[k])]),\n ),\n };\n case \"table\": {\n const columns = shape.columns;\n return columns?.length && Array.isArray(value)\n ? value.map((row) =>\n isRecord(row) ? Object.fromEntries(columns.map((c) => [c, fitCell(row[c])])) : row,\n )\n : value;\n }\n default:\n return value;\n }\n}\n\n/** Tables with free columns come back as columns + rows and are stored as records. */\nexport function recordsOf(shape: FieldShape | ListShape[\"of\"], value: unknown): unknown {\n if (shape.kind === \"table\" && !shape.columns?.length && isRecord(value)) {\n const t = value as { columns?: string[]; rows?: unknown[][] };\n if (t.columns && t.rows) {\n const columns = t.columns;\n return t.rows.map((row) => Object.fromEntries(columns.map((c, i) => [c, row[i] ?? null])));\n }\n }\n if (shape.kind === \"object\" && isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => {\n const f = shape.fields[k];\n return [k, f ? recordsOf(f, v) : v];\n }),\n );\n }\n if (shape.kind === \"list\" && Array.isArray(value)) {\n return value.map((v) => recordsOf(shape.of, v));\n }\n return value;\n}\n\n/** What a value of a shape is, in a word or two: \"list of Rezept\", \"choice: a | b\". */\nfunction kindLine(s: FieldShape | ListShape[\"of\"]): string {\n switch (s.kind) {\n case \"choice\":\n case \"score\":\n return `${s.kind}: ${s.options.join(\" | \")}`;\n case \"ref\":\n return `ref → /${s.to}[].id`;\n case \"table\":\n return s.columns?.length ? `table: ${s.columns.join(\", \")}` : \"table\";\n case \"list\":\n return s.of.kind === \"object\" ? \"list of entries\" : `list of ${s.of.kind}`;\n default:\n return s.kind;\n }\n}\n\n/** The shape as lines of paths a model binds to: \"/recipes[]/title (text): Titel\". */\nexport function shapeLines(shape: ObjectShape, at = \"\"): string[] {\n const out: string[] = [];\n for (const [k, f] of Object.entries(shape.fields)) {\n const path = `${at}/${k}`;\n const words = [f.label, f.description].filter(Boolean).join(\" — \");\n out.push(`- ${path} (${kindLine(f)})${words ? `: ${words}` : \"\"}`);\n if (f.kind === \"list\" && f.of.kind === \"object\") {\n out.push(...shapeLines(f.of, `${path}[]`));\n }\n }\n return out;\n}\n\n/**\n * The shape at a path: keys of objects, an index (digits) into a list. `any` where the data can\n * hold anything (a table's row), undefined where the shape has nothing.\n */\nexport function shapeAt(\n shape: FieldShape | ListShape[\"of\"],\n path: string[],\n): FieldShape | ListShape[\"of\"] | \"any\" | undefined {\n let at: FieldShape | ListShape[\"of\"] = shape;\n for (const part of path) {\n if (at.kind === \"object\") {\n const next: FieldShape | undefined = at.fields[part];\n if (!next) {\n return undefined;\n }\n at = next;\n } else if (at.kind === \"list\" && /^\\d+$/.test(part)) {\n at = at.of;\n } else if (at.kind === \"table\") {\n // A row, and in it whatever columns the model wrote.\n return /^\\d+$/.test(part) ? \"any\" : undefined;\n } else {\n return undefined;\n }\n }\n return at;\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { coerceRowValues, mergeRowValues, type TableColumn } from \"./engenty/data-tables/index.js\";\nimport { readNumber } from \"./numbers.js\";\n\n/**\n * What a wizard keeps between runs for one person: lists (tabular data), files and connected\n * accounts. The wizard definition says which lists and connections exist; the content belongs\n * to the person who ran it.\n */\n\n/** A list is an engenty data table: typed columns, rows of cells keyed by column id. */\nexport interface ListDef {\n id: string;\n title: string;\n description?: string;\n columns: TableColumn[];\n /** Column whose value identifies a row: saving a row with a known key updates it. */\n key?: string;\n /**\n * The rows are gone through one by one in a review: `file` holds the path of a kept file\n * shown beside the row, `status` is a select whose options are the answers (first = open).\n */\n check?: { file?: string; status?: string };\n /** Every run reads and writes the same rows; kept as a table of the space, not per person. */\n shared?: boolean;\n}\n\nexport interface ListRow {\n id: string;\n cells: Record<string, unknown>;\n updatedAt: string;\n}\n\nexport interface StoreFile {\n path: string;\n mime: string;\n size: number;\n /** Where the file came from, in words: \"E-Mail von billing@notion.so, 3.9.2026\". */\n source: string | null;\n updatedAt: string;\n}\n\nexport const STORE_LIMITS = {\n fileBytes: 15_000_000,\n totalBytes: 200_000_000,\n files: 2000,\n rowsPerList: 5000,\n};\n\n/** Kinds of accounts a wizard can ask the person to connect. */\nexport const CONNECTION_KINDS = [\"mail\"] as const;\nexport type ConnectionKind = (typeof CONNECTION_KINDS)[number];\n\n/** An account the person connects: a built-in kind, or one of the project's imported connectors. */\nexport interface ConnectionDef {\n id: string;\n kind?: ConnectionKind;\n /** Id of an imported connector of the project. */\n connector?: string;\n /** Imported connectors: the actions steps may call. Default: every action that only reads. */\n actions?: string[];\n /**\n * Imported connectors: per action, run it without asking (\"allow\") or ask the person first\n * (\"ask\"). Default: reading is allowed, changing asks; deleting always asks.\n */\n policy?: Record<string, \"allow\" | \"ask\">;\n title?: string;\n description?: string;\n /**\n * Share targets only (never in a wizard definition): the connectors the person can pick from,\n * and the provider is asked for no more than `actions` need — a target that sends never asks\n * for the right to read.\n */\n target?: { connectors: string[] };\n}\n\n/** A connector the person can pick for a connection: an OAuth sign-in or a credentials form. */\nexport interface ConnectorOption {\n id: string;\n name: string;\n auth: \"oauth2\" | \"api_key\";\n /** `api_key` connectors: the form, in order. */\n fields?: {\n key: string;\n label: string;\n secret?: boolean;\n placeholder?: string;\n required?: boolean;\n }[];\n /** Shown under the form: where to get the values. */\n hint?: string;\n}\n\nexport interface ConnectionView {\n id: string;\n kind: ConnectionKind | null;\n /** The imported connector behind the connection, if it is one. */\n connector: string | null;\n title: string | null;\n description: string | null;\n /** Set when the person has connected an account. */\n account: { connector: string; label: string; connectedAt: string } | null;\n connectors: ConnectorOption[];\n}\n\n/** One list as a Markdown table of raw cell values — what a model reads. */\nexport function listAsMarkdown(def: ListDef, rows: ListRow[], limit = 200): string {\n if (!rows.length) {\n return \"(empty)\";\n }\n const cols = def.columns;\n const cell = (v: unknown) =>\n v === null || v === undefined\n ? \"\"\n : (Array.isArray(v) ? v.join(\", \") : String(v)).replace(/\\|/g, \"\\\\|\").replace(/\\s+/g, \" \");\n const head = `| ${cols.map((c) => c.id).join(\" | \")} |\\n|${cols.map(() => \" --- \").join(\"|\")}|`;\n const body = rows\n .slice(0, limit)\n .map((r) => `| ${cols.map((c) => cell(r.cells[c.id])).join(\" | \")} |`);\n const more = rows.length > limit ? [`… ${rows.length - limit} more rows`] : [];\n return [head, ...body, ...more].join(\"\\n\");\n}\n\n/**\n * When the first row saved now is stamped, in milliseconds: after every row the list already\n * holds, so a list reads in the order its rows came — also when two saves fall in one\n * millisecond. The rows of one save follow it a millisecond apart.\n */\nexport function firstRowAt(existing: { createdAt: Date }[]): number {\n return existing.reduce((at, row) => Math.max(at, row.createdAt.getTime() + 1), Date.now());\n}\n\n/** The key a row is matched on: trimmed and lower-cased, so \"Notion \" and \"notion\" are one row. */\nexport function rowKey(def: ListDef, cells: Record<string, unknown>): string | null {\n if (!def.key) {\n return null;\n }\n const raw = cells[def.key];\n const key = raw === null || raw === undefined ? \"\" : String(raw).trim().toLowerCase();\n return key || null;\n}\n\n/** A new row's cells, typed by the list's columns. Throws `TableColumnValueError` on a bad value. */\nexport function newCells(def: ListDef, input: Record<string, unknown>): Record<string, unknown> {\n return coerceRowValues(def.columns, input);\n}\n\n/** An existing row's cells with some columns changed; cells of columns the list no longer has are dropped. */\nexport function patchCells(\n def: ListDef,\n current: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const known = new Set(def.columns.map((c) => c.id));\n const kept = Object.fromEntries(Object.entries(current).filter(([id]) => known.has(id)));\n return mergeRowValues(def.columns, kept, patch);\n}\n\n/**\n * What a person typed into a cell, as the value sent for its column; the runtime still checks it\n * against the column. Blank is null; a number or a duration (in the column's input unit) is read\n * as people write it (\"12,5\"); a date and time from the browser's picker, in local time, becomes\n * ISO. What cannot be read goes as typed, for the runtime to refuse and name.\n */\nexport function cellValue(column: TableColumn, text: string): unknown {\n if (text.trim() === \"\") {\n return null;\n }\n switch (column.type) {\n case \"number\":\n case \"duration\":\n return readNumber(text) ?? text;\n case \"boolean\":\n return text === \"true\";\n case \"date\": {\n if (column.format.kind !== \"datetime\") {\n return text;\n }\n const at = new Date(text);\n return Number.isNaN(at.getTime()) ? text : at.toISOString();\n }\n default:\n return text;\n }\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { z } from \"zod\";\nimport { type FieldShape, type ListShape, type ObjectShape, shapeAt } from \"./shape.js\";\n\n/**\n * Surfaces: views composed from a small catalog of native components, bound to a run's data and\n * rendered by the runner itself — themed, on phones, no iframe and nothing to pay per run. A\n * surface is data, not code: only catalog components render, so it needs no sandbox. Between the\n * plain table a review shows and a widget, which is free HTML. As engenty-pro's A2UI catalog\n * (`engenty:core/v1`), kept to what a wizard's result needs.\n *\n * A surface is a flat list of components with ids; the one with id \"root\" is drawn, containers\n * name their children by id. A prop may be a literal or `{ \"path\": \"/json/pointer\" }` into the\n * surface's data. A `List`, `Table` or `Group` repeats over an array: inside a repeated row, a\n * path without a leading slash reads the row (\"name\"), one with a slash the whole data. A path\n * may turn what it reads into words: `map` looks the value up (`{ \"true\": \"im Kühlschrank\" }`),\n * `format` sets it into a text (\"{} Min\").\n */\n\nexport const SURFACE_COMPONENTS = [\n \"Column\",\n \"Text\",\n \"List\",\n \"Row\",\n \"DetailGrid\",\n \"Badge\",\n \"Grid\",\n \"Metric\",\n \"Table\",\n \"Image\",\n \"BarChart\",\n \"LineChart\",\n \"DonutChart\",\n \"Actions\",\n \"Button\",\n \"Tabs\",\n \"Card\",\n \"Fold\",\n \"Group\",\n \"Chips\",\n \"Checklist\",\n \"Steps\",\n \"Link\",\n \"Callout\",\n] as const;\nexport type SurfaceComponentName = (typeof SURFACE_COMPONENTS)[number];\n\n/** Components that hold others by id. */\nconst CONTAINERS: ReadonlySet<string> = new Set([\n \"Column\",\n \"List\",\n \"Grid\",\n \"Actions\",\n \"Card\",\n \"Fold\",\n \"Group\",\n]);\n\n/** The props each component needs. */\nconst REQUIRED: Partial<Record<SurfaceComponentName, string[]>> = {\n Text: [\"text\"],\n Row: [\"title\"],\n DetailGrid: [\"rows\"],\n Badge: [\"label\"],\n Metric: [\"label\", \"value\"],\n Table: [\"rows\"],\n Image: [\"src\"],\n BarChart: [\"points\"],\n LineChart: [\"points\"],\n DonutChart: [\"slices\"],\n Button: [\"label\", \"action\"],\n Tabs: [\"tabs\"],\n Card: [\"title\"],\n Fold: [\"title\", \"children\"],\n Group: [\"children\", \"by\"],\n Chips: [\"items\"],\n Checklist: [\"items\"],\n Steps: [\"items\"],\n Link: [\"title\", \"items\", \"value\", \"view\"],\n Callout: [\"text\"],\n};\n\nexport const SURFACE_ACTIONS = [\"regenerate\", \"open\"] as const;\n\nconst id = z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,40}$/, \"ids are letters, digits, _ and -\");\n\n/** One component: its id, its kind, its children (ids, or a template repeated over an array). */\nexport const surfaceComponentSchema = z.looseObject({\n id,\n component: z.enum(SURFACE_COMPONENTS),\n children: z\n .union([z.array(z.string()), z.object({ path: z.string(), componentId: z.string() })])\n .optional(),\n});\nexport type SurfaceComponent = z.infer<typeof surfaceComponentSchema>;\n\nexport const surfaceComponentsSchema = z.array(surfaceComponentSchema).min(1).max(200);\n\n/** What a run shows: the components and the data they are bound to. */\nexport interface Surface {\n components: SurfaceComponent[];\n data: Record<string, unknown>;\n}\n\nexport interface SurfaceIssue {\n message: string;\n}\n\nconst isPath = (v: unknown): v is { path: string } =>\n Boolean(v && typeof v === \"object\" && !Array.isArray(v) && typeof (v as any).path === \"string\");\n\n/**\n * The ids a component draws: its children, the views of its tabs. A Link's view is drawn only\n * when it is opened, so it is no part of the tree.\n */\nfunction childIds(c: SurfaceComponent): string[] {\n const kids = c.children;\n const ids = Array.isArray(kids) ? [...kids] : kids ? [kids.componentId] : [];\n const tabs = (c as Record<string, unknown>).tabs;\n if (Array.isArray(tabs)) {\n for (const tab of tabs) {\n const child = (tab as Record<string, unknown> | null)?.child;\n if (typeof child === \"string\") {\n ids.push(child);\n }\n }\n }\n return ids;\n}\n\n/** Every `{ path }` in a component's props, with whether it reads a repeated row. */\nfunction pathsOf(c: SurfaceComponent): string[] {\n const out: string[] = [];\n const walk = (v: unknown) => {\n if (isPath(v)) {\n out.push(v.path);\n } else if (Array.isArray(v)) {\n v.forEach(walk);\n } else if (v && typeof v === \"object\") {\n Object.values(v).forEach(walk);\n }\n };\n for (const [key, value] of Object.entries(c)) {\n if (key !== \"id\" && key !== \"component\") {\n walk(\n key === \"children\" && !Array.isArray(value) && isPath(value) ? { path: value.path } : value,\n );\n }\n }\n return out;\n}\n\n/** Props naming a key of the entries a component's `items` (or chart's points) holds. */\nconst ENTRY_KEYS = [\n \"labelKey\",\n \"valueKey\",\n \"flagKey\",\n \"detailKey\",\n \"noteKey\",\n \"groupKey\",\n \"textKey\",\n \"minutesKey\",\n] as const;\n\ntype Shape = FieldShape | ListShape[\"of\"];\n\n/** A path as parts: \"/days/0/label\" from the data, \"meals.slot\" from the entry. */\nconst partsOf = (path: string) =>\n (path.startsWith(\"/\") ? path.slice(1) : path)\n .split(/[./]/)\n .filter(Boolean)\n .map((p) => p.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n\n/**\n * The paths a surface reads, followed through the step's schema from \"root\": a repeated child\n * reads an entry of the list its path names, a Link's view the entry it opens. Every path has to\n * be in the schema, every key a component names in its entries.\n */\nfunction shapeIssues(byId: Map<string, SurfaceComponent>, root: ObjectShape): SurfaceIssue[] {\n const issues: SurfaceIssue[] = [];\n /** The entry drawn: its shape, \"any\" where it can hold anything, undefined outside a list. */\n type Entry = Shape | \"any\" | undefined;\n const seen = new Map<string, Set<Entry>>();\n /** The shape a path reads where `entry` is drawn; \"any\": unchecked. */\n const resolve = (path: string, entry: Entry): Shape | \"any\" | undefined => {\n if (path.startsWith(\"/\")) {\n return shapeAt(root, partsOf(path));\n }\n if (entry === \"any\") {\n return \"any\";\n }\n return entry ? shapeAt(entry, partsOf(path)) : undefined;\n };\n const say = (c: SurfaceComponent, path: string, entry: Entry) =>\n issues.push({\n message:\n !path.startsWith(\"/\") && !entry\n ? `\"${c.id}\" reads \"${path}\" outside a repeated entry; from the data it is \"/${path.replace(/\\./g, \"/\")}\".`\n : `\"${c.id}\" reads \"${path}\", which no data provides.`,\n });\n /** The entries of a list a prop binds, or undefined (and an issue) where it is no list. */\n const entriesOf = (c: SurfaceComponent, value: unknown, entry: Entry): Entry => {\n if (!isPath(value)) {\n return \"any\";\n }\n const at = resolve(value.path, entry);\n if (at === \"any\") {\n return \"any\";\n }\n if (at?.kind === \"list\") {\n return at.of;\n }\n if (at?.kind === \"table\") {\n return at.columns?.length\n ? {\n kind: \"object\",\n fields: Object.fromEntries(at.columns.map((k) => [k, { kind: \"text\" }])),\n }\n : \"any\";\n }\n if (at) {\n issues.push({ message: `\"${c.id}\" reads \"${value.path}\" as a list; it is ${at.kind}.` });\n } else {\n say(c, value.path, entry);\n }\n return undefined;\n };\n const hasKey = (shape: Entry, k: string) =>\n shape === \"any\" || shape === undefined || shape.kind !== \"object\" || k in shape.fields;\n\n const visit = (cid: string, entry: Entry) => {\n const c = byId.get(cid);\n const done = seen.get(cid) ?? new Set();\n if (!c || done.has(entry)) {\n return;\n }\n done.add(entry);\n seen.set(cid, done);\n const props = c as Record<string, unknown>;\n // What the component's items, rows or points hold, for the keys it names in them.\n const listProp = [\"items\", \"rows\", \"points\", \"slices\"].find((k) => isPath(props[k]));\n const items = listProp ? entriesOf(c, props[listProp], entry) : undefined;\n for (const k of ENTRY_KEYS) {\n const named = props[k];\n if (typeof named === \"string\" && items && !hasKey(items, named)) {\n issues.push({\n message: `\"${c.id}\": \"${k}\" names \"${named}\", which its entries do not have.`,\n });\n }\n }\n if (c.component === \"Table\" && Array.isArray(props.columns) && items) {\n for (const col of props.columns as { key?: unknown }[]) {\n if (typeof col?.key === \"string\" && !hasKey(items, col.key)) {\n issues.push({ message: `\"${c.id}\": no column \"${col.key}\" in its rows.` });\n }\n }\n }\n // A Link: title, subtitle and meta read the entry it opens, the rest the entry it sits in.\n const opened = c.component === \"Link\" ? items : undefined;\n if (c.component === \"Link\" && typeof props.key === \"string\" && !hasKey(opened, props.key)) {\n issues.push({ message: `\"${c.id}\": its items have no \"${props.key}\".` });\n }\n for (const [k, value] of Object.entries(props)) {\n if (k === \"id\" || k === \"component\" || k === \"children\" || k === listProp) {\n continue;\n }\n const reads = c.component === \"Link\" && (k === \"title\" || k === \"subtitle\" || k === \"meta\");\n const scope = reads ? opened : entry;\n const paths: string[] = [];\n const walk = (v: unknown) => {\n if (isPath(v)) {\n paths.push(v.path);\n } else if (Array.isArray(v)) {\n v.forEach(walk);\n } else if (v && typeof v === \"object\") {\n Object.values(v).forEach(walk);\n }\n };\n walk(value);\n for (const path of paths) {\n if (resolve(path, scope) === undefined) {\n say(c, path, scope);\n }\n }\n }\n const kids = c.children;\n if (Array.isArray(kids)) {\n for (const k of kids) {\n visit(k, entry);\n }\n } else if (kids) {\n const of = entriesOf(c, { path: kids.path }, entry);\n if (of !== undefined) {\n if (c.component === \"Group\" && typeof props.by === \"string\" && !hasKey(of, props.by)) {\n issues.push({\n message: `\"${c.id}\": \"by\" names \"${props.by}\", which its entries do not have.`,\n });\n }\n visit(kids.componentId, of);\n }\n }\n const tabs = props.tabs;\n if (Array.isArray(tabs)) {\n for (const tab of tabs) {\n const child = (tab as Record<string, unknown> | null)?.child;\n if (typeof child === \"string\") {\n visit(child, entry);\n }\n }\n }\n if (c.component === \"Link\" && typeof props.view === \"string\" && opened !== undefined) {\n visit(props.view, opened);\n }\n };\n if (byId.has(\"root\")) {\n visit(\"root\", undefined);\n }\n return issues;\n}\n\n/**\n * What can be wrong with a surface: an unknown or missing component, no root, a child that is\n * not there, an id twice, a loop, a prop missing, and — given the data keys a run will provide,\n * or the step's schema — a path into data nothing provides.\n */\nexport function validateSurface(raw: unknown, data?: string[] | ObjectShape): SurfaceIssue[] {\n const dataKeys = Array.isArray(data) ? data : undefined;\n const parsed = surfaceComponentsSchema.safeParse(raw);\n if (!parsed.success) {\n return parsed.error.issues.map((i) => ({ message: `${i.path.join(\".\")}: ${i.message}` }));\n }\n const components = parsed.data;\n const issues: SurfaceIssue[] = [];\n const byId = new Map<string, SurfaceComponent>();\n for (const c of components) {\n if (byId.has(c.id)) {\n issues.push({ message: `Duplicate component id \"${c.id}\".` });\n }\n byId.set(c.id, c);\n }\n if (!byId.has(\"root\")) {\n issues.push({ message: 'A surface has a component with id \"root\".' });\n }\n for (const c of components) {\n for (const prop of REQUIRED[c.component] ?? []) {\n if ((c as Record<string, unknown>)[prop] === undefined) {\n issues.push({ message: `${c.component} \"${c.id}\" needs \"${prop}\".` });\n }\n }\n const action = (c as Record<string, unknown>).action;\n if (action !== undefined && !(SURFACE_ACTIONS as readonly unknown[]).includes(action)) {\n issues.push({\n message: `\"${c.id}\": action is one of ${SURFACE_ACTIONS.join(\", \")}.`,\n });\n }\n const children = c.children;\n if (children && !CONTAINERS.has(c.component) && c.component !== \"Table\") {\n issues.push({ message: `${c.component} \"${c.id}\" holds no children.` });\n }\n if (c.component === \"Group\" && (!children || Array.isArray(children))) {\n issues.push({\n message: `Group \"${c.id}\" repeats over a list: children { \"path\", \"componentId\" }.`,\n });\n }\n const tabs = (c as Record<string, unknown>).tabs;\n if (c.component === \"Tabs\" && !(Array.isArray(tabs) && tabs.length >= 2)) {\n issues.push({ message: `Tabs \"${c.id}\" needs at least two tabs: [{ label, child }].` });\n }\n const view = (c as Record<string, unknown>).view;\n const ids = [...childIds(c), ...(typeof view === \"string\" ? [view] : [])];\n for (const child of ids) {\n if (!byId.has(child)) {\n issues.push({ message: `\"${c.id}\" names a child \"${child}\" that is not there.` });\n }\n }\n if (dataKeys) {\n for (const path of pathsOf(c)) {\n const key = path.startsWith(\"/\") ? path.split(\"/\")[1] : null;\n if (key !== null && !dataKeys.includes(key)) {\n issues.push({ message: `\"${c.id}\" reads \"${path}\", which no data provides.` });\n }\n }\n }\n }\n // A child that holds its parent would draw forever.\n const seen = new Set<string>();\n const loops = (cid: string, stack: Set<string>): boolean => {\n if (stack.has(cid)) {\n return true;\n }\n if (seen.has(cid)) {\n return false;\n }\n seen.add(cid);\n const c = byId.get(cid);\n const kids = c ? childIds(c) : [];\n const next = new Set(stack).add(cid);\n return kids.some((k) => loops(k, next));\n };\n if (byId.has(\"root\") && loops(\"root\", new Set())) {\n issues.push({ message: \"Components hold each other in a loop.\" });\n return issues;\n }\n return data && !Array.isArray(data) ? [...issues, ...shapeIssues(byId, data)] : issues;\n}\n\n/** A JSON pointer into data: \"/suppliers/0/name\". */\nexport function pointer(data: unknown, path: string): unknown {\n let at: unknown = data;\n for (const part of path.split(\"/\").slice(1)) {\n if (at === null || typeof at !== \"object\") {\n return undefined;\n }\n at = (at as Record<string, unknown>)[part.replace(/~1/g, \"/\").replace(/~0/g, \"~\")];\n }\n return at;\n}\n\n/**\n * A prop's value: a literal as it is, a path read from the data — or, without a leading slash,\n * from the row a List or Table repeats over.\n */\nexport function bound(value: unknown, data: unknown, row?: unknown): unknown {\n if (!isPath(value)) {\n return value;\n }\n const raw = value.path.startsWith(\"/\")\n ? pointer(data, value.path)\n : row === undefined\n ? undefined\n : pointer(row, `/${value.path.replace(/\\./g, \"/\")}`);\n return worded(raw, value as { map?: unknown; format?: unknown });\n}\n\n/** A value turned into words as its path says: looked up in `map`, set into `format`. */\nexport function worded(raw: unknown, spec: { map?: unknown; format?: unknown }): unknown {\n let v = raw;\n const map = spec.map;\n if (map && typeof map === \"object\" && !Array.isArray(map)) {\n const key = String(v);\n if (Object.hasOwn(map, key)) {\n v = (map as Record<string, unknown>)[key];\n }\n }\n if (typeof spec.format === \"string\" && v !== undefined && v !== null && v !== \"\") {\n v = spec.format.replace(\"{}\", Array.isArray(v) ? v.join(\", \") : String(v));\n }\n return v;\n}\n\n/** What a model needs to compose a surface: the catalog, briefly. */\nexport const SURFACE_GUIDE = `A surface is a flat JSON array of components; the one with id \"root\" is drawn. Containers list their children by id.\nComponents and props (a prop may be a literal or {\"path\": \"/key/...\"} into the data):\n- Column { children: [ids] } — vertical stack (use for root); Column and Grid may also repeat one component per entry: children {\"path\", \"componentId\"}\n- Text { text, variant?: \"h3\"|\"h4\"|\"lead\"|\"body\"|\"muted\" } — \"lead\": the one opening line in the wizard's voice\n- List { children: {\"path\": \"/rows\", \"componentId\": \"<a Row id>\"} } — one Row per array entry; inside, paths without \"/\" read the entry (\"name\")\n- Row { title, subtitle?, meta?, badge?, image? }\n- DetailGrid { rows: [{ label, value }] } — label/value facts\n- Badge { label, tone?: \"default\"|\"success\"|\"warning\"|\"accent\" }\n- Grid { children: [ids], columns?: 2|3|4, min?: rem } — tiles side by side; min: the narrowest a tile gets (14 for cards, so a phone shows one)\n- Metric { label, value, caption? } — a key figure\n- Table { rows: {\"path\": \"/rows\"}, columns?: [{ key, label }] }\n- Image { src: an asset id or {\"path\": ...}, alt? }\n- BarChart / LineChart { title?, points: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n- DonutChart { title?, slices: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n (labelKey / valueKey: the columns of bound rows that hold the label and the number, e.g. \"name\", \"price\")\n- Actions { children: [Button ids] } / Button { label, action: \"regenerate\"|\"open\" }\n- Tabs { tabs: [{ label, count?, child: id }] } — two to four views of one result; count may bind a list (shows its length)\n- Card { title, eyebrow?, subtitle?, meta?: [values], image?, children?: [ids] } — one thing: a day, a recipe, an offer\n- Fold { title, open?, children: [ids] } — details that open on a tap\n- Group { children: {\"path\", \"componentId\"}, by: \"<key>\", order?: [values] } — entries under a heading per value of a key\n- Chips { items, labelKey?, flagKey?, flag? } — short things at a glance; flagKey marks some (\"bald\")\n- Checklist { items, labelKey?, detailKey?, noteKey?, noteFormat?, noteMap?, groupKey?, groupOrder?, share? } — things to get or do; ticks are kept; a yes/no note needs noteMap: {\"true\": \"da\", \"false\": \"einkaufen\"}\n- Steps { items, textKey?, minutesKey? } — ordered work, numbered, with times\n- Link { title, subtitle?, eyebrow?, meta?, look?: \"row\"|\"card\", items: {\"path\": \"/recipes\"}, key?: \"id\", value: {\"path\": \"recipe_id\"}, view: id } — opens the entry of items whose key is value in a sheet, drawn by view; title, subtitle and meta read that entry, eyebrow the row the Link sits in\n- Callout { text, title?, tone?: \"tip\"|\"note\"|\"warning\" }\nA path may put its value into words: {\"path\": \"in_fridge\", \"map\": {\"true\": \"da\", \"false\": \"einkaufen\"}}, {\"path\": \"minutes\", \"format\": \"{} Min\"}.\nDesign it like an app, not a report: lead with a headline, the key figure or the chips; one Card per thing, never a Table of things; ordered work is Steps, things to get are a Checklist, sets are grouped by their key. A Table only for figures people compare across columns.\nKeep it small: what the person needs to see first, then the details. Never invent numbers: bind them by path.`;\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { z } from \"zod\";\nimport { tableColumnsSchema } from \"./engenty/data-tables/index.js\";\nimport { readNumber } from \"./numbers.js\";\nimport { type ObjectShape, outputShapeSchema, shapeOfFields } from \"./shape.js\";\nimport { isShareTargetId } from \"./sharing.js\";\nimport { CONNECTION_KINDS } from \"./store.js\";\nimport { type SurfaceComponent, surfaceComponentsSchema, validateSurface } from \"./surface.js\";\n\n/** The engenty avatars a wizard can wear. Same cast as engenty's ui-core. */\nexport const ENGENTY_KINDS = [\n \"round\",\n \"drop\",\n \"dome\",\n \"flame\",\n \"oval\",\n \"bean\",\n \"pebble\",\n \"sprout\",\n \"tower\",\n \"wedge\",\n] as const;\nexport type EngentyKind = (typeof ENGENTY_KINDS)[number];\n\n/** The Halloween costumes a wizard's engenty can wear. Same list as the web app's engenty figures. */\nexport const ENGENTY_COSTUMES = [\"witch\", \"devil\", \"bat\", \"pumpkin\"] as const;\n\n/** A theme's id: `halloween`, or `@owner/halloween` for a theme from the catalog (theme.ts). */\nexport const THEME_ID = /^(@[a-z0-9-]{1,39}\\/)?[a-z0-9][a-z0-9-]{0,47}$/;\nexport type EngentyCostume = (typeof ENGENTY_COSTUMES)[number];\n\n// --- languages -------------------------------------------------------------------------------\n\n/**\n * The languages engenty speaks: the studio, the runner, the mails, a wizard's own words. A\n * language joins once its strings are written; English is the one every string has, and what a\n * language still lacks is said in English.\n */\nexport const LANGS = [\"en\", \"de\"] as const;\nexport type Lang = (typeof LANGS)[number];\n\n/** Each language's name, in that language: what a switch or a menu shows. */\nexport const LANG_NAMES: Record<Lang, string> = { en: \"English\", de: \"Deutsch\" };\n\n/** The locale amounts and dates are written in for a language. */\nexport const LOCALES: Record<Lang, string> = { en: \"en-GB\", de: \"de-DE\" };\n\n/** The locale speech is heard and spoken in for a language (recognition, voices). */\nexport const SPEECH_LOCALES: Record<Lang, string> = { en: \"en-US\", de: \"de-DE\" };\n\nexport function isLang(value: unknown): value is Lang {\n return typeof value === \"string\" && (LANGS as readonly string[]).includes(value);\n}\n\n/** The language of a tag such as \"de-AT\", \"fr\" or \"pt_BR\", where engenty speaks it. */\nexport function langOf(tag: string | null | undefined): Lang | null {\n const code = tag?.trim().toLowerCase().split(/[-_]/)[0];\n return isLang(code) ? code : null;\n}\n\n/**\n * The main language of each European country. It holds languages engenty does not speak yet:\n * `langOf` passes over them until they join `LANGS`.\n */\nconst COUNTRY_LANGUAGE: Record<string, string> = {\n AT: \"de\",\n BE: \"nl\",\n BG: \"bg\",\n CH: \"de\",\n CY: \"el\",\n CZ: \"cs\",\n DE: \"de\",\n DK: \"da\",\n EE: \"et\",\n ES: \"es\",\n FI: \"fi\",\n FR: \"fr\",\n GB: \"en\",\n GR: \"el\",\n HR: \"hr\",\n HU: \"hu\",\n IE: \"en\",\n IS: \"is\",\n IT: \"it\",\n LI: \"de\",\n LT: \"lt\",\n LU: \"fr\",\n LV: \"lv\",\n MC: \"fr\",\n MT: \"en\",\n NL: \"nl\",\n NO: \"nb\",\n PL: \"pl\",\n PT: \"pt\",\n RO: \"ro\",\n RS: \"sr\",\n SE: \"sv\",\n SI: \"sl\",\n SK: \"sk\",\n SM: \"it\",\n UA: \"uk\",\n VA: \"it\",\n};\n\n/**\n * The languages a wizard is offered in when its author picks one: English, German and the main\n * languages of Europe. A wizard may name any other real language by its code as well.\n */\nexport const WIZARD_LANGS: readonly string[] = [\n ...new Set([\"en\", \"de\", ...Object.values(COUNTRY_LANGUAGE)]),\n];\n\n/** The country of each European time zone (IANA names, as `Intl` gives them). */\nconst ZONE_COUNTRY: Record<string, string> = {\n \"Europe/Amsterdam\": \"NL\",\n \"Europe/Athens\": \"GR\",\n \"Europe/Belgrade\": \"RS\",\n \"Europe/Berlin\": \"DE\",\n \"Europe/Bratislava\": \"SK\",\n \"Europe/Brussels\": \"BE\",\n \"Europe/Bucharest\": \"RO\",\n \"Europe/Budapest\": \"HU\",\n \"Europe/Busingen\": \"DE\",\n \"Europe/Copenhagen\": \"DK\",\n \"Europe/Dublin\": \"IE\",\n \"Europe/Helsinki\": \"FI\",\n \"Europe/Kiev\": \"UA\",\n \"Europe/Kyiv\": \"UA\",\n \"Europe/Lisbon\": \"PT\",\n \"Europe/Ljubljana\": \"SI\",\n \"Europe/London\": \"GB\",\n \"Europe/Luxembourg\": \"LU\",\n \"Europe/Madrid\": \"ES\",\n \"Europe/Malta\": \"MT\",\n \"Europe/Monaco\": \"MC\",\n \"Europe/Oslo\": \"NO\",\n \"Europe/Paris\": \"FR\",\n \"Europe/Prague\": \"CZ\",\n \"Europe/Riga\": \"LV\",\n \"Europe/Rome\": \"IT\",\n \"Europe/San_Marino\": \"SM\",\n \"Europe/Sofia\": \"BG\",\n \"Europe/Stockholm\": \"SE\",\n \"Europe/Tallinn\": \"EE\",\n \"Europe/Vaduz\": \"LI\",\n \"Europe/Vatican\": \"VA\",\n \"Europe/Vienna\": \"AT\",\n \"Europe/Vilnius\": \"LT\",\n \"Europe/Warsaw\": \"PL\",\n \"Europe/Zagreb\": \"HR\",\n \"Europe/Zurich\": \"CH\",\n \"Atlantic/Canary\": \"ES\",\n \"Atlantic/Madeira\": \"PT\",\n \"Atlantic/Reykjavik\": \"IS\",\n \"Asia/Nicosia\": \"CY\",\n};\n\n/**\n * The person's own language beside English: the first of their languages (the browser's, in\n * its order) that engenty speaks, else the main language of the country their time zone lies\n * in; null where neither names one.\n */\nexport function localLang(languages: readonly string[], timeZone?: string | null): Lang | null {\n for (const tag of languages) {\n const found = langOf(tag);\n if (found && found !== \"en\") {\n return found;\n }\n }\n const country = timeZone ? ZONE_COUNTRY[timeZone] : undefined;\n const found = country ? langOf(COUNTRY_LANGUAGE[country]) : null;\n return found === \"en\" ? null : found;\n}\n\n/**\n * A language a wizard can be translated into: any language, by its two- or three-letter code\n * (\"fr\", \"it\", \"pl\"), not only those of `LANGS`.\n */\nexport const LANG_CODE = /^[a-z]{2,3}$/;\n\n/** The code of a tag such as \"fr-CA\" or \"pt_BR\"; null where it names no language. */\nexport function langCodeOf(tag: string | null | undefined): string | null {\n const code = tag?.trim().toLowerCase().split(/[-_]/)[0] ?? \"\";\n return LANG_CODE.test(code) ? code : null;\n}\n\n/**\n * A real language, as the platform's own language data knows it: \"it\" and \"nb\" are, \"xx\" is\n * not. The schema only checks the shape of a code; this checks that it names a language.\n */\nexport function isRealLanguage(code: string): boolean {\n if (!LANG_CODE.test(code)) {\n return false;\n }\n try {\n return Boolean(new Intl.DisplayNames([\"en\"], { type: \"language\", fallback: \"none\" }).of(code));\n } catch {\n return false;\n }\n}\n\n/** The language engenty's own strings are read in for any language: itself where they are written, else English. */\nexport function textLang(code: string): Lang {\n return isLang(code) ? code : \"en\";\n}\n\n/**\n * The language the person reads, for a wizard translated on request: the first of their\n * languages (the browser's, in its order), else the main language of the country their time\n * zone lies in. Any language, not only one engenty's own strings are written in.\n */\nexport function viewerLang(languages: readonly string[], timeZone?: string | null): string | null {\n for (const tag of languages) {\n const code = langCodeOf(tag);\n if (code) {\n return code;\n }\n }\n const country = timeZone ? ZONE_COUNTRY[timeZone] : undefined;\n return country ? langCodeOf(COUNTRY_LANGUAGE[country]) : null;\n}\n\n/** A language's name in that language, as a switch shows it: \"Italiano\", \"Polski\". */\nexport function langName(code: string): string {\n if (isLang(code)) {\n return LANG_NAMES[code];\n }\n try {\n const name = new Intl.DisplayNames([code], { type: \"language\" }).of(code) ?? code;\n return name.charAt(0).toLocaleUpperCase(code) + name.slice(1);\n } catch {\n return code.toUpperCase();\n }\n}\n\n/** A language's name in English, for a model told what to write in: \"Italian\". */\nexport function langNameEn(code: string): string {\n try {\n return new Intl.DisplayNames([\"en\"], { type: \"language\" }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/** The locale amounts, dates and plural forms are written in for any language. */\nexport function localeOf(code: string): string {\n return isLang(code) ? LOCALES[code] : code;\n}\n\n/** The locale speech is recognised and read aloud in for any language. */\nexport function speechLocaleOf(code: string): string {\n return isLang(code) ? SPEECH_LOCALES[code] : code;\n}\n\nexport const FIELD_KINDS = [\n \"text\",\n \"textarea\",\n \"number\",\n \"select\",\n \"multiselect\",\n \"date\",\n \"email\",\n \"url\",\n \"toggle\",\n \"color\",\n \"image\",\n \"file\",\n \"items\",\n \"connection\",\n \"list\",\n \"location\",\n \"audio\",\n \"signature\",\n \"slot\",\n] as const;\nexport type FieldKind = (typeof FIELD_KINDS)[number];\n\n/**\n * How a field is answered without the page's form: `typed` as text, `tapped` from its choices,\n * `value` as a plain value (a colour, line items, a place), `device` only with the person's\n * device or account (a file, a recording, a signature, a connection, a kept list). The chat\n * types and taps; an AI client over MCP gives every way but `device`.\n */\nexport type FieldWay = \"typed\" | \"tapped\" | \"value\" | \"device\";\n\nexport const FIELD_WAYS: Record<FieldKind, FieldWay> = {\n text: \"typed\",\n textarea: \"typed\",\n number: \"typed\",\n date: \"typed\",\n email: \"typed\",\n url: \"typed\",\n select: \"tapped\",\n multiselect: \"tapped\",\n slot: \"tapped\",\n toggle: \"tapped\",\n color: \"value\",\n items: \"value\",\n location: \"value\",\n image: \"device\",\n file: \"device\",\n audio: \"device\",\n signature: \"device\",\n connection: \"device\",\n list: \"device\",\n};\n\n/**\n * What a `location` field holds: where the person stands (from the device), a place they typed,\n * or both — the label is then the address of the position.\n */\nexport interface LocationValue {\n lat?: number;\n lng?: number;\n /** Radius in metres the device vouches for. */\n accuracy?: number;\n label?: string;\n}\n\n/** What an `audio` field holds: the recording, and what is said in it once it was listened to. */\nexport interface AudioValue {\n /** Upload id of the recording. */\n asset: string;\n seconds?: number;\n transcript?: string;\n /** The language the runner was in when the note was taken: what it is most likely spoken in. */\n lang?: Lang;\n}\n\nexport function isLocationValue(v: unknown): v is LocationValue {\n if (!v || typeof v !== \"object\" || Array.isArray(v)) {\n return false;\n }\n const { lat, lng, label } = v as LocationValue;\n return (\n (typeof lat === \"number\" && typeof lng === \"number\") ||\n (typeof label === \"string\" && label.trim().length > 0)\n );\n}\n\nexport function isAudioValue(v: unknown): v is AudioValue {\n return Boolean(\n v &&\n typeof v === \"object\" &&\n typeof (v as AudioValue).asset === \"string\" &&\n (v as AudioValue).asset,\n );\n}\n\n/** A position the way a person reads it: \"Hauptplatz 1, Graz (47.07071, 15.43950, ±12 m)\". */\nexport function locationText(v: LocationValue): string {\n const point =\n typeof v.lat === \"number\" && typeof v.lng === \"number\"\n ? `${v.lat.toFixed(5)}, ${v.lng.toFixed(5)}${v.accuracy ? `, ±${Math.round(v.accuracy)} m` : \"\"}`\n : \"\";\n const label = v.label?.trim() ?? \"\";\n return label && point ? `${label} (${point})` : label || point;\n}\n\n/** A field takes at most this many files. */\nexport const MAX_FILES = 30;\n\nexport const TOOL_IDS = [\n \"web_search\",\n \"web_fetch\",\n \"browser\",\n \"sandbox\",\n \"image\",\n \"http\",\n \"pages\",\n \"code\",\n] as const;\n\n/**\n * A tool a plugin of the runtime adds: `<plugin id>.<tool name>`. A wizard that names one runs\n * only where that plugin is installed.\n */\nexport const PLUGIN_ID = /^[a-z][a-z0-9-]{0,39}$/;\nexport const PLUGIN_TOOL_NAME = /^[a-z][a-z0-9_]{0,39}$/;\nexport type PluginToolId = `${string}.${string}`;\n\n/** The plugin and the tool a step's tool id names, or null for one of the built-in tools. */\nexport function pluginToolOf(id: string): { plugin: string; tool: string } | null {\n const [plugin, tool, ...rest] = id.split(\".\");\n return tool !== undefined &&\n rest.length === 0 &&\n PLUGIN_ID.test(plugin) &&\n PLUGIN_TOOL_NAME.test(tool)\n ? { plugin, tool }\n : null;\n}\n\n/**\n * The kinds of model a step can ask for. A step names a class; which model serves it is bound\n * outside the wizard (the model-gateway, or the settings of a runtime that runs alone).\n */\nexport const TEXT_CLASSES = [\"classifier\", \"standard\", \"high\", \"highest\"] as const;\nexport type TextClass = (typeof TEXT_CLASSES)[number];\nexport const MODEL_CLASSES = [...TEXT_CLASSES, \"image\", \"video\", \"audio\", \"speech\"] as const;\nexport type ModelClass = (typeof MODEL_CLASSES)[number];\n/** How hard the model should think, where the bound model can be told. */\nexport const EFFORTS = [\"low\", \"medium\", \"high\"] as const;\nexport type Effort = (typeof EFFORTS)[number];\nexport type ToolId = (typeof TOOL_IDS)[number];\n\nexport const ASSET_KINDS = [\"image\", \"video\", \"voice\", \"document\", \"dashboard\"] as const;\nexport type AssetKind = (typeof ASSET_KINDS)[number];\n\nexport const FORMATS = [\n \"png\",\n \"mp4\",\n \"mp3\",\n \"pdf\",\n \"docx\",\n \"html\",\n \"md\",\n \"txt\",\n \"csv\",\n \"xlsx\",\n \"json\",\n \"zip\",\n] as const;\nexport type Format = (typeof FORMATS)[number];\n\nexport const ASPECT_RATIOS = [\"1:1\", \"16:9\", \"9:16\", \"4:5\", \"3:2\", \"2:3\"] as const;\n\n/** What a video model renders at: 720p unless the step asks for less. Never more. */\nexport const VIDEO_RESOLUTIONS = [\"720p\", \"480p\"] as const;\nexport type VideoResolution = (typeof VIDEO_RESOLUTIONS)[number];\n\nconst id = z\n .string()\n .regex(/^[a-zA-Z][a-zA-Z0-9_]{0,40}$/, \"ids are letters, digits and _ and start with a letter\");\n\nexport const itemColumnSchema = z.object({\n id,\n label: z.string().min(1),\n kind: z.enum([\"text\", \"number\", \"money\"]),\n});\n\nexport const CONDITION_OPS = [\n \"equals\",\n \"notEquals\",\n \"in\",\n \"notEmpty\",\n \"empty\",\n \"gt\",\n \"lt\",\n \"contains\",\n] as const;\nexport type ConditionOp = (typeof CONDITION_OPS)[number];\n\n/**\n * One test on what the run knows: an answer by field id, an output of an agent step as\n * \"steps.<step>.<field>\", or how many rows a stored list has as \"lists.<list>.count\".\n */\nexport const conditionSchema = z.object({\n field: z.string(),\n op: z.enum(CONDITION_OPS),\n value: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]).optional(),\n});\nexport type Condition = z.infer<typeof conditionSchema>;\n\n/** One condition, or several that must all hold. */\nexport const whenSchema = z.union([conditionSchema, z.array(conditionSchema).min(1)]);\nexport type When = z.infer<typeof whenSchema>;\n\n/** What a card of a choice shows: the columns of the table the choices come from. */\nexport const cardsSchema = z.object({\n label: z.string().min(1),\n value: z.string().optional(),\n image: z.string().optional(),\n subtitle: z.string().optional(),\n meta: z.string().optional(),\n link: z.string().optional(),\n});\nexport type CardsDef = z.infer<typeof cardsSchema>;\n\n/** A choice drawn as a card, as the runner gets it. */\nexport interface CardOption {\n value: string;\n label: string;\n image?: string;\n subtitle?: string;\n meta?: string;\n link?: string;\n}\n\nexport const fieldSchema = z.object({\n id,\n label: z.string().min(1),\n kind: z.enum(FIELD_KINDS),\n required: z.boolean().optional(),\n placeholder: z.string().optional(),\n help: z.string().optional(),\n /**\n * Choices for select / multiselect. slot: the appointment times offered, as ISO 8601 date-times\n * with their offset (\"2026-10-12T09:00:00+02:00\").\n */\n options: z.array(z.string()).optional(),\n default: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]).optional(),\n /** Line-item columns for `items`. A row's amount is the product of its number and money columns. */\n columns: z.array(itemColumnSchema).optional(),\n /** VAT for `items`: a fixed rate in percent, or the id of a number/select field holding it. */\n vat: z.object({ rate: z.number().optional(), field: z.string().optional() }).optional(),\n currency: z.string().optional(),\n /** image / file: several files; the value is then a list, in the order the person put them. */\n multiple: z.boolean().optional(),\n /** image / file with `multiple`: how many files at least and at most (up to 30). */\n min: z.number().int().min(1).max(MAX_FILES).optional(),\n max: z.number().int().min(1).max(MAX_FILES).optional(),\n /** file: also offer the camera, for documents the person only has on paper. Images always offer it. */\n camera: z.boolean().optional(),\n /** file: the camera also records short video clips. */\n video: z.boolean().optional(),\n /**\n * file: a recording (video or audio) is listened to before the next step runs — what is said,\n * piece by piece between pauses, with exact times. Read as {{field.speech}}.\n */\n listen: z.boolean().optional(),\n /** text: also fill it by scanning a QR code or barcode with the camera. */\n scan: z.boolean().optional(),\n /** connection: id of the wizard connection the person connects here. */\n connection: z.string().optional(),\n /** list: id of the wizard list shown here for the person to check and correct. */\n list: z.string().optional(),\n /**\n * What the field starts with, from an earlier step: \"steps.<id>\" or \"steps.<id>.<key>\". An\n * `items` field takes a table whose columns are its column ids; the person corrects it.\n */\n prefill: z.string().optional(),\n /**\n * The field is shown only while this holds. It reads an answer of this page (decided as the\n * person types) or anything known before the page. A hidden field is not asked and not kept.\n */\n when: whenSchema.optional(),\n /**\n * select / multiselect / slot: the choices come from earlier data — a list output\n * (\"steps.<id>.<key>\"), a column of a table output (\"steps.<id>.<key>.<column>\") or a column\n * of a stored list (\"lists.<id>.<column>\"). `options` stand in while that data is empty.\n */\n optionsFrom: z.string().optional(),\n /**\n * select / multiselect with `optionsFrom` naming a table output (\"steps.<id>.<key>\"): each row\n * is a choice drawn as a card. The columns that hold what the card shows; `value` (default:\n * `label`) is what the answer holds, `link` a page the card opens.\n */\n cards: cardsSchema.optional(),\n /**\n * The field is shown when a decision, made as the run reaches the page, finds this statement\n * true of the run (\"The complaint is about a damaged article\").\n */\n ask: z.string().min(1).optional(),\n /** The id of one of the page's `groups`: of a group's fields a decision shows one (or none). */\n group: z.string().optional(),\n});\nexport type Field = z.infer<typeof fieldSchema>;\n\nexport const fieldGroupSchema = z.object({\n id,\n /** What the decision picks: \"How should we reach the person?\" */\n instructions: z.string().min(1),\n /** True when showing none of the group's fields is a valid answer. */\n optional: z.boolean().optional(),\n});\n\nexport const nextRuleSchema = z\n .object({\n /** The rule holds when this holds … */\n when: whenSchema.optional(),\n /**\n * … or, instead, when a decision finds this statement true of the run (\"The person wants a\n * refund\"). All `ask` rules of a step are decided together, after no `when` rule matched.\n */\n ask: z.string().min(1).optional(),\n /**\n * A step id, or \"end\". A rule with neither `when` nor `ask` is the step's \"otherwise\": where\n * the run goes when no other rule holds, in place of the next step in the list.\n */\n goto: z.string(),\n /**\n * How often this rule may send the run on in one run; afterwards it is skipped. Meant for a\n * branch back to an earlier step (a loop), which without it is taken at most ten times.\n */\n max: z.number().int().min(1).max(50).optional(),\n })\n .refine((rule) => rule.when === undefined || rule.ask === undefined, {\n message: 'A branch has \"when\" or \"ask\", not both.',\n });\nexport type NextRule = z.infer<typeof nextRuleSchema>;\n\nconst stepBase = {\n id,\n title: z.string().min(1),\n description: z.string().optional(),\n next: z.array(nextRuleSchema).optional(),\n};\n\nexport const outputFieldSchema = z\n .object({\n id,\n kind: z.enum([\"text\", \"number\", \"list\", \"table\", \"yesno\", \"choice\", \"score\"]),\n /** What the field holds; for `yesno`, `choice` and `score` the question it answers. */\n description: z.string().optional(),\n /** Table only: the exact column keys every row has — what a widget reads. */\n columns: z.array(z.string().min(1)).optional(),\n /** Choice: the options, one of which is the answer. Score: the levels, lowest first. */\n options: z.array(z.string().min(1)).min(2).max(40).optional(),\n })\n .refine(\n (field) =>\n (field.kind !== \"choice\" && field.kind !== \"score\") || Boolean(field.options?.length),\n { message: \"A choice or score field lists its options.\", path: [\"options\"] },\n )\n .refine((field) => field.kind !== \"score\" || (field.options?.length ?? 0) <= 10, {\n message: \"A score has at most ten levels.\",\n path: [\"options\"],\n });\n\nexport const pageStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"page\"),\n fields: z.array(fieldSchema).min(1),\n /** Fields of which a decision shows one: see `group` on a field. */\n groups: z.array(fieldGroupSchema).max(6).optional(),\n cta: z.string().optional(),\n});\n\n/** A plugin's tool as a step names it: `<plugin>.<tool>`. */\nconst pluginToolIdSchema = z.templateLiteral([\n z.string().regex(PLUGIN_ID),\n \".\",\n z.string().regex(PLUGIN_TOOL_NAME),\n]);\n\nexport const agentStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"agent\"),\n /** What the agent does. A template: {{field}}, {{steps.id}}, {{brand.name}}. Empty with `call`. */\n instructions: z.string().default(\"\"),\n /**\n * One tool of a plugin, called once with these inputs and no model: its answer is the step's\n * json output, as it is. For data a later page shows unchanged (free appointment times), where\n * a model would only copy it. String inputs are templates; a filled-in whole number or\n * true/false is passed as one, an empty one is left out.\n */\n call: z\n .object({\n tool: pluginToolIdSchema,\n input: z.record(z.string(), z.unknown()).default({}),\n })\n .optional(),\n tools: z.array(z.union([z.enum(TOOL_IDS), pluginToolIdSchema])).default([]),\n /** Ids of project MCP servers this step may use. */\n mcp: z.array(z.string()).optional(),\n /** Ids of wizard connections (the person's accounts) this step may use. */\n connections: z.array(z.string()).optional(),\n output: z\n .object({\n format: z.enum([\"text\", \"markdown\", \"json\"]),\n /** The short form: one level of keys. A step has `fields` or `schema`, not both. */\n fields: z.array(outputFieldSchema).optional(),\n /**\n * json only: nested data (lists of entries with lists of their own), in the kinds of\n * `shape.ts`. Objects nest at most four deep, a hundred keys in all.\n */\n schema: outputShapeSchema.optional(),\n /**\n * json only: a view of the result from the surface catalog, bound to the step's own fields;\n * reviews and the result show it instead of a plain table. Components: written once, the\n * same every run, nothing to pay. `true`: a model composes one each run.\n */\n surface: z.union([z.boolean(), surfaceComponentsSchema]).optional(),\n })\n .default({ format: \"markdown\" }),\n /** The kind of model the step needs; default `high`. The model itself is bound elsewhere. */\n model: z.enum(TEXT_CLASSES).optional(),\n effort: z.enum(EFFORTS).optional(),\n /** Shown to the person while it works. */\n /**\n * One run of the step per entry, at most twenty: the rows of a table output\n * (\"steps.<id>.<key>\"), the entries of a list output, or the rows of a stored list\n * (\"lists.<id>\"). The instructions read the entry as {{item.<column>}}, {{index}}, {{count}}.\n * The output is a table: the entry's columns and the step's output fields, one row per entry.\n */\n each: z.string().optional(),\n working: z.string().optional(),\n});\n\nexport const generateStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"generate\"),\n asset: z.enum(ASSET_KINDS),\n /** For image/video the visual prompt; for document/dashboard the brief. A template. */\n prompt: z.string().min(1),\n options: z\n .object({\n aspectRatio: z.enum(ASPECT_RATIOS).optional(),\n /** Video length in seconds. */\n duration: z.number().optional(),\n /** Video: the height the model renders at; default 720p, the most there is. */\n resolution: z.enum(VIDEO_RESOLUTIONS).optional(),\n style: z.string().optional(),\n /** Document flavour, steers the layout. */\n template: z.enum([\"invoice\", \"offer\", \"briefing\", \"letter\", \"report\", \"free\"]).optional(),\n })\n .optional(),\n /**\n * The image the image/video model starts from: an earlier image field, or an earlier step\n * that made images.\n */\n referenceImage: z.string().optional(),\n /**\n * Image / video: one result per entry instead of one. Names an image field with several\n * uploads, an earlier step that made several images, or a table of an earlier agent step\n * (\"steps.<id>.<key>\"). The prompt reads the entry as {{item.<column>}}, {{index}}, {{count}};\n * `referenceImage` gives each entry its own image when it holds as many.\n */\n each: z.string().optional(),\n /** For document/dashboard: the kind of model that writes it; default `high`. */\n model: z.enum(TEXT_CLASSES).optional(),\n effort: z.enum(EFFORTS).optional(),\n working: z.string().optional(),\n});\n\nexport const widgetStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"widget\"),\n /** Workspace path of the widget's HTML. Written once; every run only brings new data. */\n entry: z.string().min(1),\n /** What the widget gets as `wizard.data`: key → a field id, steps.id, steps.id.key, brand.name or today. */\n data: z.record(z.string(), z.string()).default({}),\n /** Workspace path of example data (JSON) for previews before any run. */\n sample: z.string().optional(),\n /**\n * How the run shows it: `fixed` (default) at `size`, scaled to the page; `page` as a part of\n * the page, as wide as it and as tall as its content — a result people scroll and use, not a\n * picture. PNG/PDF/MP4 still render at `size`.\n */\n layout: z.enum([\"fixed\", \"page\"]).optional(),\n /** The size the widget is designed for; previews scale it, PNG/PDF/MP4 render at it. */\n size: z\n .object({\n width: z.number().int().min(200).max(3840),\n height: z.number().int().min(200).max(3840),\n })\n .optional(),\n /**\n * The result is a film: the timeline is rendered to an MP4 with sound when the step runs,\n * and that video is what the person sees and downloads.\n */\n video: z.boolean().optional(),\n working: z.string().optional(),\n});\n\n/** Formats a film step makes; the composition is drawn for this frame. */\nexport const FILM_FORMATS = [\"16:9\", \"9:16\", \"1:1\"] as const;\nexport type FilmFormat = (typeof FILM_FORMATS)[number];\n\nexport const FILM_SIZES: Record<FilmFormat, { width: number; height: number }> = {\n \"16:9\": { width: 1920, height: 1080 },\n \"9:16\": { width: 1080, height: 1920 },\n \"1:1\": { width: 1080, height: 1080 },\n};\n\n/**\n * A film the AI client installed on this machine makes in a folder of its own: it writes the\n * composition as code (HTML, CSS, JS) with the skills it is given, looks at its frames and fixes\n * them; the runtime renders the MP4. It runs on the person's subscription, never on credits.\n */\nexport const filmStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"film\"),\n /** What the film is: story, look, what to use. A template. */\n brief: z.string().min(1),\n /**\n * Skill packages the client reads: platform packages (\"hyperframes\") or a folder of the\n * workspace with a SKILL.md (\"skills/<name>\").\n */\n skills: z.array(z.string().min(1)).max(12).default([\"hyperframes\"]),\n /**\n * A style kit in the workspace — a showreel made once with its rules, helpers and stills, as\n * a .zip — unpacked as `showcase/`: the bar every film of this wizard is made to.\n */\n kit: z.string().optional(),\n /**\n * What the film is made from: name → a field id or \"steps.<id>\". Files (uploads, voice lines,\n * pictures) are copied into `input/<name>/`, text is written to `input/<name>.md`.\n */\n inputs: z.record(z.string(), z.string()).default({}),\n format: z.enum(FILM_FORMATS).default(\"16:9\"),\n /**\n * \"steps.<id>\" of an earlier film step: this film starts from that one's finished code and\n * lays it out for its own format — scenes, timing and sound stay. Made from scratch when that\n * step did not run.\n */\n from: z.string().optional(),\n /** About how long the film runs, in seconds. */\n seconds: z.number().int().min(3).max(600).optional(),\n /** The kind of model; default `standard` — the kit carries the craft. */\n model: z.enum(TEXT_CLASSES).optional(),\n effort: z.enum(EFFORTS).optional(),\n working: z.string().optional(),\n});\n\n/** A piece a decided surface may show: its components (the first has the piece's id) and what it shows. */\nexport const surfaceCandidateSchema = z.object({\n id,\n /** What this piece shows, for the decision: \"A chart of prices per supplier\". */\n description: z.string().min(1),\n components: surfaceComponentsSchema,\n /** Pieces of a group exclude each other: the decision shows one (or none, if optional). */\n group: z.string().optional(),\n /** Always shown: a title, the main list. */\n required: z.boolean().optional(),\n});\n\nexport const surfaceStepSchema = z\n .object({\n ...stepBase,\n type: z.literal(\"surface\"),\n /** A view from the surface catalog, written once like a widget; every run brings new data. */\n components: surfaceComponentsSchema.optional(),\n /**\n * Instead of `components`: pieces a decision picks from per run (no chart when there is\n * nothing to chart), drawn in this order under one column.\n */\n candidates: z.array(surfaceCandidateSchema).max(16).optional(),\n groups: z.array(fieldGroupSchema).max(6).optional(),\n /** What the surface reads as data: key → a field id, steps.id, steps.id.key, lists.id, brand.name or today. */\n data: z.record(z.string(), z.string()).default({}),\n working: z.string().optional(),\n })\n .refine((step) => Boolean(step.components) !== Boolean(step.candidates), {\n message: 'A surface step has either \"components\" or \"candidates\".',\n });\n\n/**\n * The components of a decided surface for the pieces kept: one root column holding them in\n * their order. Every piece kept is the same as all of them for the validator.\n */\nexport function assembleSurface(\n candidates: { id: string; components: SurfaceComponent[] }[],\n kept: Iterable<string>,\n): SurfaceComponent[] {\n const keep = new Set(kept);\n const chosen = candidates.filter((c) => keep.has(c.id));\n return [\n { id: \"root\", component: \"Column\", children: chosen.map((c) => c.components[0]?.id ?? c.id) },\n ...chosen.flatMap((c) => c.components),\n ];\n}\n\nexport const reviewStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"review\"),\n /** Step ids whose output is shown. */\n show: z.array(z.string()).min(1),\n edit: z.boolean().optional(),\n regenerate: z.boolean().optional(),\n});\n\nexport const deliverableSchema = z.object({\n from: z.string(),\n label: z.string().optional(),\n formats: z.array(z.enum(FORMATS)).min(1),\n});\n\n/** One share target the result offers, with what its form starts with. */\nexport const shareOptionSchema = z.object({\n /** \"email\", \"slack\", \"browser\", \"storage:<connector>\" or \"connector:<connector>\". */\n target: z.string().min(1),\n /** How the result names it, e.g. \"Auf LinkedIn posten\". Default: the target's own name. */\n label: z.string().optional(),\n /** Prefills the target's form by field id. Templates: {{field}}, {{steps.id}}, {{brand.name}}. */\n values: z.record(z.string(), z.string()).optional(),\n});\nexport type ShareOption = z.infer<typeof shareOptionSchema>;\n\nexport const resultStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"result\"),\n message: z.string().optional(),\n deliverables: z.array(deliverableSchema),\n /**\n * Where the person can send or publish the result besides the link and the downloads. Left\n * out: the targets that need no model. An empty list: none.\n */\n share: z.array(shareOptionSchema).max(12).optional(),\n});\n\nexport const stepSchema = z.discriminatedUnion(\"type\", [\n pageStepSchema,\n agentStepSchema,\n generateStepSchema,\n widgetStepSchema,\n surfaceStepSchema,\n filmStepSchema,\n reviewStepSchema,\n resultStepSchema,\n]);\nexport type Step = z.infer<typeof stepSchema>;\nexport type PageStep = z.infer<typeof pageStepSchema>;\nexport type SurfaceStep = z.infer<typeof surfaceStepSchema>;\nexport type AgentStep = z.infer<typeof agentStepSchema>;\n\n/**\n * A decision: a step on the classifier class that uses no tools and whose output is only\n * yes/no and choice fields. It is answered in one call, which a model that only decides\n * (no text) can take.\n */\nexport function isDecisionStep(step: AgentStep): boolean {\n const fields = step.output.fields ?? [];\n return (\n !step.call &&\n !step.output.schema &&\n step.model === \"classifier\" &&\n step.output.format === \"json\" &&\n fields.length > 0 &&\n fields.every((f) => f.kind === \"yesno\" || f.kind === \"choice\" || f.kind === \"score\") &&\n !step.each &&\n step.tools.length === 0 &&\n !step.mcp?.length &&\n !step.connections?.length\n );\n}\n\n/**\n * What an agent step's json output holds: its schema, or its fields as one. Undefined when it\n * names neither (the model then returns one table).\n */\nexport function declaredShape(step: AgentStep): ObjectShape | undefined {\n if (step.output.schema) {\n return step.output.schema;\n }\n return step.output.fields?.length ? shapeOfFields(step.output.fields) : undefined;\n}\n\n/** What an agent step's json output holds: its declared shape, or else one table. */\nexport function stepShape(step: AgentStep): ObjectShape {\n return (\n declaredShape(step) ?? {\n kind: \"object\",\n fields: { data: { kind: \"table\", description: \"The result as a table\" } },\n }\n );\n}\n\n/** The top-level keys of an agent step's output: what `steps.<id>.<key>` may name. */\nexport function outputKeys(step: AgentStep): string[] {\n return Object.keys(declaredShape(step)?.fields ?? {});\n}\nexport type GenerateStep = z.infer<typeof generateStepSchema>;\nexport type WidgetStep = z.infer<typeof widgetStepSchema>;\nexport type FilmStep = z.infer<typeof filmStepSchema>;\nexport type ReviewStep = z.infer<typeof reviewStepSchema>;\nexport type ResultStep = z.infer<typeof resultStepSchema>;\nexport type StepType = Step[\"type\"];\n\nexport const listSchema = z.object({\n id,\n title: z.string().min(1),\n description: z.string().optional(),\n /** engenty data-table columns: `{ id, name, type, format }`. */\n columns: tableColumnsSchema,\n /** Column that identifies a row; saving a row with a known key updates it. */\n key: z.string().optional(),\n /**\n * The person goes through the rows one by one in a review: `file` is the column holding the\n * path of a kept file, shown beside the row; `status` a select column whose options are the\n * answers — the first one means \"not looked at yet\".\n */\n check: z.object({ file: z.string().optional(), status: z.string().optional() }).optional(),\n /**\n * The list is the wizard's, not one person's: every run reads and writes the same rows, and\n * the studio shows it under Space → Data. It is never shown to the person running the wizard,\n * who would see what others gave.\n */\n shared: z.boolean().optional(),\n});\n\nexport const connectionSchema = z.object({\n id,\n /** A built-in kind of account … */\n kind: z.enum(CONNECTION_KINDS).optional(),\n /** … or the id of one of the project's imported connectors. */\n connector: z.string().optional(),\n /** Imported connectors: the actions steps may call. Default: every action that only reads. */\n actions: z.array(z.string()).max(200).optional(),\n /** Imported connectors, per action: \"allow\" runs it without asking, \"ask\" asks the person first. */\n policy: z.record(z.string(), z.enum([\"allow\", \"ask\"])).optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n});\n\n/** The version of the definition this app writes and reads; raised only by a breaking change. */\nexport const DEFINITION_VERSION = 1 as const;\n\nexport const wizardSchema = z.object({\n version: z.literal(DEFINITION_VERSION).default(DEFINITION_VERSION),\n title: z.string().min(1),\n description: z.string().default(\"\"),\n avatar: z.enum(ENGENTY_KINDS).default(\"round\"),\n /** A costume the avatar wears; none without one. */\n costume: z.enum(ENGENTY_COSTUMES).optional(),\n /** Shown on the first page above the first question. */\n intro: z.string().optional(),\n /**\n * The language the wizard speaks to people: its texts, the runner's words, its numbers and\n * dates, by its two-letter code (\"en\", \"de\", \"it\"). Any language, not only those engenty's own\n * strings are written in; `validateWizard` checks it names a real one. Without one it is read\n * from the wizard's own words (`wizardLang`).\n */\n lang: z\n .string()\n .regex(/^[a-z]{2}$/)\n .optional(),\n /** Tabular data the wizard keeps between runs, per person — or for all runs (`shared`). */\n lists: z.array(listSchema).max(12).optional(),\n /** Accounts the person connects; kept between runs, per person. */\n connections: z.array(connectionSchema).max(12).optional(),\n /** How the wizard's pages look, over its space's brand: colours, typefaces, effects, CSS. */\n /**\n * The themes the wizard offers, in its order: ids of the space's themes, or `brand`, `host`\n * and `default`. The place that shows the wizard picks one; its own pages take the first the\n * space has. Without any: the space's brand.\n */\n themes: z.array(z.string().regex(THEME_ID)).max(8).optional(),\n steps: z.array(stepSchema).min(1),\n});\nexport type WizardDefinition = z.infer<typeof wizardSchema>;\n\nexport const INTERACTIVE: ReadonlySet<StepType> = new Set([\"page\", \"review\", \"result\"]);\n\n/** Which formats each producing step can be downloaded in. */\nexport function formatsFor(step: Step): Format[] {\n if (step.type === \"generate\") {\n switch (step.asset) {\n case \"image\":\n return step.each ? [\"png\", \"zip\"] : [\"png\"];\n case \"video\":\n return step.each ? [\"mp4\", \"zip\"] : [\"mp4\"];\n case \"voice\":\n return [\"mp3\"];\n case \"document\":\n return [\"pdf\", \"docx\", \"html\", \"md\", \"png\"];\n case \"dashboard\":\n return [\"html\", \"pdf\", \"png\"];\n }\n }\n if (step.type === \"film\") {\n return [\"mp4\"];\n }\n if (step.type === \"widget\") {\n return step.video ? [\"mp4\", \"png\"] : [\"html\", \"png\", \"pdf\", \"mp4\", \"json\"];\n }\n if (step.type === \"surface\") {\n return [\"json\"];\n }\n if (step.type === \"agent\") {\n if (step.output.format === \"json\") {\n // Nested data reads as a document too.\n return step.output.schema\n ? [\"json\", \"csv\", \"xlsx\", \"md\", \"pdf\", \"zip\"]\n : [\"json\", \"csv\", \"xlsx\", \"md\", \"zip\"];\n }\n return [\"md\", \"txt\", \"docx\", \"pdf\", \"html\", \"zip\"];\n }\n return [];\n}\n\n/** Formats a stored list can be downloaded in; zip = the kept files its rows name, with the list. */\nexport const LIST_FORMATS: Format[] = [\"xlsx\", \"csv\", \"json\", \"md\", \"zip\"];\n\nconst LIST_REF = /^lists\\.([a-zA-Z][a-zA-Z0-9_]*)$/;\n\n/** \"lists.providers\" → \"providers\"; anything else → null. */\nexport function listRef(ref: string): string | null {\n return ref.match(LIST_REF)?.[1] ?? null;\n}\n\nexport const DEFAULT_WIDGET_SIZE = { width: 1280, height: 720 };\n\nexport function widgetSize(step: WidgetStep) {\n return step.size ?? DEFAULT_WIDGET_SIZE;\n}\n\n/** A widget data reference without braces: \"{{steps.x}}\" and \"steps.x\" mean the same. */\nexport function dataRef(raw: string): string {\n return raw\n .trim()\n .replace(/^\\{\\{\\s*/, \"\")\n .replace(/\\s*\\}\\}$/, \"\");\n}\n\nexport interface ValidationIssue {\n stepId?: string;\n message: string;\n}\n\nconst TEMPLATE_RE = /\\{\\{\\s*([^}]+?)\\s*\\}\\}/g;\n\nexport function templateRefs(template: string): string[] {\n return [...template.matchAll(TEMPLATE_RE)].map((m) => m[1]);\n}\n\n/**\n * Structural checks the schema cannot express: ids, references between steps,\n * templates naming things that exist by the time the step runs.\n */\nexport function validateWizard(def: WizardDefinition, files?: string[]): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const stepIds = new Set<string>();\n const fieldIds = new Set<string>();\n const seenSteps = new Set<string>();\n const seenFields = new Set<string>();\n const listIds = new Set<string>();\n const sharedLists = new Set<string>();\n const connectionIds = new Set<string>();\n const notShown = (id: string) =>\n `List \"${id}\" is shared: every run writes it, so the person running the wizard never sees it.`;\n\n if (def.lang && !isRealLanguage(def.lang)) {\n issues.push({\n message: `\"${def.lang}\" isn't a language code. Use a two-letter code such as \"en\", \"de\" or \"it\".`,\n });\n }\n\n if (def.themes && new Set(def.themes).size !== def.themes.length) {\n issues.push({ message: \"A theme is named twice in themes.\" });\n }\n\n for (const list of def.lists ?? []) {\n if (listIds.has(list.id)) {\n issues.push({ message: `Duplicate list id \"${list.id}\".` });\n }\n listIds.add(list.id);\n if (list.shared) {\n sharedLists.add(list.id);\n if (list.check) {\n issues.push({ message: `${notShown(list.id)} It cannot be checked row by row.` });\n }\n }\n if (list.key && !list.columns.some((c) => c.id === list.key)) {\n issues.push({ message: `List \"${list.id}\": key \"${list.key}\" is not one of its columns.` });\n }\n for (const [role, column] of Object.entries(list.check ?? {})) {\n const found = list.columns.find((c) => c.id === column);\n if (!found) {\n issues.push({\n message: `List \"${list.id}\": check.${role} \"${column}\" is not one of its columns.`,\n });\n } else if (role === \"status\" && found.type !== \"select\") {\n issues.push({ message: `List \"${list.id}\": check.status \"${column}\" must be a select.` });\n }\n }\n }\n for (const connection of def.connections ?? []) {\n if (connectionIds.has(connection.id)) {\n issues.push({ message: `Duplicate connection id \"${connection.id}\".` });\n }\n connectionIds.add(connection.id);\n if (Boolean(connection.kind) === Boolean(connection.connector)) {\n issues.push({\n message: `Connection \"${connection.id}\" needs either \"kind\" or \"connector\", not both.`,\n });\n }\n }\n\n for (const step of def.steps) {\n if (stepIds.has(step.id)) {\n issues.push({ stepId: step.id, message: `Duplicate step id \"${step.id}\".` });\n }\n stepIds.add(step.id);\n if (step.type === \"page\") {\n for (const field of step.fields) {\n if (fieldIds.has(field.id)) {\n issues.push({ stepId: step.id, message: `Duplicate field id \"${field.id}\".` });\n }\n fieldIds.add(field.id);\n if (\n (field.kind === \"select\" || field.kind === \"multiselect\" || field.kind === \"slot\") &&\n !field.options?.length &&\n !field.optionsFrom\n ) {\n issues.push({ stepId: step.id, message: `Field \"${field.id}\" needs options.` });\n }\n if (field.kind === \"slot\") {\n const wrong = (field.options ?? []).find((o) => !slotTime(o));\n if (wrong !== undefined) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"${wrong}\" is not a date and time with its offset, like \"2026-10-12T09:00:00+02:00\".`,\n });\n }\n }\n if (field.kind === \"items\" && !field.columns?.length) {\n issues.push({ stepId: step.id, message: `Field \"${field.id}\" needs columns.` });\n }\n if (field.kind === \"connection\" && !connectionIds.has(field.connection ?? \"\")) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" needs \"connection\": the id of one of the wizard's connections.`,\n });\n }\n if (field.kind === \"list\" && !listIds.has(field.list ?? \"\")) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" needs \"list\": the id of one of the wizard's lists.`,\n });\n } else if (field.kind === \"list\" && sharedLists.has(field.list ?? \"\")) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": ${notShown(field.list ?? \"\")}`,\n });\n }\n if (field.min !== undefined || field.max !== undefined) {\n if ((field.kind !== \"image\" && field.kind !== \"file\") || !field.multiple) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"min\" and \"max\" count the files of an image or file field with \"multiple\".`,\n });\n } else if (field.min !== undefined && field.max !== undefined && field.min > field.max) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": min is larger than max.`,\n });\n }\n }\n if (field.scan && field.kind !== \"text\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"scan\" fills a text field; kind is \"${field.kind}\".`,\n });\n }\n if (field.listen && field.kind !== \"file\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"listen\" belongs to a file field; kind is \"${field.kind}\".`,\n });\n }\n if (field.video && field.kind !== \"file\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"video\" belongs to a file field; kind is \"${field.kind}\".`,\n });\n }\n }\n }\n }\n\n const last = def.steps.at(-1);\n if (last?.type !== \"result\") {\n issues.push({ message: \"The last step must be a result step.\" });\n }\n\n const checkTemplate = (step: Step, template: string) => {\n for (const ref of templateRefs(template)) {\n const [head, second] = ref.split(\".\");\n if (head === \"steps\") {\n if (!second || !seenSteps.has(second)) {\n issues.push({\n stepId: step.id,\n message: `\"{{${ref}}}\" refers to a step that has not run before \"${step.id}\".`,\n });\n }\n } else if (head === \"brand\" || head === \"facts\" || head === \"today\" || head === \"notes\") {\n // provided by the runner\n } else if (head === \"item\" || head === \"index\" || head === \"count\") {\n if ((step.type !== \"generate\" && step.type !== \"agent\") || !step.each) {\n issues.push({\n stepId: step.id,\n message: `\"{{${ref}}}\" only exists in a generate or agent step with \"each\".`,\n });\n }\n } else if (head === \"lists\") {\n if (!second || !listIds.has(second)) {\n issues.push({ stepId: step.id, message: `\"{{${ref}}}\" refers to an unknown list.` });\n }\n } else if (!seenFields.has(head)) {\n issues.push({\n stepId: step.id,\n message: `\"{{${ref}}}\" refers to a field that is not asked before \"${step.id}\".`,\n });\n }\n }\n };\n\n /**\n * What a condition may read before `step`: an answer asked earlier, an output field of an\n * earlier agent step (\"steps.<step>.<field>\", the step itself for a branch), or how many rows\n * a stored list has (\"lists.<list>.count\").\n */\n const knownBefore = (step: Step, ref: string, self = false): boolean => {\n if (seenFields.has(ref)) {\n return true;\n }\n const [head, from, key, ...more] = ref.split(\".\");\n if (head === \"lists\") {\n return key === \"count\" && more.length === 0 && listIds.has(from ?? \"\");\n }\n // `steps.<step>.<field>.p`: how probable the decision's answer is.\n const probability = more.length === 1 && more[0] === \"p\";\n if (head !== \"steps\" || !key || (more.length > 0 && !probability)) {\n return false;\n }\n if (!(seenSteps.has(from) || (self && from === step.id))) {\n return false;\n }\n const source = def.steps.find((s) => s.id === from);\n return (\n source?.type === \"agent\" &&\n (!probability || isDecisionStep(source)) &&\n (outputKeys(source).includes(key) || (Boolean(source.each) && key === \"rows\" && !probability))\n );\n };\n\n const conditionIssues = (stepId: string, c: Condition): ValidationIssue[] => {\n if ((c.op === \"gt\" || c.op === \"lt\") && typeof c.value !== \"number\") {\n return [{ stepId, message: `\"${c.op}\" on \"${c.field}\" compares with a number value.` }];\n }\n if (c.op === \"in\" && !Array.isArray(c.value)) {\n return [{ stepId, message: `\"in\" on \"${c.field}\" needs a list of values.` }];\n }\n if (c.op !== \"empty\" && c.op !== \"notEmpty\" && c.value === undefined) {\n return [{ stepId, message: `\"${c.op}\" on \"${c.field}\" needs a value.` }];\n }\n return [];\n };\n\n /** Why an `optionsFrom` reference finds nothing, or null when it is fine. */\n const optionsFromProblem = (raw: string, cards?: CardsDef): string | null => {\n const [head, from, key, column, ...more] = dataRef(raw).split(\".\");\n if (head === \"lists\" && from && key && !column) {\n const list = def.lists?.find((l) => l.id === from);\n if (!list) {\n return `\"optionsFrom\" names an unknown list \"${from}\".`;\n }\n if (sharedLists.has(from)) {\n return notShown(from);\n }\n return list.columns.some((c) => c.id === key)\n ? null\n : `\"optionsFrom\": list \"${from}\" has no column \"${key}\".`;\n }\n if (head === \"steps\" && from && key && more.length === 0) {\n const source = seenSteps.has(from) ? def.steps.find((s) => s.id === from) : undefined;\n // An agent step with `each` hands on one table, `rows`: the entry's columns and its fields.\n if (source?.type === \"agent\" && source.each && key === \"rows\") {\n return column ? null : `\"optionsFrom\": \"${from}.rows\" is a table; name one of its columns.`;\n }\n const out = source?.type === \"agent\" ? declaredShape(source)?.fields[key] : undefined;\n if (!out) {\n return `\"optionsFrom\" names \"${from}.${key}\", which is not an output of an earlier agent step.`;\n }\n // The keys of a table's rows, or of a list's entries; undefined: any (free columns).\n const columns =\n out.kind === \"table\"\n ? out.columns?.length\n ? out.columns\n : undefined\n : out.kind === \"list\" && out.of.kind === \"object\"\n ? Object.keys(out.of.fields)\n : null;\n if (columns === null) {\n if (column || cards) {\n return column\n ? `\"optionsFrom\": \"${from}.${key}\" is not a table with the column \"${column}\".`\n : `\"cards\": \"${from}.${key}\" is not a table.`;\n }\n return out.kind === \"list\"\n ? null\n : `\"optionsFrom\": \"${from}.${key}\" is not a list (a table takes a column, or \"cards\").`;\n }\n if (column) {\n return !columns || columns.includes(column)\n ? null\n : `\"optionsFrom\": \"${from}.${key}\" is not a table with the column \"${column}\".`;\n }\n if (cards) {\n const missing = Object.values(cards).find((c) => columns && !columns.includes(c));\n return missing ? `\"cards\": \"${from}.${key}\" has no column \"${missing}\".` : null;\n }\n return `\"optionsFrom\": \"${from}.${key}\" is not a list (a table takes a column, or \"cards\").`;\n }\n return `\"optionsFrom\" is \"steps.<id>.<key>\", \"steps.<id>.<key>.<column>\" or \"lists.<id>.<column>\".`;\n };\n\n for (const step of def.steps) {\n switch (step.type) {\n case \"page\": {\n const groups = new Set<string>();\n for (const g of step.groups ?? []) {\n if (groups.has(g.id)) {\n issues.push({ stepId: step.id, message: `Duplicate field group \"${g.id}\".` });\n }\n groups.add(g.id);\n if (!step.fields.some((f) => f.group === g.id)) {\n issues.push({ stepId: step.id, message: `Field group \"${g.id}\" has no fields.` });\n }\n }\n const decided = step.fields.some((f) => f.ask || f.group);\n if (decided && step.fields.length > MAX_DECIDED_FIELDS) {\n issues.push({\n stepId: step.id,\n message: `A page whose fields are decided has at most ${MAX_DECIDED_FIELDS} fields.`,\n });\n }\n for (const field of step.fields) {\n if (field.ask && field.group) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" has \"ask\" or \"group\", not both.`,\n });\n }\n if (field.group && !groups.has(field.group)) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" names an unknown group \"${field.group}\".`,\n });\n }\n }\n for (const field of step.fields) {\n for (const c of conditionsOf(field.when)) {\n const own = step.fields.some((f) => f.id === c.field && f.id !== field.id);\n if (!own && !knownBefore(step, c.field)) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"when\" reads \"${c.field}\", which is neither on this page nor known before it.`,\n });\n }\n issues.push(...conditionIssues(step.id, c));\n }\n if (field.optionsFrom) {\n const problem =\n field.kind !== \"select\" && field.kind !== \"multiselect\" && field.kind !== \"slot\"\n ? `\"optionsFrom\" fills the choices of a select, multiselect or slot; kind is \"${field.kind}\".`\n : field.cards && field.kind === \"slot\"\n ? '\"cards\" draws the choices of a select or multiselect, not of a slot.'\n : optionsFromProblem(field.optionsFrom, field.cards);\n if (problem) {\n issues.push({ stepId: step.id, message: `Field \"${field.id}\": ${problem}` });\n }\n } else if (field.cards) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"cards\" needs \"optionsFrom\" naming a table output.`,\n });\n }\n if (field.prefill) {\n const ref = dataRef(field.prefill);\n if (ref.split(\".\")[0] !== \"steps\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": prefill names an earlier step (\"steps.<id>.<key>\").`,\n });\n } else {\n checkTemplate(step, `{{${ref}}}`);\n }\n }\n seenFields.add(field.id);\n }\n break;\n }\n case \"agent\":\n checkTemplate(step, step.instructions);\n if (step.call) {\n checkTemplate(step, JSON.stringify(step.call.input));\n if (step.each) {\n issues.push({ stepId: step.id, message: 'A step with \"call\" runs once: no \"each\".' });\n }\n if (step.output.format !== \"json\") {\n issues.push({\n stepId: step.id,\n message: 'A step with \"call\" keeps the tool\\'s answer: output format \"json\".',\n });\n }\n } else if (!step.instructions.trim()) {\n issues.push({ stepId: step.id, message: \"An AI step needs instructions.\" });\n }\n for (const c of step.connections ?? []) {\n if (!connectionIds.has(c)) {\n issues.push({ stepId: step.id, message: `Step uses unknown connection \"${c}\".` });\n }\n }\n if (step.output.surface && step.output.format !== \"json\") {\n issues.push({\n stepId: step.id,\n message: 'A step composes a view (\"surface\") of json output only.',\n });\n }\n if (step.output.schema) {\n if (step.output.fields?.length) {\n issues.push({\n stepId: step.id,\n message: 'Output has \"fields\" or \"schema\", not both.',\n });\n }\n if (step.output.format !== \"json\" || step.call) {\n issues.push({\n stepId: step.id,\n message: step.call\n ? 'A step with \"call\" keeps the tool\\'s answer as it is: no \"schema\".'\n : 'A \"schema\" describes json output: output format \"json\".',\n });\n }\n }\n if (Array.isArray(step.output.surface)) {\n // A step with `each` hands over its entries as `rows`.\n for (const issue of validateSurface(\n step.output.surface,\n step.each ? [\"rows\"] : declaredShape(step),\n )) {\n issues.push({ stepId: step.id, message: `View: ${issue.message}` });\n }\n }\n if (step.each) {\n const ref = dataRef(step.each);\n const list = ref.match(/^lists\\.([a-zA-Z][a-zA-Z0-9_]*)$/)?.[1];\n if (list) {\n if (!listIds.has(list)) {\n issues.push({ stepId: step.id, message: `each names an unknown list \"${list}\".` });\n }\n } else if (ref.startsWith(\"steps.\") && ref.split(\".\").length === 3) {\n checkTemplate(step, `{{${ref}}}`);\n } else {\n issues.push({\n stepId: step.id,\n message: `each \"${step.each}\" is \"steps.<id>.<key>\" (a table or list output) or \"lists.<id>\".`,\n });\n }\n }\n break;\n case \"generate\":\n checkTemplate(step, step.prompt);\n checkTemplate(step, step.options?.style ?? \"\");\n if (\n step.referenceImage &&\n !seenFields.has(step.referenceImage) &&\n !seenSteps.has(step.referenceImage)\n ) {\n issues.push({\n stepId: step.id,\n message: `referenceImage \"${step.referenceImage}\" is not an earlier field or step.`,\n });\n }\n if (step.each) {\n const ref = dataRef(step.each);\n if (step.asset !== \"image\" && step.asset !== \"video\") {\n issues.push({ stepId: step.id, message: `\"each\" is for image and video steps.` });\n } else if (ref.startsWith(\"steps.\")) {\n checkTemplate(step, `{{${ref}}}`);\n } else if (!seenFields.has(ref) && !seenSteps.has(ref)) {\n issues.push({\n stepId: step.id,\n message: `each \"${step.each}\" is not an earlier field, step or \"steps.<id>.<key>\".`,\n });\n }\n }\n break;\n case \"widget\":\n for (const [key, ref] of Object.entries(step.data)) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n issues.push({\n stepId: step.id,\n message: `Widget data key \"${key}\" is not an identifier.`,\n });\n }\n checkTemplate(step, `{{${dataRef(ref)}}}`);\n }\n if (files && !files.includes(step.entry)) {\n issues.push({\n stepId: step.id,\n message: `Widget entry \"${step.entry}\" is not in the workspace.`,\n });\n }\n if (files && step.sample && !files.includes(step.sample)) {\n issues.push({\n stepId: step.id,\n message: `Widget sample \"${step.sample}\" is not in the workspace.`,\n });\n }\n break;\n case \"surface\": {\n for (const [key, ref] of Object.entries(step.data)) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n issues.push({\n stepId: step.id,\n message: `Surface data key \"${key}\" is not an identifier.`,\n });\n }\n const list = listRef(dataRef(ref));\n if (list) {\n if (!listIds.has(list)) {\n issues.push({\n stepId: step.id,\n message: `Surface data reads an unknown list \"${list}\".`,\n });\n }\n } else {\n checkTemplate(step, `{{${dataRef(ref)}}}`);\n }\n }\n const groups = new Set((step.groups ?? []).map((g) => g.id));\n for (const c of step.candidates ?? []) {\n if (c.components[0]?.id !== c.id) {\n issues.push({\n stepId: step.id,\n message: `Surface piece \"${c.id}\": its first component carries the piece's id.`,\n });\n }\n if (c.group && !groups.has(c.group)) {\n issues.push({\n stepId: step.id,\n message: `Surface piece \"${c.id}\" names an unknown group \"${c.group}\".`,\n });\n }\n }\n const components =\n step.components ??\n assembleSurface(\n step.candidates ?? [],\n (step.candidates ?? []).map((c) => c.id),\n );\n for (const issue of validateSurface(components, Object.keys(step.data))) {\n issues.push({ stepId: step.id, message: `Surface: ${issue.message}` });\n }\n break;\n }\n case \"film\":\n checkTemplate(step, step.brief);\n for (const [name, ref] of Object.entries(step.inputs)) {\n if (!/^[a-z][a-z0-9-]{0,40}$/.test(name)) {\n issues.push({\n stepId: step.id,\n message: `Film input \"${name}\" is not a folder name (lowercase letters, digits, -).`,\n });\n }\n const r = dataRef(ref);\n if (r.startsWith(\"steps.\")) {\n checkTemplate(step, `{{${r}}}`);\n } else if (!seenFields.has(r)) {\n issues.push({\n stepId: step.id,\n message: `Film input \"${name}\": \"${ref}\" is not an earlier field or \"steps.<id>\".`,\n });\n }\n }\n if (step.from) {\n const id = dataRef(step.from).replace(/^steps\\./, \"\");\n if (!seenSteps.has(id) || def.steps.find((s) => s.id === id)?.type !== \"film\") {\n issues.push({\n stepId: step.id,\n message: `Film from \"${step.from}\" is not an earlier film step (\"steps.<id>\").`,\n });\n }\n }\n if (step.kit && !step.kit.endsWith(\".zip\")) {\n issues.push({ stepId: step.id, message: `Film kit \"${step.kit}\" is a .zip.` });\n } else if (files && step.kit && !files.includes(step.kit)) {\n issues.push({\n stepId: step.id,\n message: `Film kit \"${step.kit}\" is not in the workspace.`,\n });\n }\n for (const skill of step.skills) {\n if (skill.startsWith(\"skills/\") && files && !files.includes(`${skill}/SKILL.md`)) {\n issues.push({\n stepId: step.id,\n message: `Skill \"${skill}\" has no SKILL.md in the workspace.`,\n });\n }\n }\n break;\n case \"review\":\n for (const ref of step.show) {\n const list = listRef(ref);\n if (list ? !listIds.has(list) : !seenSteps.has(ref)) {\n issues.push({\n stepId: step.id,\n message: `Review shows unknown ${list ? \"list\" : \"step\"} \"${ref}\".`,\n });\n } else if (list && sharedLists.has(list)) {\n issues.push({ stepId: step.id, message: notShown(list) });\n }\n }\n break;\n case \"result\":\n for (const d of step.deliverables) {\n const list = listRef(d.from);\n if (list ? !listIds.has(list) : !seenSteps.has(d.from)) {\n issues.push({\n stepId: step.id,\n message: `Deliverable from unknown ${list ? \"list\" : \"step\"} \"${d.from}\".`,\n });\n } else if (list && sharedLists.has(list)) {\n issues.push({ stepId: step.id, message: notShown(list) });\n }\n }\n for (const option of step.share ?? []) {\n if (!isShareTargetId(option.target)) {\n issues.push({\n stepId: step.id,\n message: `Unknown share target \"${option.target}\": use email, slack, browser, storage:<connector> or connector:<connector>.`,\n });\n }\n for (const value of Object.values(option.values ?? {})) {\n checkTemplate(step, value);\n }\n }\n break;\n }\n if ((step.next ?? []).filter(isOtherwise).length > 1) {\n issues.push({\n stepId: step.id,\n message: 'A step has at most one \"otherwise\" branch (one without \"when\" and \"ask\").',\n });\n }\n for (const rule of step.next ?? []) {\n if (rule.goto !== \"end\" && !stepIds.has(rule.goto)) {\n issues.push({ stepId: step.id, message: `Branch goes to unknown step \"${rule.goto}\".` });\n }\n // A branch reads what the person answered (on any page), an output field of this or an\n // earlier agent step, or the row count of a stored list.\n for (const c of conditionsOf(rule.when)) {\n if (!fieldIds.has(c.field) && !knownBefore(step, c.field, true)) {\n issues.push({ stepId: step.id, message: `Branch reads unknown field \"${c.field}\".` });\n }\n issues.push(...conditionIssues(step.id, c));\n }\n }\n seenSteps.add(step.id);\n }\n return issues;\n}\n\n/** Parse + validate in one go. */\nexport function parseWizard(\n input: unknown,\n files?: string[],\n):\n | { ok: true; wizard: WizardDefinition; issues: ValidationIssue[] }\n | { ok: false; issues: ValidationIssue[] } {\n const parsed = wizardSchema.safeParse(input);\n if (!parsed.success) {\n return { ok: false, issues: shapeIssues(parsed.error, input) };\n }\n const issues = validateWizard(parsed.data, files);\n return { ok: true, wizard: parsed.data, issues };\n}\n\nfunction stepLabel(raw: unknown, index: number): string {\n const steps = (raw as { steps?: unknown[] } | null)?.steps;\n const id = (steps?.[index] as { id?: unknown } | undefined)?.id;\n return typeof id === \"string\" ? `steps[${index}] \"${id}\"` : `steps[${index}]`;\n}\n\n/** Where the shape is wrong, a step named by its id: `steps[2] \"draft\".title: …`. */\nexport function shapeIssues(error: z.ZodError, raw: unknown): ValidationIssue[] {\n return error.issues.map((i) => {\n const [head, index, ...rest] = i.path;\n const where =\n head === \"steps\" && typeof index === \"number\"\n ? [stepLabel(raw, index), ...rest].join(\".\")\n : i.path.join(\".\");\n return { message: `${where || \"wizard\"}: ${i.message}` };\n });\n}\n\n/**\n * What branch rules can read in a run: the person's answers by field id, and the structured\n * output of the steps run so far as `steps.<step>.<field>`.\n */\nexport function branchValues(\n values: Record<string, unknown>,\n outputs: Record<string, { json?: unknown; decided?: Record<string, number> }>,\n /** Rows per stored list, read as `lists.<list>.count`. */\n listCounts: Record<string, number> = {},\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...values };\n for (const [list, count] of Object.entries(listCounts)) {\n out[`lists.${list}.count`] = count;\n }\n for (const [stepId, output] of Object.entries(outputs)) {\n if (output.json && typeof output.json === \"object\" && !Array.isArray(output.json)) {\n for (const [key, value] of Object.entries(output.json)) {\n out[`steps.${stepId}.${key}`] = value;\n }\n }\n for (const [key, p] of Object.entries(output.decided ?? {})) {\n out[`steps.${stepId}.${key}.p`] = p;\n }\n }\n return out;\n}\n\n/** A branch back to an earlier step without `max` is taken at most this often in one run. */\nexport const DEFAULT_LOOP_MAX = 10;\n\n/** How a run counts the times it took a branch: \"<step>→<goto>\". */\nexport function loopKey(stepId: string, goto: string): string {\n return `${stepId}→${goto}`;\n}\n\n/** Whether a rule may still send the run on: one with `max`, or one back, stops after so many. */\nexport function ruleOpen(\n def: WizardDefinition,\n stepId: string,\n rule: NextRule,\n loops: Record<string, number> = {},\n): boolean {\n const from = def.steps.findIndex((s) => s.id === stepId);\n const to =\n rule.goto === \"end\" ? def.steps.length : def.steps.findIndex((s) => s.id === rule.goto);\n const max = rule.max ?? (to >= 0 && to <= from ? DEFAULT_LOOP_MAX : Number.POSITIVE_INFINITY);\n return (loops[loopKey(stepId, rule.goto)] ?? 0) < max;\n}\n\n/**\n * Where a run goes after a step: the first open `when` rule that holds (`rule` is its index in\n * `next`), else a decision over the open `ask` rules, else the next step in the list. `cursor`\n * null = the end.\n */\nexport type RuleOutcome =\n | { kind: \"go\"; cursor: string | null; rule: number | null }\n | { kind: \"decide\"; rules: number[] };\n\nexport function followRules(\n def: WizardDefinition,\n stepId: string,\n values: Record<string, unknown>,\n loops: Record<string, number> = {},\n): RuleOutcome {\n const index = def.steps.findIndex((s) => s.id === stepId);\n const step = def.steps[index];\n if (!step) {\n return { kind: \"go\", cursor: null, rule: null };\n }\n const rules = step.next ?? [];\n for (const [i, rule] of rules.entries()) {\n if (ruleOpen(def, stepId, rule, loops) && ruleMatches(rule, values)) {\n return { kind: \"go\", cursor: rule.goto === \"end\" ? null : rule.goto, rule: i };\n }\n }\n const asks = rules.flatMap((rule, i) =>\n rule.ask && ruleOpen(def, stepId, rule, loops) ? [i] : [],\n );\n if (asks.length) {\n return { kind: \"decide\", rules: asks };\n }\n return { kind: \"go\", ...otherwiseOf(def, stepId, loops) };\n}\n\n/** A rule with neither a condition nor a statement: where the run goes when no other rule holds. */\nexport function isOtherwise(rule: NextRule): boolean {\n return rule.when === undefined && rule.ask === undefined;\n}\n\n/**\n * Where a step goes when none of its rules holds: its \"otherwise\" rule (`rule` is its index in\n * `next`), else the next step in the list. `cursor` null = the end.\n */\nexport function otherwiseOf(\n def: WizardDefinition,\n stepId: string,\n loops: Record<string, number> = {},\n): { cursor: string | null; rule: number | null } {\n const index = def.steps.findIndex((s) => s.id === stepId);\n const rules = def.steps[index]?.next ?? [];\n const i = rules.findIndex((r) => isOtherwise(r) && ruleOpen(def, stepId, r, loops));\n if (i >= 0) {\n return { cursor: rules[i].goto === \"end\" ? null : rules[i].goto, rule: i };\n }\n return { cursor: def.steps[index + 1]?.id ?? null, rule: null };\n}\n\n/** The step after `step` by its `when` rules alone. `null` = the end. */\nexport function nextStepId(\n def: WizardDefinition,\n stepId: string,\n values: Record<string, unknown>,\n): string | null {\n const outcome = followRules(def, stepId, values);\n if (outcome.kind === \"go\") {\n return outcome.cursor;\n }\n const index = def.steps.findIndex((s) => s.id === stepId);\n return def.steps[index + 1]?.id ?? null;\n}\n\nfunction isEmptyValue(v: unknown): boolean {\n return v === undefined || v === null || v === \"\" || (Array.isArray(v) && v.length === 0);\n}\n\n/** The conditions of a rule or a field, as a list: one, several, or none. */\nexport function conditionsOf(when: When | undefined): Condition[] {\n return when === undefined ? [] : Array.isArray(when) ? when : [when];\n}\n\nexport function conditionMatches(c: Condition, values: Record<string, unknown>): boolean {\n const v = values[c.field];\n switch (c.op) {\n case \"empty\":\n return isEmptyValue(v);\n case \"notEmpty\":\n return !isEmptyValue(v);\n case \"equals\":\n return String(v) === String(c.value);\n case \"notEquals\":\n return String(v) !== String(c.value);\n case \"in\":\n return Array.isArray(c.value) && c.value.map(String).includes(String(v));\n case \"gt\":\n case \"lt\": {\n const a = readNumber(v);\n const b = readNumber(c.value);\n return a !== null && b !== null && (c.op === \"gt\" ? a > b : a < b);\n }\n case \"contains\":\n if (Array.isArray(v)) {\n return v.map(String).includes(String(c.value));\n }\n return (\n typeof v === \"string\" &&\n c.value !== undefined &&\n v.toLowerCase().includes(String(c.value).toLowerCase())\n );\n }\n}\n\n/** Whether every condition holds; no conditions hold trivially. */\nexport function whenHolds(when: When | undefined, values: Record<string, unknown>): boolean {\n return conditionsOf(when).every((c) => conditionMatches(c, values));\n}\n\n/** Whether a `when` rule holds. An `ask` rule never holds here: a decision takes it (see decide). */\nexport function ruleMatches(rule: NextRule, values: Record<string, unknown>): boolean {\n return rule.when !== undefined && whenHolds(rule.when, values);\n}\n\n/** A page with decided fields has at most this many; it shows at most MAX_SHOWN_FIELDS of them. */\nexport const MAX_DECIDED_FIELDS = 12;\nexport const MAX_SHOWN_FIELDS = 5;\n\n/** Whether a field is shown only when a decision keeps it. */\nexport function isDecidedField(field: Field): boolean {\n return Boolean(field.ask || field.group);\n}\n\n/**\n * The fields of a page that are shown: those whose `when` holds on what was known before the\n * page (`known`) and what the page holds so far (`page`). A hidden field's value does not count\n * for the fields after it.\n */\nexport function shownFields(\n fields: Field[],\n known: Record<string, unknown>,\n page: Record<string, unknown>,\n): Field[] {\n const values = { ...known, ...page };\n const out: Field[] = [];\n for (const field of fields) {\n if (whenHolds(field.when, values)) {\n out.push(field);\n } else {\n delete values[field.id];\n }\n }\n return out;\n}\n\n/** The references the `when` of a page's fields read outside the page: what the page must know. */\nexport function pageNeeds(fields: Field[]): string[] {\n const own = new Set(fields.map((f) => f.id));\n return [\n ...new Set(\n fields.flatMap((f) => conditionsOf(f.when).map((c) => c.field)).filter((r) => !own.has(r)),\n ),\n ];\n}\n\n/** At most this many choices come from data. */\nexport const MAX_DATA_OPTIONS = 100;\n\n/**\n * The choices an `optionsFrom` reference finds in a run: the entries of a list output, one\n * column of a table output, or one column of a stored list — as text, without duplicates and\n * empties. Empty when the data is not there (yet).\n */\nexport function optionsFromData(\n ref: string,\n outputs: Record<string, { json?: unknown }>,\n lists: Record<string, { rows: { cells: Record<string, unknown> }[] }> = {},\n cards?: CardsDef,\n): string[] {\n if (cards) {\n return cardsFromData(ref, outputs, cards).map((c) => c.value);\n }\n const [head, id, key, column, ...more] = dataRef(ref).split(\".\");\n let raw: unknown[] = [];\n if (head === \"lists\" && id && key && !column) {\n raw = (lists[id]?.rows ?? []).map((r) => r.cells[key]);\n } else if (head === \"steps\" && id && key && more.length === 0) {\n const json = outputs[id]?.json as Record<string, unknown> | undefined;\n const value = json && typeof json === \"object\" ? json[key] : undefined;\n if (Array.isArray(value)) {\n raw = column\n ? value.map((row) =>\n row && typeof row === \"object\" ? (row as Record<string, unknown>)[column] : undefined,\n )\n : value;\n }\n }\n const seen = new Set<string>();\n for (const v of raw) {\n if (v === null || v === undefined || typeof v === \"object\") {\n continue;\n }\n const text = String(v).trim().slice(0, 200);\n if (text) {\n seen.add(text);\n }\n if (seen.size >= MAX_DATA_OPTIONS) {\n break;\n }\n }\n return [...seen];\n}\n\n/** The rows of a table output as cards: what `optionsFrom` with `cards` finds in the run. */\nexport function cardsFromData(\n ref: string,\n outputs: Record<string, { json?: unknown }>,\n cards: CardsDef,\n): CardOption[] {\n const [head, id, key, ...more] = dataRef(ref).split(\".\");\n if (head !== \"steps\" || !id || !key || more.length) {\n return [];\n }\n const json = outputs[id]?.json as Record<string, unknown> | undefined;\n const rows = json && typeof json === \"object\" ? json[key] : undefined;\n if (!Array.isArray(rows)) {\n return [];\n }\n const cell = (row: Record<string, unknown>, column: string | undefined, max = 200) => {\n const v = column ? row[column] : undefined;\n if (v === null || v === undefined || typeof v === \"object\") {\n return \"\";\n }\n return String(v).trim().slice(0, max);\n };\n const out: CardOption[] = [];\n const seen = new Set<string>();\n for (const raw of rows) {\n if (!raw || typeof raw !== \"object\") {\n continue;\n }\n const row = raw as Record<string, unknown>;\n const label = cell(row, cards.label);\n const value = cell(row, cards.value) || label;\n if (!value || seen.has(value)) {\n continue;\n }\n seen.add(value);\n const card: CardOption = { value, label: label || value };\n const image = cell(row, cards.image, 2000);\n const link = cell(row, cards.link, 2000);\n const subtitle = cell(row, cards.subtitle, 300);\n const meta = cell(row, cards.meta, 80);\n if (/^(https?:|data:|\\/)/.test(image) || /^[a-zA-Z0-9_-]{6,64}$/.test(image)) {\n card.image = image;\n }\n if (/^https?:\\/\\//.test(link)) {\n card.link = link;\n }\n if (subtitle) {\n card.subtitle = subtitle;\n }\n if (meta) {\n card.meta = meta;\n }\n out.push(card);\n if (out.length >= MAX_DATA_OPTIONS) {\n break;\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Appointment times\n\nconst SLOT_RE =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$/;\n\n/** An offered appointment time read on its own clock: the offset it was written with. */\nexport interface SlotTime {\n /** The calendar day there: \"2026-10-12\". */\n day: string;\n /** The time of day there: \"09:00\". */\n time: string;\n /** That day and time as if it were UTC — to name the weekday and month without moving it. */\n wall: Date;\n}\n\n/**\n * A slot option as day and time in its own offset (the business's time zone, not the reader's).\n * Null when it is not an ISO 8601 date-time with an offset.\n */\nexport function slotTime(iso: string): SlotTime | null {\n const m = SLOT_RE.exec(iso.trim());\n if (!m) {\n return null;\n }\n const [, y, mo, d, h, mi] = m.map(Number);\n const wall = new Date(Date.UTC(y, mo - 1, d, h, mi));\n if (\n wall.getUTCMonth() !== mo - 1 ||\n wall.getUTCDate() !== d ||\n h > 23 ||\n mi > 59 ||\n !Number.isFinite(Date.parse(iso))\n ) {\n return null;\n }\n return { day: `${m[1]}-${m[2]}-${m[3]}`, time: `${m[4]}:${m[5]}`, wall };\n}\n\n/** The weekday and date of a slot's day: \"Montag, 12. Oktober\" / \"Monday, 12 October\". */\nexport function slotDayText(iso: string, lang = \"en\"): string {\n const slot = slotTime(iso);\n if (!slot) {\n return iso;\n }\n const locale = localeOf(lang);\n const weekday = slot.wall.toLocaleDateString(locale, { weekday: \"long\", timeZone: \"UTC\" });\n const date = slot.wall.toLocaleDateString(locale, {\n day: \"numeric\",\n month: \"long\",\n timeZone: \"UTC\",\n });\n return `${weekday}, ${date}`;\n}\n\n/** A chosen slot as a person reads it back: \"Di 13.10.2026, 10:30\" / \"Tue 13/10/2026, 10:30\". */\nexport function slotText(iso: string, lang = \"en\"): string {\n const slot = slotTime(iso);\n if (!slot) {\n return iso;\n }\n const locale = localeOf(lang);\n const weekday = slot.wall\n .toLocaleDateString(locale, { weekday: \"short\", timeZone: \"UTC\" })\n .replace(/\\.$/, \"\");\n const date = slot.wall.toLocaleDateString(locale, {\n day: \"2-digit\",\n month: \"2-digit\",\n year: \"numeric\",\n timeZone: \"UTC\",\n });\n return `${weekday} ${date}, ${slot.time}`;\n}\n\n/**\n * The slot among `options` that is the same moment as `value`, written as offered — so an answer\n * in another offset (\"…T07:00:00Z\" for \"…T09:00:00+02:00\") picks the offered time.\n */\nexport function offeredSlot(value: string, options: string[]): string | undefined {\n if (options.includes(value)) {\n return value;\n }\n const at = slotTime(value) ? Date.parse(value) : Number.NaN;\n return Number.isFinite(at) ? options.find((o) => slotTime(o) && Date.parse(o) === at) : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Line items\n\nexport interface ItemsTotals {\n rows: Record<string, unknown>[];\n net: number;\n vatRate: number;\n vat: number;\n gross: number;\n currency: string;\n}\n\nexport function itemsTotals(\n field: Field,\n value: unknown,\n values: Record<string, unknown>,\n): ItemsTotals {\n const rows = Array.isArray(value) ? (value as Record<string, unknown>[]) : [];\n const numeric = (field.columns ?? []).filter((c) => c.kind !== \"text\");\n const withAmount = rows.map((row) => {\n const amount = numeric.length ? numeric.reduce((acc, c) => acc * amountOf(row[c.id]), 1) : 0;\n return { ...row, amount: round2(amount) };\n });\n const net = round2(withAmount.reduce((a, r) => a + (r.amount as number), 0));\n let vatRate = field.vat?.rate ?? 0;\n if (field.vat?.field) {\n const raw = values[field.vat.field];\n const parsed = readNumber(raw, { units: true });\n if (parsed !== null) {\n vatRate = parsed;\n }\n }\n const vat = round2((net * vatRate) / 100);\n return {\n rows: withAmount,\n net,\n vatRate,\n vat,\n gross: round2(net + vat),\n currency: field.currency ?? \"EUR\",\n };\n}\n\n/** A typed amount as a number: a phone's number pad in German gives \"89,90\". */\nfunction amountOf(v: unknown): number {\n return readNumber(v) ?? 0;\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nexport function allFields(def: WizardDefinition): Field[] {\n return def.steps.flatMap((s) => (s.type === \"page\" ? s.fields : []));\n}\n\nconst GERMAN =\n /\\b(und|der|die|das|ist|nicht|für|mit|ein|eine|wird|zu|dein|deine|ihr|wir|was|wie|oder)\\b|[äöüß]/gi;\nconst ENGLISH = /\\b(and|the|is|not|for|with|a|an|your|you|we|what|how|or|to|of)\\b/gi;\n\n/**\n * The language a wizard speaks to people: the one it names, else read from its own words\n * (titles, labels, intro) — English where they are not clearly German.\n */\nexport function wizardLang(def: WizardDefinition): string {\n if (def.lang) {\n return def.lang;\n }\n const text = [\n def.title,\n def.description,\n def.intro,\n ...def.steps.flatMap((s) => [\n s.title,\n s.description,\n ...(s.type === \"page\" ? s.fields.flatMap((f) => [f.label, f.help, f.placeholder]) : []),\n ]),\n ]\n .filter(Boolean)\n .join(\" \");\n const de = text.match(GERMAN)?.length ?? 0;\n const en = text.match(ENGLISH)?.length ?? 0;\n return de > en ? \"de\" : \"en\";\n}\n\n// --- can this app read a definition? ---------------------------------------------------------\n// The schema drops what it does not know. A definition written for a newer app would be read\n// without complaint and run wrongly, so it counts only when nothing of it is lost.\n\nfunction keepsAll(given: unknown, read: unknown): boolean {\n if (Array.isArray(given)) {\n return Array.isArray(read) && given.every((v, i) => keepsAll(v, read[i]));\n }\n if (given && typeof given === \"object\") {\n return (\n Boolean(read) &&\n typeof read === \"object\" &&\n Object.entries(given).every(\n ([k, v]) => v === undefined || (k in (read as object) && keepsAll(v, (read as never)[k])),\n )\n );\n }\n return true;\n}\n\n/** True when this app's schema reads the definition without losing anything of it. */\nexport function readable(definition: unknown): boolean {\n const parsed = wizardSchema.safeParse(definition);\n return parsed.success && keepsAll(definition, parsed.data);\n}\n","import { z } from \"zod\";\nimport { ENGENTY_COSTUMES, THEME_ID } from \"./definition.js\";\nimport { luminance } from \"./projects.js\";\nimport type { RunFontFace, RunTheme } from \"./run.js\";\n\n// --- themes ------------------------------------------------------------------------\n// How a wizard's pages look, as a document of its own: values only (colours for light and dark,\n// fonts, shape, effects from the runner's library), kept in the space and shipped in a wizard\n// file. No CSS, no files, no addresses: a theme is data a schema checks completely, and every\n// place a wizard runs draws as much of it as it can. docs/plans/themes.md\n\n/** The themes every space has. Nobody defines or publishes them. */\nexport const BUILT_IN_THEMES = [\"brand\", \"host\", \"default\"] as const;\nexport type BuiltInTheme = (typeof BUILT_IN_THEMES)[number];\n\n/** Ids no theme of a space may take, and scopes only engenty wizards publishes under. */\nexport const RESERVED_THEME_IDS: readonly string[] = [\n ...BUILT_IN_THEMES,\n \"engenty\",\n \"wizard\",\n \"wizards\",\n];\nexport const RESERVED_THEME_SCOPES: readonly string[] = [\"@wizards\", \"@engenty\", \"@wizard\"];\n\nexport { THEME_ID };\n\n/** A wizard names at most this many themes; a space keeps at most this many. */\nexport const MAX_WIZARD_THEMES = 8;\nexport const MAX_SPACE_THEMES = 40;\n\n/**\n * The fonts the runner ships (OFL): a run page loads them from its own address. A theme names\n * one of them by family, or the space's brand by role (`\"brand\"`).\n */\nexport const SHIPPED_FONTS = [\n \"Inter\",\n \"Figtree\",\n \"DM Sans\",\n \"Nunito\",\n \"Fredoka\",\n \"Bricolage Grotesque\",\n \"Fraunces\",\n \"Playfair Display\",\n \"Lora\",\n \"Young Serif\",\n \"Caveat\",\n \"Creepster\",\n \"Nosifer\",\n] as const;\nexport type ShippedFont = (typeof SHIPPED_FONTS)[number];\n\n/**\n * The runner's effects and their options. Names stay open in the schema: a theme that names an\n * effect this runner does not know is drawn without it.\n */\nexport const THEME_EFFECTS = {\n glow: {},\n corners: { kind: [\"webs\", \"frost\"] },\n particles: { kind: [\"embers\", \"snow\", \"confetti\", \"stars\"] },\n figures: { costume: ENGENTY_COSTUMES, motion: [\"fly\", \"peek\"] },\n fog: {},\n pattern: { kind: [\"dots\", \"grid\"] },\n} as const satisfies Record<string, Record<string, readonly string[]>>;\nexport type ThemeEffectId = keyof typeof THEME_EFFECTS;\n\nconst hex = z.string().regex(/^#[0-9a-fA-F]{6}$/, \"a colour as #rrggbb\");\n\nexport const themeColoursSchema = z.object({\n /** Buttons and marks. */\n accent: hex.optional(),\n /** The ground the pages stand on. */\n background: hex.optional(),\n /** Text. Left out: taken from the ground. */\n text: hex.optional(),\n});\nexport type ThemeColours = z.infer<typeof themeColoursSchema>;\n\nexport const COLOR_SCHEMES = [\"light\", \"dark\"] as const;\nexport type ColorScheme = (typeof COLOR_SCHEMES)[number];\n\n/** The colours of light or of dark pages (`scheme`, as CSS's `color-scheme` names them). */\nexport const themeColorsSchema = themeColoursSchema.extend({ scheme: z.enum(COLOR_SCHEMES) });\nexport type ThemeColors = z.infer<typeof themeColorsSchema>;\n\nexport const themeShapeSchema = z.object({\n radius: z.enum([\"sharp\", \"soft\", \"round\"]).optional(),\n cards: z.enum([\"solid\", \"outline\", \"glass\"]).optional(),\n headings: z.enum([\"normal\", \"uppercase\"]).optional(),\n});\nexport type ThemeShape = z.infer<typeof themeShapeSchema>;\n\nexport const themeEffectSchema = z\n .object({ id: z.string().min(1).max(40) })\n .catchall(z.union([z.string().max(40), z.number(), z.boolean()]));\nexport type ThemeEffect = z.infer<typeof themeEffectSchema>;\n\n/** A shipped family by name, or `brand`: never an address. */\nconst fontName = z\n .string()\n .min(1)\n .max(60)\n .regex(/^[A-Za-z0-9 -]+$/, \"a font by its family name, or brand\");\n\nexport const themeSchema = z.object({\n id: z.string().regex(THEME_ID, \"a theme id: lowercase letters, digits and dashes\"),\n name: z.string().min(1).max(80),\n version: z\n .string()\n .regex(/^\\d+\\.\\d+\\.\\d+$/)\n .default(\"1.0.0\"),\n /** What the theme builds on: what it leaves out comes from there. */\n base: z.enum(BUILT_IN_THEMES).default(\"brand\"),\n /**\n * The colours of light and of dark pages, in order: the first shows until the person picks.\n * One entry: the pages are always that.\n */\n colors: z\n .array(themeColorsSchema)\n .min(1)\n .max(2)\n .refine((list) => new Set(list.map((c) => c.scheme)).size === list.length, {\n message: \"Each scheme once: light, dark.\",\n })\n .optional(),\n fonts: z\n .object({\n heading: fontName.optional(),\n text: fontName.optional(),\n })\n .optional(),\n shape: themeShapeSchema.optional(),\n effects: z.array(themeEffectSchema).max(8).optional(),\n});\nexport type Theme = z.infer<typeof themeSchema>;\n\n/** Why an id cannot be a theme of a space; null when it can. */\nexport function themeIdProblem(id: string): string | null {\n if (!THEME_ID.test(id)) {\n return `\"${id}\" is no theme id: lowercase letters, digits and dashes, optionally after @owner/.`;\n }\n const scope = id.startsWith(\"@\") ? id.slice(0, id.indexOf(\"/\")) : null;\n if (scope && RESERVED_THEME_SCOPES.includes(scope) && scope !== \"@wizards\") {\n return `The scope ${scope} is reserved.`;\n }\n if (!scope && RESERVED_THEME_IDS.includes(id)) {\n return `\"${id}\" is reserved for engenty wizards.`;\n }\n return null;\n}\n\n/** A theme's content as one string: the same content gives the same key, whatever the order of keys. */\nexport function themeContentKey(theme: Theme): string {\n const sorted = (v: unknown): unknown =>\n Array.isArray(v)\n ? v.map(sorted)\n : v && typeof v === \"object\"\n ? Object.fromEntries(\n Object.entries(v)\n .filter(([, x]) => x !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, x]) => [k, sorted(x)]),\n )\n : v;\n const { id: _, ...content } = theme;\n return JSON.stringify(sorted(content));\n}\n\n/** An id like `id` that `taken` does not hold yet: `halloween`, `halloween-2`, … */\nexport function freeThemeId(id: string, taken: ReadonlySet<string>): string {\n if (!taken.has(id)) {\n return id;\n }\n for (let n = 2; ; n++) {\n const next = `${id.slice(0, 44)}-${n}`;\n if (!taken.has(next)) {\n return next;\n }\n }\n}\n\n/** A theme id from a wizard's title: \"Spukhaus-Exposé\" → `spukhaus-expose`. */\nexport function themeIdFrom(title: string): string {\n const slug = title\n .normalize(\"NFKD\")\n .replace(/[̀-ͯ]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 48);\n return slug && !RESERVED_THEME_IDS.includes(slug) ? slug : \"look\";\n}\n\n/**\n * Whether the place that shows a wizard may pick `asked`: a built-in name, or a theme of the\n * wizard's own chain. The host always wins, but only among what the wizard offers.\n */\nexport function themeOffered(asked: string, chain: readonly string[] | undefined): boolean {\n return (BUILT_IN_THEMES as readonly string[]).includes(asked) || Boolean(chain?.includes(asked));\n}\n\n/**\n * The theme a wizard's pages show: what the place showing it asks for (`asked`, an embed's\n * `data-theme`), where the wizard offers it and the space has it; else the first of its chain\n * the space has (a built-in name counts). Undefined: none of them, so the brand.\n */\nexport function chosenTheme(\n chain: readonly string[] | undefined,\n themes: readonly Theme[],\n asked?: string | null,\n): Theme | BuiltInTheme | undefined {\n const ask = asked && themeOffered(asked, chain) ? [asked] : [];\n for (const id of [...ask, ...(chain ?? [])]) {\n if ((BUILT_IN_THEMES as readonly string[]).includes(id)) {\n return id as BuiltInTheme;\n }\n const found = themes.find((t) => t.id === id);\n if (found) {\n return found;\n }\n }\n return undefined;\n}\n\n/** The engenty wizards look without a brand: what `default` shows and builds on. */\nconst NEUTRAL: RunTheme = {\n accent: null,\n second: null,\n background: null,\n display: null,\n body: null,\n faces: [],\n dark: false,\n pinned: false,\n modes: null,\n prefer: null,\n shape: null,\n effects: [],\n};\n\n/**\n * The look of a wizard's pages: the space's brand (`runTheme`), or the theme the wizard chose\n * built on its base. `host` is drawn as the brand on pages of our own; a host that passes a\n * look of its own puts it over this. The base's colours stay in `accent` and `background`; the\n * theme's colours for light and dark pages go into `modes`, and the page takes those of what it\n * shows.\n */\nexport function themedLook(brand: RunTheme, theme: Theme | BuiltInTheme | undefined): RunTheme {\n if (theme === undefined || theme === \"brand\" || theme === \"host\") {\n return brand;\n }\n if (theme === \"default\") {\n return NEUTRAL;\n }\n const base = theme.base === \"default\" ? NEUTRAL : brand;\n // `brand` is the brand's font for the role, whatever the theme builds on.\n const font = (name: string | undefined, role: \"display\" | \"body\") =>\n name === \"brand\" ? brand[role] : (name ?? base[role]);\n const display = font(theme.fonts?.heading, \"display\");\n const body = font(theme.fonts?.text, \"body\");\n const schemes = (theme.colors ?? []).map((c) => c.scheme);\n const only = schemes.length === 1 ? schemes[0] : null;\n const shown = schemes[0] ?? (base.dark ? \"dark\" : \"light\");\n const background = themeColors(theme, shown)?.background;\n return {\n ...base,\n display,\n body,\n faces: brand.faces.filter((f) => f.family === display || f.family === body),\n dark: background ? luminance(background) < 0.18 : shown === \"dark\",\n pinned: only !== null,\n modes: schemes.length\n ? { light: themeColors(theme, \"light\") ?? null, dark: themeColors(theme, \"dark\") ?? null }\n : null,\n prefer: schemes.length === 2 ? shown : null,\n shape: theme.shape ?? null,\n effects: theme.effects ?? [],\n };\n}\n\nconst SANS = \"ui-sans-serif, system-ui, sans-serif\";\nconst SERIF = \"ui-serif, Georgia, serif\";\nconst SERIFS =\n /serif|fraunces|playfair|lora|garamond|antiqua|baskerville|caslon|bodoni|didot|times|georgia|merriweather|tiempos/i;\n\n/** A family looks like a serif by its name: what takes its place is a serif too. */\nexport const serifFamily = (family: string) => SERIFS.test(family) && !/sans/i.test(family);\n\n/** The shipped font that shows where a brand font does not load: one of its kind. */\nexport const shippedLike = (family: string): ShippedFont =>\n serifFamily(family) ? \"Lora\" : \"Inter\";\n\n/**\n * A family as CSS takes it, with a fallback of its kind while it loads or where it is missing. A\n * brand font with a source (`faces`) names the shipped font of its kind next: it shows if the\n * brand font does not load.\n */\nexport function fontStack(family: string, faces: readonly RunFontFace[] = []): string {\n const next = faces.some((f) => f.family === family) ? `\"${shippedLike(family)}\", ` : \"\";\n return `\"${family.replace(/\"/g, \"\")}\", ${next}${serifFamily(family) ? SERIF : SANS}`;\n}\n\n/** A theme's colours for light or dark pages, without the scheme's name; undefined: it has none. */\nexport function themeColors(\n theme: Pick<Theme, \"colors\"> | undefined,\n scheme: ColorScheme,\n): ThemeColours | undefined {\n const found = theme?.colors?.find((c) => c.scheme === scheme);\n if (!found) {\n return undefined;\n }\n const { scheme: _, ...colours } = found;\n return colours;\n}\n\n/** The colours a page shows in light or dark: the theme's for that mode, else the base's. */\nexport function lookColours(\n look: Pick<RunTheme, \"accent\" | \"background\" | \"modes\">,\n mode: \"light\" | \"dark\",\n): { accent: string | null; background: string | null; text: string | null } {\n const own = look.modes?.[mode];\n return {\n accent: own?.accent ?? look.accent,\n background: own?.background ?? look.background,\n text: own?.text ?? null,\n };\n}\n","import type { RunTheme } from \"@engenty/wizards-shared/run\";\nimport { fontStack, lookColours } from \"@engenty/wizards-shared/theme\";\n\n/**\n * A wizard's theme in a host's own page (OpenUI, an own UI): values on the element with\n * `.engenty-runner`, never CSS in the page around it. runner.css derives every token from them.\n */\n\n/** The effects the wizard's card draws itself, when the host turns them on: CSS inside the card. */\nexport const CARD_EFFECTS = [\"glow\", \"pattern\"] as const;\n\nexport interface WizardLookOptions {\n /** Light or dark, as the host shows; else what the theme prefers. A theme with only one keeps it. */\n mode?: \"light\" | \"dark\";\n /** The effects the host turns on (`CARD_EFFECTS`); none unless given. */\n effects?: readonly string[];\n}\n\n/** What goes on the element with `.engenty-runner`: CSS variables and data attributes. */\nexport interface WizardLookProps {\n style: Record<string, string>;\n \"data-cards\"?: string;\n \"data-headings\"?: string;\n \"data-effects\"?: string;\n}\n\nconst RADIUS = { sharp: \"0.25rem\", soft: \"0.5rem\", round: \"0.8rem\" } as const;\n\n/**\n * A theme's values as props for the runner's element: colours, fonts by family and the corner\n * radius as `--wizard-*` variables, how cards and headings look as data attributes, and of the\n * effects only those the host turns on and the card can draw. A brand font is named by its\n * family; the host loads it.\n */\nexport function wizardLook(look: RunTheme, options: WizardLookOptions = {}): WizardLookProps {\n const own = look.dark ? \"dark\" : \"light\";\n const mode = look.pinned ? own : (options.mode ?? look.prefer ?? own);\n const colours = lookColours(look, mode);\n const style: Record<string, string> = {};\n const set = (name: string, value: string | null | undefined) => {\n if (value) {\n style[name] = value;\n }\n };\n set(\"--wizard-accent\", colours.accent);\n set(\"--wizard-background\", colours.background);\n set(\"--wizard-text\", colours.text);\n set(\"--wizard-font-heading\", look.display ? fontStack(look.display) : null);\n set(\"--wizard-font-text\", look.body ? fontStack(look.body) : null);\n set(\"--wizard-radius\", look.shape?.radius ? RADIUS[look.shape.radius] : null);\n // runner.css styles what is inside the element; the ground of the element itself is set here.\n set(\"backgroundColor\", colours.background ? \"var(--paper)\" : null);\n\n const on = new Set(options.effects ?? []);\n const effects = look.effects.flatMap((e) =>\n !on.has(e.id)\n ? []\n : e.id === \"glow\"\n ? [\"glow\"]\n : e.id === \"pattern\"\n ? [`pattern-${e.kind === \"grid\" ? \"grid\" : \"dots\"}`]\n : [],\n );\n return {\n style,\n ...(look.shape?.cards ? { \"data-cards\": look.shape.cards } : {}),\n ...(look.shape?.headings ? { \"data-headings\": look.shape.headings } : {}),\n ...(effects.length ? { \"data-effects\": effects.join(\" \") } : {}),\n };\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { type Lang, localeOf } from \"./definition.js\";\n\n/**\n * A line with a form for each plural category of its `{count}` (or `{n}`, `Intl.PluralRules`):\n * \"one\" and \"other\" in English and German, more in languages that need them.\n */\nexport interface Plural {\n zero?: string;\n one?: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\n/** A line of a string table: plain, or with plural forms. */\nexport type Line = string | Plural;\n\n/**\n * A string table: each language's lines by key. English has every line; another language may\n * lack some, and those are said in English. A new language needs only its own table.\n */\nexport type Texts<K extends string> = { en: Record<K, Line> } & {\n [L in Exclude<Lang, \"en\">]: Partial<Record<K, Line>>;\n};\n\n/** What fills a line's gaps: words, a number (written the language's way), or a list of them. */\nexport type Gap = string | number | readonly Gap[];\n\nconst plurals = new Map<string, Intl.PluralRules>();\n\n/** The plural rules of a language: any language, by its code. */\nexport function pluralRules(lang: string): Intl.PluralRules {\n let rules = plurals.get(lang);\n if (!rules) {\n rules = new Intl.PluralRules(localeOf(lang));\n plurals.set(lang, rules);\n }\n return rules;\n}\n\nfunction form(line: Line, lang: string, count: unknown): string {\n if (typeof line === \"string\") {\n return line;\n }\n if (typeof count !== \"number\") {\n return line.other;\n }\n return line[pluralRules(lang).select(count)] ?? line.other;\n}\n\n/** A gap's words in a language: numbers as the language writes them, lists joined. */\nexport function gapText(value: Gap, lang: string): string {\n if (typeof value === \"number\") {\n return value.toLocaleString(localeOf(lang));\n }\n if (Array.isArray(value)) {\n return value.map((item) => gapText(item, lang)).join(\", \");\n }\n return value as string;\n}\n\n/** Fills `{name}` gaps; a gap with nothing for it stays as it is. */\nexport function fillGaps(\n text: string,\n lang: string,\n params?: Record<string, Gap | undefined>,\n): string {\n return text.replace(/\\{(\\w+)\\}/g, (gap, key: string) => {\n const value = params?.[key];\n return value === undefined ? gap : gapText(value, lang);\n });\n}\n\n/**\n * A line of a table in a language, its gaps filled and its plural form picked by `{count}`\n * (or `{n}`);\n * the English line where the language lacks one.\n */\nexport function textOf<K extends string>(\n texts: Texts<K>,\n key: K,\n lang: Lang,\n params?: Record<string, Gap | undefined>,\n): string {\n const line = (texts[lang] as Partial<Record<K, Line>>)[key] ?? texts.en[key];\n if (line === undefined) {\n return key;\n }\n return fillGaps(form(line, lang, params?.count ?? params?.n), lang, params);\n}\n\n/**\n * A string table of one language outside `LANGS`, translated on request: lines by key, a plural\n * line with the forms of that language's plural categories.\n */\nexport type TextTable = Record<string, Line>;\n\n/** A line of a table, in a language: its gaps filled and its plural form picked. */\nexport function lineText(\n line: Line,\n lang: string,\n params?: Record<string, Gap | undefined>,\n): string {\n return fillGaps(form(line, lang, params?.count ?? params?.n), lang, params);\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport {\n type CardOption,\n type EngentyCostume,\n type Format,\n isLang,\n type Lang,\n type ModelClass,\n type Step,\n type WizardDefinition,\n} from \"./definition.js\";\nimport type { ShareJobView } from \"./sharing.js\";\nimport type { ConnectionView, ListDef, ListRow } from \"./store.js\";\nimport type { Surface } from \"./surface.js\";\nimport { type Gap, type Line, lineText, type Texts, type TextTable, textOf } from \"./texts.js\";\nimport type { ThemeColours, ThemeEffect, ThemeShape } from \"./theme.js\";\n\nexport type RunStatus = \"waiting_input\" | \"running\" | \"done\" | \"failed\" | \"cancelled\";\n\nexport interface AssetRef {\n id: string;\n /** image | video | html | text | json */\n kind: string;\n mime: string;\n name: string;\n /**\n * Media a model made (\"generated\") or changed (\"edited\"). Shown with a label wherever it is\n * displayed; the file itself carries the marking in its metadata (EU AI Act, Art. 50).\n */\n ai?: \"generated\" | \"edited\";\n}\n\nexport interface StepOutput {\n text?: string;\n json?: unknown;\n /** A decision step: how probable each answer is (1 or 0 where a language model answered). */\n decided?: Record<string, number>;\n /** A view from the surface catalog and the data it is bound to. */\n surface?: Surface;\n assets?: AssetRef[];\n /**\n * What the person did in the step's view, kept with the run: a checklist's ticks by component\n * id, a widget's own state (`wizard.save`).\n */\n view?: Record<string, unknown>;\n /** Widgets: what loading it with this run's data showed. */\n widget?: {\n /** Seconds of animation the widget registered for video export; null = a still widget. */\n duration: number | null;\n errors: string[];\n };\n at: string;\n}\n\nexport interface RunState {\n values: Record<string, unknown>;\n outputs: Record<string, StepOutput>;\n /** Interactive steps answered, oldest first — \"back\" pops this. */\n history: string[];\n /** Regenerate notes per step. */\n notes: Record<string, string>;\n /** Steps that make several results: the entries (from 0) to make again; the others stay. */\n redo?: Record<string, number[]>;\n /** The step whose `ask` branches are being decided; the run waits on that decision. */\n deciding?: string;\n /** What decided `ask` branches answered, by step. */\n decisions?: Record<string, BranchDecision>;\n /** Pages whose fields a decision chose: the field ids kept, by page. */\n pages?: Record<string, { shown: string[] }>;\n /** How often each branch was taken, by \"<step>→<goto>\": loops stop at the rule's max. */\n loops?: Record<string, number>;\n /** File fields with `listen`: what is said in the recording, piece by piece with its times. */\n heard?: Record<string, { start: number; end: number; text: string }[]>;\n /**\n * A test run's own copy of the wizard's memory: the pages it wrote, by title. The wizard's\n * pages stay as they are; the copy goes with the run.\n */\n memory?: Record<string, string>;\n /**\n * Finished results translated on request, by language and step: the text the person reads in\n * place of the step's own (`StepOutput.text`); the step's output stays as it was made.\n */\n translated?: Record<string, Record<string, string>>;\n}\n\n/** What a decision over a step's `ask` branches found. */\nexport interface BranchDecision {\n /** The index of the rule in the step's `next`, or null: none of them, go on. */\n rule: number | null;\n source: \"systemone\" | \"llm\";\n probabilities?: Record<string, number>;\n at: string;\n}\n\n/** A branch decision as the studio sees it: with the step's branches it was made over. */\nexport interface ShownDecision extends BranchDecision {\n over: NonNullable<Step[\"next\"]>;\n}\n\ninterface AskBase {\n id: string;\n stepId: string;\n /** Why the wizard asks, in the person's language. */\n reason: string;\n at: string;\n}\n\n/**\n * A running step asks the person to sign in on a page the wizard's browser has open. What the\n * person types goes into that page; the model never sees it.\n */\nexport interface LoginAsk extends AskBase {\n kind: \"login\";\n site: { host: string; title: string };\n /** Inputs found on the page, to fill here instead of clicking into the picture. */\n fields: { id: string; label: string; secret: boolean }[];\n}\n\n/** A running step wants to change something in one of the person's accounts and asks first. */\nexport interface ConfirmAsk extends AskBase {\n kind: \"confirm\";\n /** The connected service, e.g. \"Notion\". */\n service: string;\n action: { id: string; summary: string; destructive: boolean };\n /** What would be sent, as readable JSON. */\n input: string;\n /** Asked for this one thing: there is nothing to allow for the rest of the run. */\n once?: boolean;\n}\n\n/** What a running step asks the person; the step waits for the answer. */\nexport type RunAsk = LoginAsk | ConfirmAsk;\n\n/** A question as a step puts it; the runner adds id, step and time. */\nexport type AskInput =\n | Omit<LoginAsk, \"id\" | \"stepId\" | \"at\">\n | Omit<ConfirmAsk, \"id\" | \"stepId\" | \"at\">;\n\n/**\n * `fill` and `done` answer a sign-in (remember = keep the sign-in); `done` also allows a change\n * (remember = allow that action for the rest of the run); `skip` declines either.\n */\nexport type AskAnswer =\n | { type: \"fill\"; values: Record<string, string>; remember?: boolean }\n | { type: \"done\"; remember?: boolean }\n | { type: \"skip\" };\n\n/** One thing the person does in the wizard's browser while it waits for them. */\nexport type BrowserAct =\n /** Where on the picture, as a share of its width and height (0–1). */\n | { type: \"click\"; fx: number; fy: number }\n | { type: \"type\"; text: string }\n | { type: \"key\"; key: \"Enter\" | \"Tab\" | \"Backspace\" | \"Escape\" }\n | { type: \"scroll\"; dy: number };\n\n/** A stored list the current step shows. */\nexport interface ShownList {\n def: ListDef;\n rows: ListRow[];\n formats: Format[];\n label: string | null;\n}\n\n/**\n * What a step reports while it works, in words for each language: the runtime writes the English\n * line into the run's log, a runner shows it in the language the person reads. The runtime's\n * answers to the person running a shared wizard (a refusal, a failure) are notes too: it answers\n * them in the wizard's language.\n */\nconst NOTES_EN = {\n entry: \"Entry {n} of {total}\",\n deciding: \"Deciding what to do next…\",\n choosingFields: \"Choosing the right questions…\",\n batchDone: \"{done} of {total} done\",\n editing: \"Editing {n} of {total}\",\n filming: \"Filming {n} of {total}\",\n clipsRendering: {\n one: \"Rendering {count} clip – this takes a few minutes.\",\n other: \"Rendering {count} clips – this takes a few minutes.\",\n },\n videoRendering: \"Rendering the video – this usually takes 1–3 minutes.\",\n photo: \"Looking at photo {n} of {total}\",\n // An entry a step has just written, while it writes the rest: \"Rezepte: Shakshuka mit Feta\".\n found: \"{label}: {name}\",\n listen: \"Listening to “{label}”…\",\n listenFailed: \"“{label}” couldn’t be transcribed.\",\n filmCutting: \"Cutting the film – this takes about a minute.\",\n filmProgress: \"{pct} % cut\",\n filmError: \"The film reports: {detail}\",\n widgetError: \"The widget reports an error: {detail}\",\n mcpConnected: \"Connected to {names}\",\n mcpUnreachable: \"MCP server unreachable: {detail}\",\n reads: \"Reading {name}\",\n readsMany: { one: \"Reading {count} document\", other: \"Reading {count} documents\" },\n opens: \"Opening {name}\",\n clicks: \"Clicking in the browser\",\n clicksOn: \"Clicking “{name}”\",\n types: \"Typing in the browser\",\n typesText: \"Typing “{text}”\",\n selects: \"Choosing “{option}”\",\n scrolls: \"Scrolling\",\n presses: \"Pressing {key}\",\n goesBack: \"Going back a page\",\n waitsForPage: \"Waiting for the page\",\n fastLoop: \"Doing in the browser: {goal}\",\n personDrives: \"You’re driving the browser – the wizard waits\",\n agentDrives: \"The wizard carries on in the browser\",\n looksAtPage: \"Looking at the page\",\n waitsForSignIn: \"Waiting for you to sign in to {name}\",\n downloads: \"Downloading {name}\",\n attaches: \"Attaching {name}\",\n runs: \"Running: {command}\",\n python: \"Running Python\",\n runsProgram: \"Working through the data in one go\",\n drawing: \"Drawing an image\",\n writesPage: \"Writing the page “{title}”\",\n searchesDocuments: \"Searching the documents: {query}\",\n searchesKnowledge: \"Searching knowledge: {query} – {relevant} of {candidates} fit\",\n listsKnowledge: \"Listing knowledge\",\n searchesMail: \"Searching {label}\",\n savesReceipts: {\n one: \"Saving {count} receipt from {label}\",\n other: \"Saving {count} receipts from {label}\",\n },\n remembers: \"Remembering {title}\",\n files: { one: \"Filing {count} file\", other: \"Filing {count} files\" },\n filmSetup: \"Setting up the folder for the film\",\n filmClient: \"{client} is working on the film – this usually takes 10–40 minutes.\",\n filmTask: \"On the film: {task}\",\n filmLooks: \"Looking at frames of the film\",\n filmFix: \"The film didn’t render – Claude Code is fixing it\",\n filmResume: \"Picking the film up where it stopped\",\n wizardUnavailable: \"This wizard isn’t available right now.\",\n translationFailed: \"This wizard can’t be translated right now. It’s shown as it was written.\",\n translationOff: \"This wizard is only offered as it was written.\",\n translationPlaceholder:\n \"The translation of “{text}” needs every placeholder in curly brackets the original has.\",\n wizardLimit: \"This wizard has reached its limit for today. Try again tomorrow.\",\n confirmHuman: \"Confirm that you’re a person.\",\n tooManyRuns: \"You’ve started a lot of runs just now. Try again in an hour.\",\n clientRefused: \"This app may not start runs here.\",\n clientLimit: \"This app has started a lot of runs just now. Try again later.\",\n runOver: \"The run is over.\",\n runBusy: \"The wizard is working right now.\",\n pageOutdated: \"This page is out of date.\",\n noStepBefore: \"There is no step before this one.\",\n checkFields: \"Check the marked fields.\",\n talkOff: \"Live conversations aren’t turned on for this wizard.\",\n talkKeyRefused: \"The conversation couldn’t start: the OpenAI API key was refused.\",\n talkFailed: \"The conversation couldn’t start ({status}).\",\n talkNoSecret: \"The conversation couldn’t start: no access key came back.\",\n tryLater: \"Try again later.\",\n recordingTooLarge: \"The recording can be 10 MB at most.\",\n fileTooLarge: \"Choose a file of {mb} MB or less.\",\n uploadNotPicture: \"This file isn’t a picture that can be read. Choose a PNG, JPEG, WebP or GIF.\",\n uploadPictureTooLarge: \"This picture is too large. Choose one of {mp} megapixels or less.\",\n uploadNotItsType: \"This file holds something other than its type says. Choose the file again.\",\n uploadSvgNotUsable: \"This SVG can’t be used. Save it again as a plain SVG, or choose a PNG.\",\n askClosed: \"This question is no longer open.\",\n noBrowser: \"The wizard has no browser open right now.\",\n notWaiting: \"The wizard isn’t waiting for you right now.\",\n pageActFailed: \"That didn’t work on the page.\",\n linkGone: \"This link has expired or was withdrawn.\",\n connected: \"Connected. You can close this window.\",\n connectFailed: \"Connecting didn’t work. Try again.\",\n connectCancelled: \"Connecting was cancelled.\",\n appleOff:\n \"Apple Intelligence is turned off on this Mac. Turn it on in System Settings → Apple Intelligence & Siri.\",\n appleLoading:\n \"Apple is still loading the model for Apple Intelligence onto this Mac. Try again in a moment.\",\n appleMissing: \"The helper for Apple Intelligence (wizards-apple) is missing from this install.\",\n appleOs: \"Apple Intelligence needs macOS 26 or later.\",\n appleDevice: \"Apple Intelligence only works on a Mac with Apple silicon.\",\n appleBusy: \"Apple Intelligence isn’t taking more requests right now. Try again in a moment.\",\n appleTooLong:\n \"The text is too long for Apple Intelligence on this Mac (4,096 tokens for question and answer). Choose another model for this class under Settings → Models.\",\n appleRefused: \"Apple Intelligence turned the request down: Apple’s content rules don’t allow it.\",\n appleLanguage: \"Apple Intelligence doesn’t understand the language of this request.\",\n appleFormat: \"Apple Intelligence can’t answer in this format: {detail}\",\n appleFailed: \"Apple Intelligence: {detail}\",\n appleNoFfmpeg:\n \"Apple Intelligence can’t read {type}, and without ffmpeg the recording can’t be converted. Install ffmpeg or record as MP4 in the browser.\",\n appleNotConverted: \"Apple Intelligence couldn’t convert the recording: {detail}\",\n connectorAlreadyExistsSpace: \"The connector “{id}” already exists in this space.\",\n connectorNotExist: \"This connector doesn’t exist.\",\n fieldMissing: \"“{label}” is missing.\",\n mailServerNotExist:\n \"The mail server{host} doesn’t exist. Enter the IMAP server. For Gmail and Google Workspace, it’s imap.gmail.com.\",\n mailServerNotResponding:\n \"The mail server{host} isn’t responding. Check the IMAP server and port.\",\n connectingNotWork: \"Connecting didn’t work{host}: {detail}\",\n connectEngentyAccountFirst:\n \"Connect your engenty account first (Settings → Account). Then you can connect Google here.\",\n engentyAccountNotReached: \"Your engenty account can’t be reached right now. Try again later.\",\n googleNoLongerAccepts: \"Google no longer accepts this connection. Connect the account again.\",\n googleNotConnectedThrough: \"Google can’t be connected through your engenty account right now.\",\n stepNeedsToolPlugin:\n \"This step needs the tool “{id}”. The plugin “{plugin}” isn’t installed here.\",\n clientNotSignedIn: \"{name} isn’t signed in on this computer. Sign in under Settings → Models.\",\n clientNotInstalled:\n \"{name} isn’t installed on this computer. Install it under Settings → Models.\",\n clientNoCredit: \"The account {name} is signed in with has no credit or quota left.\",\n clientAccountNotServed:\n \"{name} no longer serves the account it is signed in with. Sign it in with another account, or choose another way under Settings → Models.\",\n anthropicAccountClaudeCode:\n \"The Anthropic account Claude Code is signed in with has no credit. Sign Claude Code in with your subscription under Settings → Models.\",\n chatgptAccountCodexSigned:\n \"The ChatGPT account Codex is signed in with has used up its quota. Try again later or choose another client.\",\n builtTerminalNotAvailable:\n \"The built-in terminal isn’t available on this computer. Run the command in your own terminal.\",\n terminalNoLongerExists: \"This terminal no longer exists.\",\n imageTypeNotReadable: \"Images of type {mime} can’t be read (PNG, JPEG and WebP work).\",\n fileNotReadable: \"“{name}” ({mime}) can’t be read.\",\n creditsNotSignedIn: \"This is set to run on credits, but you’re not signed in to an account.\",\n accountNoLongerSigned:\n \"The account is no longer signed in. Sign in again under Settings → Account.\",\n modelNotUsedYet:\n \"The model “{ref}” can’t be used yet. Add an API key under Settings → Models, or sign in to an account.\",\n noModelForImages: \"No model is set up for images.\",\n noModelForVideos: \"No model is set up for videos.\",\n noModelForSpeech: \"No model is set up for speech.\",\n noOpenaiApiKey: \"No OpenAI API key is set for voice conversations (Settings → Models).\",\n modelNotAvailableAccount: \"This model isn’t available with your account.\",\n accountNoModelSet: \"Your account has no model set up for this.\",\n claudeCodeMakesFilms:\n \"Claude Code makes films on this computer, using your subscription. Set it up as an AI subscription under Settings → Models.\",\n macNeedsFfmpegTranscribe:\n \"This Mac needs ffmpeg to transcribe recordings from Chrome or Firefox (WebM, Ogg). Safari and the app don’t. Install ffmpeg, e.g. with “brew install ffmpeg”.\",\n fieldRequired: \"Required\",\n chooseAtLeast: \"Choose at least {min}\",\n chooseAtMost: \"At most {max} – remove some\",\n enterNumber: \"Enter a number\",\n invalidChoice: \"Invalid choice\",\n timeNotOffered: \"This time isn’t offered\",\n notValidEmailAddress: \"Not a valid email address\",\n notValidUrl: \"Not a valid URL\",\n wizardRunOutCredits: \"This wizard has run out of credits for now. Try again later.\",\n providerCreditLow:\n \"Your credit with the model provider isn’t enough for this (videos need a minimum balance there). Top up there and try again.\",\n aiServiceBusyRight: \"The AI service is busy right now. Try again in a moment.\",\n stepTookTooLong: \"The step took too long. Try again.\",\n aiServiceNotReached: \"The AI service can’t be reached right now. Try again later.\",\n notAvailableNow: \"That isn’t available here right now.\",\n fileNotFound: \"File not found\",\n connectFirst: \"Connect first\",\n noEntriesStepWork: \"There are no entries for this step to work on.\",\n stepNotReturnResult: \"The step didn’t return a result.\",\n documentNotCreated: \"The document couldn’t be created.\",\n stepMissingSourcesImages: \"This step is missing its sources (images or scenes).\",\n noTextReadAloud: \"There is no text to read aloud.\",\n wizardStillErrors: \"The wizard still has errors.\",\n noLanguageModelSet: \"No language model is set up here.\",\n creditsUsedUp: \"Your credits are used up.\",\n chooseFile: \"Choose a file.\",\n pageNotReached: \"The page can’t be reached.\",\n unknownEntry: \"Unknown entry.\",\n chooseWizardFileMb: \"Choose a wizard file ({PACKAGE_EXTENSION}) of 30 MB or less.\",\n recordingMbMost: \"The recording can be 10 MB at most.\",\n onlyFinishedResultsShared: \"Only finished results can be shared.\",\n gradientFailed: \"Couldn’t make a gradient from that. Try describing it differently.\",\n onlyOneSpaceAllowed: \"Only one space is allowed here.\",\n mostSpaces: {\n one: \"You can have at most {count} space here.\",\n other: \"You can have at most {count} spaces here.\",\n },\n twoEntriesSameKey: \"Two entries have the same key.\",\n notDeleteLastSpace: \"You can’t delete the last space.\",\n notFound: \"This doesn’t exist or was deleted.\",\n categoryNeedsName: \"A category needs a name.\",\n unknownCategoryType: \"Unknown type “{type}”.\",\n spaceMostCategories: {\n one: \"A space can have at most {count} category.\",\n other: \"A space can have at most {count} categories.\",\n },\n categoryAlreadyExists: \"The category “{name}” already exists.\",\n onlyChoiceCategoriesValues: \"Only choice categories have values.\",\n onlyValuesOneCategory: \"Only values of one category can be merged.\",\n templateNeedsNewerVersion:\n \"This template needs a newer version of engenty wizards. Update engenty wizards first.\",\n chatNotExist: \"This chat doesn’t exist.\",\n unknownRunner: \"There’s no runner “{unknown}” here.\",\n leastOneRunnerStay: \"At least one runner has to stay on.\",\n linkOpenRunnerTurned: \"The link has to open a runner that’s turned on.\",\n jobNotExistAlready: \"This job doesn’t exist or has already finished.\",\n accountAlreadySpace: \"This account already has a space here.\",\n accountAlreadySpaces: {\n one: \"This account already has {count} space here.\",\n other: \"This account already has {count} spaces here.\",\n },\n roomMostPublishedWizards: {\n one: \"There’s room for at most {count} published wizard here.\",\n other: \"There’s room for at most {count} published wizards here.\",\n },\n spaceIdAlreadyExists:\n \"A space with this ID already exists here and didn’t come from your computer.\",\n wizardIdAlreadyBelongs: \"A wizard with this ID already belongs to another space here.\",\n idAlreadyUse: \"This ID is already in use here.\",\n wizardNotSpace: \"This wizard isn’t in the space.\",\n invalidColumns: \"Invalid columns.\",\n spaceMostTables: {\n one: \"A space can have at most {count} table.\",\n other: \"A space can have at most {count} tables.\",\n },\n tableBelongsOneWizard:\n \"This table belongs to one of the wizard’s lists. Its columns come from the wizard.\",\n entryAlreadyExists: \"This entry already exists.\",\n tableMostRows: {\n one: \"A table can have at most {count} row.\",\n other: \"A table can have at most {count} rows.\",\n },\n spaceMostPages: {\n one: \"A space can have at most {count} page.\",\n other: \"A space can have at most {count} pages.\",\n },\n pageNotSubpages: \"This page can’t have subpages.\",\n pageNotOwnSubpage: \"A page can’t be its own subpage.\",\n pageNeedsTitle: \"A page needs a title.\",\n unknownSpace: \"There’s no space “{space}”.\",\n noParentPage: \"There’s no page with the key “{parent}” to put this page under.\",\n onlyTeamAdmins:\n \"Only team admins can do that. As a member, you can edit the wizards that already exist.\",\n spaceEditedLocally: \"You edit this space in engenty wizards on your computer, not here.\",\n wizardsRunOncePublished:\n \"Wizards run here once you publish them in engenty wizards on your computer. You build and edit them there.\",\n logoImagePngSvg: \"A logo is an image (PNG, SVG, JPEG, WebP).\",\n patternImageSvgPng: \"A pattern is an image (SVG, PNG, JPEG, WebP).\",\n filesGoHere:\n \"Images, videos, audio, PDFs, fonts, Lottie and 3D models go here. Texts to look things up in go under knowledge.\",\n addressNotReached: \"The address can’t be reached.\",\n addressResponded: \"The address responded with {status}.\",\n addressLeadsWebPage: \"The address leads to a web page, not an image.\",\n addressFileTooLarge: \"The file is too large.\",\n onlyDocumentsIndex: \"Only documents are in the index.\",\n emptyTooLargeDocument: \"“{name}” is empty or too large for a document.\",\n spaceMostDocuments: {\n one: \"A space can have at most {count} document.\",\n other: \"A space can have at most {count} documents.\",\n },\n accountSignedOut: \"The account is signed out. Sign in again.\",\n cloudNotReachedRight: \"The cloud can’t be reached right now.\",\n publishWizardFirst: \"Publish the wizard first.\",\n wizardJsonUnreadable: \"This isn’t a wizard file: its wizard.json can’t be read.\",\n wizardFileComesNewer:\n \"This wizard file comes from a newer version, or it’s damaged. Update engenty wizards or export the wizard again.\",\n fileOver5Mb: \"{name} is larger than 5 MB.\",\n wizardFileTooLarge:\n \"The wizard file is too large: a workspace holds at most 200 files and 25 MB.\",\n wizardFileNotOpened:\n \"The wizard file can’t be opened. Export the wizard again and try once more.\",\n wizardJsonMissing: \"This isn’t a wizard file: wizard.json is missing.\",\n notValidFilePath: \"“{name}” isn’t a valid file path.\",\n workspaceWizardFileLarger: \"The workspace in the wizard file is larger than 25 MB.\",\n unknownTemplate: \"There’s no template “{starterId}”.\",\n wizardChangedMeantime: \"The wizard was changed in the meantime.\",\n valueNotExist: \"This value doesn’t exist.\",\n nothingFiledUnderValue: \"Nothing is filed under this value yet.\",\n filmNotRenderedNeeds:\n \"The film couldn’t be rendered. It needs ffmpeg and a timeline in the widget.\",\n signInRefused:\n \"The sign-in was refused{host}. Are the address and (app) password right? Gmail and Google Workspace need an app password and IMAP turned on.{answer}\",\n serverSaid: \" The server said: {answer}\",\n viaAccountFailed: \"Connecting through your engenty account didn’t work ({code}).\",\n pluginInvalidInput: \"“{id}” got invalid input: {path} – {problem}\",\n filmClientStopped:\n \"{name} stopped working on the film: {detail}. The work is saved. A new try carries on from there.\",\n filmWorkSaved: \"{problem} The work is saved. A new try carries on from there.\",\n filmRenderFailed: \"The film couldn’t be rendered: {detail}\",\n commandNotStarted: \"The command couldn’t start: {detail}\",\n providerKeyMissing: \"{provider} is chosen for {makes}, but no API key is set.\",\n noModelFor: \"No model is set up for {makes}.\",\n noApiKeyFor: \"No API key is set for {provider}.\",\n freeTier:\n \"Your AI Gateway key is on Vercel’s free tier, which doesn’t include {model}. Top up at Vercel ({url}) or choose another model under Settings → Models.\",\n thisModel: \"this model\",\n quoted: \"“{text}”\",\n viewErrors: \"The view has errors: {detail}\",\n blockedSteps: \"{steps}: {problem}\",\n joined: \"{first} {second}\",\n stepFailed: \"This step failed: {detail}\",\n answersMissing: \"Answers are missing or don’t fit: {answers}\",\n fieldError: \"{field} – {message}\",\n templateNeedsPlugins: {\n one: \"This template needs the plugin {plugins}: included with Pro on engenty.ai.\",\n other: \"This template needs the plugins {plugins}: included with Pro on engenty.ai.\",\n },\n pageMostChars: {\n one: \"A page can have at most {count} character.\",\n other: \"A page can have at most {count} characters.\",\n },\n chooseFileUpTo: \"Choose a file of {mb} MB or less.\",\n fontSourceNoFont: \"{family} needs a font file of the space: choose a .woff2 from the assets.\",\n roomMostFiles: {\n one: \"There’s room for at most {count} file here.\",\n other: \"There’s room for at most {count} files here.\",\n },\n makesText: \"text\",\n makesImages: \"images\",\n makesVideos: \"videos\",\n makesSpeech: \"speech\",\n makesVoiceNotes: \"voice notes\",\n} as const satisfies Record<string, Line>;\nexport type RunNoteCode = keyof typeof NOTES_EN;\n\nconst NOTES_DE: Partial<Record<RunNoteCode, Line>> = {\n entry: \"Eintrag {n} von {total}\",\n deciding: \"Entscheidet, wie es weitergeht …\",\n choosingFields: \"Wählt die passenden Fragen …\",\n batchDone: \"{done} von {total} fertig\",\n editing: \"Bearbeitet {n} von {total}\",\n filming: \"Dreht {n} von {total}\",\n clipsRendering: {\n one: \"{count} Clip wird gerendert – das dauert einige Minuten.\",\n other: \"{count} Clips werden gerendert – das dauert einige Minuten.\",\n },\n videoRendering: \"Das Video wird gerendert – das dauert meist 1–3 Minuten.\",\n photo: \"Sieht sich Foto {n} von {total} an\",\n found: \"{label}: {name}\",\n listen: \"Hört „{label}“ an …\",\n listenFailed: \"„{label}“ konnte nicht verschriftlicht werden.\",\n filmCutting: \"Der Film wird geschnitten – das dauert etwa eine Minute.\",\n filmProgress: \"{pct} % geschnitten\",\n filmError: \"Der Film meldet: {detail}\",\n widgetError: \"Das Widget meldet einen Fehler: {detail}\",\n mcpConnected: \"Verbunden mit {names}\",\n mcpUnreachable: \"MCP-Server nicht erreichbar: {detail}\",\n reads: \"Liest {name}\",\n readsMany: { one: \"Liest {count} Dokument\", other: \"Liest {count} Dokumente\" },\n opens: \"Öffnet {name}\",\n clicks: \"Klickt im Browser\",\n clicksOn: \"Klickt auf „{name}“\",\n types: \"Tippt im Browser\",\n typesText: \"Tippt „{text}“\",\n selects: \"Wählt „{option}“\",\n scrolls: \"Scrollt\",\n presses: \"Drückt {key}\",\n goesBack: \"Geht eine Seite zurück\",\n waitsForPage: \"Wartet auf die Seite\",\n fastLoop: \"Erledigt im Browser: {goal}\",\n personDrives: \"Du steuerst den Browser – der Wizard wartet\",\n agentDrives: \"Der Wizard macht im Browser weiter\",\n looksAtPage: \"Sieht sich die Seite an\",\n waitsForSignIn: \"Wartet auf deine Anmeldung bei {name}\",\n downloads: \"Lädt {name} herunter\",\n attaches: \"Hängt {name} an\",\n runs: \"Führt aus: {command}\",\n runsProgram: \"Arbeitet die Daten in einem Zug durch\",\n python: \"Führt Python aus\",\n drawing: \"Zeichnet ein Bild\",\n writesPage: \"Schreibt die Seite „{title}“\",\n searchesDocuments: \"Sucht in den Dokumenten: {query}\",\n searchesKnowledge: \"Sucht in Wissen: {query} – {relevant} von {candidates} passen\",\n listsKnowledge: \"Listet Wissen\",\n searchesMail: \"Durchsucht {label}\",\n savesReceipts: {\n one: \"Speichert {count} Beleg aus {label}\",\n other: \"Speichert {count} Belege aus {label}\",\n },\n remembers: \"Merkt sich {title}\",\n files: { one: \"Legt {count} Datei ab\", other: \"Legt {count} Dateien ab\" },\n filmSetup: \"Richtet den Arbeitsordner für den Film ein\",\n filmClient: \"{client} arbeitet am Film – das dauert meist 10–40 Minuten.\",\n filmTask: \"Am Film: {task}\",\n filmLooks: \"Sieht sich Bilder des Films an\",\n filmFix: \"Der Film ließ sich nicht rendern – Claude Code bessert nach\",\n filmResume: \"Macht dort weiter, wo der Film stehen geblieben ist\",\n wizardUnavailable: \"Dieser Wizard ist gerade nicht verfügbar.\",\n translationFailed:\n \"Dieser Wizard lässt sich gerade nicht übersetzen. Du siehst ihn so, wie er geschrieben wurde.\",\n translationOff: \"Diesen Wizard gibt es nur so, wie er geschrieben wurde.\",\n translationPlaceholder:\n \"Die Übersetzung von „{text}“ braucht jeden Platzhalter in geschweiften Klammern, den das Original hat.\",\n wizardLimit: \"Für heute ist das Limit dieses Wizards erreicht. Versuch es morgen wieder.\",\n confirmHuman: \"Bestätige kurz, dass du ein Mensch bist.\",\n tooManyRuns: \"Du hast gerade viele Läufe gestartet. Versuch es in einer Stunde wieder.\",\n clientRefused: \"Diese App darf hier keine Läufe starten.\",\n clientLimit: \"Diese App hat gerade viele Läufe gestartet. Versuch es später wieder.\",\n runOver: \"Der Lauf ist beendet.\",\n runBusy: \"Der Wizard arbeitet gerade.\",\n pageOutdated: \"Diese Seite ist nicht mehr aktuell.\",\n noStepBefore: \"Kein vorheriger Schritt.\",\n checkFields: \"Prüf die markierten Felder.\",\n talkOff: \"Live-Gespräche sind für diesen Wizard nicht eingeschaltet.\",\n talkKeyRefused: \"Das Gespräch ließ sich nicht starten: Der OpenAI-API-Key wurde abgelehnt.\",\n talkFailed: \"Das Gespräch ließ sich nicht starten ({status}).\",\n talkNoSecret: \"Das Gespräch ließ sich nicht starten: Es kam kein Zugang zurück.\",\n tryLater: \"Versuch es später noch einmal.\",\n recordingTooLarge: \"Die Aufnahme darf höchstens 10 MB groß sein.\",\n fileTooLarge: \"Wähl eine Datei bis {mb} MB.\",\n uploadNotPicture: \"Diese Datei ist kein lesbares Bild. Wähl ein PNG, JPEG, WebP oder GIF.\",\n uploadPictureTooLarge: \"Dieses Bild ist zu groß. Wähl eins mit höchstens {mp} Megapixeln.\",\n uploadNotItsType:\n \"In dieser Datei steckt etwas anderes, als ihr Typ sagt. Wähl die Datei noch einmal.\",\n uploadSvgNotUsable: \"Dieses SVG geht nicht. Speicher es neu als einfaches SVG oder wähl ein PNG.\",\n askClosed: \"Diese Frage ist nicht mehr offen.\",\n noBrowser: \"Der Wizard hat gerade keinen Browser offen.\",\n notWaiting: \"Der Wizard wartet gerade nicht auf dich.\",\n pageActFailed: \"Das hat auf der Seite nicht geklappt.\",\n linkGone: \"Dieser Link ist abgelaufen oder wurde zurückgezogen.\",\n connected: \"Verbunden. Du kannst dieses Fenster schließen.\",\n connectFailed: \"Verbinden hat nicht geklappt. Versuch es noch einmal.\",\n connectCancelled: \"Verbinden wurde abgebrochen.\",\n appleOff:\n \"Apple Intelligence ist auf diesem Mac ausgeschaltet. Schalte es unter Systemeinstellungen → Apple Intelligence & Siri ein.\",\n appleLoading:\n \"Apple lädt das Modell für Apple Intelligence noch auf diesen Mac. Versuch es gleich noch einmal.\",\n appleMissing: \"Der Helfer für Apple Intelligence (wizards-apple) fehlt in dieser Installation.\",\n appleOs: \"Apple Intelligence braucht macOS 26 oder neuer.\",\n appleDevice: \"Apple Intelligence gibt es nur auf einem Mac mit Apple Silicon.\",\n appleBusy:\n \"Apple Intelligence nimmt gerade keine weiteren Anfragen an. Versuch es gleich noch einmal.\",\n appleTooLong:\n \"Der Text ist zu lang für Apple Intelligence auf diesem Mac (4.096 Tokens für Frage und Antwort). Wähle unter Einstellungen → Modelle ein anderes Modell für diese Klasse.\",\n appleRefused:\n \"Apple Intelligence hat die Anfrage abgelehnt: Apples Inhaltsregeln lassen sie nicht zu.\",\n appleLanguage: \"Apple Intelligence versteht die Sprache dieser Anfrage nicht.\",\n appleFormat: \"Apple Intelligence kann dieses Antwortformat nicht liefern: {detail}\",\n appleFailed: \"Apple Intelligence: {detail}\",\n appleNoFfmpeg:\n \"Apple Intelligence liest {type} nicht, und ohne ffmpeg lässt sich die Aufnahme nicht umwandeln. Installiere ffmpeg oder nimm im Browser als MP4 auf.\",\n appleNotConverted: \"Apple Intelligence konnte die Aufnahme nicht umwandeln: {detail}\",\n connectorAlreadyExistsSpace: \"Den Connector „{id}“ gibt es in diesem Space schon.\",\n connectorNotExist: \"Diesen Connector gibt es nicht.\",\n fieldMissing: \"„{label}“ fehlt.\",\n mailServerNotExist:\n \"Den Mail-Server{host} gibt es nicht. Trag den IMAP-Server ein, bei Gmail und Google Workspace imap.gmail.com.\",\n mailServerNotResponding: \"Der Mail-Server{host} antwortet nicht. Prüf IMAP-Server und Port.\",\n connectingNotWork: \"Verbinden hat nicht geklappt{host}: {detail}\",\n connectEngentyAccountFirst:\n \"Verbinde zuerst dein engenty-Konto (Einstellungen → Konto). Dann kannst du Google hier verbinden.\",\n engentyAccountNotReached:\n \"Dein engenty-Konto ist gerade nicht erreichbar. Versuch es später noch einmal.\",\n googleNoLongerAccepts: \"Google nimmt diese Verbindung nicht mehr an. Verbinde das Konto neu.\",\n googleNotConnectedThrough: \"Google lässt sich über dein engenty-Konto gerade nicht verbinden.\",\n stepNeedsToolPlugin:\n \"Dieser Schritt braucht das Werkzeug „{id}“. Das Plugin „{plugin}“ ist hier nicht installiert.\",\n clientNotSignedIn:\n \"{name} ist auf diesem Computer nicht angemeldet. Melde dich unter Einstellungen → Modelle an.\",\n clientNotInstalled:\n \"{name} ist auf diesem Computer nicht installiert. Installiere es unter Einstellungen → Modelle.\",\n clientNoCredit:\n \"Das Konto, mit dem {name} angemeldet ist, hat kein Guthaben oder Kontingent mehr.\",\n clientAccountNotServed:\n \"{name} bedient das Konto, mit dem es angemeldet ist, nicht mehr. Melde es mit einem anderen Konto an oder wähle unter Einstellungen → Modelle einen anderen Weg.\",\n anthropicAccountClaudeCode:\n \"Das Anthropic-Konto, mit dem Claude Code angemeldet ist, hat kein Guthaben. Melde Claude Code unter Einstellungen → Modelle mit deinem Abo an.\",\n chatgptAccountCodexSigned:\n \"Das Kontingent des ChatGPT-Kontos, mit dem Codex angemeldet ist, ist aufgebraucht. Versuch es später noch einmal oder wähle einen anderen Client.\",\n builtTerminalNotAvailable:\n \"Das eingebaute Terminal ist auf diesem Computer nicht verfügbar. Führe den Befehl in deinem eigenen Terminal aus.\",\n terminalNoLongerExists: \"Dieses Terminal gibt es nicht mehr.\",\n imageTypeNotReadable: \"Bilder vom Typ {mime} lassen sich nicht lesen (PNG, JPEG und WebP gehen).\",\n fileNotReadable: \"„{name}“ ({mime}) lässt sich nicht lesen.\",\n creditsNotSignedIn: \"Dafür sind Credits gewählt, aber du bist mit keinem Konto angemeldet.\",\n accountNoLongerSigned:\n \"Das Konto ist nicht mehr angemeldet. Melde dich unter Einstellungen → Konto neu an.\",\n modelNotUsedYet:\n \"Das Modell „{ref}“ lässt sich noch nicht nutzen. Hinterleg unter Einstellungen → Modelle einen API-Key oder melde dich mit einem Konto an.\",\n noModelForImages: \"Für Bilder ist kein Modell eingerichtet.\",\n noModelForVideos: \"Für Videos ist kein Modell eingerichtet.\",\n noModelForSpeech: \"Für Sprachausgabe ist kein Modell eingerichtet.\",\n noOpenaiApiKey:\n \"Für Sprachgespräche ist kein OpenAI-API-Key hinterlegt (Einstellungen → Modelle).\",\n modelNotAvailableAccount: \"Dieses Modell gibt es mit deinem Konto nicht.\",\n accountNoModelSet: \"Dafür ist bei deinem Konto kein Modell eingerichtet.\",\n claudeCodeMakesFilms:\n \"Filme macht Claude Code auf diesem Computer mit deinem Abo. Richte es unter Einstellungen → Modelle als KI-Abo ein.\",\n macNeedsFfmpegTranscribe:\n \"Aufnahmen aus Chrome oder Firefox (WebM, Ogg) schreibt dieser Mac erst mit ffmpeg auf. Safari und die App brauchen es nicht. Installiere ffmpeg, z. B. mit „brew install ffmpeg“.\",\n fieldRequired: \"Pflichtfeld\",\n chooseAtLeast: \"Wähl mindestens {min} aus\",\n chooseAtMost: \"Höchstens {max} – entferne einige\",\n enterNumber: \"Gib eine Zahl ein\",\n invalidChoice: \"Ungültige Auswahl\",\n timeNotOffered: \"Dieser Termin wird nicht angeboten\",\n notValidEmailAddress: \"Keine gültige E-Mail-Adresse\",\n notValidUrl: \"Keine gültige URL\",\n wizardRunOutCredits:\n \"Dieser Wizard hat gerade kein Guthaben mehr. Versuch es später noch einmal.\",\n providerCreditLow:\n \"Das Guthaben beim Modellanbieter reicht dafür nicht aus (Videos brauchen dort ein Mindestguthaben). Lade dort auf und versuch es noch einmal.\",\n aiServiceBusyRight: \"Der KI-Dienst ist gerade ausgelastet. Versuch es gleich noch einmal.\",\n stepTookTooLong: \"Der Schritt hat zu lange gedauert. Versuch es noch einmal.\",\n aiServiceNotReached: \"Der KI-Dienst ist gerade nicht erreichbar. Versuch es später noch einmal.\",\n notAvailableNow: \"Das ist hier gerade nicht verfügbar.\",\n fileNotFound: \"Datei nicht gefunden\",\n connectFirst: \"Verbinde zuerst\",\n noEntriesStepWork: \"Es gibt keine Einträge, für die dieser Schritt arbeiten könnte.\",\n stepNotReturnResult: \"Der Schritt hat kein Ergebnis geliefert.\",\n documentNotCreated: \"Das Dokument konnte nicht erstellt werden.\",\n stepMissingSourcesImages: \"Für diesen Schritt fehlen die Vorlagen (Bilder oder Szenen).\",\n noTextReadAloud: \"Es gibt keinen Text zum Vorlesen.\",\n wizardStillErrors: \"Der Wizard hat noch Fehler.\",\n noLanguageModelSet: \"Hier ist kein Sprachmodell eingerichtet.\",\n creditsUsedUp: \"Dein Guthaben ist aufgebraucht.\",\n chooseFile: \"Wähl eine Datei.\",\n pageNotReached: \"Die Seite ist nicht erreichbar.\",\n unknownEntry: \"Unbekannter Eintrag.\",\n chooseWizardFileMb: \"Wähl eine Wizard-Datei ({PACKAGE_EXTENSION}) bis 30 MB.\",\n recordingMbMost: \"Die Aufnahme darf höchstens 10 MB groß sein.\",\n onlyFinishedResultsShared: \"Nur fertige Ergebnisse lassen sich teilen.\",\n gradientFailed: \"Daraus ließ sich kein Verlauf machen. Beschreib ihn anders.\",\n onlyOneSpaceAllowed: \"Hier ist nur ein Space möglich.\",\n mostSpaces: {\n one: \"Hier ist höchstens {count} Space möglich.\",\n other: \"Hier sind höchstens {count} Spaces möglich.\",\n },\n twoEntriesSameKey: \"Zwei Einträge haben denselben Schlüssel.\",\n notDeleteLastSpace: \"Der letzte Space lässt sich nicht löschen.\",\n notFound: \"Das gibt es nicht oder nicht mehr.\",\n categoryNeedsName: \"Eine Kategorie braucht einen Namen.\",\n unknownCategoryType: \"Unbekannter Typ „{type}“.\",\n spaceMostCategories: {\n one: \"Ein Space hat höchstens {count} Kategorie.\",\n other: \"Ein Space hat höchstens {count} Kategorien.\",\n },\n categoryAlreadyExists: \"Die Kategorie „{name}“ gibt es schon.\",\n onlyChoiceCategoriesValues: \"Werte gibt es nur bei Kategorien vom Typ Auswahl.\",\n onlyValuesOneCategory: \"Nur Werte einer Kategorie lassen sich zusammenführen.\",\n templateNeedsNewerVersion:\n \"Diese Vorlage braucht eine neuere Version von engenty wizards. Aktualisiere zuerst engenty wizards.\",\n chatNotExist: \"Diesen Chat gibt es nicht.\",\n unknownRunner: \"Einen Runner „{unknown}“ gibt es hier nicht.\",\n leastOneRunnerStay: \"Mindestens ein Runner muss eingeschaltet bleiben.\",\n linkOpenRunnerTurned: \"Der Link muss einen eingeschalteten Runner öffnen.\",\n jobNotExistAlready: \"Diesen Vorgang gibt es nicht, oder er ist schon beendet.\",\n accountAlreadySpace: \"Dieses Konto hat hier schon einen Space.\",\n accountAlreadySpaces: {\n one: \"Dieses Konto hat hier schon {count} Space.\",\n other: \"Dieses Konto hat hier schon {count} Spaces.\",\n },\n roomMostPublishedWizards: {\n one: \"Hier hat höchstens {count} veröffentlichter Wizard Platz.\",\n other: \"Hier haben höchstens {count} veröffentlichte Wizards Platz.\",\n },\n spaceIdAlreadyExists:\n \"Einen Space mit dieser Kennung gibt es hier schon, und er kommt nicht von deinem Computer.\",\n wizardIdAlreadyBelongs: \"Ein Wizard mit dieser Kennung gehört hier schon zu einem anderen Space.\",\n idAlreadyUse: \"Diese Kennung ist hier schon vergeben.\",\n wizardNotSpace: \"Diesen Wizard gibt es im Space nicht.\",\n invalidColumns: \"Ungültige Spalten.\",\n spaceMostTables: {\n one: \"Ein Space hat höchstens {count} Tabelle.\",\n other: \"Ein Space hat höchstens {count} Tabellen.\",\n },\n tableBelongsOneWizard:\n \"Diese Tabelle gehört zu einer Liste des Wizards. Die Spalten kommen aus dem Wizard.\",\n entryAlreadyExists: \"Diesen Eintrag gibt es schon.\",\n tableMostRows: {\n one: \"Eine Tabelle hat höchstens {count} Zeile.\",\n other: \"Eine Tabelle hat höchstens {count} Zeilen.\",\n },\n spaceMostPages: {\n one: \"Ein Space hat höchstens {count} Seite.\",\n other: \"Ein Space hat höchstens {count} Seiten.\",\n },\n pageNotSubpages: \"Diese Seite kann keine Unterseiten haben.\",\n pageNotOwnSubpage: \"Eine Seite kann nicht ihre eigene Unterseite sein.\",\n pageNeedsTitle: \"Eine Seite braucht einen Titel.\",\n unknownSpace: \"Den Space „{space}“ gibt es nicht.\",\n noParentPage: \"Es gibt keine Seite mit dem Schlüssel „{parent}“, unter die diese Seite könnte.\",\n onlyTeamAdmins:\n \"Das dürfen nur Admins des Teams. Als Mitglied bearbeitest du die Wizards, die es schon gibt.\",\n spaceEditedLocally:\n \"Diesen Space bearbeitest du in engenty wizards auf deinem Computer, nicht hier.\",\n wizardsRunOncePublished:\n \"Hier laufen die Wizards, die du in engenty wizards auf deinem Computer veröffentlichst. Gebaut und bearbeitet wird dort.\",\n logoImagePngSvg: \"Ein Logo ist ein Bild (PNG, SVG, JPEG, WebP).\",\n patternImageSvgPng: \"Ein Muster ist ein Bild (SVG, PNG, JPEG, WebP).\",\n filesGoHere:\n \"Hierher gehören Bilder, Videos, Audio, PDFs, Schriften, Lottie und 3D-Modelle. Texte zum Nachschlagen gehören ins Wissen.\",\n addressNotReached: \"Die Adresse ist nicht erreichbar.\",\n addressResponded: \"Die Adresse antwortete mit {status}.\",\n addressLeadsWebPage: \"Unter der Adresse steht eine Webseite, kein Bild.\",\n addressFileTooLarge: \"Die Datei ist zu groß.\",\n onlyDocumentsIndex: \"Nur Dokumente stehen im Index.\",\n emptyTooLargeDocument: \"„{name}“ ist leer oder zu groß für ein Dokument.\",\n spaceMostDocuments: {\n one: \"Ein Space hat höchstens {count} Dokument.\",\n other: \"Ein Space hat höchstens {count} Dokumente.\",\n },\n accountSignedOut: \"Das Konto ist abgemeldet. Melde dich neu an.\",\n cloudNotReachedRight: \"Die Cloud ist gerade nicht erreichbar.\",\n publishWizardFirst: \"Veröffentliche den Wizard zuerst.\",\n wizardJsonUnreadable: \"Das ist keine Wizard-Datei: Die wizard.json darin lässt sich nicht lesen.\",\n wizardFileComesNewer:\n \"Diese Wizard-Datei stammt aus einer neueren Version oder ist beschädigt. Aktualisiere engenty wizards oder exportiere den Wizard neu.\",\n fileOver5Mb: \"{name} ist größer als 5 MB.\",\n wizardFileTooLarge:\n \"Die Wizard-Datei ist zu groß: Ein Arbeitsbereich fasst höchstens 200 Dateien und 25 MB.\",\n wizardFileNotOpened:\n \"Die Wizard-Datei lässt sich nicht öffnen. Exportiere den Wizard neu und versuche es noch einmal.\",\n wizardJsonMissing: \"Das ist keine Wizard-Datei: Die wizard.json fehlt.\",\n notValidFilePath: \"„{name}“ ist kein gültiger Dateipfad.\",\n workspaceWizardFileLarger: \"Der Arbeitsbereich in der Wizard-Datei ist größer als 25 MB.\",\n unknownTemplate: \"Die Vorlage „{starterId}“ gibt es nicht.\",\n wizardChangedMeantime: \"Der Wizard wurde inzwischen geändert.\",\n valueNotExist: \"Diesen Wert gibt es nicht.\",\n nothingFiledUnderValue: \"Unter diesem Wert steht noch nichts.\",\n filmNotRenderedNeeds:\n \"Der Film ließ sich nicht rendern. Dafür braucht es ffmpeg und eine Zeitleiste im Widget.\",\n signInRefused:\n \"Anmeldung abgelehnt{host}. Stimmen Adresse und (App-)Passwort? Gmail und Google Workspace brauchen ein App-Passwort und eingeschaltetes IMAP.{answer}\",\n serverSaid: \" Antwort des Servers: {answer}\",\n viaAccountFailed: \"Verbinden über dein engenty-Konto hat nicht geklappt ({code}).\",\n pluginInvalidInput: \"„{id}“ bekam ungültige Angaben: {path} – {problem}\",\n filmClientStopped:\n \"{name} hat beim Film aufgehört: {detail}. Die Arbeit ist gespeichert. Ein neuer Versuch macht dort weiter.\",\n filmWorkSaved: \"{problem} Die Arbeit ist gespeichert. Ein neuer Versuch macht dort weiter.\",\n filmRenderFailed: \"Der Film ließ sich nicht rendern: {detail}\",\n commandNotStarted: \"Der Befehl konnte nicht starten: {detail}\",\n providerKeyMissing: \"Für {makes} ist {provider} gewählt, aber kein API-Key hinterlegt.\",\n noModelFor: \"Für {makes} ist kein Modell eingerichtet.\",\n noApiKeyFor: \"Für {provider} ist kein API-Key hinterlegt.\",\n freeTier:\n \"Dein AI-Gateway-Key nutzt bei Vercel die kostenlose Stufe, und die schließt {model} aus. Lade bei Vercel Guthaben auf ({url}) oder wähle unter Einstellungen → Modelle ein anderes Modell.\",\n thisModel: \"dieses Modell\",\n quoted: \"„{text}“\",\n viewErrors: \"Die Ansicht hat Fehler: {detail}\",\n stepFailed: \"Dieser Schritt hat nicht geklappt: {detail}\",\n answersMissing: \"Antworten fehlen oder passen nicht: {answers}\",\n templateNeedsPlugins: {\n one: \"Diese Vorlage braucht das Plugin {plugins}: bei Pro auf engenty.ai dabei.\",\n other: \"Diese Vorlage braucht die Plugins {plugins}: bei Pro auf engenty.ai dabei.\",\n },\n pageMostChars: \"Eine Seite hat höchstens {count} Zeichen.\",\n chooseFileUpTo: \"Wähl eine Datei bis {mb} MB.\",\n fontSourceNoFont:\n \"{family} braucht eine Schriftdatei des Space: Wähl eine .woff2 aus den Assets.\",\n roomMostFiles: {\n one: \"Hier hat höchstens {count} Datei Platz.\",\n other: \"Hier haben höchstens {count} Dateien Platz.\",\n },\n makesText: \"Text\",\n makesImages: \"Bilder\",\n makesVideos: \"Videos\",\n makesSpeech: \"Sprachausgabe\",\n makesVoiceNotes: \"Sprachnotizen\",\n};\n\nexport const RUN_NOTES: Texts<RunNoteCode> = { en: NOTES_EN, de: NOTES_DE };\n\n/** What fills a note's gaps: words, numbers, other notes (said in the same language), lists. */\nexport type NoteGap = Gap | RunNote | readonly NoteGap[];\n\n/** A line of `RUN_NOTES` with what goes into its gaps. */\nexport interface RunNote {\n code: RunNoteCode;\n params?: Record<string, NoteGap | undefined>;\n}\n\n/** What the person reads: plain words, or a note that has a line for each language. */\nexport type Said = string | RunNote;\n\n/** A note: a line of `RUN_NOTES`, said in whichever language the reader reads. */\nexport function note(code: RunNoteCode, params?: Record<string, NoteGap | undefined>): RunNote {\n return params ? { code, params } : { code };\n}\n\n/** What is said, in a language. */\nexport function saidText(said: Said, lang: Lang): string {\n return typeof said === \"string\" ? said : noteText(said, lang);\n}\n\nfunction gapIn(value: NoteGap, lang: string, table?: TextTable): Gap {\n if (Array.isArray(value)) {\n return value.map((item: NoteGap) => gapIn(item, lang, table));\n }\n if (typeof value === \"object\" && value !== null && \"code\" in value) {\n return noteText(value, lang, table);\n }\n return value as Gap;\n}\n\n/**\n * A note in a language, its gaps filled; English where the language lacks the line. A language\n * outside `LANGS` reads its lines from `table`, the notes translated on request.\n */\nexport function noteText(note: RunNote, lang: string, table?: TextTable): string {\n if (!(note.code in NOTES_EN)) {\n return \"\";\n }\n const params: Record<string, Gap | undefined> = {};\n for (const [key, value] of Object.entries(note.params ?? {})) {\n params[key] = value === undefined ? undefined : gapIn(value, lang, table);\n }\n const own = table?.[note.code];\n if (own !== undefined) {\n return lineText(own, lang, params);\n }\n return textOf(RUN_NOTES, note.code, isLang(lang) ? lang : \"en\", params);\n}\n\nexport interface RunEvent {\n id: number;\n at: string;\n stepId: string | null;\n type: \"step_started\" | \"step_done\" | \"tool\" | \"info\" | \"error\";\n /** In German, as the run's log keeps it. */\n message: string;\n /** The same as a note a runner shows in the person's language; null for free text. */\n note?: RunNote | null;\n /** A picture of the run this is about (a photo being looked at, an image just made). */\n asset?: string | null;\n}\n\nexport interface RunView {\n id: string;\n status: RunStatus;\n mode: \"test\" | \"live\";\n wizard: Pick<WizardDefinition, \"title\" | \"description\" | \"avatar\" | \"costume\" | \"intro\">;\n /** The language the wizard speaks, by its code: what is read aloud, and in which voice. */\n lang: string;\n /**\n * The run in the viewer's language (a wizard translated on request): every text of the view\n * is written in it, the choices keep their values and show `labels[value]`. Null: the\n * wizard's own words.\n */\n translation: RunTranslation | null;\n /** A live conversation can be started on this run: the runtime has a model for it and the wizard has live voice or video on (always in a test). */\n talk: boolean;\n /** The step the person is on (interactive) or the one running. */\n step: Step | null;\n /** Pages and reviews answered before it, oldest first: what a chat shows above the current step. */\n answered: Step[];\n values: Record<string, unknown>;\n /** What fields of the current page start with, from earlier steps (`prefill`). */\n prefill: Record<string, unknown>;\n /** What the `when` of the current page's fields read from before the page, by reference. */\n known?: Record<string, unknown>;\n /** Choices of the current page's fields that come from earlier data (`optionsFrom`). */\n options?: Record<string, string[]>;\n /** The same choices as cards, for fields that have `cards`. */\n cards?: Record<string, CardOption[]>;\n /** The decided fields (`ask`, `group`) of the current page that a decision kept. */\n decidedFields?: string[];\n /**\n * What decided branches answered so far, by step, with the branches decided over (test runs:\n * the studio shows them while the draft's branches are still those).\n */\n decisions?: Record<string, ShownDecision>;\n /** Choices of the current page that lead to a step without a model here, by field id. */\n closed: Record<string, ClosedChoice>;\n outputs: Record<string, StepOutput>;\n /** Steps whose outputs the current step shows, with their definitions. */\n shown: { step: Step; output: StepOutput | null; formats: Format[]; label: string | null }[];\n progress: { done: number; total: number };\n canBack: boolean;\n error: string | null;\n events: RunEvent[];\n brand: BrandView;\n /** What the running step asks the person right now. */\n ask: RunAsk | null;\n /** Stored lists the current step shows (a page's list fields, a review, the result). */\n lists: ShownList[];\n /** The wizard's connections with what the person has connected. */\n connections: ConnectionView[];\n /** The wizard keeps things for the person between runs (lists, files, accounts). */\n keeps: boolean;\n /** Set once the result is shared. */\n shareUrl: string | null;\n /** When the run and its shared link are deleted; null = kept. */\n expiresAt: string | null;\n /** The result on its way to a share target, or the last one that arrived or failed. */\n shareJob: ShareJobView | null;\n}\n\n/** How a run in the viewer's language shows. */\nexport interface RunTranslation {\n /** The language, by its code (\"fr\"): any language, not only one of `LANGS`. */\n lang: string;\n /** What a choice shows, by its value. */\n labels: Record<string, string>;\n /** A model wrote some of it; false where the author wrote every text by hand. */\n machine: boolean;\n /** Results shown in this language, by step (`RunState.translated`). */\n results: Record<string, string>;\n}\n\n/** A shared result: what `/s/<token>` shows. Never the person's answers. */\nexport interface ShareView {\n token: string;\n title: string;\n message: string | null;\n wizard: Pick<WizardDefinition, \"title\" | \"description\" | \"avatar\" | \"costume\">;\n brand: BrandView;\n shown: RunView[\"shown\"];\n createdAt: string;\n expiresAt: string | null;\n /** The wizard's public link, to make your own — when it is published and open. */\n wizardUrl: string | null;\n}\n\nexport interface BrandView {\n name: string;\n accent: string | null;\n logoUrl: string | null;\n /** How the pages look: the run page sets its tokens from it. */\n theme: RunTheme;\n}\n\n/**\n * How a wizard's pages look: its space's brand (`runTheme`) with the wizard's own style on top\n * (`themedLook`). Null: the runner's own.\n */\nexport interface RunTheme {\n /** Buttons and marks. */\n accent: string | null;\n /** What is there, done or good to know: ticks, tips, group headings. */\n second: string | null;\n /** The ground the pages stand on; its hue tints paper and ink. */\n background: string | null;\n /** Typefaces as CSS names them. */\n display: string | null;\n body: string | null;\n /** The brand fonts of the two typefaces that have a source: the page loads them from there. */\n faces: RunFontFace[];\n /** The brand stands on a dark ground. */\n dark: boolean;\n /** The theme has only dark or only light pages: the person's own setting does not change it. */\n pinned: boolean;\n /** The theme's colours for light and for dark pages; the page takes those of what it shows. */\n modes: { light: ThemeColours | null; dark: ThemeColours | null } | null;\n /** Which of the two the pages show while the person has not chosen. */\n prefer: \"light\" | \"dark\" | null;\n shape: ThemeShape | null;\n /** Effects from the runner's library (`THEME_EFFECTS`); names it does not know are skipped. */\n effects: ThemeEffect[];\n}\n\n/** A brand font as a run page loads it: from our copy of its file, or from the space's website. */\nexport interface RunFontFace {\n family: string;\n /** Ours (`/api/public/fonts/…`) or the website's: the font file or a stylesheet that holds it. */\n url: string;\n stylesheet: boolean;\n}\n\nexport interface PublicWizard {\n token: string;\n title: string;\n description: string;\n avatar: string;\n costume?: EngentyCostume;\n intro: string | null;\n brand: BrandView;\n turnstileSiteKey: string | null;\n available: boolean;\n unavailableReason: string | null;\n /**\n * The runners switched on for this wizard, the one its link opens first: what the page offers\n * beside \"Let's go\". A page runner has an address; a channel (a number, a bot) has none.\n */\n runners: { id: string; label: string; kind: \"page\" | \"channel\"; url: string | null }[];\n /** The language the wizard is written in, by its code: the page opens in it. */\n lang: string;\n /** The author offers the wizard in the viewer's language, translated on request. */\n translatable: boolean;\n /** The page in the viewer's language, where it was asked for (`?lang=`); null: the original. */\n translation: Omit<RunTranslation, \"results\"> | null;\n /**\n * What the wizard's pages ask, in order: an AI app that starts the wizard (the OpenUI\n * component) can fill in what it already knows. The person still sees and sends each page.\n */\n fields: PublicField[];\n}\n\n/** A field of a wizard's page, as `PublicWizard.fields` lists it. */\nexport interface PublicField {\n id: string;\n label: string;\n kind: string;\n options?: string[];\n required?: boolean;\n}\n\n/** The runner's own words in a language outside `LANGS`: `GET /api/public/texts/:lang`. */\nexport interface UiTexts {\n lang: string;\n /** The runner's table (`packages/shared/src/runner-texts.ts`). */\n runner: TextTable;\n /** The run notes (`RUN_NOTES`). */\n notes: TextTable;\n}\n\n/** What a step is expected to cost, in credits. `high` is the 90th percentile once measured. */\nexport interface StepEstimate {\n credits: number;\n high: number;\n /** From at least five runs of this version; otherwise from a formula. */\n measured: boolean;\n}\n\n/** What a run is expected to cost. `available` is false where no credits are involved. */\n/** A model class a wizard needs that this runtime cannot serve, with the steps that call it. */\nexport interface MissingModel {\n cls: ModelClass;\n /** Why the class cannot run, as the person reads it. */\n problem: string;\n steps: { id: string; title: string }[];\n /** A step that needs it lies on every path: the run cannot start. */\n blocking: boolean;\n}\n\n/** A page's choice whose values lead to a step this runtime has no model for. */\nexport interface ClosedChoice {\n /** The options (or a toggle's true / false) that lead there; empty = the field as a whole. */\n values: (string | boolean)[];\n /** What is missing on the way. */\n classes: ModelClass[];\n}\n\nexport interface RunEstimate {\n available: boolean;\n credits: number;\n /** Credits held when a run starts. */\n reserve: number;\n steps: Record<string, StepEstimate>;\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport type { Line, Texts } from \"./texts.js\";\n\n// Wording: docs/copy-style.md (voice, glossary, EN/DE mechanics). Write each language as its\n// own sentence, not a word-for-word copy of the other. Check with `pnpm copy:check`.\n/**\n * What the runner says to the person running a wizard, in German and English. The studio spreads\n * these into its own dictionary; a host without one (the WordPress plugin) uses them as they are.\n */\nconst de: Record<RunnerKey, Line> = {\n \"result.translate\": \"Übersetzen\",\n \"translation.working\": \"Wird übersetzt …\",\n \"translation.machine\": \"Maschinell übersetzt\",\n \"translation.showOriginal\": \"Original zeigen\",\n \"translation.showTranslated\": \"Übersetzung zeigen\",\n \"translation.failed\": \"Dieser Wizard lässt sich gerade nicht übersetzen.\",\n \"share.copied\": \"Kopiert\",\n \"surface.done\": \"{done} von {total}\",\n \"surface.allDone\": \"Alles erledigt\",\n \"surface.close\": \"Schließen\",\n \"data.view\": \"Ansicht\",\n \"data.edit\": \"Bearbeiten\",\n \"data.json\": \"JSON\",\n \"data.modes\": \"Daten zeigen als\",\n \"data.add\": \"{what} hinzufügen\",\n \"data.remove\": \"Entfernen\",\n \"data.missing\": \"{id} fehlt\",\n \"data.yes\": \"Ja\",\n \"data.no\": \"Nein\",\n \"data.menu\": \"Mehr\",\n \"data.open\": \"Daten ansehen und bearbeiten\",\n \"data.close\": \"Daten schließen\",\n \"data.save\": \"Speichern\",\n \"data.saved\": \"Gespeichert\",\n \"data.schema\": \"JSON Schema\",\n \"data.copy\": \"Kopieren\",\n \"data.download\": \"Herunterladen\",\n \"run.closed\": \"Hier gerade nicht verfügbar, dafür fehlt: {list}\",\n \"slot.later\": \"Spätere Termine zeigen\",\n \"slot.none\": \"Gerade sind keine Termine frei.\",\n \"cards.open\": \"Details\",\n \"cards.picked\": \"Ausgewählt ✓\",\n \"cards.pick\": \"Auswählen\",\n \"run.cls.text\": \"Text\",\n \"run.cls.image\": \"Bilder\",\n \"run.cls.video\": \"Videos\",\n \"run.cls.speech\": \"Sprachausgabe\",\n \"run.cls.audio\": \"Sprachnotizen\",\n \"run.cls.account\": \"ein engenty-Konto\",\n \"run.next\": \"Weiter\",\n \"run.back\": \"Zurück\",\n \"run.accept\": \"Passt so\",\n \"run.edit\": \"Bearbeiten\",\n \"run.pickItem\": \"Nr. {n}\",\n \"run.pickedItem\": \"Nr. {n} neu\",\n \"run.regeneratePicked\": \"Nur Nr. {n} wird neu erstellt.\",\n \"run.regenerateAll\":\n \"Alle werden neu erstellt. Tippe oben auf eine Nummer, um nur einzelne zu erneuern.\",\n \"check.progress\": \"{done} von {total} geprüft\",\n \"check.onlyOpen\": \"Nur offene\",\n \"check.noFile\": \"Zu dieser Zeile gibt es keine Datei.\",\n \"check.noPreview\": \"Für diese Datei gibt es keine Vorschau – öffne sie mit dem Link oben.\",\n \"check.reopen\": \"Wieder öffnen\",\n \"run.feedbackPlaceholder\": \"Passt etwas nicht? Schreib, was anders sein soll …\",\n \"run.feedbackTarget\": \"Was soll sich ändern?\",\n \"run.feedbackPick\": \"Wähle oben, was sich ändern soll.\",\n \"ai.generated\": \"KI-generiert\",\n \"ai.modified\": \"Mit KI verändert\",\n \"ai.publish\":\n \"Mit KI erstellt: Wer das veröffentlicht, muss es als KI-generiert kennzeichnen (EU AI Act, Art. 50). Die Datei trägt die Kennzeichnung bereits in ihren Metadaten.\",\n \"run.regenerateGo\": \"Neu erstellen\",\n \"run.retry\": \"Erneut versuchen\",\n \"run.again\": \"Nochmal\",\n \"run.copy\": \"Text kopieren\",\n \"run.failed\": \"Da hat etwas nicht geklappt.\",\n \"run.notFound\": \"Diesen Wizard gibt es nicht, oder er wurde gelöscht.\",\n \"run.working\": \"Einen Moment …\",\n \"run.elapsed\": \"{s} s\",\n \"run.cancelled\": \"Abgebrochen.\",\n \"run.addRow\": \"Zeile hinzufügen\",\n \"run.upload\": \"Datei wählen oder hierher ziehen\",\n \"run.uploading\": \"Lädt hoch …\",\n \"run.net\": \"Netto\",\n \"run.vat\": \"USt. {r} %\",\n \"run.total\": \"Gesamt\",\n \"run.uploadMore\": \"Weitere Datei\",\n \"run.camera\": \"Kamera\",\n \"camera.title\": \"Mit der Kamera aufnehmen\",\n \"camera.hint\": \"Gerade und gut beleuchtet ins Bild halten.\",\n \"camera.taken\": \"{n} aufgenommen\",\n \"camera.shoot\": \"Aufnehmen\",\n \"camera.done\": \"Fertig\",\n \"camera.denied\":\n \"Die Kamera ist für diese Seite nicht freigegeben. Erlaube sie in den Website-Einstellungen deines Browsers (Schloss-Symbol in der Adresszeile) – oder nimm das Foto mit der Kamera-App auf.\",\n \"connect.go\": \"Verbinden\",\n \"connect.connected\": \"Verbunden über {name}\",\n \"connect.disconnect\": \"Trennen\",\n \"connect.none\": \"Auf diesem Server ist noch kein Anbieter zum Verbinden eingerichtet.\",\n \"connect.openLink\": \"Anmeldung in neuem Tab öffnen\",\n \"list.empty\": \"Noch keine Einträge.\",\n \"list.delete\": \"Zeile löschen\",\n \"ask.typeInto\": \"Text in die Seite tippen …\",\n \"ask.hide\": \"verdeckt\",\n \"ask.up\": \"Nach oben\",\n \"ask.down\": \"Nach unten\",\n \"ask.pictureHint\":\n \"Hier siehst du live die Seite, die der Wizard geöffnet hat. Du kannst auch direkt hineinklicken und tippen.\",\n \"ask.remember\": \"Anmeldung für nächstes Mal merken\",\n \"ask.private\":\n \"Was du eingibst, geht direkt in die Seite. Die KI bekommt es nicht zu sehen. Gemerkte Anmeldungen werden verschlüsselt gespeichert.\",\n \"ask.skip\": \"Überspringen\",\n \"ask.done\": \"Ich bin angemeldet\",\n \"ask.signIn\": \"Anmelden\",\n \"ask.wants\": \"Der Wizard möchte in {service} Folgendes ausführen:\",\n \"ask.allowRest\": \"Für den Rest dieses Laufs erlauben\",\n \"ask.allow\": \"Erlauben\",\n \"ask.deny\": \"Nicht erlauben\",\n \"store.open\": \"Was dieser Wizard sich merkt\",\n \"store.title\": \"Für dich gemerkt\",\n \"store.explain\":\n \"Dieser Wizard merkt sich Listen, Dateien und verbundene Konten für deinen nächsten Lauf. Nur du siehst sie.\",\n \"store.empty\": \"Noch nichts gespeichert.\",\n \"store.rows\": { one: \"{n} Eintrag\", other: \"{n} Einträge\" },\n \"store.signIns\": \"Gemerkte Anmeldungen im Browser\",\n \"store.files\": { one: \"{n} Datei · {size}\", other: \"{n} Dateien · {size}\" },\n \"store.delete\": \"Alles löschen\",\n \"store.confirmDelete\": \"Ja, alles löschen\",\n \"common.close\": \"Schließen\",\n \"run.uploadTouch\": \"Datei wählen\",\n \"run.maxFiles\": {\n one: \"Hier geht höchstens {n} Datei – die übrigen sind weggelassen.\",\n other: \"Hier gehen höchstens {n} Dateien – die übrigen sind weggelassen.\",\n },\n \"run.filesMin\": \"{n} von mindestens {min}\",\n \"run.filesOf\": \"{n} von höchstens {max}\",\n \"run.moveFile\": \"Nr. {n} verschieben\",\n \"run.moveFileHint\": \"Ziehen, um die Reihenfolge zu ändern\",\n \"run.removeFile\": \"Entfernen\",\n \"run.awake\": \"Der Bildschirm bleibt an, solange der Wizard arbeitet.\",\n \"run.openFull\": \"Groß öffnen\",\n \"run.yes\": \"Ja\",\n \"run.no\": \"Nein\",\n \"run.share\": \"Teilen\",\n \"run.shareNow\": \"Jetzt teilen\",\n \"run.shareFile\": \"Als Datei teilen oder in einer App öffnen\",\n \"run.print\": \"Drucken\",\n \"camera.asking\": \"Dein Browser fragt gleich nach der Kamera. Das Bild bleibt in diesem Wizard.\",\n \"camera.native\": \"Kamera-App öffnen\",\n \"camera.pick\": \"Foto auswählen\",\n \"camera.torch\": \"Licht\",\n \"camera.flip\": \"Kamera wechseln\",\n \"camera.photo\": \"Foto\",\n \"camera.video\": \"Video\",\n \"camera.record\": \"Aufnahme starten\",\n \"camera.stop\": \"Aufnahme beenden\",\n \"camera.recording\": \"Nimmt auf – tippe zum Beenden.\",\n \"camera.clipHint\": \"Ein kurzer Clip, höchstens {s} Sekunden.\",\n \"camera.hintMany\": \"Seite für Seite aufnehmen, dann „Fertig“.\",\n \"scan.button\": \"Scannen\",\n \"scan.title\": \"Code scannen\",\n \"scan.asking\": \"Dein Browser fragt gleich nach der Kamera – sie liest nur den Code.\",\n \"scan.hint\": \"Halte den QR- oder Barcode in den Rahmen.\",\n \"scan.hintQr\": \"Halte den QR-Code in den Rahmen. Barcodes kann dieses Gerät hier nicht lesen.\",\n \"scan.miss\": \"Auf dem Foto war kein Code zu erkennen. Versuch es näher und schärfer.\",\n \"scan.fromPhoto\": \"Foto mit dem Code wählen\",\n \"scan.typeInstead\": \"Lieber eintippen\",\n \"location.use\": \"Meinen Standort verwenden\",\n \"location.locating\": \"Standort wird bestimmt …\",\n \"location.refining\": \"wird noch genauer …\",\n \"location.accuracy\": \"auf etwa {m} m genau\",\n \"location.map\": \"Karte\",\n \"location.remove\": \"Standort entfernen\",\n \"location.why\":\n \"Dein Browser fragt nach deinem Standort. Er wird nur für diesen Wizard verwendet. Du kannst auch einfach die Adresse eintippen.\",\n \"location.denied\":\n \"Der Standort ist für diese Seite nicht freigegeben. Erlaube ihn in den Website-Einstellungen deines Browsers (Schloss-Symbol in der Adresszeile) – oder tippe die Adresse unten ein.\",\n \"location.manual\": \"Adresse oder Ort eintippen\",\n \"location.label\": \"Adresse oder Beschreibung des Orts\",\n \"voice.start\": \"Sprachnotiz aufnehmen\",\n \"voice.stop\": \"Stopp\",\n \"voice.recording\": \"Aufnahme läuft …\",\n \"voice.left\": \"noch {s} s\",\n \"voice.again\": \"Neu aufnehmen\",\n \"voice.remove\": \"Löschen\",\n \"voice.pick\": \"Audiodatei wählen\",\n \"voice.why\":\n \"Dein Browser fragt nach dem Mikrofon. Die Aufnahme wird danach in Text umgewandelt.\",\n \"voice.denied\":\n \"Das Mikrofon ist für diese Seite nicht freigegeben. Erlaube es in den Website-Einstellungen deines Browsers – oder nimm die Notiz mit der Diktier-App auf und wähle die Datei.\",\n \"voice.noRecorder\":\n \"Dieser Browser kann hier nicht aufnehmen. Nimm die Notiz mit der Diktier-App auf und wähle die Datei.\",\n \"sign.open\": \"Hier unterschreiben\",\n \"sign.hint\": \"Mit dem Finger unterschreiben\",\n \"sign.pad\": \"Unterschriftsfeld\",\n \"sign.clear\": \"Löschen\",\n \"sign.accept\": \"Übernehmen\",\n \"sign.again\": \"Neu unterschreiben\",\n \"sign.remove\": \"Unterschrift entfernen\",\n \"notify.ask\": \"Bescheid geben, wenn es fertig ist\",\n \"notify.on\": \"Du bekommst Bescheid\",\n \"notify.why\":\n \"Mit Ton, Vibration oder einer Mitteilung. Dein Browser fragt dafür einmal um Erlaubnis.\",\n \"notify.onHint\": \"Du kannst die App wechseln – eine Mitteilung holt dich zurück.\",\n \"notify.quiet\": \"Mit Ton und Vibration, solange diese Seite offen ist.\",\n \"notify.blocked\":\n \"Mitteilungen sind für diese Seite blockiert – es gibt Ton und Vibration, solange sie offen ist. Erlauben kannst du sie in den Website-Einstellungen deines Browsers.\",\n \"notify.done\": \"Dein Ergebnis ist fertig.\",\n \"notify.next\": \"Es geht weiter – wirf einen Blick darauf.\",\n \"notify.needsYou\": \"Der Wizard braucht dich kurz.\",\n \"common.offline\": \"Keine Verbindung. Prüf dein Netz und versuch es noch einmal.\",\n \"common.retry\": \"Erneut versuchen\",\n \"common.cancel\": \"Abbrechen\",\n \"run.start\": \"Los geht’s\",\n \"run.unavailable\": \"Dieser Wizard ist gerade nicht verfügbar.\",\n \"run.resume\": \"Letzten Lauf fortsetzen\",\n \"output.preview\": \"Vorschau\",\n \"package.newer\":\n \"Diese Wizard-Datei stammt aus einer neueren Version oder ist beschädigt. Aktualisiere engenty wizards oder exportiere den Wizard neu.\",\n \"package.badJson\": \"Das ist keine Wizard-Datei: Die wizard.json darin lässt sich nicht lesen.\",\n \"package.unreadable\":\n \"Die Wizard-Datei lässt sich nicht öffnen. Exportiere den Wizard neu und versuche es noch einmal.\",\n \"package.noManifest\": \"Das ist keine Wizard-Datei: Die wizard.json fehlt.\",\n \"browser.driving\": \"Du steuerst den Browser – klick und tipp in die Seite. Der Wizard wartet.\",\n \"browser.handBack\": \"Zurückgeben\",\n \"browser.takeOver\": \"Übernehmen\",\n \"chat.above\": \"Antworte oben im Chat\",\n \"chat.badEmail\": \"Das sieht nicht nach einer E-Mail-Adresse aus.\",\n \"chat.badNumber\": \"Das sieht nicht nach einer Zahl aus.\",\n \"chat.badUrl\": \"Das sieht nicht nach einer Webadresse aus.\",\n \"chat.change\": \"Ändern\",\n \"chat.checked\": \"Geprüft\",\n \"chat.connected\": \"Verbunden\",\n \"chat.dictate\": \"Diktieren (⌘⇧M)\",\n \"chat.dictateStop\": \"Diktat beenden\",\n \"chat.file\": \"1 Datei\",\n \"chat.files\": { one: \"{n} Datei\", other: \"{n} Dateien\" },\n \"chat.listening\": \"Ich höre zu …\",\n \"chat.micDenied\":\n \"Das Mikrofon ist für diese Seite nicht freigegeben. Erlaube es in den Website-Einstellungen deines Browsers.\",\n \"chat.placeholder\": \"Deine Antwort …\",\n \"chat.readAloud\": \"Vorlesen\",\n \"chat.readAloudOff\": \"Vorlesen beenden\",\n \"chat.required\": \"Dafür brauche ich eine Antwort.\",\n \"chat.rows\": { one: \"{n} Zeile\", other: \"{n} Zeilen\" },\n \"chat.send\": \"Senden\",\n \"chat.skip\": \"Überspringen\",\n \"chat.skipped\": \"Übersprungen\",\n \"chat.transcribing\": \"Wird in Text umgewandelt …\",\n \"chat.voice\": \"Sprachnotiz\",\n \"install.add\": \"Zum Startbildschirm hinzufügen\",\n \"install.app\": \"In der App öffnen\",\n \"install.bookmark\": \"Als Lesezeichen speichern\",\n \"install.bookmark.mac\": \"Drücke ⌘ D, dann liegt dieser Wizard in deinen Lesezeichen.\",\n \"install.bookmark.pc\": \"Drücke Strg + D, dann liegt dieser Wizard in deinen Lesezeichen.\",\n \"install.ios\": \"Tippe unten auf „Teilen“ und dann auf „Zum Home-Bildschirm“.\",\n \"run.madeWith\": \"Erstellt mit engenty wizards\",\n \"run.orAs\": \"Oder: {label}\",\n \"talk.camera\": \"Kamera einschalten\",\n \"talk.cameraDenied\":\n \"Die Kamera ist für diese Seite nicht freigegeben. Erlaube sie in den Website-Einstellungen deines Browsers.\",\n \"talk.cameraOff\": \"Kamera ausschalten\",\n \"talk.connecting\": \"Verbindet …\",\n \"talk.failed\": \"Das Gespräch ließ sich nicht starten.\",\n \"talk.hint\": \"Sprich mit dem Wizard. Auf dem Bildschirm kannst du mitlesen.\",\n \"talk.joinHint\":\n \"Beim Start fragt dein Browser nach dem Mikrofon, nach der Kamera erst, wenn du sie einschaltest. Im Chat daneben kannst du mitlesen und eingeben, was sich schlecht sagen lässt.\",\n \"talk.listening\": \"Hört zu\",\n \"talk.live\": \"Im Gespräch\",\n \"talk.speaking\": \"Spricht\",\n \"talk.start\": \"Gespräch beginnen\",\n \"talk.stop\": \"Gespräch beenden\",\n \"video.cameraOff\": \"Kamera aus\",\n \"video.ended\": \"Anruf beendet\",\n \"video.flip\": \"Kamera wechseln\",\n \"video.hint\":\n \"Beim Beitreten fragt dein Browser nach Mikrofon und Kamera. Im Chat daneben kannst du mitlesen und eingeben, was sich schlecht sagen lässt.\",\n \"video.join\": \"Beitreten\",\n \"video.leave\": \"Verlassen\",\n \"video.mute\": \"Stummschalten\",\n \"video.rejoin\": \"Wieder beitreten\",\n \"video.unmute\": \"Stummschaltung aufheben\",\n \"video.you\": \"Du\",\n \"nav.language\": \"Sprache\",\n};\n\nexport type RunnerKey = keyof typeof en;\n\nconst en = {\n \"result.translate\": \"Translate\",\n \"translation.working\": \"Translating…\",\n \"translation.machine\": \"Machine-translated\",\n \"translation.showOriginal\": \"Show original\",\n \"translation.showTranslated\": \"Show translation\",\n \"translation.failed\": \"This wizard can’t be translated right now.\",\n \"share.copied\": \"Copied\",\n \"surface.done\": \"{done} of {total}\",\n \"surface.allDone\": \"All done\",\n \"surface.close\": \"Close\",\n \"data.view\": \"View\",\n \"data.edit\": \"Edit\",\n \"data.json\": \"JSON\",\n \"data.modes\": \"Show the data as\",\n \"data.add\": \"Add {what}\",\n \"data.remove\": \"Remove\",\n \"data.missing\": \"{id} is missing\",\n \"data.yes\": \"Yes\",\n \"data.no\": \"No\",\n \"data.menu\": \"More\",\n \"data.open\": \"View and edit the data\",\n \"data.close\": \"Close the data\",\n \"data.save\": \"Save\",\n \"data.saved\": \"Saved\",\n \"data.schema\": \"JSON Schema\",\n \"data.copy\": \"Copy\",\n \"data.download\": \"Download\",\n \"run.closed\": \"Not available here right now. It needs {list}.\",\n \"slot.later\": \"Show later times\",\n \"slot.none\": \"No times are free right now.\",\n \"cards.open\": \"Details\",\n \"cards.picked\": \"Chosen ✓\",\n \"cards.pick\": \"Choose\",\n \"run.cls.text\": \"text\",\n \"run.cls.image\": \"images\",\n \"run.cls.video\": \"video\",\n \"run.cls.speech\": \"speech output\",\n \"run.cls.audio\": \"voice notes\",\n \"run.cls.account\": \"an engenty account\",\n \"run.next\": \"Continue\",\n \"run.back\": \"Back\",\n \"run.accept\": \"Looks good\",\n \"run.edit\": \"Edit\",\n \"run.pickItem\": \"No. {n}\",\n \"run.pickedItem\": \"No. {n} again\",\n \"run.regeneratePicked\": \"Only no. {n} will be redone.\",\n \"run.regenerateAll\": \"Applies to all. Tap a number to redo just that one.\",\n \"check.progress\": \"{done} of {total} checked\",\n \"check.onlyOpen\": \"Open only\",\n \"check.noFile\": \"There’s no file for this row.\",\n \"check.noPreview\": \"This file has no preview – open it with the link above.\",\n \"check.reopen\": \"Open again\",\n \"run.feedbackPlaceholder\": \"Something not right? Write what should be different…\",\n \"run.feedbackTarget\": \"What should change?\",\n \"run.feedbackPick\": \"Choose above what should change.\",\n \"ai.generated\": \"AI-generated\",\n \"ai.modified\": \"AI-modified\",\n \"ai.publish\":\n \"Made with AI: whoever publishes this has to label it as AI-generated (EU AI Act, Art. 50). The file already carries the marking in its metadata.\",\n \"run.regenerateGo\": \"Recreate\",\n \"run.retry\": \"Try again\",\n \"run.again\": \"Start over\",\n \"run.copy\": \"Copy text\",\n \"run.failed\": \"Something went wrong.\",\n \"run.notFound\": \"This wizard doesn’t exist or was deleted.\",\n \"run.working\": \"One moment…\",\n \"run.elapsed\": \"{s} s\",\n \"run.cancelled\": \"Cancelled.\",\n \"run.addRow\": \"Add row\",\n \"run.upload\": \"Choose a file or drop it here\",\n \"run.uploading\": \"Uploading…\",\n \"run.net\": \"Net\",\n \"run.vat\": \"VAT {r}%\",\n \"run.total\": \"Total\",\n \"run.uploadMore\": \"Another file\",\n \"run.camera\": \"Camera\",\n \"camera.title\": \"Take a picture\",\n \"camera.hint\": \"Hold it flat and well lit.\",\n \"camera.taken\": \"{n} taken\",\n \"camera.shoot\": \"Capture\",\n \"camera.done\": \"Done\",\n \"camera.denied\":\n \"The camera isn’t allowed for this page. Allow it in your browser’s site settings (the lock icon in the address bar) – or take the photo with your camera app.\",\n \"connect.go\": \"Connect\",\n \"connect.connected\": \"Connected through {name}\",\n \"connect.disconnect\": \"Disconnect\",\n \"connect.none\": \"This server has no provider for connecting accounts yet.\",\n \"connect.openLink\": \"Click here to open the sign-in in a new tab\",\n \"list.empty\": \"No entries yet.\",\n \"list.delete\": \"Delete row\",\n \"ask.typeInto\": \"Type into the page…\",\n \"ask.hide\": \"hidden\",\n \"ask.up\": \"Scroll up\",\n \"ask.down\": \"Scroll down\",\n \"ask.pictureHint\":\n \"This is the page the wizard has open, live. You can also click and type right in it.\",\n \"ask.remember\": \"Remember this sign-in for next time\",\n \"ask.private\":\n \"What you enter goes straight into the page. The AI never sees it. Remembered sign-ins are stored encrypted.\",\n \"ask.skip\": \"Skip\",\n \"ask.done\": \"I’m signed in\",\n \"ask.signIn\": \"Sign in\",\n \"ask.wants\": \"The wizard wants to run this in {service}:\",\n \"ask.allowRest\": \"Allow for the rest of this run\",\n \"ask.allow\": \"Allow\",\n \"ask.deny\": \"Don’t allow\",\n \"store.open\": \"What this wizard remembers\",\n \"store.title\": \"Kept for you\",\n \"store.explain\":\n \"This wizard keeps lists, files and connected accounts for your next run. Only you see them.\",\n \"store.empty\": \"Nothing kept yet.\",\n \"store.rows\": { one: \"{n} entry\", other: \"{n} entries\" },\n \"store.signIns\": \"Remembered sign-ins in the browser\",\n \"store.files\": { one: \"{n} file · {size}\", other: \"{n} files · {size}\" },\n \"store.delete\": \"Delete everything\",\n \"store.confirmDelete\": \"Yes, delete everything\",\n \"common.close\": \"Close\",\n \"run.uploadTouch\": \"Choose a file\",\n \"run.maxFiles\": {\n one: \"At most {n} fits here – the rest were left out.\",\n other: \"At most {n} fit here – the rest were left out.\",\n },\n \"run.filesMin\": \"{n} of at least {min}\",\n \"run.filesOf\": \"{n} of at most {max}\",\n \"run.moveFile\": \"Move no. {n}\",\n \"run.moveFileHint\": \"Drag to change the order\",\n \"run.removeFile\": \"Remove\",\n \"run.awake\": \"The screen stays on while the wizard works.\",\n \"run.openFull\": \"Open full size\",\n \"run.yes\": \"Yes\",\n \"run.no\": \"No\",\n \"run.share\": \"Share\",\n \"run.shareNow\": \"Share now\",\n \"run.shareFile\": \"Share as a file or open in an app\",\n \"run.print\": \"Print\",\n \"camera.asking\": \"Your browser is about to ask for the camera. The picture stays in this wizard.\",\n \"camera.native\": \"Open the camera app\",\n \"camera.pick\": \"Choose a photo\",\n \"camera.torch\": \"Light\",\n \"camera.flip\": \"Switch camera\",\n \"camera.photo\": \"Photo\",\n \"camera.video\": \"Video\",\n \"camera.record\": \"Start recording\",\n \"camera.stop\": \"Stop recording\",\n \"camera.recording\": \"Recording – tap to stop.\",\n \"camera.clipHint\": \"A short clip, {s} seconds at most.\",\n \"camera.hintMany\": \"Capture page after page, then “Done”.\",\n \"scan.button\": \"Scan\",\n \"scan.title\": \"Scan a code\",\n \"scan.asking\": \"Your browser is about to ask for the camera – it only reads the code.\",\n \"scan.hint\": \"Hold the QR code or barcode inside the frame.\",\n \"scan.hintQr\": \"Hold the QR code inside the frame. This device doesn’t read barcodes here.\",\n \"scan.miss\": \"No code was found in the photo. Try closer and sharper.\",\n \"scan.fromPhoto\": \"Choose a photo of the code\",\n \"scan.typeInstead\": \"Type it instead\",\n \"location.use\": \"Use my location\",\n \"location.locating\": \"Finding your location…\",\n \"location.refining\": \"getting more accurate…\",\n \"location.accuracy\": \"accurate to about {m} m\",\n \"location.map\": \"Map\",\n \"location.remove\": \"Remove location\",\n \"location.why\":\n \"Your browser asks for your location. It’s only used for this wizard. You can also just type the address.\",\n \"location.denied\":\n \"Location isn’t allowed for this page. Allow it in your browser’s site settings (the lock icon in the address bar) – or type the address below.\",\n \"location.manual\": \"Type an address or place\",\n \"location.label\": \"Address or description of the place\",\n \"voice.start\": \"Record a voice note\",\n \"voice.stop\": \"Stop\",\n \"voice.recording\": \"Recording…\",\n \"voice.left\": \"{s} s left\",\n \"voice.again\": \"Record again\",\n \"voice.remove\": \"Delete\",\n \"voice.pick\": \"Choose an audio file\",\n \"voice.why\":\n \"Your browser asks for the microphone. The recording is turned into text afterwards.\",\n \"voice.denied\":\n \"The microphone isn’t allowed for this page. Allow it in your browser’s site settings – or record the note with your voice memo app and choose the file.\",\n \"voice.noRecorder\":\n \"This browser can’t record here. Record the note with your voice memo app and choose the file.\",\n \"sign.open\": \"Sign here\",\n \"sign.hint\": \"Sign with your finger\",\n \"sign.pad\": \"Signature pad\",\n \"sign.clear\": \"Clear\",\n \"sign.accept\": \"Use it\",\n \"sign.again\": \"Sign again\",\n \"sign.remove\": \"Remove signature\",\n \"notify.ask\": \"Tell me when it’s done\",\n \"notify.on\": \"We’ll let you know\",\n \"notify.why\": \"With a sound, a buzz or a notification. Your browser asks once for permission.\",\n \"notify.onHint\": \"You can switch apps – a notification brings you back.\",\n \"notify.quiet\": \"With a sound and a buzz while this page is open.\",\n \"notify.blocked\":\n \"Notifications are blocked for this page – you get a sound and a buzz while it’s open. You can allow them in your browser’s site settings.\",\n \"notify.done\": \"Your result is ready.\",\n \"notify.next\": \"The next step is ready – have a look.\",\n \"notify.needsYou\": \"The wizard needs you for a moment.\",\n \"common.offline\": \"No connection. Check your network and try again.\",\n \"common.retry\": \"Try again\",\n \"common.cancel\": \"Cancel\",\n \"run.start\": \"Let’s go\",\n \"run.unavailable\": \"This wizard isn’t available right now.\",\n \"run.resume\": \"Continue your last run\",\n \"output.preview\": \"Preview\",\n \"package.newer\":\n \"This wizard file comes from a newer version, or it’s damaged. Update engenty wizards or export the wizard again.\",\n \"package.badJson\": \"This isn’t a wizard file: its wizard.json can’t be read.\",\n \"package.unreadable\":\n \"The wizard file can’t be opened. Export the wizard again and try once more.\",\n \"package.noManifest\": \"This isn’t a wizard file: wizard.json is missing.\",\n \"browser.driving\":\n \"You’re in control of the browser – click and type in the page. The wizard waits.\",\n \"browser.handBack\": \"Hand back\",\n \"browser.takeOver\": \"Take over\",\n \"chat.above\": \"Answer above in the chat\",\n \"chat.badEmail\": \"That doesn’t look like an email address.\",\n \"chat.badNumber\": \"Enter a number.\",\n \"chat.badUrl\": \"That isn’t a valid address.\",\n \"chat.change\": \"Change\",\n \"chat.checked\": \"Checked\",\n \"chat.connected\": \"Connected\",\n \"chat.dictate\": \"Dictate (⌘⇧M)\",\n \"chat.dictateStop\": \"Stop dictating\",\n \"chat.file\": \"1 file\",\n \"chat.files\": { one: \"{n} file\", other: \"{n} files\" },\n \"chat.listening\": \"Listening…\",\n \"chat.micDenied\":\n \"The microphone isn’t allowed for this page. Allow it in your browser’s site settings.\",\n \"chat.placeholder\": \"Your answer…\",\n \"chat.readAloud\": \"Read aloud\",\n \"chat.readAloudOff\": \"Stop reading aloud\",\n \"chat.required\": \"I need an answer for this one.\",\n \"chat.rows\": { one: \"{n} row\", other: \"{n} rows\" },\n \"chat.send\": \"Send\",\n \"chat.skip\": \"Skip\",\n \"chat.skipped\": \"Skipped\",\n \"chat.transcribing\": \"Writing it down…\",\n \"chat.voice\": \"Voice note\",\n \"install.add\": \"Add to home screen\",\n \"install.app\": \"Open in the app\",\n \"install.bookmark\": \"Bookmark this wizard\",\n \"install.bookmark.mac\": \"Press ⌘ D to keep this wizard in your bookmarks.\",\n \"install.bookmark.pc\": \"Press Ctrl + D to keep this wizard in your bookmarks.\",\n \"install.ios\": \"Tap “Share” below, then “Add to Home Screen”.\",\n \"run.madeWith\": \"Made with engenty wizards\",\n \"run.orAs\": \"Or: {label}\",\n \"talk.camera\": \"Switch the camera on\",\n \"talk.cameraDenied\":\n \"The camera isn’t allowed for this page. Allow it in your browser’s site settings.\",\n \"talk.cameraOff\": \"Switch the camera off\",\n \"talk.connecting\": \"Connecting…\",\n \"talk.failed\": \"The conversation couldn’t start. Check your connection and try again.\",\n \"talk.hint\": \"Talk to the wizard – the screen follows along.\",\n \"talk.joinHint\":\n \"Your browser asks for the microphone when you start, and for the camera only when you switch it on. The chat beside it follows along and handles what voice can’t.\",\n \"talk.listening\": \"Listening\",\n \"talk.live\": \"In conversation\",\n \"talk.speaking\": \"Speaking\",\n \"talk.start\": \"Start talking\",\n \"talk.stop\": \"End the conversation\",\n \"video.cameraOff\": \"Camera off\",\n \"video.ended\": \"Call ended\",\n \"video.flip\": \"Switch camera\",\n \"video.hint\":\n \"Your browser asks for the microphone and camera when you join. The chat beside it follows along and handles what voice can’t.\",\n \"video.join\": \"Join\",\n \"video.leave\": \"Leave\",\n \"video.mute\": \"Mute\",\n \"video.rejoin\": \"Rejoin\",\n \"video.unmute\": \"Unmute\",\n \"video.you\": \"You\",\n \"nav.language\": \"Language\",\n};\n\n/**\n * The runner's words in each language. English has every one; another language may lack some,\n * and those are said in English.\n */\nexport const RUNNER_TEXTS = { en, de } satisfies Texts<RunnerKey>;\n","import type { Lang } from \"@engenty/wizards-shared/definition\";\nimport { noteText, type RunNote } from \"@engenty/wizards-shared/run\";\nimport { RUNNER_TEXTS, type RunnerKey } from \"@engenty/wizards-shared/runner-texts\";\nimport { lineText, type TextTable, textOf } from \"@engenty/wizards-shared/texts\";\nimport { useSyncExternalStore } from \"react\";\n\nexport type { Lang };\n/**\n * What the runner says to the person running a wizard: its table lives in shared/runner-texts,\n * where the runtime reads it too (a language outside `LANGS` is translated from its English).\n */\nexport { RUNNER_TEXTS, type RunnerKey };\n\n/** The language the runner speaks: set by the host (`configureRunner`, `setRunnerLang`). */\nexport let lang: Lang = \"en\";\n\n/**\n * A language outside `LANGS`, translated on request (`GET /api/public/texts/:lang`): its lines\n * win over `lang`'s, and what it lacks is said in English. Null: the runner speaks `lang`.\n */\nexport interface RunnerTable {\n lang: string;\n runner: TextTable;\n notes: TextTable;\n}\nlet table: RunnerTable | null = null;\nlet version = 0;\nconst listeners = new Set<() => void>();\n\nfunction changed() {\n version += 1;\n for (const listener of listeners) {\n listener();\n }\n}\n\nexport function setRunnerLang(next: Lang) {\n if (next === lang) {\n return;\n }\n lang = next;\n changed();\n}\n\n/** Speaks a translated language from its table, or `lang` again with null. */\nexport function setRunnerTable(next: RunnerTable | null) {\n if (next === table) {\n return;\n }\n table = next;\n changed();\n}\n\n/** The translated table in effect, for a host that shows the runner's words itself. */\nexport function runnerTable(): RunnerTable | null {\n return table;\n}\n\n/** The language the person reads, by its code: the translated one, else `lang`. */\nexport function runnerLangCode(): string {\n return table?.lang ?? lang;\n}\n\n/** The language, for a component that must render again when it changes. */\nexport function useRunnerLang(): string {\n useSyncExternalStore(\n (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n () => version,\n );\n return runnerLangCode();\n}\n\n/** What a run reports, in the language the person reads: its note where it has one. */\nexport function eventText(ev: { message: string; note?: RunNote | null }): string {\n return (ev.note && noteText(ev.note, runnerLangCode(), table?.notes)) || ev.message;\n}\n\n/**\n * What the choices of a translated wizard show, by value (`RunView.translation.labels`): the\n * answer keeps the value, the person reads the label.\n */\nlet labels: Record<string, string> = {};\n\nexport function setChoiceLabels(next: Record<string, string> | null | undefined) {\n labels = next ?? {};\n}\n\n/** What a choice shows: its translated label, else its value. */\nexport function choiceLabel(value: string): string {\n return labels[value] ?? value;\n}\n\n/** A string in the runner's language: its plural form by `{count}` or `{n}`, its gaps filled. */\nexport function t(key: RunnerKey, vars?: Record<string, string | number>): string {\n const own = table?.runner[key];\n if (table && own !== undefined) {\n return lineText(own, table.lang, vars);\n }\n return textOf(RUNNER_TEXTS, key, table ? \"en\" : lang, vars);\n}\n","import { lang, t } from \"./i18n.js\";\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly body: any,\n ) {\n super(message);\n }\n}\n\n/** The request never reached the server: no network, a tunnel, a phone switching cells. */\nexport function isOffline(err: unknown): boolean {\n return err instanceof ApiError && err.status === 0;\n}\n\n/** A body as JSON; one that is not (a proxy's error page) as `{ error: <the text> }`. */\nexport function safeJson(text: string) {\n try {\n return JSON.parse(text);\n } catch {\n return { error: text };\n }\n}\n\nexport interface Api {\n get<T>(path: string): Promise<T>;\n post<T>(path: string, body?: unknown): Promise<T>;\n put<T>(path: string, body?: unknown): Promise<T>;\n patch<T>(path: string, body?: unknown): Promise<T>;\n del<T>(path: string): Promise<T>;\n upload<T>(path: string, file: File): Promise<T>;\n}\n\n/**\n * JSON calls with the host's credentials; a refused call throws an `ApiError` with the server's\n * `error` and its body (`fields`, `issues`, a `code`).\n */\nexport function createApi(\n withBase: (path: string) => string,\n headers: Record<string, string> = {},\n /** Told of every answer of 500 and above, e.g. to send it to the host's log. */\n onServerError?: (line: string) => void,\n): Api {\n async function request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(withBase(path), {\n method,\n credentials: \"include\",\n headers: {\n // The server answers in the language the person picked, not the browser's.\n \"accept-language\": lang,\n ...headers,\n ...(body !== undefined && !(body instanceof FormData)\n ? { \"content-type\": \"application/json\" }\n : {}),\n },\n body: body === undefined ? undefined : body instanceof FormData ? body : JSON.stringify(body),\n }).catch(() => {\n throw new ApiError(t(\"common.offline\"), 0, null);\n });\n const text = await res.text();\n const data = text ? safeJson(text) : null;\n if (!res.ok) {\n if (res.status >= 500) {\n onServerError?.(`${method} ${path} answered ${res.status}: ${data?.error ?? \"\"}`);\n }\n // WordPress answers `{ code, message }`; a runtime `{ error, code }`.\n throw new ApiError(data?.error ?? data?.message ?? res.statusText, res.status, data);\n }\n return data as T;\n }\n return {\n get: <T>(path: string) => request<T>(\"GET\", path),\n post: <T>(path: string, body?: unknown) => request<T>(\"POST\", path, body ?? {}),\n put: <T>(path: string, body?: unknown) => request<T>(\"PUT\", path, body),\n patch: <T>(path: string, body?: unknown) => request<T>(\"PATCH\", path, body),\n del: <T>(path: string) => request<T>(\"DELETE\", path),\n upload: <T>(path: string, file: File) => {\n const form = new FormData();\n form.set(\"file\", file);\n return request<T>(\"POST\", path, form);\n },\n };\n}\n","import type { EngentyCostume } from \"@engenty/wizards-shared/definition\";\nimport type { RunView } from \"@engenty/wizards-shared/run\";\nimport type { ComponentType } from \"react\";\nimport { type Api, createApi } from \"./api.js\";\nimport { type Lang, setRunnerLang } from \"./i18n.js\";\n\n/**\n * What the runner needs of the page around it, given once by the host before anything renders:\n * the studio (apps/web) with its base path, its mobile-app bridge and its engenty; the WordPress\n * plugin with its REST routes and its own engenty. The runner itself knows no server.\n */\n\n/** What a mobile app around the page may offer (apps/web/src/lib/app.ts names them). */\nexport type AppAbility =\n | \"scan\"\n | \"share\"\n | \"download\"\n | \"keepAwake\"\n | \"notify\"\n | \"notifyPermission\"\n | \"signIn\"\n | \"run\"\n | \"transcribe\"\n | \"think\";\n\nexport interface AppBridge {\n can(ability: AppAbility): boolean;\n call<T = unknown>(ability: AppAbility, args?: unknown): Promise<T>;\n tell(ability: AppAbility, args?: unknown): void;\n /** A download link's click: the app fetches the file itself. Returns whether it took it. */\n download(event: { preventDefault(): void }, href: string, filename?: string): boolean;\n}\n\nexport interface MascotProps {\n kind: string;\n costume?: EngentyCostume;\n size?: number;\n fluffy?: boolean;\n}\n\nexport interface ShareResultProps {\n /** The finished run: what it made, its link, a share job at work. */\n view: RunView;\n title: string;\n}\n\nexport interface RunnerEnv {\n lang: Lang;\n /** The run's API: `/api/runs/<id>` on a runtime, `/wp-json/engenty/v1/local/runs/<id>` in WordPress. */\n runBase(runId: string): string;\n /** A root-relative address as the browser must request it (a base path, a remote runtime). */\n withBase(path: string): string;\n /** A file of the host's public folder (`ai-labels/…`, `icons/…`). */\n asset(path: string): string;\n /** Where the service worker for notifications lives; none where the host has none. */\n serviceWorker?: string;\n /** The mobile app's bridge; a page in a browser has none. */\n app?: AppBridge;\n /** The wizard's engenty. */\n Mascot: ComponentType<MascotProps>;\n /** The result's share button; a host without shared results has none. */\n ShareResultButton?: ComponentType<ShareResultProps>;\n /** Told of every answer of 500 and above, e.g. to send it to the host's log. */\n onServerError?: (line: string) => void;\n /** Extra headers on every request (a WordPress nonce). */\n headers?: Record<string, string>;\n /**\n * A host that runs wizards on its own (the WordPress plugin): its server writes no PDF, so the\n * runner writes one from a written output in the browser (pdf.ts); an HTML download of a\n * written output is a page to print.\n */\n standalone?: boolean;\n}\n\nconst none: AppBridge = {\n can: () => false,\n call: (ability) => Promise.reject(new Error(`the app cannot ${ability}`)),\n tell: () => undefined,\n download: () => false,\n};\n\nlet env: RunnerEnv | null = null;\n\n/** The host names its environment once, before the first render. */\nexport function configureRunner(next: RunnerEnv) {\n env = next;\n api = createApi(next.withBase, next.headers, next.onServerError);\n setRunnerLang(next.lang);\n}\n\nexport function runnerEnv(): RunnerEnv {\n if (!env) {\n throw new Error(\"configureRunner() first\");\n }\n return env;\n}\n\nexport let api: Api = createApi((path) => path);\n\nexport const withBase = (path: string) => runnerEnv().withBase(path);\nexport const asset = (path: string) => runnerEnv().asset(path);\nexport const runBase = (runId: string) => runnerEnv().runBase(runId);\n\nexport const appCan = (ability: AppAbility) => (env?.app ?? none).can(ability);\nexport const appCall = <T = unknown>(ability: AppAbility, args?: unknown) =>\n (env?.app ?? none).call<T>(ability, args);\nexport const appTell = (ability: AppAbility, args?: unknown) =>\n (env?.app ?? none).tell(ability, args);\nexport const appDownload = (event: { preventDefault(): void }, href: string, filename?: string) =>\n (env?.app ?? none).download(event, href, filename);\nexport const standalone = () => env?.standalone === true;\n","import {\n type ButtonHTMLAttributes,\n forwardRef,\n type InputHTMLAttributes,\n type ReactNode,\n type TextareaHTMLAttributes,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { t } from \"./i18n.js\";\n\nexport function cn(...parts: (string | false | null | undefined)[]): string {\n return parts.filter(Boolean).join(\" \");\n}\n\ntype Variant = \"primary\" | \"secondary\" | \"ghost\" | \"quiet\" | \"danger\";\n\nconst VARIANTS: Record<Variant, string> = {\n primary:\n \"bg-primary text-primary-foreground hover:brightness-[1.06] active:brightness-95 shadow-[0_1px_0_oklch(0%_0_0/0.08)]\",\n secondary: \"bg-card text-ink border border-border hover:bg-paper-2\",\n ghost: \"text-ink-2 hover:text-ink hover:bg-accent\",\n quiet: \"bg-paper-2 text-ink hover:bg-paper-3\",\n danger: \"text-rose hover:bg-rose-tint\",\n};\n\nexport const Button = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: Variant;\n size?: \"sm\" | \"md\" | \"lg\";\n busy?: boolean;\n }\n>(function Button(\n { variant = \"primary\", size = \"md\", busy, className, children, disabled, ...rest },\n ref,\n) {\n return (\n <button\n ref={ref}\n type=\"button\"\n data-variant={variant}\n disabled={disabled || busy}\n className={cn(\n \"inline-flex select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium transition-[background,filter,color,transform] duration-150 active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50\",\n size === \"sm\" && \"h-8 px-3 text-[0.8125rem] coarse:h-11 coarse:px-4\",\n size === \"md\" && \"h-10 px-4 text-sm coarse:h-11\",\n size === \"lg\" && \"h-12 px-6 text-[0.9375rem]\",\n VARIANTS[variant],\n variant === \"primary\" && \"wizard-button\",\n className,\n )}\n {...rest}\n >\n {busy ? <Spinner className=\"size-4\" /> : null}\n {children}\n </button>\n );\n});\n\nexport function IconButton({\n label,\n className,\n children,\n ...rest\n}: ButtonHTMLAttributes<HTMLButtonElement> & { label: string }) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n className={cn(\n \"inline-flex size-9 shrink-0 items-center justify-center rounded-full text-ink-3 transition hover:bg-accent hover:text-ink disabled:opacity-40 coarse:size-11\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n}\n\nconst fieldBase =\n \"wizard-field rounded-lg border border-input bg-card px-3.5 text-[0.9375rem] text-ink shadow-[inset_0_1px_0_oklch(0%_0_0/0.02)] outline-none transition placeholder:text-ink-4 focus:border-focus focus:ring-4 focus:ring-focus-glow disabled:opacity-60\";\n\n/** A field fills its row unless the caller gives it a width. */\nfunction fieldWidth(className?: string) {\n return /(^|\\s)w-/.test(className ?? \"\") ? null : \"w-full\";\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>(\n function Input({ className, ...rest }, ref) {\n return (\n <input\n ref={ref}\n className={cn(fieldBase, fieldWidth(className), \"h-11\", className)}\n {...rest}\n />\n );\n },\n);\n\n/** The native colour picker as a swatch; its chip sits concentric in the frame. */\nexport function Swatch(props: Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"className\">) {\n return (\n <input\n type=\"color\"\n className=\"swatch size-11 shrink-0 cursor-pointer rounded-lg border border-input bg-card p-1\"\n {...props}\n />\n );\n}\n\n/** A textarea that grows with its content. */\nexport const Textarea = forwardRef<\n HTMLTextAreaElement,\n TextareaHTMLAttributes<HTMLTextAreaElement> & { minRows?: number; maxRows?: number }\n>(function Textarea({ className, minRows = 3, maxRows = 14, onChange, ...rest }, outer) {\n const inner = useRef<HTMLTextAreaElement | null>(null);\n const resize = () => {\n const el = inner.current;\n if (!el) {\n return;\n }\n const lh = Number.parseFloat(getComputedStyle(el).lineHeight) || 22;\n el.style.height = \"auto\";\n const max = lh * maxRows + 20;\n el.style.height = `${Math.min(Math.max(el.scrollHeight, lh * minRows + 20), max)}px`;\n el.style.overflowY = el.scrollHeight > max ? \"auto\" : \"hidden\";\n };\n useLayoutEffect(resize);\n return (\n <textarea\n ref={(el) => {\n inner.current = el;\n if (typeof outer === \"function\") {\n outer(el);\n } else if (outer) {\n outer.current = el;\n }\n }}\n className={cn(\n fieldBase,\n fieldWidth(className),\n \"resize-none py-2.5 leading-[1.5]\",\n className,\n )}\n onChange={(e) => {\n resize();\n onChange?.(e);\n }}\n {...rest}\n />\n );\n});\n\nexport function Select({\n value,\n onChange,\n options,\n className,\n placeholder,\n}: {\n value: string;\n onChange: (v: string) => void;\n options: { value: string; label: string; disabled?: boolean }[];\n className?: string;\n placeholder?: string;\n}) {\n return (\n <div className={cn(\"relative\", className)}>\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className={cn(fieldBase, \"h-11 w-full appearance-none pr-9\")}\n >\n {placeholder !== undefined ? <option value=\"\">{placeholder}</option> : null}\n {options.map((o) => (\n <option key={o.value} value={o.value} disabled={o.disabled}>\n {o.label}\n </option>\n ))}\n </select>\n <svg\n className=\"-translate-y-1/2 pointer-events-none absolute top-1/2 right-3 size-4 text-ink-3\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n </div>\n );\n}\n\n/** Pills for a handful of options — calmer than a dropdown. */\nexport function Segmented({\n value,\n onChange,\n options,\n multi,\n disabled,\n label,\n}: {\n value: string | string[];\n onChange: (v: any) => void;\n options: string[];\n multi?: boolean;\n /** Options shown but not to be picked. */\n disabled?: string[];\n /** What an option shows; default: the option itself. */\n label?: (option: string) => string;\n}) {\n const selected = new Set(Array.isArray(value) ? value : value ? [value] : []);\n return (\n <div className=\"flex flex-wrap gap-2\">\n {options.map((o) => {\n const on = selected.has(o);\n return (\n <button\n key={o}\n type=\"button\"\n aria-pressed={on}\n disabled={disabled?.includes(o)}\n onClick={() => {\n if (multi) {\n const next = new Set(selected);\n if (on) {\n next.delete(o);\n } else {\n next.add(o);\n }\n onChange(options.filter((x) => next.has(x)));\n } else {\n onChange(o);\n }\n }}\n className={cn(\n \"h-10 rounded-full border px-4 text-sm transition disabled:pointer-events-none disabled:opacity-60 disabled:line-through coarse:h-11\",\n on\n ? \"border-ember bg-ember-tint text-ink\"\n : \"border-input bg-card text-ink-2 hover:border-ink-4 hover:text-ink\",\n )}\n >\n {label ? label(o) : o}\n </button>\n );\n })}\n </div>\n );\n}\n\nconst SLIDE = \"cubic-bezier(0.3, 0.7, 0.2, 1)\";\n\n/**\n * A row of tabs as one button group, in the look of the theme switch: a thumb slides to the\n * pick and takes its width. The tabs' panels are the caller's.\n */\nexport function Tabs<T extends string>({\n value,\n onChange,\n options,\n label,\n}: {\n value: T;\n onChange: (next: T) => void;\n options: { id: T; label: string }[];\n /** The group's name for a screen reader. */\n label?: string;\n}) {\n const buttons = useRef(new Map<T, HTMLButtonElement>());\n const [thumb, setThumb] = useState<{ x: number; w: number } | null>(null);\n // Measured from the picked tab, again when its width changes (fonts, a resize).\n useLayoutEffect(() => {\n const el = buttons.current.get(value);\n if (!el) {\n return;\n }\n const measure = () => setThumb({ x: el.offsetLeft, w: el.offsetWidth });\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [value]);\n return (\n <div\n role=\"tablist\"\n aria-label={label}\n className=\"relative inline-flex items-center rounded-full bg-paper-2 p-0.5 ring-1 ring-border-soft\"\n >\n {thumb ? (\n <span\n aria-hidden=\"true\"\n className=\"absolute top-0.5 bottom-0.5 left-0 rounded-full bg-card shadow-sm motion-reduce:transition-none\"\n style={{\n width: thumb.w,\n transform: `translateX(${thumb.x}px)`,\n transition: `transform 300ms ${SLIDE}, width 300ms ${SLIDE}`,\n }}\n />\n ) : null}\n {options.map((option) => {\n const on = option.id === value;\n return (\n <button\n key={option.id}\n ref={(el) => {\n if (el) {\n buttons.current.set(option.id, el);\n } else {\n buttons.current.delete(option.id);\n }\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={on}\n onClick={() => onChange(option.id)}\n className={cn(\n \"relative h-8 whitespace-nowrap rounded-full px-4 font-medium text-[0.875rem] transition-colors motion-reduce:transition-none coarse:h-9\",\n on ? \"text-ink\" : \"text-ink-3 hover:text-ink-2\",\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function Switch({\n checked,\n onChange,\n label,\n disabled,\n}: {\n checked: boolean;\n onChange: (v: boolean) => void;\n label?: string;\n disabled?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n disabled={disabled}\n onClick={() => onChange(!checked)}\n className={cn(\n // The track stays slim; the tap area around it is a full 44 px.\n \"relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition before:absolute before:-inset-x-1 before:-inset-y-2.5 before:content-[''] disabled:pointer-events-none disabled:opacity-60\",\n checked ? \"bg-primary\" : \"bg-paper-3\",\n )}\n >\n <span\n className={cn(\n \"inline-block size-5 rounded-full bg-white shadow-sm transition-transform\",\n checked ? \"translate-x-[22px]\" : \"translate-x-[2px]\",\n )}\n />\n </button>\n );\n}\n\nexport function Label({\n children,\n hint,\n required,\n}: {\n children: ReactNode;\n hint?: ReactNode;\n required?: boolean;\n}) {\n return (\n <div className=\"mb-2\">\n <div className=\"font-medium text-[0.875rem] text-ink\">\n {children}\n {required ? <span className=\"ml-1 text-ember\">*</span> : null}\n </div>\n {hint ? <div className=\"mt-0.5 text-[0.8125rem] text-ink-3\">{hint}</div> : null}\n </div>\n );\n}\n\nexport function Spinner({ className }: { className?: string }) {\n return (\n <svg className={cn(\"size-5 animate-spin\", className)} viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" strokeOpacity=\"0.2\" strokeWidth=\"3\" />\n <path d=\"M21 12a9 9 0 0 0-9-9\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n\nexport function Card({\n className,\n children,\n ...rest\n}: { className?: string; children: ReactNode } & React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n \"wizard-card rounded-xl bg-card shadow-soft ring-1 ring-border-soft\",\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/** `icon`: in place of the live dot. `title`: what the chip means, on hover. */\nexport function Chip({\n children,\n tone = \"neutral\",\n icon,\n title,\n}: {\n children: ReactNode;\n tone?: \"neutral\" | \"live\" | \"warn\" | \"ember\";\n icon?: ReactNode;\n title?: string;\n}) {\n return (\n <span\n title={title}\n className={cn(\n \"inline-flex h-6 items-center gap-1.5 whitespace-nowrap rounded-full px-2.5 font-medium text-[0.75rem]\",\n tone === \"neutral\" && \"bg-paper-2 text-ink-2\",\n tone === \"live\" && \"bg-moss-tint text-moss\",\n tone === \"warn\" && \"bg-amber-tint text-ink-2\",\n tone === \"ember\" && \"bg-ember-tint text-ember-strong\",\n )}\n >\n {icon ?? (tone === \"live\" ? <span className=\"size-1.5 rounded-full bg-moss\" /> : null)}\n {children}\n </span>\n );\n}\n\n/**\n * A centred modal on the native <dialog>; on a phone it fills the screen, with no gutter. Its\n * height does not jump while it is open: a dialog\n * with tabs, folds or lists (`height=\"tall\"`) stands at a height taken from the window and\n * scrolls inside; any other keeps the tallest height it has had, so switching to a shorter tab\n * or folding a section leaves it where it is.\n */\nexport function Dialog({\n open,\n onClose,\n title,\n children,\n wide,\n bare,\n height = \"auto\",\n}: {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n children: ReactNode;\n /** `\"page\"`: room for a document. */\n wide?: boolean | \"page\";\n /**\n * The children are the panel: the dialog itself draws no card, clips nothing (a close button\n * may sit on the panel's edge) and fills the screen of a phone.\n */\n bare?: boolean;\n /** `\"tall\"`: as tall as the window allows (up to 56 rem), whatever is in it. */\n height?: \"auto\" | \"tall\";\n}) {\n const ref = useRef<HTMLDialogElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) {\n return;\n }\n if (open && !el.open) {\n el.showModal();\n // A modal dialog focuses its first control (the close button); a field marked\n // `data-autofocus` is where typing starts instead.\n el.querySelector<HTMLElement>(\"[data-autofocus]\")?.focus();\n } else if (!open && el.open) {\n el.close();\n }\n }, [open]);\n // Open, the dialog never gets shorter than it has been — within what the window allows.\n useEffect(() => {\n const el = ref.current;\n if (!el || !open || bare || height === \"tall\") {\n return;\n }\n let tallest = 0;\n const keep = () => {\n tallest = Math.max(tallest, el.getBoundingClientRect().height);\n el.style.minHeight = `${Math.min(tallest, window.innerHeight - 32)}px`;\n };\n const observer = new ResizeObserver(keep);\n observer.observe(el);\n window.addEventListener(\"resize\", keep);\n return () => {\n observer.disconnect();\n window.removeEventListener(\"resize\", keep);\n el.style.minHeight = \"\";\n };\n }, [open, bare, height]);\n return (\n <dialog\n ref={ref}\n onClose={onClose}\n onClick={(e) => {\n if (e.target === ref.current) {\n onClose();\n }\n }}\n className={cn(\n \"m-auto p-0 text-ink backdrop:bg-[oklch(20%_0.01_60/0.28)] backdrop:backdrop-blur-[2px]\",\n // A phone: the whole screen, no gutter, clear of the notch and the home indicator.\n \"max-sm:m-0 max-sm:h-dvh max-sm:max-h-none max-sm:w-full max-sm:max-w-none\",\n bare\n ? \"w-[calc(100%-48px)] overflow-visible bg-transparent\"\n : \"max-h-[calc(100dvh-32px)] w-[calc(100%-32px)] overflow-y-auto overscroll-contain rounded-2xl bg-card shadow-overlay max-sm:rounded-none max-sm:pt-[env(safe-area-inset-top)] max-sm:pb-[env(safe-area-inset-bottom)]\",\n wide === \"page\" ? \"sm:max-w-4xl\" : wide ? \"sm:max-w-2xl\" : \"sm:max-w-md\",\n !bare && height === \"tall\" && \"sm:h-[min(calc(100dvh-32px),56rem)]\",\n )}\n >\n {open && bare ? (\n children\n ) : open ? (\n <div className=\"p-5 sm:p-7\">\n {title ? (\n <div className=\"mb-5 flex items-start justify-between gap-3\">\n <h2 className=\"min-w-0 font-display font-semibold text-xl\">{title}</h2>\n <IconButton label={t(\"common.close\")} onClick={onClose} className=\"-mt-1.5 -mr-2\">\n <svg viewBox=\"0 0 16 16\" fill=\"none\" className=\"size-4\" aria-hidden=\"true\">\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </IconButton>\n </div>\n ) : null}\n {children}\n </div>\n ) : null}\n </dialog>\n );\n}\n\nexport function Empty({ children }: { children: ReactNode }) {\n return <div className=\"py-16 text-center text-ink-3\">{children}</div>;\n}\n\n/** A sentence of the server with its web addresses as links, named by their host. */\nexport function LinkedText({ text }: { text: string }) {\n return text.split(/(https?:\\/\\/[^\\s)]+)/).map((part, i) =>\n i % 2 ? (\n <a\n key={part}\n href={part}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"font-medium text-ink underline underline-offset-2\"\n >\n {new URL(part).host}\n </a>\n ) : (\n part\n ),\n );\n}\n","import type { BrowserAct } from \"@engenty/wizards-shared/run\";\nimport { ArrowDown, ArrowUp, CornerDownLeft, MousePointerClick } from \"lucide-react\";\nimport { type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { api, runBase, withBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { cn, Input } from \"./ui.js\";\n\n/** Scrolling in the page is sent at most this often; the wheel's movement in between adds up. */\nconst WHEEL_EVERY_MS = 250;\n\n/**\n * The wizard's browser, live: a picture from the run that changes as the page does. Watching,\n * it shows over the page what the wizard just did; driving, the person clicks, scrolls and\n * types in it — what they type goes into the page and no model reads it back.\n */\nexport function LiveBrowser({\n runId,\n driving,\n caption,\n action,\n hint,\n className,\n onBroken,\n}: {\n runId: string;\n driving: boolean;\n /** What the wizard just did, over the page while watching. */\n caption?: string;\n /** A button in the corner: take over, hand back. */\n action?: ReactNode;\n /** A line over the controls while driving. */\n hint?: string;\n className?: string;\n /** The stream broke off: the run let the browser go. */\n onBroken?: () => void;\n}) {\n const image = useRef<HTMLImageElement>(null);\n const controls = useRef<HTMLDivElement>(null);\n const [text, setText] = useState(\"\");\n const [hidden, setHidden] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const act = async (body: BrowserAct) => {\n setError(null);\n try {\n await api.post(`${runBase(runId)}/browser/act`, body);\n } catch (err) {\n setError((err as Error).message);\n }\n };\n\n // Taking over brings the controls under the page into view.\n useEffect(() => {\n if (driving) {\n controls.current?.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }\n }, [driving]);\n\n // The wheel scrolls the page, not the chat around it: a listener that may prevent that.\n useEffect(() => {\n const el = image.current;\n if (!(el && driving)) {\n return;\n }\n let pending = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n pending += e.deltaY;\n timer ??= setTimeout(() => {\n timer = null;\n const dy = Math.max(-2000, Math.min(2000, Math.round(pending)));\n pending = 0;\n if (dy) {\n void api\n .post(`${runBase(runId)}/browser/act`, { type: \"scroll\", dy })\n .catch(() => undefined);\n }\n }, WHEEL_EVERY_MS);\n };\n el.addEventListener(\"wheel\", onWheel, { passive: false });\n return () => {\n el.removeEventListener(\"wheel\", onWheel);\n if (timer) {\n clearTimeout(timer);\n }\n };\n }, [driving, runId]);\n\n const click = (e: React.MouseEvent<HTMLImageElement>) => {\n if (!driving) {\n return;\n }\n const box = e.currentTarget.getBoundingClientRect();\n void act({\n type: \"click\",\n fx: Math.min(1, Math.max(0, (e.clientX - box.left) / box.width)),\n fy: Math.min(1, Math.max(0, (e.clientY - box.top) / box.height)),\n });\n };\n\n return (\n <div className={className}>\n <div\n className={cn(\n \"relative aspect-[1280/900] w-full overflow-hidden rounded-xl bg-paper-2 ring-1\",\n driving ? \"ring-2 ring-ember\" : \"ring-border-soft\",\n )}\n >\n <img\n ref={image}\n src={withBase(`${runBase(runId)}/browser/live`)}\n alt=\"\"\n draggable={false}\n onClick={click}\n onError={onBroken}\n className={cn(\"size-full object-cover object-top\", driving && \"cursor-pointer\")}\n />\n {action ? <div className=\"absolute top-2 right-2\">{action}</div> : null}\n {caption && !driving ? (\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 flex items-center gap-1.5 bg-gradient-to-t from-black/75 to-transparent px-3 pt-8 pb-2 text-[0.8125rem] text-white\">\n <MousePointerClick className=\"size-3.5 shrink-0\" />\n <span className=\"truncate\">{caption}</span>\n </div>\n ) : null}\n </div>\n {driving ? (\n <div ref={controls} className=\"mt-1.5\">\n {hint ? <p className=\"mb-1.5 text-[0.8125rem] text-ink-3\">{hint}</p> : null}\n <div className=\"flex flex-wrap items-center gap-1.5 rounded-xl bg-card p-2 ring-1 ring-border-soft\">\n <Input\n type={hidden ? \"password\" : \"text\"}\n autoComplete=\"off\"\n value={text}\n placeholder={t(\"ask.typeInto\")}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void act({ type: \"type\", text }).then(() => setText(\"\"));\n }\n }}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n enterKeyHint=\"send\"\n className=\"h-9 min-w-[9rem] flex-1 basis-full text-[0.8125rem] sm:basis-0 coarse:h-11\"\n />\n <button\n type=\"button\"\n onClick={() => setHidden((h) => !h)}\n className={cn(\n \"h-9 shrink-0 rounded-md px-2.5 text-[0.75rem] coarse:h-11 coarse:px-3.5\",\n hidden ? \"bg-ember-veil text-ink\" : \"text-ink-3 hover:bg-paper-2\",\n )}\n >\n {t(\"ask.hide\")}\n </button>\n <ToolButton label=\"Enter\" onClick={() => void act({ type: \"key\", key: \"Enter\" })}>\n <CornerDownLeft className=\"size-4\" />\n </ToolButton>\n <ToolButton label={t(\"ask.up\")} onClick={() => void act({ type: \"scroll\", dy: -500 })}>\n <ArrowUp className=\"size-4\" />\n </ToolButton>\n <ToolButton label={t(\"ask.down\")} onClick={() => void act({ type: \"scroll\", dy: 500 })}>\n <ArrowDown className=\"size-4\" />\n </ToolButton>\n </div>\n {error ? <p className=\"mt-1.5 text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ToolButton({\n label,\n onClick,\n children,\n}: {\n label: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n onClick={onClick}\n className=\"flex size-9 shrink-0 items-center justify-center rounded-md text-ink-3 hover:bg-paper-2 hover:text-ink coarse:size-11\"\n >\n {children}\n </button>\n );\n}\n","import type { AskAnswer, ConfirmAsk, LoginAsk, RunAsk } from \"@engenty/wizards-shared/run\";\nimport { LockKeyhole, PencilLine, ShieldCheck, TriangleAlert } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { LiveBrowser } from \"./browser-live.js\";\nimport { api, runBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, cn, Input, Label, Switch } from \"./ui.js\";\n\n/** What a running step asks the person: a sign-in, or leave to change something. */\nexport function AskPanel({ runId, ask }: { runId: string; ask: RunAsk }) {\n return ask.kind === \"confirm\" ? (\n <ConfirmPanel runId={runId} ask={ask} />\n ) : (\n <LoginPanel runId={runId} ask={ask} />\n );\n}\n\n/**\n * A running step wants to change something in an account the person connected. They see what\n * and with which values, and decide.\n */\nfunction ConfirmPanel({ runId, ask }: { runId: string; ask: ConfirmAsk }) {\n const [remember, setRemember] = useState(false);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const answer = async (body: AskAnswer) => {\n setBusy(true);\n setError(null);\n try {\n await api.post(`${runBase(runId)}/ask/${ask.id}`, body);\n } catch (err) {\n setError((err as Error).message);\n setBusy(false);\n }\n };\n const Icon = ask.action.destructive ? TriangleAlert : PencilLine;\n return (\n <div className=\"animate-rise\">\n <div className=\"mb-5 flex items-start gap-3\">\n <div\n className={cn(\n \"flex size-10 shrink-0 items-center justify-center rounded-full\",\n ask.action.destructive ? \"bg-rose-tint text-rose\" : \"bg-ember-tint text-ember-strong\",\n )}\n >\n <Icon className=\"size-5\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-[0.8125rem] text-ink-3\">{t(\"ask.wants\", { service: ask.service })}</p>\n <h2 className=\"wizard-heading font-display font-semibold text-[1.25rem] leading-snug tracking-tight\">\n {ask.reason}\n </h2>\n </div>\n </div>\n <pre className=\"max-h-72 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-paper-2 p-4 text-[0.8125rem] leading-relaxed ring-1 ring-border-soft\">\n {ask.input}\n </pre>\n {ask.once ? null : (\n <div className=\"mt-5 flex items-center gap-4\">\n <Switch checked={remember} onChange={setRemember} label={t(\"ask.allowRest\")} />\n <span className=\"flex-1 text-[0.8125rem] text-ink-2\">{t(\"ask.allowRest\")}</span>\n </div>\n )}\n {error ? (\n <div className=\"mt-3 rounded-lg bg-rose-tint px-4 py-3 text-[0.875rem] text-rose\">\n {error}\n </div>\n ) : null}\n <div className=\"action-bar mt-6 flex items-center justify-between gap-3\">\n <Button variant=\"ghost\" disabled={busy} onClick={() => void answer({ type: \"skip\" })}>\n {t(\"ask.deny\")}\n </Button>\n <Button busy={busy} onClick={() => void answer({ type: \"done\", remember })}>\n {t(\"ask.allow\")}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * A running step asks the person to sign in on a page the wizard has open. The page is shown\n * live: they fill the form here, or click and type in the page itself (a captcha, \"continue\n * with Google\"). What they enter goes into the page — the model never gets it.\n */\nfunction LoginPanel({ runId, ask }: { runId: string; ask: LoginAsk }) {\n const [values, setValues] = useState<Record<string, string>>({});\n const [remember, setRemember] = useState(false);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const answer = async (body: AskAnswer) => {\n setBusy(true);\n setError(null);\n try {\n await api.post(`${runBase(runId)}/ask/${ask.id}`, body);\n } catch (err) {\n setError((err as Error).message);\n setBusy(false);\n }\n };\n const filled = ask.fields.some((f) => values[f.id]);\n\n return (\n <div className=\"animate-rise\">\n <div className=\"mb-5 flex items-start gap-3\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-ember-tint text-ember-strong\">\n <LockKeyhole className=\"size-5\" />\n </div>\n <div className=\"min-w-0\">\n <h2 className=\"wizard-heading font-display font-semibold text-[1.25rem] leading-snug tracking-tight\">\n {ask.reason}\n </h2>\n <p className=\"mt-0.5 truncate text-[0.8125rem] text-ink-3\">\n {ask.site.host}\n {ask.site.title ? ` · ${ask.site.title}` : \"\"}\n </p>\n </div>\n </div>\n\n <LiveBrowser runId={runId} driving />\n <p className=\"mt-2 text-[0.75rem] text-ink-4\">{t(\"ask.pictureHint\")}</p>\n\n {ask.fields.length ? (\n <form\n className=\"mt-5 flex flex-col gap-4\"\n onSubmit={(e) => {\n e.preventDefault();\n void answer({ type: \"fill\", values, remember });\n }}\n >\n {ask.fields.map((f, i) => (\n <div key={f.id}>\n <Label>{f.label}</Label>\n <Input\n autoFocus={i === 0}\n type={f.secret ? \"password\" : \"text\"}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n enterKeyHint={i === ask.fields.length - 1 ? \"go\" : \"next\"}\n value={values[f.id] ?? \"\"}\n onChange={(e) => setValues((v) => ({ ...v, [f.id]: e.target.value }))}\n />\n </div>\n ))}\n <button type=\"submit\" hidden />\n </form>\n ) : null}\n\n <div className=\"mt-5 flex items-center justify-between gap-4\">\n <Switch checked={remember} onChange={setRemember} label={t(\"ask.remember\")} />\n <span className=\"flex-1 text-[0.8125rem] text-ink-2\">{t(\"ask.remember\")}</span>\n </div>\n <p className=\"mt-3 flex items-start gap-2 text-[0.8125rem] text-ink-3\">\n <ShieldCheck className=\"mt-0.5 size-4 shrink-0 text-moss\" /> {t(\"ask.private\")}\n </p>\n {error ? (\n <div className=\"mt-3 rounded-lg bg-rose-tint px-4 py-3 text-[0.875rem] text-rose\">\n {error}\n </div>\n ) : null}\n\n <div className=\"action-bar mt-6 flex flex-wrap items-center justify-between gap-3\">\n <Button variant=\"ghost\" disabled={busy} onClick={() => void answer({ type: \"skip\" })}>\n {t(\"ask.skip\")}\n </Button>\n <div className=\"flex flex-wrap gap-2\">\n {ask.fields.length ? (\n <Button\n variant=\"secondary\"\n disabled={busy}\n onClick={() => void answer({ type: \"done\", remember })}\n >\n {t(\"ask.done\")}\n </Button>\n ) : null}\n {ask.fields.length ? (\n <Button\n busy={busy}\n disabled={!filled}\n onClick={() => void answer({ type: \"fill\", values, remember })}\n >\n {t(\"ask.signIn\")}\n </Button>\n ) : (\n <Button busy={busy} onClick={() => void answer({ type: \"done\", remember })}>\n {t(\"ask.done\")}\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n}\n","import { useEffect, useState, useSyncExternalStore } from \"react\";\nimport { appCall, appCan, appTell, asset, runnerEnv } from \"./env.js\";\n\n/** A finger as the main pointer: a phone or a tablet. */\nexport const isTouch =\n typeof window !== \"undefined\" && window.matchMedia?.(\"(pointer: coarse)\").matches === true;\n\n/** The camera, the microphone and the position only exist on https (and localhost). */\nexport const canUseMedia =\n typeof navigator !== \"undefined\" && Boolean(navigator.mediaDevices?.getUserMedia);\n\n/**\n * Keeps `--kb` on the root: how much of the page the on-screen keyboard covers. iOS lays the\n * keyboard over the page without resizing it, so a bar stuck to the bottom would hide behind it.\n */\nexport function useKeyboardInset() {\n useEffect(() => {\n const vv = window.visualViewport;\n if (!vv) {\n return;\n }\n const root = document.documentElement;\n // The field being typed in stays in sight: above the bar on the keyboard (its\n // scroll-margin, app.css), once the keyboard is up and on every move to another field.\n const reveal = () => {\n const el = document.activeElement;\n if (\n root.classList.contains(\"keyboard-open\") &&\n el instanceof HTMLElement &&\n el !== document.body\n ) {\n requestAnimationFrame(() => el.scrollIntoView({ block: \"nearest\" }));\n }\n };\n const update = () => {\n // Pinch-zoom shrinks the visual viewport too; only an unzoomed page measures the keyboard.\n const covered = vv.scale > 1.01 ? 0 : window.innerHeight - vv.height - vv.offsetTop;\n const open = covered > 80;\n const opened = open && !root.classList.contains(\"keyboard-open\");\n root.style.setProperty(\"--kb\", open ? `${Math.round(covered)}px` : \"0px\");\n root.classList.toggle(\"keyboard-open\", open);\n if (opened) {\n reveal();\n }\n };\n update();\n vv.addEventListener(\"resize\", update);\n vv.addEventListener(\"scroll\", update);\n document.addEventListener(\"focusin\", reveal);\n return () => {\n vv.removeEventListener(\"resize\", update);\n vv.removeEventListener(\"scroll\", update);\n document.removeEventListener(\"focusin\", reveal);\n root.style.removeProperty(\"--kb\");\n root.classList.remove(\"keyboard-open\");\n };\n }, []);\n}\n\n/**\n * Keeps the screen on while `active` — a phone that dims and locks mid-step freezes the page.\n * The lock ends whenever the page is hidden and is taken again when the person comes back.\n */\nexport function useWakeLock(active: boolean): boolean {\n const [held, setHeld] = useState(false);\n useEffect(() => {\n if (active && appCan(\"keepAwake\")) {\n // The app keeps the screen on; the page's lock ends whenever iOS hides the WebView.\n appTell(\"keepAwake\", true);\n setHeld(true);\n return () => {\n appTell(\"keepAwake\", false);\n setHeld(false);\n };\n }\n if (!active || !(\"wakeLock\" in navigator)) {\n return;\n }\n let lock: WakeLockSentinel | null = null;\n let stopped = false;\n const acquire = async () => {\n if (stopped || lock || document.visibilityState !== \"visible\") {\n return;\n }\n try {\n const taken = await navigator.wakeLock.request(\"screen\");\n if (stopped) {\n void taken.release().catch(() => undefined);\n return;\n }\n lock = taken;\n setHeld(true);\n taken.addEventListener(\"release\", () => {\n if (lock === taken) {\n lock = null;\n setHeld(false);\n }\n });\n } catch {\n // Low battery or a browser policy: the run goes on, the screen may dim.\n }\n };\n void acquire();\n document.addEventListener(\"visibilitychange\", acquire);\n return () => {\n stopped = true;\n document.removeEventListener(\"visibilitychange\", acquire);\n void lock?.release().catch(() => undefined);\n lock = null;\n setHeld(false);\n };\n }, [active]);\n return held;\n}\n\n// --- telling the person a long step is done ----------------------------------------------\n\nconst NOTIFY_KEY = \"wz.notify\";\nconst listeners = new Set<() => void>();\nlet audio: AudioContext | null = null;\n\nfunction wanted(): boolean {\n try {\n return localStorage.getItem(NOTIFY_KEY) === \"1\";\n } catch {\n return false;\n }\n}\n\nfunction setWanted(on: boolean) {\n try {\n if (on) {\n localStorage.setItem(NOTIFY_KEY, \"1\");\n } else {\n localStorage.removeItem(NOTIFY_KEY);\n }\n } catch {\n // private mode: the wish lasts until the page is reloaded\n }\n for (const listener of listeners) {\n listener();\n }\n}\n\nconst hasNotifications = typeof window !== \"undefined\" && \"Notification\" in window;\n\n/**\n * `off` — not asked for. `on` — a notification when the page is in the background, a sound and a\n * buzz when it is open. `quiet` — asked for, but the browser shows no notifications for this\n * page (blocked, or a phone browser without them): only sound and buzz while the page is open.\n */\nexport type NotifyState = \"off\" | \"on\" | \"quiet\";\n\n/** In the mobile app: what the person answered the app's own question. */\nlet appAllows: boolean | null = null;\n\nfunction notifyState(): NotifyState {\n if (!wanted()) {\n return \"off\";\n }\n if (appCan(\"notify\")) {\n return appAllows === false ? \"quiet\" : \"on\";\n }\n return hasNotifications && Notification.permission === \"granted\" ? \"on\" : \"quiet\";\n}\n\nexport function useNotifyState(): NotifyState {\n return useSyncExternalStore(\n (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n notifyState,\n () => \"off\" as const,\n );\n}\n\n/** Whether the browser has blocked notifications for this page (the person can undo it there). */\nexport function notificationsBlocked(): boolean {\n if (appCan(\"notify\")) {\n return appAllows === false;\n }\n return hasNotifications && Notification.permission === \"denied\";\n}\n\n/**\n * The person asks to be told. Called from their tap: the browser's permission question and the\n * sound both need one.\n */\nexport async function enableNotify(): Promise<NotifyState> {\n setWanted(true);\n if (appCan(\"notify\")) {\n appAllows = appCan(\"notifyPermission\")\n ? await appCall<boolean>(\"notifyPermission\").catch(() => false)\n : true;\n for (const listener of listeners) {\n listener();\n }\n return notifyState();\n }\n // A sound may only play on a page the person has tapped; this is that tap.\n try {\n audio ??= new AudioContext();\n void audio.resume();\n } catch {\n audio = null;\n }\n if (hasNotifications && Notification.permission === \"default\") {\n try {\n await Notification.requestPermission();\n } catch {\n // stays \"default\": sound and buzz only\n }\n }\n if (hasNotifications && Notification.permission === \"granted\") {\n // Phones only show a page's notification through a service worker.\n const worker = runnerEnv().serviceWorker;\n if (worker) {\n await navigator.serviceWorker?.register(worker).catch(() => undefined);\n }\n }\n for (const listener of listeners) {\n listener();\n }\n return notifyState();\n}\n\nexport function disableNotify() {\n setWanted(false);\n}\n\nfunction chime() {\n const ctx = audio;\n if (ctx?.state !== \"running\") {\n return;\n }\n const now = ctx.currentTime;\n for (const [i, freq] of [660, 880].entries()) {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.frequency.value = freq;\n gain.gain.setValueAtTime(0, now + i * 0.16);\n gain.gain.linearRampToValueAtTime(0.18, now + i * 0.16 + 0.02);\n gain.gain.exponentialRampToValueAtTime(0.001, now + i * 0.16 + 0.32);\n osc.connect(gain).connect(ctx.destination);\n osc.start(now + i * 0.16);\n osc.stop(now + i * 0.16 + 0.34);\n }\n}\n\n/** Tells the person, in whatever way they agreed to and the device has. A no-op otherwise. */\nexport async function signalPerson(message: { title: string; body: string; tag: string }) {\n if (!wanted()) {\n return;\n }\n if (appCan(\"notify\")) {\n // The app knows whether it is in front: a buzz there, a notification otherwise.\n appTell(\"notify\", message);\n return;\n }\n if (document.visibilityState === \"visible\") {\n chime();\n navigator.vibrate?.([120, 60, 120]);\n return;\n }\n if (!hasNotifications || Notification.permission !== \"granted\") {\n return;\n }\n const options = {\n body: message.body,\n tag: message.tag,\n icon: asset(\"icons/icon-192.png\"),\n badge: asset(\"icons/icon-192.png\"),\n data: { url: location.href },\n };\n try {\n const registration = await navigator.serviceWorker?.getRegistration();\n if (registration?.active) {\n await registration.showNotification(message.title, options);\n return;\n }\n } catch {\n // falls through to the page's own notification\n }\n try {\n new Notification(message.title, options);\n } catch {\n // a phone without the service worker: the page title still says it\n }\n}\n\n/** A share sheet that takes files: phones, and desktop Safari and Chrome. */\nexport function canShareFiles(): boolean {\n if (typeof navigator === \"undefined\" || !navigator.canShare) {\n return false;\n }\n try {\n return navigator.canShare({ files: [new File([\"x\"], \"x.pdf\", { type: \"application/pdf\" })] });\n } catch {\n return false;\n }\n}\n","import { Camera, Check, Flashlight, FlashlightOff, SwitchCamera, Video, X } from \"lucide-react\";\nimport { type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { isTouch } from \"./device\";\nimport { t } from \"./i18n.js\";\nimport { cn, Spinner } from \"./ui.js\";\n\n/**\n * A photo as small as a reader needs it: phone pictures are several megabytes, which is slow to\n * upload and more than a vision model takes.\n */\nexport async function shrinkImage(file: File, max = 2400): Promise<File> {\n if (!/^image\\/(jpeg|png|webp)$/.test(file.type) || file.size < 1_200_000) {\n return file;\n }\n try {\n const bitmap = await createImageBitmap(file);\n const scale = Math.min(1, max / Math.max(bitmap.width, bitmap.height));\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.round(bitmap.width * scale);\n canvas.height = Math.round(bitmap.height * scale);\n canvas.getContext(\"2d\")?.drawImage(bitmap, 0, 0, canvas.width, canvas.height);\n const blob = await new Promise<Blob | null>((r) => canvas.toBlob(r, \"image/jpeg\", 0.86));\n return blob && blob.size < file.size\n ? new File([blob], `${file.name.replace(/\\.[^.]+$/, \"\")}.jpg`, { type: \"image/jpeg\" })\n : file;\n } catch {\n return file;\n }\n}\n\nexport function stamp(): string {\n return new Date().toISOString().slice(0, 19).replace(/[:T]/g, \"-\");\n}\n\nexport type Facing = \"environment\" | \"user\";\n/** Why there is no picture: the person (or the browser) said no, there is no camera, or it is in use. */\nexport type CameraError = \"denied\" | \"missing\" | \"busy\";\n\nfunction cameraError(err: unknown): CameraError {\n const name = (err as DOMException)?.name;\n if (name === \"NotFoundError\" || name === \"OverconstrainedError\") {\n return \"missing\";\n }\n if (name === \"NotReadableError\" || name === \"AbortError\") {\n return \"busy\";\n }\n return \"denied\";\n}\n\n/** The phone's light, where the camera track has one (Chrome on Android). */\nfunction hasTorch(track: MediaStreamTrack | undefined): boolean {\n const capabilities = track?.getCapabilities?.() as { torch?: boolean } | undefined;\n return Boolean(capabilities?.torch);\n}\n\n/**\n * The device's camera as a live picture, for as long as `active`. The browser asks for the\n * camera when this starts — callers open it from the person's tap. With `audio` the microphone\n * is asked for too; a refused microphone still gives a silent picture.\n */\nexport function useCameraStream(active: boolean, facing: Facing, audio = false) {\n const video = useRef<HTMLVideoElement>(null);\n const [stream, setStream] = useState<MediaStream | null>(null);\n const [error, setError] = useState<CameraError | null>(null);\n const [cameras, setCameras] = useState(1);\n const [torchable, setTorchable] = useState(false);\n const [torch, setTorchOn] = useState(false);\n\n useEffect(() => {\n if (!active) {\n return;\n }\n let live: MediaStream | null = null;\n let stopped = false;\n setError(null);\n setStream(null);\n setTorchable(false);\n setTorchOn(false);\n const picture = {\n facingMode: { ideal: facing },\n width: { ideal: 2560 },\n height: { ideal: 1440 },\n };\n const start = async () => {\n if (!navigator.mediaDevices?.getUserMedia) {\n throw new DOMException(\"no camera api\", \"NotAllowedError\");\n }\n try {\n live = await navigator.mediaDevices.getUserMedia({ video: picture, audio });\n } catch (err) {\n if (!audio) {\n throw err;\n }\n live = await navigator.mediaDevices.getUserMedia({ video: picture });\n }\n if (stopped) {\n for (const track of live.getTracks()) {\n track.stop();\n }\n return;\n }\n setStream(live);\n const track = live.getVideoTracks()[0];\n // Phones report the torch a moment after the picture starts.\n const readTorch = () => !stopped && setTorchable(hasTorch(track));\n readTorch();\n setTimeout(readTorch, 600);\n const devices = await navigator.mediaDevices.enumerateDevices().catch(() => []);\n if (!stopped) {\n setCameras(devices.filter((d) => d.kind === \"videoinput\").length);\n }\n };\n start().catch((err) => !stopped && setError(cameraError(err)));\n return () => {\n stopped = true;\n for (const track of live?.getTracks() ?? []) {\n track.stop();\n }\n };\n }, [active, facing, audio]);\n\n useEffect(() => {\n if (video.current && stream) {\n video.current.srcObject = stream;\n }\n }, [stream]);\n\n const setTorch = async (on: boolean) => {\n const track = stream?.getVideoTracks()[0];\n try {\n await track?.applyConstraints({ advanced: [{ torch: on } as MediaTrackConstraintSet] });\n setTorchOn(on);\n } catch {\n setTorchable(false);\n }\n };\n const mirrored = stream?.getVideoTracks()[0]?.getSettings().facingMode === \"user\";\n return { video, stream, error, cameras, torchable, torch, setTorch, mirrored };\n}\n\n/** The camera or the scanner: the whole screen on a phone, a centred sheet on a desk. */\nexport function MediaSheet({\n open,\n onClose,\n label,\n children,\n}: {\n open: boolean;\n onClose: () => void;\n label: string;\n children: ReactNode;\n}) {\n const ref = useRef<HTMLDialogElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) {\n return;\n }\n if (open && !el.open) {\n el.showModal();\n } else if (!open && el.open) {\n el.close();\n }\n }, [open]);\n return (\n <dialog ref={ref} onClose={onClose} aria-label={label} className=\"media-sheet\">\n {open ? <div className=\"flex h-full flex-col\">{children}</div> : null}\n </dialog>\n );\n}\n\nexport function SheetButton({\n label,\n onClick,\n active,\n children,\n}: {\n label: string;\n onClick: () => void;\n active?: boolean;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n aria-pressed={active}\n onClick={onClick}\n className={cn(\n \"flex size-11 shrink-0 items-center justify-center rounded-full transition\",\n active ? \"bg-white text-black\" : \"bg-white/12 text-white hover:bg-white/20\",\n )}\n >\n {children}\n </button>\n );\n}\n\n/** The top row of a media sheet: close, what this is, and the camera's switches. */\nexport function SheetBar({\n title,\n onClose,\n camera,\n onFlip,\n}: {\n title: string;\n onClose: () => void;\n camera: ReturnType<typeof useCameraStream>;\n onFlip: () => void;\n}) {\n return (\n <div className=\"safe-top\">\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <SheetButton label={t(\"common.close\")} onClick={onClose}>\n <X className=\"size-5\" />\n </SheetButton>\n <div className=\"min-w-0 flex-1 truncate text-center font-medium text-[0.9375rem]\">\n {title}\n </div>\n {camera.torchable ? (\n <SheetButton\n label={t(\"camera.torch\")}\n active={camera.torch}\n onClick={() => void camera.setTorch(!camera.torch)}\n >\n {camera.torch ? (\n <Flashlight className=\"size-5\" />\n ) : (\n <FlashlightOff className=\"size-5\" />\n )}\n </SheetButton>\n ) : null}\n {camera.stream && (camera.cameras > 1 || isTouch) ? (\n <SheetButton label={t(\"camera.flip\")} onClick={onFlip}>\n <SwitchCamera className=\"size-5\" />\n </SheetButton>\n ) : (\n <span className=\"size-11\" />\n )}\n </div>\n </div>\n );\n}\n\n/** The live picture with what to say while there is none: the browser is asking, or it said no. */\nexport function CameraStage({\n camera,\n asking,\n children,\n actions,\n}: {\n camera: ReturnType<typeof useCameraStream>;\n /** One sentence shown while the browser asks for the camera. */\n asking: string;\n children?: ReactNode;\n /** Ways on when there is no camera. */\n actions?: ReactNode;\n}) {\n return (\n <div className=\"relative min-h-0 flex-1 overflow-hidden\">\n <video\n ref={camera.video}\n autoPlay\n playsInline\n muted\n className={cn(\n \"absolute inset-0 size-full object-contain\",\n camera.mirrored && \"-scale-x-100\",\n )}\n />\n {camera.error ? (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-5 bg-black px-8 text-center\">\n <p className=\"max-w-sm text-[0.9375rem] text-white/85 leading-relaxed\">\n {t(`camera.${camera.error}` as \"camera.denied\")}\n </p>\n {actions}\n </div>\n ) : camera.stream ? (\n children\n ) : (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-4 px-8 text-center text-white/75\">\n <Spinner />\n <p className=\"max-w-xs text-[0.875rem] leading-relaxed\">{asking}</p>\n </div>\n )}\n </div>\n );\n}\n\nconst CLIP_SECONDS = 30;\n\nfunction clipType(): string | undefined {\n if (typeof MediaRecorder === \"undefined\") {\n return undefined;\n }\n // MP4 plays everywhere a clip may later be opened; WebM is what older Chrome and Firefox record.\n return [\n \"video/mp4;codecs=avc1.42E01E,mp4a.40.2\",\n \"video/mp4\",\n \"video/webm;codecs=vp9,opus\",\n \"video/webm;codecs=vp8,opus\",\n \"video/webm\",\n ].find((type) => MediaRecorder.isTypeSupported(type));\n}\n\n/** Whether this browser can record a clip itself; otherwise the phone's camera app does it. */\nexport const canRecordClips = Boolean(clipType());\n\n/**\n * Takes pictures with the device's camera: one, or several in a row (the pages of a document),\n * and short clips when the field takes video. Front and back camera, and the torch where the\n * device has one.\n */\nexport function CameraDialog({\n open,\n multiple,\n video: allowVideo,\n onClose,\n onCapture,\n onNative,\n}: {\n open: boolean;\n multiple: boolean;\n /** Also record clips of up to half a minute. */\n video?: boolean;\n onClose: () => void;\n onCapture: (file: File) => Promise<void> | void;\n /** Opens the phone's own camera app instead — the way on when the browser has no camera for us. */\n onNative?: () => void;\n}) {\n const [facing, setFacing] = useState<Facing>(\"environment\");\n const [mode, setMode] = useState<\"photo\" | \"video\">(\"photo\");\n const [taken, setTaken] = useState(0);\n const [busy, setBusy] = useState(false);\n const [recording, setRecording] = useState<number | null>(null);\n const recorder = useRef<MediaRecorder | null>(null);\n const camera = useCameraStream(open, facing, mode === \"video\");\n\n useEffect(() => {\n if (open) {\n setTaken(0);\n setMode(\"photo\");\n setRecording(null);\n }\n }, [open]);\n\n const deliver = async (file: File) => {\n setBusy(true);\n try {\n await onCapture(file);\n setTaken((n) => n + 1);\n if (!multiple) {\n onClose();\n }\n } finally {\n setBusy(false);\n }\n };\n\n const shoot = async () => {\n const el = camera.video.current;\n if (!el?.videoWidth) {\n return;\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = el.videoWidth;\n canvas.height = el.videoHeight;\n canvas.getContext(\"2d\")?.drawImage(el, 0, 0);\n const blob = await new Promise<Blob | null>((r) => canvas.toBlob(r, \"image/jpeg\", 0.9));\n if (blob) {\n await deliver(new File([blob], `foto-${stamp()}.jpg`, { type: \"image/jpeg\" }));\n }\n };\n\n const stopClip = () => {\n if (recorder.current?.state === \"recording\") {\n recorder.current.stop();\n }\n };\n const startClip = () => {\n const type = clipType();\n if (!camera.stream || !type) {\n return;\n }\n const chunks: Blob[] = [];\n const rec = new MediaRecorder(camera.stream, {\n mimeType: type,\n videoBitsPerSecond: 2_500_000,\n audioBitsPerSecond: 96_000,\n });\n rec.ondataavailable = (e) => e.data.size && chunks.push(e.data);\n rec.onstop = () => {\n setRecording(null);\n recorder.current = null;\n const mime = type.split(\";\")[0];\n if (chunks.length) {\n const ext = mime === \"video/mp4\" ? \"mp4\" : \"webm\";\n void deliver(new File(chunks, `video-${stamp()}.${ext}`, { type: mime }));\n }\n };\n recorder.current = rec;\n rec.start(1000);\n setRecording(0);\n };\n // The clock of a running clip; it ends by itself at the limit.\n useEffect(() => {\n if (recording === null) {\n return;\n }\n if (recording >= CLIP_SECONDS) {\n if (recorder.current?.state === \"recording\") {\n recorder.current.stop();\n }\n return;\n }\n const id = setTimeout(() => setRecording((s) => (s === null ? null : s + 1)), 1000);\n return () => clearTimeout(id);\n }, [recording]);\n // Closing the sheet mid-clip keeps nothing.\n useEffect(() => {\n if (!open && recorder.current) {\n recorder.current.onstop = null;\n recorder.current.stop();\n recorder.current = null;\n }\n }, [open]);\n\n const clock = (s: number) => `0:${String(s).padStart(2, \"0\")}`;\n return (\n <MediaSheet open={open} onClose={onClose} label={t(\"camera.title\")}>\n <SheetBar\n title={\n recording !== null\n ? `${clock(recording)} / ${clock(CLIP_SECONDS)}`\n : taken\n ? t(\"camera.taken\", { n: taken })\n : t(\"camera.title\")\n }\n onClose={onClose}\n camera={camera}\n onFlip={() => setFacing((f) => (f === \"environment\" ? \"user\" : \"environment\"))}\n />\n <CameraStage\n camera={camera}\n asking={t(\"camera.asking\")}\n actions={\n <div className=\"flex flex-col gap-2\">\n {onNative ? (\n <SheetAction\n onClick={() => {\n onClose();\n onNative();\n }}\n >\n <Camera className=\"size-4\" /> {t(isTouch ? \"camera.native\" : \"camera.pick\")}\n </SheetAction>\n ) : null}\n <SheetAction quiet onClick={onClose}>\n {t(\"common.close\")}\n </SheetAction>\n </div>\n }\n />\n <div className={cn(\"safe-bottom px-4 pt-3\", camera.error && \"invisible\")}>\n {allowVideo && canRecordClips && recording === null ? (\n <div className=\"mb-3 flex justify-center gap-1 text-[0.8125rem]\">\n {([\"photo\", \"video\"] as const).map((m) => (\n <button\n key={m}\n type=\"button\"\n aria-pressed={mode === m}\n onClick={() => setMode(m)}\n className={cn(\n \"h-9 rounded-full px-4 font-medium transition\",\n mode === m ? \"bg-white text-black\" : \"text-white/70 hover:text-white\",\n )}\n >\n {t(m === \"photo\" ? \"camera.photo\" : \"camera.video\")}\n </button>\n ))}\n </div>\n ) : null}\n <div className=\"grid grid-cols-[1fr_auto_1fr] items-center gap-3\">\n <span className=\"text-[0.8125rem] text-white/70 leading-snug\">\n {recording !== null\n ? t(\"camera.recording\")\n : mode === \"video\"\n ? t(\"camera.clipHint\", { s: CLIP_SECONDS })\n : multiple\n ? t(\"camera.hintMany\")\n : t(\"camera.hint\")}\n </span>\n <button\n type=\"button\"\n aria-label={\n mode === \"photo\"\n ? t(\"camera.shoot\")\n : recording === null\n ? t(\"camera.record\")\n : t(\"camera.stop\")\n }\n disabled={!camera.stream || busy}\n onClick={() =>\n mode === \"photo\" ? void shoot() : recording === null ? startClip() : stopClip()\n }\n className=\"flex size-[72px] items-center justify-center rounded-full border-4 border-white transition active:scale-95 disabled:opacity-40\"\n >\n {busy ? (\n <Spinner className=\"text-white\" />\n ) : mode === \"photo\" ? (\n <span className=\"size-[54px] rounded-full bg-white\" />\n ) : recording === null ? (\n <span className=\"flex size-[54px] items-center justify-center rounded-full bg-[#e5484d]\">\n <Video className=\"size-6 text-white\" />\n </span>\n ) : (\n <span className=\"size-7 rounded-md bg-[#e5484d]\" />\n )}\n </button>\n <div className=\"flex justify-end\">\n {multiple && taken && recording === null ? (\n <SheetAction onClick={onClose}>\n <Check className=\"size-4\" /> {t(\"camera.done\")}\n </SheetAction>\n ) : null}\n </div>\n </div>\n </div>\n </MediaSheet>\n );\n}\n\nexport function SheetAction({\n onClick,\n quiet,\n children,\n}: {\n onClick: () => void;\n quiet?: boolean;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"inline-flex h-11 items-center justify-center gap-2 rounded-full px-5 font-medium text-[0.875rem] transition\",\n quiet ? \"text-white/75 hover:text-white\" : \"bg-white text-black hover:bg-white/90\",\n )}\n >\n {children}\n </button>\n );\n}\n","import { type AgentStep, stepShape } from \"@engenty/wizards-shared/definition\";\nimport type { StepOutput } from \"@engenty/wizards-shared/run\";\nimport {\n type FieldShape,\n type ListShape,\n labelOf,\n type ObjectShape,\n shapeJsonSchema,\n titleKey,\n} from \"@engenty/wizards-shared/shape\";\nimport {\n Braces,\n Check,\n ChevronRight,\n Copy,\n Database,\n Download,\n Link2,\n MoreVertical,\n Plus,\n Trash2,\n X,\n} from \"lucide-react\";\nimport { type ReactNode, useEffect, useId, useRef, useState } from \"react\";\nimport { api, runBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, cn, Dialog, Tabs } from \"./ui.js\";\n\n/**\n * A json step's data, shown and edited by its schema: lists of flat entries are tables as in\n * Space → Data; entries that hold lists of their own are cards that open; lists of words are\n * chips; a link to another list shows that entry's title. Ansicht · Bearbeiten · JSON.\n */\n\ntype Path = (string | number)[];\nexport type DataMode = \"view\" | \"edit\" | \"json\";\ntype Shape = FieldShape | ListShape[\"of\"];\ntype Entry = Record<string, unknown>;\n\ninterface Ctx {\n root: Entry;\n shape: ObjectShape;\n edit: boolean;\n /** Prefix of the ids entries get, so two editors on one page do not meet. */\n scope: string;\n set: (path: Path, value: unknown) => void;\n open: (id: string) => void;\n}\n\nconst cellField =\n \"w-full min-w-0 rounded-md bg-transparent px-2 py-1.5 text-[0.875rem] outline-none transition placeholder:text-ink-4 hover:bg-accent focus:bg-paper focus:ring-1 focus:ring-ring\";\n\nconst caption = \"font-medium text-[0.6875rem] text-ink-3 uppercase tracking-[0.08em]\";\n\nconst isEntry = (v: unknown): v is Entry =>\n Boolean(v) && typeof v === \"object\" && !Array.isArray(v);\n\nfunction setIn(value: unknown, path: Path, next: unknown): unknown {\n if (!path.length) {\n return next;\n }\n const [head, ...rest] = path;\n if (Array.isArray(value)) {\n const copy = [...value];\n copy[head as number] = setIn(copy[head as number], rest, next);\n return copy;\n }\n const obj = (value ?? {}) as Entry;\n return { ...obj, [head]: setIn(obj[head], rest, next) };\n}\n\n/** A table's rows as entries of text fields: its columns, or the keys its rows have. */\nfunction tableShape(columns: string[] | undefined, rows: unknown[]): ObjectShape {\n const keys = columns?.length\n ? columns\n : [...new Set(rows.filter(isEntry).flatMap((r) => Object.keys(r)))];\n return { kind: \"object\", fields: Object.fromEntries(keys.map((k) => [k, { kind: \"text\" }])) };\n}\n\n/** Fields that fit in a table cell: no lists of entries, no long text. */\nconst flat = (s: Shape) =>\n s.kind !== \"object\" &&\n s.kind !== \"table\" &&\n !(s.kind === \"list\" && s.of.kind === \"object\") &&\n !(s.kind === \"text\" && s.long);\n\nconst isTable = (s: ObjectShape) => Object.values(s.fields).every(flat);\n\n/** Entries without lists of their own but with long text: numbered rows (steps of a recipe). */\nconst isRows = (s: ObjectShape) =>\n Object.values(s.fields).every(\n (f) => f.kind !== \"table\" && !(f.kind === \"list\" && f.of.kind === \"object\"),\n );\n\n/** An entry's name: its first short text. */\nfunction titleOf(shape: ObjectShape, entry: Entry): string {\n const key = titleKey(shape);\n return key ? String(entry[key] ?? \"\") : \"\";\n}\n\nfunction Words({ text }: { text: string }) {\n return <span className=\"whitespace-pre-wrap\">{text}</span>;\n}\n\n/** One value by its kind, shown or edited in place. */\nfunction Value({\n shape,\n value,\n path,\n ctx,\n cell,\n}: {\n shape: Shape;\n value: unknown;\n path: Path;\n ctx: Ctx;\n cell?: boolean;\n}) {\n switch (shape.kind) {\n case \"text\":\n if (!ctx.edit) {\n return <Words text={value === null || value === undefined ? \"\" : String(value)} />;\n }\n return shape.long ? (\n <textarea\n className={cn(cellField, \"field-sizing-content max-h-60 resize-none\")}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n />\n ) : (\n <input\n className={cellField}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n />\n );\n case \"number\":\n return ctx.edit ? (\n <span className=\"flex items-center gap-1\">\n <input\n type=\"number\"\n className={cn(cellField, \"text-right tabular-nums\", cell && \"w-20\")}\n value={value === undefined || value === null ? \"\" : Number(value)}\n onChange={(e) => ctx.set(path, e.target.value === \"\" ? null : Number(e.target.value))}\n />\n {shape.unit ? <span className=\"text-[0.8125rem] text-ink-3\">{shape.unit}</span> : null}\n </span>\n ) : (\n <span className=\"tabular-nums\">\n {value === null || value === undefined\n ? \"\"\n : `${value}${shape.unit ? ` ${shape.unit}` : \"\"}`}\n </span>\n );\n case \"yesno\": {\n const word = value ? (shape.yes ?? t(\"data.yes\")) : (shape.no ?? t(\"data.no\"));\n return ctx.edit ? (\n <label className=\"flex items-center gap-2 px-2 py-1.5 text-[0.8125rem] text-ink-2\">\n <input\n type=\"checkbox\"\n checked={Boolean(value)}\n onChange={(e) => ctx.set(path, e.target.checked)}\n className=\"size-4 accent-[var(--second)]\"\n />\n {word}\n </label>\n ) : (\n <span\n className={cn(\n \"inline-flex rounded-full px-2 py-0.5 text-[0.75rem]\",\n value ? \"bg-second-tint text-second\" : \"bg-paper-2 text-ink-3\",\n )}\n >\n {word}\n </span>\n );\n }\n case \"choice\":\n case \"score\":\n return ctx.edit ? (\n <select\n className={cellField}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n >\n {[...new Set([String(value ?? \"\"), ...shape.options])].map((o) => (\n <option key={o} value={o}>\n {o}\n </option>\n ))}\n </select>\n ) : (\n <span>{String(value ?? \"\")}</span>\n );\n case \"ref\": {\n const target = ctx.shape.fields[shape.to];\n const fields: ObjectShape =\n target?.kind === \"list\" && target.of.kind === \"object\"\n ? target.of\n : { kind: \"object\", fields: {} };\n const list = (Array.isArray(ctx.root[shape.to]) ? ctx.root[shape.to] : []) as unknown[];\n const entries = list.filter(isEntry);\n const hit = entries.find((e) => e.id === value);\n if (ctx.edit) {\n return (\n <select\n className={cellField}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n >\n {hit ? null : <option value={String(value ?? \"\")}>{String(value ?? \"\")}</option>}\n {entries.map((e) => (\n <option key={String(e.id)} value={String(e.id)}>\n {titleOf(fields, e) || String(e.id)}\n </option>\n ))}\n </select>\n );\n }\n return hit ? (\n <button\n type=\"button\"\n onClick={() => ctx.open(String(hit.id))}\n className=\"inline-flex items-center gap-1 text-left text-ember-strong hover:underline\"\n >\n <Link2 className=\"size-3.5 shrink-0\" />\n {titleOf(fields, hit) || String(hit.id)}\n </button>\n ) : (\n <span className=\"text-rose\">{t(\"data.missing\", { id: String(value ?? \"\") })}</span>\n );\n }\n case \"table\": {\n const rows = Array.isArray(value) ? value : [];\n return (\n <EntryTable shape={tableShape(shape.columns, rows)} value={rows} path={path} ctx={ctx} />\n );\n }\n case \"list\":\n if (shape.of.kind === \"object\") {\n const of = shape.of;\n const Entries = isTable(of) ? EntryTable : isRows(of) ? EntryRows : EntryCards;\n return <Entries shape={of} value={value} path={path} ctx={ctx} />;\n }\n return <Chips value={value} path={path} ctx={ctx} />;\n case \"object\":\n return <Form shape={shape} value={value} path={path} ctx={ctx} />;\n }\n}\n\nfunction Chips({ value, path, ctx }: { value: unknown; path: Path; ctx: Ctx }) {\n const items = Array.isArray(value) ? value.map(String) : [];\n const [draft, setDraft] = useState(\"\");\n return (\n <span className=\"flex flex-wrap items-center gap-1\">\n {items.map((item, i) => (\n <span\n key={`${item}-${i}`}\n className=\"inline-flex items-center gap-1 rounded-full bg-paper-2 px-2 py-0.5 text-[0.75rem]\"\n >\n {item}\n {ctx.edit ? (\n <button\n type=\"button\"\n aria-label={t(\"data.remove\")}\n onClick={() =>\n ctx.set(\n path,\n items.filter((_, j) => j !== i),\n )\n }\n className=\"text-ink-3 hover:text-ink\"\n >\n <X className=\"size-3\" />\n </button>\n ) : null}\n </span>\n ))}\n {ctx.edit ? (\n <input\n className=\"w-20 rounded-full bg-transparent px-2 py-0.5 text-[0.75rem] outline-none ring-1 ring-border-soft focus:ring-ring\"\n placeholder=\"+\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && draft.trim()) {\n e.preventDefault();\n ctx.set(path, [...items, draft.trim()]);\n setDraft(\"\");\n }\n }}\n />\n ) : null}\n </span>\n );\n}\n\ninterface EntriesProps {\n shape: ObjectShape;\n value: unknown;\n path: Path;\n ctx: Ctx;\n}\n\nconst entriesIn = (value: unknown) => (Array.isArray(value) ? value : []).filter(isEntry);\n\n/** A new entry: an id where the entries have one, so a link can point at it. */\nconst fresh = (shape: ObjectShape): Entry =>\n shape.fields.id ? { id: `n${Date.now().toString(36)}` } : {};\n\n/** Flat entries: a table as in Space → Data. */\nfunction EntryTable({ shape, value, path, ctx }: EntriesProps) {\n const rows = entriesIn(value);\n const cols = Object.entries(shape.fields);\n return (\n <div className=\"overflow-x-auto rounded-lg ring-1 ring-border-soft\">\n <table className=\"w-full border-collapse text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {cols.map(([key, f]) => (\n <th key={key} className=\"whitespace-nowrap px-3 py-2 text-left font-medium\">\n {labelOf(key, f)}\n </th>\n ))}\n {ctx.edit ? <th className=\"w-8\" /> : null}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, i) => (\n <tr key={i} className=\"group border-border-soft border-t\">\n {cols.map(([key, f]) => (\n <td key={key} className={cn(\"align-top\", ctx.edit ? \"p-0.5\" : \"px-3 py-2\")}>\n <Value shape={f} value={row[key]} path={[...path, i, key]} ctx={ctx} cell />\n </td>\n ))}\n {ctx.edit ? (\n <td className=\"p-0.5 align-middle\">\n <RemoveButton\n onClick={() =>\n ctx.set(\n path,\n rows.filter((_, j) => j !== i),\n )\n }\n />\n </td>\n ) : null}\n </tr>\n ))}\n </tbody>\n </table>\n {ctx.edit ? (\n <AddButton what={shape.label} onClick={() => ctx.set(path, [...rows, fresh(shape)])} />\n ) : null}\n </div>\n );\n}\n\n/** Entries with long text and no lists: numbered rows, the long text first, the rest beside it. */\nfunction EntryRows({ shape, value, path, ctx }: EntriesProps) {\n const rows = entriesIn(value);\n const fields = Object.entries(shape.fields);\n const main = fields.filter(([, f]) => f.kind === \"text\" && f.long);\n const rest = fields.filter(([, f]) => !(f.kind === \"text\" && f.long));\n return (\n <div className=\"overflow-hidden rounded-lg ring-1 ring-border-soft\">\n <ol>\n {rows.map((row, i) => (\n <li\n key={i}\n className=\"grid grid-cols-[1.75rem_1fr_auto] items-start gap-2 border-border-soft border-t px-3 py-2 first:border-0\"\n >\n <span className=\"pt-1.5 font-display font-semibold text-ember-strong tabular-nums\">\n {i + 1}\n </span>\n <div className={cn(\"flex min-w-0 flex-col\", !ctx.edit && \"pt-1\")}>\n {main.map(([key, f]) => (\n <Value key={key} shape={f} value={row[key]} path={[...path, i, key]} ctx={ctx} />\n ))}\n </div>\n <div\n className={cn(\n \"flex items-center gap-2 text-[0.8125rem] text-ink-3\",\n !ctx.edit && \"pt-1\",\n )}\n >\n {rest.map(([key, f]) => (\n <Value\n key={key}\n shape={f}\n value={row[key]}\n path={[...path, i, key]}\n ctx={ctx}\n cell\n />\n ))}\n {ctx.edit ? (\n <RemoveButton\n onClick={() =>\n ctx.set(\n path,\n rows.filter((_, j) => j !== i),\n )\n }\n />\n ) : null}\n </div>\n </li>\n ))}\n </ol>\n {ctx.edit ? (\n <AddButton what={shape.label} onClick={() => ctx.set(path, [...rows, fresh(shape)])} />\n ) : null}\n </div>\n );\n}\n\n/** Entries that hold lists of their own: one card each, opened to show and edit everything. */\nfunction EntryCards({ shape, value, path, ctx }: EntriesProps) {\n const entries = entriesIn(value);\n const fields = Object.entries(shape.fields);\n // The summary line: every short value but the title, then how many each list holds.\n const title = titleKey(shape);\n const short = fields.filter(\n ([key, f]) =>\n key !== title &&\n key !== \"id\" &&\n ((f.kind === \"text\" && !f.long) || f.kind === \"number\" || f.kind === \"choice\"),\n );\n const lists = fields.filter(([, f]) => f.kind === \"list\" && f.of.kind === \"object\");\n return (\n <div className=\"flex flex-col gap-2\">\n {entries.map((entry, i) => {\n const id = typeof entry.id === \"string\" ? entry.id : undefined;\n return (\n <details\n key={i}\n id={id ? `${ctx.scope}-${id}` : undefined}\n className=\"group rounded-xl bg-card ring-1 ring-border-soft open:ring-ink-4/40\"\n >\n <summary className=\"flex cursor-pointer list-none items-center gap-3 px-4 py-3 [&::-webkit-details-marker]:hidden\">\n <ChevronRight className=\"size-4 shrink-0 text-ink-3 transition-transform group-open:rotate-90\" />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium text-[0.9375rem]\">\n {titleOf(shape, entry) || `${shape.label ?? \"\"} ${i + 1}`.trim()}\n </span>\n <span className=\"flex flex-wrap gap-x-2 text-[0.75rem] text-ink-3\">\n {short.map(([key, f]) =>\n entry[key] === undefined || entry[key] === \"\" ? null : (\n <span key={key}>\n {f.kind === \"number\" && f.unit\n ? `${entry[key]} ${f.unit}`\n : String(entry[key])}\n </span>\n ),\n )}\n {lists.map(([key, f]) => (\n <span key={key}>\n {Array.isArray(entry[key]) ? (entry[key] as unknown[]).length : 0}{\" \"}\n {labelOf(key, f)}\n </span>\n ))}\n </span>\n </span>\n {ctx.edit ? (\n <RemoveButton\n onClick={() =>\n ctx.set(\n path,\n entries.filter((_, j) => j !== i),\n )\n }\n />\n ) : null}\n </summary>\n <div className=\"border-border-soft border-t px-4 py-4\">\n <Form shape={shape} value={entry} path={[...path, i]} ctx={ctx} />\n </div>\n </details>\n );\n })}\n {ctx.edit ? (\n <AddButton what={shape.label} onClick={() => ctx.set(path, [...entries, fresh(shape)])} />\n ) : null}\n </div>\n );\n}\n\n/** An entry's fields: short ones side by side, long text and lists across the width. */\nfunction Form({ shape, value, path, ctx }: EntriesProps) {\n const obj = isEntry(value) ? value : {};\n const wide = (f: Shape) =>\n f.kind === \"list\" ||\n f.kind === \"object\" ||\n f.kind === \"table\" ||\n (f.kind === \"text\" && Boolean(f.long));\n return (\n <div className=\"grid grid-cols-[repeat(auto-fill,minmax(10rem,1fr))] gap-x-4 gap-y-4\">\n {Object.entries(shape.fields).map(([key, f]) => (\n <Field\n key={key}\n title={labelOf(key, f)}\n wide={wide(f)}\n count={Array.isArray(obj[key]) ? (obj[key] as unknown[]).length : null}\n >\n <Value shape={f} value={obj[key]} path={[...path, key]} ctx={ctx} />\n </Field>\n ))}\n </div>\n );\n}\n\nfunction Field({\n title,\n wide,\n count,\n children,\n}: {\n title: string;\n wide: boolean;\n count: number | null;\n children: ReactNode;\n}) {\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1.5 text-[0.875rem]\", wide && \"col-span-full\")}>\n <span className={caption}>\n {title}\n {count !== null ? <span className=\"ml-1 text-ink-4\">{count}</span> : null}\n </span>\n {children}\n </div>\n );\n}\n\nfunction RemoveButton({ onClick }: { onClick: () => void }) {\n return (\n <button\n type=\"button\"\n aria-label={t(\"data.remove\")}\n onClick={(e) => {\n e.preventDefault();\n onClick();\n }}\n className=\"grid size-7 place-items-center rounded-md text-ink-3 hover:bg-accent hover:text-rose\"\n >\n <Trash2 className=\"size-3.5\" />\n </button>\n );\n}\n\nfunction AddButton({ what, onClick }: { what?: string; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"flex w-full items-center gap-1.5 border-border-soft border-t px-3 py-2 text-[0.8125rem] text-ink-3 hover:bg-accent hover:text-ink\"\n >\n <Plus className=\"size-3.5\" /> {t(\"data.add\", { what: what ?? \"\" }).trim()}\n </button>\n );\n}\n\n/**\n * The data of one step: a bar with the parts to jump to and Ansicht · Bearbeiten · JSON, then\n * the parts. `mode` and `onMode` hold the bar's choice from outside where given.\n */\nexport function DataEditor({\n shape,\n value,\n onChange,\n mode: held,\n onMode,\n modes = [\"view\", \"edit\", \"json\"],\n start,\n}: {\n shape: ObjectShape;\n value: Entry;\n onChange?: (next: Entry) => void;\n mode?: DataMode;\n onMode?: (mode: DataMode) => void;\n /** The modes offered; without `onChange` there is no edit. */\n modes?: DataMode[];\n /** The mode it opens in. */\n start?: DataMode;\n}) {\n const offered = onChange ? modes : modes.filter((m) => m !== \"edit\");\n const [own, setOwn] = useState<DataMode>(\n start && offered.includes(start) ? start : (offered[0] ?? \"view\"),\n );\n const mode = held ?? own;\n const setMode = onMode ?? setOwn;\n const scope = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n const ctx: Ctx = {\n root: value,\n shape,\n edit: mode === \"edit\" && Boolean(onChange),\n scope,\n set: (path, next) => onChange?.(setIn(value, path, next) as Entry),\n open: (id) => {\n const el = document.getElementById(`${scope}-${id}`) as HTMLDetailsElement | null;\n if (el) {\n el.open = true;\n el.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n },\n };\n const parts = Object.entries(shape.fields);\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-border-soft border-b px-3 py-2\">\n <div className=\"flex min-w-0 flex-wrap gap-1\">\n {parts.length > 1\n ? parts.map(([key, f]) => (\n <a\n key={key}\n href={`#${scope}-part-${key}`}\n className=\"rounded-full px-2.5 py-1 text-[0.8125rem] text-ink-2 hover:bg-accent\"\n >\n {labelOf(key, f)}\n {Array.isArray(value[key]) ? (\n <span className=\"ml-1 text-ink-4 tabular-nums\">\n {(value[key] as unknown[]).length}\n </span>\n ) : null}\n </a>\n ))\n : null}\n </div>\n {offered.length > 1 ? (\n <Tabs<DataMode>\n value={mode}\n onChange={setMode}\n label={t(\"data.modes\")}\n options={offered.map((id) => ({ id, label: t(`data.${id}`) }))}\n />\n ) : null}\n </div>\n {mode === \"json\" ? (\n <pre className=\"max-h-[36rem] overflow-auto p-4 font-mono text-[0.75rem] text-ink-2 leading-relaxed\">\n {JSON.stringify(value, null, 2)}\n </pre>\n ) : (\n <div className=\"flex flex-col gap-7 p-4 sm:p-5\">\n {parts.map(([key, f]) => (\n <section\n key={key}\n id={`${scope}-part-${key}`}\n className=\"flex scroll-mt-4 flex-col gap-2\"\n >\n <h3 className=\"flex items-baseline gap-2 font-display font-semibold text-[1rem]\">\n {labelOf(key, f)}\n {Array.isArray(value[key]) ? (\n <span className=\"font-normal font-sans text-[0.8125rem] text-ink-4 tabular-nums\">\n {(value[key] as unknown[]).length}\n </span>\n ) : null}\n </h3>\n <div className=\"text-[0.9375rem] leading-relaxed\">\n <Value shape={f} value={value[key]} path={[key]} ctx={ctx} />\n </div>\n </section>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/** A ⋮ menu of a step's output: a few entries for whoever builds or keeps the wizard. */\nexport function DataMenu({\n items,\n}: {\n items: { label: string; icon: ReactNode; onClick: () => void }[];\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (!open) {\n return;\n }\n const outside = (e: MouseEvent) => {\n if (!ref.current?.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && setOpen(false);\n document.addEventListener(\"mousedown\", outside);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"mousedown\", outside);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [open]);\n return (\n <div ref={ref} className=\"relative\">\n <button\n type=\"button\"\n aria-label={t(\"data.menu\")}\n title={t(\"data.menu\")}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n className={cn(\n \"grid size-8 place-items-center rounded-full text-ink-3 transition hover:bg-accent hover:text-ink coarse:size-11\",\n open && \"bg-accent text-ink\",\n )}\n >\n <MoreVertical className=\"size-4\" />\n </button>\n {open ? (\n <div\n role=\"menu\"\n className=\"absolute top-full right-0 z-50 mt-1 w-60 animate-rise rounded-xl bg-card p-1.5 shadow-overlay ring-1 ring-border-soft\"\n >\n {items.map((item) => (\n <button\n key={item.label}\n type=\"button\"\n role=\"menuitem\"\n className=\"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-[0.875rem] text-ink-2 transition hover:bg-accent hover:text-ink\"\n onClick={() => {\n setOpen(false);\n item.onClick();\n }}\n >\n {item.icon}\n {item.label}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\n/** A file name from a title: \"Menüplan\" → \"menueplan\". */\nfunction fileName(title: string): string {\n return (\n title\n .toLowerCase()\n .replace(/ä/g, \"ae\")\n .replace(/ö/g, \"oe\")\n .replace(/ü/g, \"ue\")\n .replace(/ß/g, \"ss\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\") || \"output\"\n );\n}\n\n/** The JSON Schema (draft 2020-12) a json step's data has: shown, copied or downloaded. */\nexport function JsonSchemaDialog({\n shape,\n title,\n open,\n onClose,\n}: {\n shape: ObjectShape;\n title: string;\n open: boolean;\n onClose: () => void;\n}) {\n const [copied, setCopied] = useState(false);\n const text = open ? JSON.stringify(shapeJsonSchema(shape, title), null, 2) : \"\";\n const download = () => {\n const url = URL.createObjectURL(new Blob([text], { type: \"application/schema+json\" }));\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${fileName(title)}.schema.json`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n };\n return (\n <Dialog\n open={open}\n onClose={onClose}\n title={`${t(\"data.schema\")} · ${title}`}\n wide\n height=\"tall\"\n >\n <div className=\"flex min-h-0 flex-1 flex-col gap-3\">\n <pre className=\"min-h-0 flex-1 overflow-auto rounded-lg bg-paper-2 p-3 font-mono text-[0.75rem] text-ink-2 leading-relaxed\">\n {text}\n </pre>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n void navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n }}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n {copied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {copied ? t(\"share.copied\") : t(\"data.copy\")}\n </button>\n <button\n type=\"button\"\n onClick={download}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n <Download className=\"size-3.5\" /> {t(\"data.download\")}\n </button>\n </div>\n </div>\n </Dialog>\n );\n}\n\n/** A json step whose data can be edited by its shape: not one run per entry, not a tool's answer. */\nexport function editableData(step: { type: string }): step is AgentStep {\n const s = step as AgentStep;\n return s.type === \"agent\" && s.output.format === \"json\" && !s.each && !s.call;\n}\n\n/**\n * A json step's output in the studio: its ⋮ menu (the data to view and edit, the JSON Schema)\n * goes into the header, the data takes the place of the view while it is open. Saved edits go\n * to the run like a review's do, checked against the step's schema.\n */\nexport function StudioData({\n runId,\n step,\n output,\n header,\n children,\n}: {\n runId: string;\n step: AgentStep;\n output: StepOutput;\n header: (menu: ReactNode) => ReactNode;\n children: ReactNode;\n}) {\n const shape = stepShape(step);\n const [open, setOpen] = useState(false);\n const [schema, setSchema] = useState(false);\n const [draft, setDraft] = useState<Entry | null>(null);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const value = draft ?? (isEntry(output.json) ? output.json : {});\n const save = async () => {\n if (!draft) {\n return;\n }\n setSaving(true);\n setError(null);\n try {\n await api.put(`${runBase(runId)}/outputs/${step.id}`, { json: draft });\n setDraft(null);\n setOpen(false);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSaving(false);\n }\n };\n const menu = (\n <DataMenu\n items={[\n {\n label: t(open ? \"data.close\" : \"data.open\"),\n icon: <Database className=\"size-4 shrink-0\" />,\n onClick: () => {\n setOpen((o) => !o);\n setDraft(null);\n },\n },\n {\n label: t(\"data.schema\"),\n icon: <Braces className=\"size-4 shrink-0\" />,\n onClick: () => setSchema(true),\n },\n ]}\n />\n );\n return (\n <>\n {header(menu)}\n {open ? (\n <div className=\"overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n <DataEditor shape={shape} value={value} onChange={setDraft} />\n {draft ? (\n <div className=\"flex items-center justify-end gap-2 border-border-soft border-t px-3 py-2\">\n {error ? <span className=\"mr-auto text-[0.8125rem] text-rose\">{error}</span> : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setDraft(null)}>\n {t(\"common.cancel\")}\n </Button>\n <Button size=\"sm\" busy={saving} onClick={() => void save()}>\n {t(\"data.save\")}\n </Button>\n </div>\n ) : null}\n </div>\n ) : (\n children\n )}\n <JsonSchemaDialog\n shape={shape}\n title={step.title}\n open={schema}\n onClose={() => setSchema(false)}\n />\n </>\n );\n}\n","import { isLocationValue, type LocationValue } from \"@engenty/wizards-shared/definition\";\nimport { ExternalLink, LocateFixed, MapPin, X } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { api, runBase } from \"./env.js\";\nimport { lang, t } from \"./i18n.js\";\nimport { Button, IconButton, Input } from \"./ui.js\";\n\n/** Good enough for an address; the device keeps refining until then or until it has tried long enough. */\nconst GOOD_METRES = 25;\nconst REFINE_MS = 9000;\n\ntype Trouble = \"denied\" | \"unavailable\" | \"timeout\";\n\nfunction trouble(err: GeolocationPositionError): Trouble {\n return err.code === err.PERMISSION_DENIED\n ? \"denied\"\n : err.code === err.TIMEOUT\n ? \"timeout\"\n : \"unavailable\";\n}\n\n/**\n * Where the person is: the device's position on their tap, with how exact it is, and an address\n * line they can correct — or type alone, when the device gives no position.\n */\nexport function LocationField({\n value,\n runId,\n placeholder,\n onChange,\n onBusy,\n}: {\n value: unknown;\n runId: string;\n placeholder?: string;\n onChange: (v: LocationValue | undefined) => void;\n onBusy?: (busy: boolean) => void;\n}) {\n const place = isLocationValue(value) ? value : null;\n const [locating, setLocating] = useState(false);\n const [error, setError] = useState<Trouble | null>(null);\n const watch = useRef<number | null>(null);\n // The address line is the server's suggestion until the person types in it.\n const typed = useRef(Boolean(place?.label));\n const latest = useRef(place);\n latest.current = place;\n const hasPoint = place?.lat !== undefined && place.lng !== undefined;\n const supported = typeof navigator !== \"undefined\" && \"geolocation\" in navigator;\n\n const stop = () => {\n if (watch.current !== null) {\n navigator.geolocation.clearWatch(watch.current);\n watch.current = null;\n }\n setLocating(false);\n onBusy?.(false);\n };\n useEffect(\n () => () => {\n if (watch.current !== null) {\n navigator.geolocation.clearWatch(watch.current);\n }\n },\n [],\n );\n\n const name = async (lat: number, lng: number) => {\n try {\n const { label } = await api.post<{ label: string | null }>(`${runBase(runId)}/geocode`, {\n lat,\n lng,\n language: lang,\n });\n const now = latest.current;\n if (label && !typed.current && now?.lat === lat && now.lng === lng) {\n onChange({ ...now, label });\n }\n } catch {\n // the coordinates stand on their own\n }\n };\n\n const locate = () => {\n setError(null);\n setLocating(true);\n onBusy?.(true);\n const started = Date.now();\n let best = Number.POSITIVE_INFINITY;\n watch.current = navigator.geolocation.watchPosition(\n (pos) => {\n const { latitude, longitude, accuracy } = pos.coords;\n if (accuracy < best) {\n best = accuracy;\n const lat = Math.round(latitude * 1e6) / 1e6;\n const lng = Math.round(longitude * 1e6) / 1e6;\n const label = typed.current ? latest.current?.label : undefined;\n const next = { lat, lng, accuracy: Math.round(accuracy), ...(label ? { label } : {}) };\n latest.current = next;\n onChange(next);\n }\n if (best <= GOOD_METRES || Date.now() - started > REFINE_MS) {\n stop();\n const now = latest.current;\n if (now?.lat !== undefined && now.lng !== undefined) {\n void name(now.lat, now.lng);\n }\n }\n },\n (err) => {\n stop();\n // A fix already taken stays; only a first try that fails is reported.\n if (best === Number.POSITIVE_INFINITY) {\n setError(trouble(err));\n }\n },\n { enableHighAccuracy: true, timeout: 15_000, maximumAge: 10_000 },\n );\n };\n\n const setLabel = (label: string) => {\n typed.current = label.trim().length > 0;\n const next = { ...(hasPoint ? place : {}), label };\n onChange(hasPoint || label.trim() ? next : undefined);\n };\n\n return (\n <div className=\"flex flex-col gap-3\">\n {hasPoint ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-3 ring-1 ring-input\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-moss-tint text-moss\">\n <MapPin className=\"size-5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium text-[0.9375rem] tabular-nums\">\n {place.lat?.toFixed(5)}, {place.lng?.toFixed(5)}\n </div>\n <div className=\"flex flex-wrap items-center gap-x-3 text-[0.8125rem] text-ink-3\">\n <span>\n {locating\n ? t(\"location.refining\")\n : place.accuracy\n ? t(\"location.accuracy\", { m: place.accuracy })\n : null}\n </span>\n <a\n href={`https://www.openstreetmap.org/?mlat=${place.lat}&mlon=${place.lng}#map=17/${place.lat}/${place.lng}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 underline-offset-2 hover:text-ink hover:underline coarse:-my-3 coarse:min-h-11 coarse:min-w-11\"\n >\n {t(\"location.map\")} <ExternalLink className=\"size-3\" />\n </a>\n </div>\n </div>\n <IconButton\n label={t(\"location.remove\")}\n onClick={() => {\n stop();\n typed.current = false;\n onChange(undefined);\n }}\n >\n <X className=\"size-4\" />\n </IconButton>\n </div>\n ) : supported ? (\n <div>\n <Button\n variant=\"secondary\"\n size=\"lg\"\n busy={locating}\n onClick={locate}\n className=\"w-full sm:w-auto\"\n >\n {locating ? null : <LocateFixed className=\"size-4\" />}\n {locating ? t(\"location.locating\") : t(\"location.use\")}\n </Button>\n {error ? (\n <p className=\"mt-2 rounded-lg bg-amber-tint px-3 py-2 text-[0.8125rem] text-ink-2 leading-relaxed\">\n {t(`location.${error}` as \"location.denied\")}\n </p>\n ) : (\n <p className=\"mt-2 text-[0.8125rem] text-ink-3 leading-relaxed\">{t(\"location.why\")}</p>\n )}\n </div>\n ) : null}\n <Input\n value={place?.label ?? \"\"}\n placeholder={placeholder ?? t(hasPoint ? \"location.label\" : \"location.manual\")}\n autoComplete=\"street-address\"\n enterKeyHint=\"done\"\n aria-label={t(\"location.manual\")}\n onChange={(e) => setLabel(e.target.value)}\n />\n </div>\n );\n}\n","import { ImageUp } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n CameraStage,\n type Facing,\n MediaSheet,\n SheetAction,\n SheetBar,\n useCameraStream,\n} from \"./camera\";\nimport { appCall, appCan } from \"./env.js\";\nimport { t } from \"./i18n.js\";\n\ntype Detect = (source: HTMLVideoElement | ImageBitmap) => Promise<string | null>;\n\ninterface Reader {\n detect: Detect;\n /** The fallback reads QR codes only; the browser's own detector also reads barcodes. */\n qrOnly: boolean;\n}\n\ninterface NativeDetector {\n detect(source: ImageBitmapSource): Promise<{ rawValue: string }[]>;\n}\ninterface NativeDetectorClass {\n new (options?: { formats: string[] }): NativeDetector;\n getSupportedFormats(): Promise<string[]>;\n}\n\nlet reader: Promise<Reader> | null = null;\n\n/**\n * The browser's BarcodeDetector where it exists (Chrome on Android and macOS); elsewhere — iOS,\n * Firefox, Chrome on Windows — a small QR decoder that is only downloaded when first needed.\n */\nfunction codeReader(): Promise<Reader> {\n reader ??= (async () => {\n const Native = (window as unknown as { BarcodeDetector?: NativeDetectorClass }).BarcodeDetector;\n if (Native) {\n try {\n const formats = await Native.getSupportedFormats();\n if (formats.includes(\"qr_code\")) {\n const detector = new Native({ formats });\n return {\n qrOnly: false,\n detect: async (source) => (await detector.detect(source))[0]?.rawValue || null,\n };\n }\n } catch {\n // falls through to the decoder\n }\n }\n const { default: QrScanner } = await import(\"qr-scanner\");\n const engine = QrScanner.createQrEngine();\n return {\n qrOnly: true,\n detect: async (source) => {\n try {\n const found = await QrScanner.scanImage(source, {\n qrEngine: engine,\n returnDetailedScanResult: true,\n });\n return found.data || null;\n } catch {\n return null;\n }\n },\n };\n })();\n return reader;\n}\n\ninterface ScanProps {\n open: boolean;\n onClose: () => void;\n onResult: (text: string) => void;\n}\n\n/** In the mobile app its own scanner reads every common barcode; the page draws nothing. */\nfunction AppScan({ open, onClose, onResult }: ScanProps) {\n const found = useRef(onResult);\n found.current = onResult;\n const close = useRef(onClose);\n close.current = onClose;\n useEffect(() => {\n if (!open) {\n return;\n }\n void appCall<string | null>(\"scan\")\n .then((text) => {\n if (text) {\n found.current(text);\n }\n })\n .catch(() => undefined)\n .finally(() => close.current());\n }, [open]);\n return null;\n}\n\n/** Reads a QR code or barcode with the camera — or from a photo, when there is no camera. */\nexport function ScanDialog(props: ScanProps) {\n return appCan(\"scan\") ? <AppScan {...props} /> : <WebScan {...props} />;\n}\n\nfunction WebScan({ open, onClose, onResult }: ScanProps) {\n const [facing, setFacing] = useState<Facing>(\"environment\");\n const [qrOnly, setQrOnly] = useState(false);\n const [miss, setMiss] = useState(false);\n const photo = useRef<HTMLInputElement>(null);\n const camera = useCameraStream(open, facing);\n const found = useRef(onResult);\n found.current = onResult;\n const close = useRef(onClose);\n close.current = onClose;\n\n useEffect(() => {\n if (!open) {\n return;\n }\n setMiss(false);\n void codeReader().then((r) => setQrOnly(r.qrOnly));\n }, [open]);\n\n useEffect(() => {\n if (!open || !camera.stream) {\n return;\n }\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const tick = async () => {\n const el = camera.video.current;\n if (!stopped && el && el.readyState >= 2 && el.videoWidth) {\n const text = await (await codeReader()).detect(el).catch(() => null);\n if (text && !stopped) {\n navigator.vibrate?.(60);\n found.current(text);\n close.current();\n return;\n }\n }\n if (!stopped) {\n timer = setTimeout(tick, 200);\n }\n };\n void tick();\n return () => {\n stopped = true;\n clearTimeout(timer);\n };\n }, [open, camera.stream, camera.video]);\n\n const fromPhoto = async (file: File | undefined) => {\n if (!file) {\n return;\n }\n setMiss(false);\n const bitmap = await createImageBitmap(file).catch(() => null);\n const text = bitmap ? await (await codeReader()).detect(bitmap).catch(() => null) : null;\n if (text) {\n onResult(text);\n onClose();\n } else {\n setMiss(true);\n }\n };\n\n return (\n <MediaSheet open={open} onClose={onClose} label={t(\"scan.title\")}>\n <SheetBar\n title={t(\"scan.title\")}\n onClose={onClose}\n camera={camera}\n onFlip={() => setFacing((f) => (f === \"environment\" ? \"user\" : \"environment\"))}\n />\n <CameraStage\n camera={camera}\n asking={t(\"scan.asking\")}\n actions={\n <div className=\"flex flex-col gap-2\">\n <SheetAction onClick={() => photo.current?.click()}>\n <ImageUp className=\"size-4\" /> {t(\"scan.fromPhoto\")}\n </SheetAction>\n <SheetAction quiet onClick={onClose}>\n {t(\"scan.typeInstead\")}\n </SheetAction>\n </div>\n }\n >\n {/* The frame the code goes into. */}\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"aspect-square w-[min(68%,320px)] rounded-3xl border-2 border-white/90 shadow-[0_0_0_100vmax_rgb(0_0_0/0.35)]\" />\n </div>\n </CameraStage>\n <div className=\"safe-bottom flex flex-col items-center gap-3 px-5 pt-3 text-center\">\n <p className=\"text-[0.8125rem] text-white/75 leading-snug\">\n {miss ? t(\"scan.miss\") : qrOnly ? t(\"scan.hintQr\") : t(\"scan.hint\")}\n </p>\n {camera.stream ? (\n <SheetAction quiet onClick={() => photo.current?.click()}>\n <ImageUp className=\"size-4\" /> {t(\"scan.fromPhoto\")}\n </SheetAction>\n ) : null}\n </div>\n <input\n ref={photo}\n type=\"file\"\n hidden\n accept=\"image/*\"\n onChange={(e) => {\n void fromPhoto(e.target.files?.[0]);\n e.target.value = \"\";\n }}\n />\n </MediaSheet>\n );\n}\n","import { Eraser, PenLine, X } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { api, runBase, withBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, Dialog, IconButton } from \"./ui.js\";\n\ntype Point = { x: number; y: number };\n/** Strokes in pad units: x from 0 to 1, y from 0 to 1 — they survive a rotated phone. */\ntype Strokes = Point[][];\n\nconst INK = \"#1d1a17\";\n/** The kept picture: wide like a signature line, sharp enough for print. */\nconst OUT = { width: 1200, height: 480 };\n\nfunction draw(ctx: CanvasRenderingContext2D, strokes: Strokes, w: number, h: number, pen: number) {\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = INK;\n ctx.fillStyle = INK;\n ctx.lineWidth = pen;\n for (const stroke of strokes) {\n if (stroke.length === 1) {\n ctx.beginPath();\n ctx.arc(stroke[0].x * w, stroke[0].y * h, pen / 2, 0, Math.PI * 2);\n ctx.fill();\n continue;\n }\n ctx.beginPath();\n ctx.moveTo(stroke[0].x * w, stroke[0].y * h);\n // Curves through the midpoints: a finger's jittery samples become one smooth line.\n for (let i = 1; i < stroke.length - 1; i++) {\n const a = stroke[i];\n const b = stroke[i + 1];\n ctx.quadraticCurveTo(a.x * w, a.y * h, ((a.x + b.x) / 2) * w, ((a.y + b.y) / 2) * h);\n }\n const last = stroke[stroke.length - 1];\n ctx.lineTo(last.x * w, last.y * h);\n ctx.stroke();\n }\n}\n\nfunction Pad({ strokes, onStrokes }: { strokes: Strokes; onStrokes: (s: Strokes) => void }) {\n const canvas = useRef<HTMLCanvasElement>(null);\n const current = useRef<Point[] | null>(null);\n const all = useRef(strokes);\n all.current = strokes;\n\n const paint = () => {\n const el = canvas.current;\n const ctx = el?.getContext(\"2d\");\n if (!el || !ctx) {\n return;\n }\n const ratio = window.devicePixelRatio || 1;\n const w = Math.round(el.clientWidth * ratio);\n const h = Math.round(el.clientHeight * ratio);\n if (el.width !== w || el.height !== h) {\n el.width = w;\n el.height = h;\n }\n ctx.clearRect(0, 0, w, h);\n const live = current.current ? [...all.current, current.current] : all.current;\n draw(ctx, live, w, h, 2.4 * ratio);\n };\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: repaints whenever the strokes change\n useEffect(() => {\n paint();\n const el = canvas.current;\n if (!el) {\n return;\n }\n const ro = new ResizeObserver(paint);\n ro.observe(el);\n return () => ro.disconnect();\n }, [strokes]);\n\n const at = (e: React.PointerEvent<HTMLCanvasElement>): Point => {\n const box = e.currentTarget.getBoundingClientRect();\n return {\n x: Math.min(1, Math.max(0, (e.clientX - box.left) / box.width)),\n y: Math.min(1, Math.max(0, (e.clientY - box.top) / box.height)),\n };\n };\n\n return (\n <div className=\"relative overflow-hidden rounded-xl bg-white ring-1 ring-input\">\n <canvas\n ref={canvas}\n aria-label={t(\"sign.pad\")}\n className=\"block aspect-[5/2] w-full cursor-crosshair touch-none select-none\"\n onPointerDown={(e) => {\n e.currentTarget.setPointerCapture(e.pointerId);\n current.current = [at(e)];\n paint();\n }}\n onPointerMove={(e) => {\n if (current.current) {\n current.current.push(at(e));\n paint();\n }\n }}\n onPointerUp={() => {\n if (current.current) {\n const done = current.current;\n current.current = null;\n onStrokes([...all.current, done]);\n }\n }}\n onPointerCancel={() => {\n current.current = null;\n paint();\n }}\n />\n {/* The line to sign on. */}\n <div className=\"pointer-events-none absolute inset-x-6 bottom-[22%] border-[#1d1a17]/25 border-b\" />\n {strokes.length ? null : (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center text-[#1d1a17]/40 text-[0.875rem]\">\n {t(\"sign.hint\")}\n </div>\n )}\n </div>\n );\n}\n\nasync function picture(strokes: Strokes): Promise<File | null> {\n const canvas = document.createElement(\"canvas\");\n canvas.width = OUT.width;\n canvas.height = OUT.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n return null;\n }\n // Clear ground, dark ink: the signature sits on any paper it is placed on.\n draw(ctx, strokes, OUT.width, OUT.height, 7);\n const blob = await new Promise<Blob | null>((r) => canvas.toBlob(r, \"image/png\"));\n return blob ? new File([blob], \"unterschrift.png\", { type: \"image/png\" }) : null;\n}\n\n/** A signature drawn with the finger, a pen or the mouse; kept as a picture. */\nexport function SignatureField({\n label,\n value,\n runId,\n onChange,\n}: {\n label: string;\n value: unknown;\n runId: string;\n onChange: (v: string | undefined) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [strokes, setStrokes] = useState<Strokes>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const id = typeof value === \"string\" && value ? value : null;\n\n const accept = async () => {\n setBusy(true);\n setError(null);\n try {\n const file = await picture(strokes);\n if (!file) {\n return;\n }\n const ref = await api.upload<{ id: string }>(`${runBase(runId)}/uploads`, file);\n onChange(ref.id);\n setOpen(false);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div>\n {id ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-2 ring-1 ring-input\">\n <button\n type=\"button\"\n onClick={() => {\n setStrokes([]);\n setOpen(true);\n }}\n className=\"min-w-0 flex-1 rounded-lg bg-white px-3\"\n aria-label={t(\"sign.again\")}\n >\n <img\n src={withBase(`${runBase(runId)}/assets/${id}`)}\n alt={label}\n className=\"mx-auto h-20 object-contain\"\n />\n </button>\n <IconButton label={t(\"sign.remove\")} onClick={() => onChange(undefined)}>\n <X className=\"size-4\" />\n </IconButton>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => {\n setStrokes([]);\n setOpen(true);\n }}\n className=\"flex w-full flex-col items-center justify-center gap-2 rounded-xl border border-input border-dashed bg-card px-4 py-7 text-[0.875rem] text-ink-3 transition hover:border-ember hover:text-ink\"\n >\n <PenLine className=\"size-6\" />\n {t(\"sign.open\")}\n </button>\n )}\n <Dialog open={open} onClose={() => setOpen(false)} title={label} wide>\n <Pad strokes={strokes} onStrokes={setStrokes} />\n {error ? <p className=\"mt-2 text-[0.8125rem] text-rose\">{error}</p> : null}\n <div className=\"mt-5 flex items-center justify-between gap-3\">\n <Button variant=\"ghost\" disabled={!strokes.length || busy} onClick={() => setStrokes([])}>\n <Eraser className=\"size-4\" /> {t(\"sign.clear\")}\n </Button>\n <Button busy={busy} disabled={!strokes.length} onClick={() => void accept()}>\n {t(\"sign.accept\")}\n </Button>\n </div>\n </Dialog>\n </div>\n );\n}\n","import type { Format } from \"@engenty/wizards-shared/definition\";\nimport { formatTableCell, type TableColumn } from \"@engenty/wizards-shared/engenty/data-tables\";\nimport { formatBytes } from \"@engenty/wizards-shared/numbers\";\nimport type { ShownList } from \"@engenty/wizards-shared/run\";\nimport {\n type ConnectionView,\n type ConnectorOption,\n cellValue,\n type StoreFile,\n} from \"@engenty/wizards-shared/store\";\nimport { Check, Database, FileText, Link2, Plus, Trash2, Unplug } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { ApiError } from \"./api.js\";\nimport { api, appCall, appCan, runBase, withBase } from \"./env.js\";\nimport { lang, t } from \"./i18n.js\";\nimport { Button, cn, Dialog, IconButton, Input, Label, Spinner } from \"./ui.js\";\n\n// --- connecting an account -------------------------------------------------------\n\nfunction CredentialsForm({\n runId,\n connectionId,\n connector,\n onCancel,\n}: {\n runId: string;\n connectionId: string;\n connector: ConnectorOption;\n onCancel: () => void;\n}) {\n const [values, setValues] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const submit = async () => {\n setBusy(true);\n setError(null);\n try {\n await api.post(`${runBase(runId)}/connections/${connectionId}/credentials/${connector.id}`, {\n values,\n });\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n return (\n <div className=\"flex flex-col gap-3 rounded-xl bg-card p-4 ring-1 ring-input\">\n {(connector.fields ?? []).map((f) => (\n <div key={f.key}>\n <Label>{f.label}</Label>\n <Input\n type={f.secret ? \"password\" : \"text\"}\n autoComplete=\"off\"\n value={values[f.key] ?? \"\"}\n placeholder={f.placeholder}\n onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}\n onKeyDown={(e) => {\n // Enter connects; it must not submit the wizard page around this form.\n if (e.key === \"Enter\") {\n e.preventDefault();\n void submit();\n }\n }}\n />\n </div>\n ))}\n {connector.hint ? <p className=\"text-[0.8125rem] text-ink-3\">{connector.hint}</p> : null}\n {error ? <p className=\"text-[0.8125rem] text-rose\">{error}</p> : null}\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {t(\"common.cancel\")}\n </Button>\n <Button size=\"sm\" busy={busy} onClick={() => void submit()}>\n {t(\"connect.go\")}\n </Button>\n </div>\n </div>\n );\n}\n\n/** The person connects an account (their mailbox) to the wizard, or sees which one is connected. */\nexport function ConnectionField({\n runId,\n connection,\n}: {\n runId: string;\n connection: ConnectionView | undefined;\n}) {\n const [form, setForm] = useState<string | null>(null);\n const [link, setLink] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n if (!connection) {\n return null;\n }\n if (connection.account) {\n const name =\n connection.connectors.find((c) => c.id === connection.account?.connector)?.name ?? \"\";\n return (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-3 ring-1 ring-input\">\n <div className=\"flex size-10 items-center justify-center rounded-full bg-moss-tint text-moss\">\n <Check className=\"size-5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium text-[0.9375rem]\">{connection.account.label}</div>\n <div className=\"text-[0.8125rem] text-ink-3\">{t(\"connect.connected\", { name })}</div>\n </div>\n <IconButton\n label={t(\"connect.disconnect\")}\n onClick={() => void api.del(`${runBase(runId)}/connections/${connection.id}`)}\n >\n <Unplug className=\"size-4\" />\n </IconButton>\n </div>\n );\n }\n const oauth = async (connector: ConnectorOption) => {\n setError(null);\n setLink(null);\n if (appCan(\"signIn\")) {\n // The app opens the system's sign-in sheet: Google refuses a sign-in inside a WebView.\n // The run's stream says when the account is connected, as with the popup.\n try {\n const { url } = await api.post<{ url: string }>(\n `${runBase(runId)}/connections/${connection.id}/oauth/${connector.id}`,\n );\n await appCall(\"signIn\", { url });\n } catch (err) {\n setError((err as Error).message);\n }\n return;\n }\n // Opened inside the click, before the address is known: a popup opened later is blocked.\n const popup = window.open(\"about:blank\", \"wizard-connect\", \"width=540,height=700\");\n try {\n const { url } = await api.post<{ url: string }>(\n `${runBase(runId)}/connections/${connection.id}/oauth/${connector.id}`,\n );\n if (popup) {\n popup.location.replace(url);\n } else {\n setLink(url);\n }\n } catch (err) {\n popup?.close();\n setError((err as Error).message);\n }\n };\n const open = connection.connectors.find((c) => c.id === form);\n if (!connection.connectors.length) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"connect.none\")}</p>;\n }\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex flex-wrap gap-2\">\n {connection.connectors.map((c) => (\n <button\n key={c.id}\n type=\"button\"\n onClick={() =>\n c.auth === \"oauth2\" ? void oauth(c) : setForm(form === c.id ? null : c.id)\n }\n className={cn(\n \"inline-flex h-11 items-center gap-2 rounded-full px-4 font-medium text-[0.875rem] ring-1 transition\",\n form === c.id\n ? \"bg-ember-veil text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink hover:ring-ember\",\n )}\n >\n <Link2 className=\"size-4\" /> {c.name}\n </button>\n ))}\n </div>\n {open ? (\n <CredentialsForm\n runId={runId}\n connectionId={connection.id}\n connector={open}\n onCancel={() => setForm(null)}\n />\n ) : null}\n {link ? (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-[0.875rem] text-ember underline\"\n >\n {t(\"connect.openLink\")}\n </a>\n ) : null}\n {error ? <p className=\"text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n );\n}\n\n// --- lists ---------------------------------------------------------------------\n\n/** A cell's value as the text its input shows. */\nfunction inputText(value: unknown): string {\n return value === null || value === undefined\n ? \"\"\n : Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n}\n\nfunction CellInput({\n column,\n value,\n boxed,\n onCommit,\n}: {\n column: TableColumn;\n value: unknown;\n /** On a card (phone) the input shows its own ground; in the table the cell is the frame. */\n boxed?: boolean;\n onCommit: (value: unknown) => void;\n}) {\n const [text, setText] = useState(inputText(value));\n useEffect(() => setText(inputText(value)), [value]);\n const base = cn(\n \"w-full min-w-0 rounded-md border border-transparent px-2 text-[0.8125rem] outline-none focus:border-ember focus:bg-card\",\n boxed ? \"h-11 bg-paper-2\" : \"h-9 bg-transparent hover:bg-paper-2 coarse:h-11\",\n );\n if (column.type === \"boolean\") {\n return (\n // The box stays small; the label around it is the full touch target.\n <label className=\"flex size-9 cursor-pointer items-center justify-center coarse:size-11\">\n <input\n type=\"checkbox\"\n aria-label={column.name}\n checked={value === true}\n onChange={(e) => onCommit(e.target.checked)}\n className=\"size-4 accent-[var(--ember)] coarse:size-6\"\n />\n </label>\n );\n }\n if (column.type === \"select\" && !column.format.multiple && !column.format.allowCustom) {\n return (\n <select value={text} onChange={(e) => onCommit(e.target.value || null)} className={base}>\n <option value=\"\" />\n {column.format.options.map((o) => (\n <option key={o.id} value={o.id}>\n {o.label}\n </option>\n ))}\n </select>\n );\n }\n const commit = () => {\n if (text !== inputText(value)) {\n onCommit(cellValue(column, text));\n }\n };\n return (\n <input\n aria-label={column.name}\n type={column.type === \"date\" && column.format.kind === \"date\" ? \"date\" : \"text\"}\n inputMode={column.type === \"number\" ? \"decimal\" : undefined}\n enterKeyHint=\"done\"\n autoComplete=\"off\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={commit}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n (e.target as HTMLInputElement).blur();\n }\n }}\n className={cn(base, column.type === \"number\" && \"text-right tabular-nums\")}\n />\n );\n}\n\n/** One of the wizard's stored lists: read, or edited in place by the person it belongs to. */\nexport function ListTable({\n runId,\n list,\n editable,\n}: {\n runId: string;\n list: ShownList;\n editable?: boolean;\n}) {\n const { def, rows } = list;\n const [error, setError] = useState<string | null>(null);\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n const base = `${runBase(runId)}/lists/${def.id}/rows`;\n const call = async (run: () => Promise<unknown>) => {\n setError(null);\n try {\n await run();\n } catch (err) {\n setError(err instanceof ApiError ? err.message : String(err));\n }\n };\n const addRow = () =>\n call(async () => {\n await api.post(base, { cells: draft });\n setDraft({});\n });\n const hasDraft = Object.values(draft).some((v) => v !== null && v !== undefined && v !== \"\");\n if (!rows.length && !editable) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"list.empty\")}</p>;\n }\n const wide = (c: TableColumn, i: number) =>\n i === 0 || (c.type === \"text\" && c.format?.style === \"multiline\");\n const commitCell = (rowId: string, columnId: string, value: unknown) =>\n void call(() => api.patch(`${base}/${rowId}`, { cells: { [columnId]: value } }));\n return (\n <div>\n {/* A phone shows each row as a card of labelled cells; a table would scroll sideways. */}\n <div className=\"flex flex-col gap-2 sm:hidden\">\n {rows.map((row) => (\n <div key={row.id} className=\"rounded-lg bg-paper p-2 ring-1 ring-border-soft\">\n <div className=\"grid grid-cols-2 gap-x-2 gap-y-1.5\">\n {def.columns.map((c, i) => (\n <div key={c.id} className={cn(\"min-w-0\", wide(c, i) && \"col-span-2\")}>\n <div className=\"px-1 pb-0.5 text-[0.6875rem] text-ink-3\">{c.name}</div>\n {editable ? (\n <CellInput\n boxed\n column={c}\n value={row.cells[c.id]}\n onCommit={(value) => commitCell(row.id, c.id, value)}\n />\n ) : (\n <div\n className={cn(\n \"break-words px-1 text-[0.875rem]\",\n c.type === \"number\" && \"tabular-nums\",\n )}\n >\n {formatTableCell(c, row.cells[c.id], lang) || \"—\"}\n </div>\n )}\n </div>\n ))}\n </div>\n {editable ? (\n <div className=\"mt-1 flex justify-end\">\n <IconButton\n label={t(\"list.delete\")}\n onClick={() => void call(() => api.del(`${base}/${row.id}`))}\n >\n <Trash2 className=\"size-4\" />\n </IconButton>\n </div>\n ) : null}\n </div>\n ))}\n {editable ? (\n <div className=\"rounded-lg border border-input border-dashed p-2\">\n <div className=\"grid grid-cols-2 gap-x-2 gap-y-1.5\">\n {def.columns.map((c, i) => (\n <div key={c.id} className={cn(\"min-w-0\", wide(c, i) && \"col-span-2\")}>\n <div className=\"px-1 pb-0.5 text-[0.6875rem] text-ink-3\">{c.name}</div>\n <CellInput\n boxed\n column={c}\n value={draft[c.id]}\n onCommit={(value) => setDraft((d) => ({ ...d, [c.id]: value }))}\n />\n </div>\n ))}\n </div>\n <div className=\"mt-2 flex justify-end\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n // The cell being typed in commits on blur, just before this click lands.\n onClick={() => (hasDraft ? void addRow() : undefined)}\n >\n <Plus className=\"size-4\" /> {t(\"run.addRow\")}\n </Button>\n </div>\n </div>\n ) : null}\n </div>\n <div className=\"hidden overflow-x-auto rounded-lg ring-1 ring-border-soft sm:block\">\n <table className=\"w-full text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {def.columns.map((c) => (\n <th key={c.id} className=\"whitespace-nowrap px-3 py-2 text-left font-medium\">\n {c.name}\n </th>\n ))}\n {editable ? <th className=\"w-10\" /> : null}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.id} className=\"border-border-soft border-t align-top\">\n {def.columns.map((c) => (\n <td\n key={c.id}\n className={cn(\"min-w-[7.5rem]\", editable ? \"px-1 py-0.5\" : \"px-3 py-2\")}\n >\n {editable ? (\n <CellInput\n column={c}\n value={row.cells[c.id]}\n onCommit={(value) => commitCell(row.id, c.id, value)}\n />\n ) : (\n <span className={cn(c.type === \"number\" && \"tabular-nums\")}>\n {formatTableCell(c, row.cells[c.id], lang)}\n </span>\n )}\n </td>\n ))}\n {editable ? (\n <td className=\"px-1 py-0.5\">\n <IconButton\n label={t(\"list.delete\")}\n className=\"size-9\"\n onClick={() => void call(() => api.del(`${base}/${row.id}`))}\n >\n <Trash2 className=\"size-3.5\" />\n </IconButton>\n </td>\n ) : null}\n </tr>\n ))}\n {editable ? (\n <tr className=\"border-border-soft border-t bg-paper\">\n {def.columns.map((c) => (\n <td key={c.id} className=\"px-1 py-0.5\">\n <CellInput\n column={c}\n value={draft[c.id]}\n onCommit={(value) => setDraft((d) => ({ ...d, [c.id]: value }))}\n />\n </td>\n ))}\n <td className=\"px-1 py-0.5\">\n <IconButton\n label={t(\"run.addRow\")}\n className=\"size-9\"\n onClick={() => (hasDraft ? void addRow() : undefined)}\n >\n <Plus className=\"size-4\" />\n </IconButton>\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n {error ? <p className=\"mt-2 text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n );\n}\n\n/** The path of a kept file as its address: shown in place for PDFs and photos. */\nfunction storeFileUrl(runId: string, path: string, inline: boolean): string {\n const safe = path.split(\"/\").map(encodeURIComponent).join(\"/\");\n return withBase(`${runBase(runId)}/store/files/${safe}${inline ? \"?inline=1\" : \"\"}`);\n}\n\nconst ANSWER_TONE = [\n \"bg-paper-3 text-ink-3\",\n \"bg-moss-tint text-moss\",\n \"bg-rose-tint text-rose\",\n \"bg-ember-tint text-ember-strong\",\n];\n\n/**\n * A list the person goes through row by row: the rows on the left, the row's kept file and its\n * cells on the right, and the answers of the list's status column as buttons. An answer saves\n * and moves on to the next open row.\n */\nexport function ListCheck({ runId, list }: { runId: string; list: ShownList }) {\n const { def, rows } = list;\n const fileColumn = def.columns.find((c) => c.id === def.check?.file);\n const statusColumn = def.columns.find((c) => c.id === def.check?.status);\n const answers = statusColumn?.type === \"select\" ? statusColumn.format.options : [];\n const openId = answers[0]?.id;\n const statusOf = (row: ShownList[\"rows\"][number]) =>\n statusColumn ? String(row.cells[statusColumn.id] ?? openId ?? \"\") : \"\";\n const isOpen = (row: ShownList[\"rows\"][number]) => !statusColumn || statusOf(row) === openId;\n const [selected, setSelected] = useState<string | null>(\n () => (rows.find(isOpen) ?? rows[0])?.id ?? null,\n );\n const [onlyOpen, setOnlyOpen] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const base = `${runBase(runId)}/lists/${def.id}/rows`;\n const current = rows.find((r) => r.id === selected) ?? rows[0];\n const shown = onlyOpen ? rows.filter((r) => isOpen(r) || r.id === current?.id) : rows;\n const done = rows.filter((r) => !isOpen(r)).length;\n const labelled = def.columns.filter((c) => c !== fileColumn && c !== statusColumn);\n // A row is named by its first text cell; the next two cells (a date, an amount) stand below.\n const named = labelled.filter((c) => c.id !== def.key);\n const titleColumn = named.find((c) => c.type === \"text\") ?? named[0];\n const restColumns = named.filter((c) => c !== titleColumn);\n const patch = async (rowId: string, cells: Record<string, unknown>) => {\n setError(null);\n try {\n await api.patch(`${base}/${rowId}`, { cells });\n } catch (err) {\n setError(err instanceof ApiError ? err.message : String(err));\n }\n };\n const move = (step: number) => {\n const at = shown.findIndex((r) => r.id === current?.id);\n const next = shown[Math.min(shown.length - 1, Math.max(0, at + step))];\n if (next) {\n setSelected(next.id);\n }\n };\n const answer = async (id: string) => {\n if (!current || !statusColumn) {\n return;\n }\n const at = rows.findIndex((r) => r.id === current.id);\n // The next row still open, looking onward from this one and then from the top.\n const next = [...rows.slice(at + 1), ...rows.slice(0, at)].find(isOpen);\n await patch(current.id, { [statusColumn.id]: id });\n if (next && id !== openId) {\n setSelected(next.id);\n }\n };\n // Arrow keys walk the list and digits answer, as long as nobody is typing in a cell.\n const keys = (e: React.KeyboardEvent) => {\n if ((e.target as HTMLElement).closest(\"input, textarea, select\")) {\n return;\n }\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n move(e.key === \"ArrowDown\" ? 1 : -1);\n } else if (/^[1-9]$/.test(e.key) && answers[Number(e.key)]) {\n e.preventDefault();\n void answer(answers[Number(e.key)].id);\n }\n };\n if (!rows.length) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"list.empty\")}</p>;\n }\n const path = fileColumn && current ? String(current.cells[fileColumn.id] ?? \"\").trim() : \"\";\n const ext = path.split(\".\").pop()?.toLowerCase() ?? \"\";\n const tone = (row: ShownList[\"rows\"][number]) =>\n ANSWER_TONE[\n Math.min(\n Math.max(\n 0,\n answers.findIndex((a) => a.id === statusOf(row)),\n ),\n 3,\n )\n ];\n return (\n <div className=\"grid gap-4 lg:grid-cols-[minmax(280px,360px)_minmax(0,1fr)]\" onKeyDown={keys}>\n <div className=\"flex min-h-0 flex-col\">\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <span className=\"text-[0.8125rem] text-ink-3 tabular-nums\">\n {t(\"check.progress\", { done, total: rows.length })}\n </span>\n {statusColumn ? (\n <button\n type=\"button\"\n aria-pressed={onlyOpen}\n onClick={() => setOnlyOpen((v) => !v)}\n className={cn(\n \"inline-flex h-8 items-center rounded-full px-3 text-[0.8125rem] ring-1 transition coarse:h-11\",\n onlyOpen\n ? \"bg-ember-tint text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink\",\n )}\n >\n {t(\"check.onlyOpen\")}\n </button>\n ) : null}\n </div>\n <ul className=\"flex max-h-[38vh] flex-col gap-1.5 overflow-y-auto p-0.5 pr-1 lg:max-h-[calc(100vh-15rem)]\">\n {shown.map((row) => (\n <li key={row.id}>\n <button\n type=\"button\"\n onClick={() => setSelected(row.id)}\n aria-current={row.id === current?.id}\n className={cn(\n \"flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-left ring-1 transition\",\n row.id === current?.id\n ? \"bg-card shadow-soft ring-ember\"\n : \"bg-paper ring-border-soft hover:bg-card\",\n )}\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium text-[0.875rem]\">\n {(titleColumn &&\n formatTableCell(titleColumn, row.cells[titleColumn.id], lang)) ||\n \"—\"}\n </span>\n <span className=\"block truncate text-[0.75rem] text-ink-3 tabular-nums\">\n {restColumns\n .slice(0, 2)\n .map((c) => formatTableCell(c, row.cells[c.id], lang))\n .filter(Boolean)\n .join(\" · \")}\n </span>\n </span>\n {statusColumn ? (\n <span\n className={cn(\n \"shrink-0 rounded-full px-2 py-0.5 font-medium text-[0.6875rem]\",\n tone(row),\n )}\n >\n {answers.find((a) => a.id === statusOf(row))?.label ?? statusOf(row)}\n </span>\n ) : null}\n </button>\n </li>\n ))}\n </ul>\n </div>\n {current ? (\n <div className=\"flex min-w-0 flex-col gap-3\">\n {answers.length > 1 ? (\n <div className=\"flex flex-wrap gap-2\">\n {answers.slice(1).map((a, i) => (\n <Button\n key={a.id}\n size=\"md\"\n variant={statusOf(current) === a.id ? \"primary\" : \"secondary\"}\n onClick={() => void answer(a.id)}\n >\n {statusOf(current) === a.id ? <Check className=\"size-4\" /> : null}\n {a.label}\n <kbd className=\"ml-1 hidden rounded bg-black/10 px-1.5 text-[0.6875rem] lg:inline\">\n {i + 1}\n </kbd>\n </Button>\n ))}\n {statusOf(current) !== openId ? (\n <Button size=\"md\" variant=\"ghost\" onClick={() => void answer(openId ?? \"\")}>\n {t(\"check.reopen\")}\n </Button>\n ) : null}\n </div>\n ) : null}\n <div className=\"overflow-hidden rounded-lg bg-paper-2 ring-1 ring-border-soft\">\n {path ? (\n <>\n <div className=\"flex items-center gap-2 border-border-soft border-b bg-card px-3 py-2 text-[0.8125rem]\">\n <FileText className=\"size-3.5 shrink-0 text-ink-3\" />\n <span className=\"min-w-0 flex-1 truncate\">{path.split(\"/\").pop()}</span>\n <a\n href={storeFileUrl(runId, path, ext === \"pdf\")}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"shrink-0 text-ink-2 underline-offset-2 hover:text-ink hover:underline\"\n >\n {t(\"run.openFull\")}\n </a>\n </div>\n {ext === \"pdf\" ? (\n <iframe\n key={path}\n title={path}\n src={`${storeFileUrl(runId, path, true)}#toolbar=0&navpanes=0&view=FitH`}\n className=\"h-[46vh] w-full border-0 bg-white lg:h-[calc(100vh-27rem)] lg:min-h-[360px]\"\n />\n ) : [\"png\", \"jpg\", \"jpeg\", \"webp\"].includes(ext) ? (\n <div className=\"flex max-h-[46vh] justify-center overflow-auto bg-white lg:max-h-[calc(100vh-27rem)]\">\n <img\n key={path}\n src={storeFileUrl(runId, path, true)}\n alt={path}\n className=\"max-w-full object-contain\"\n />\n </div>\n ) : (\n <p className=\"px-4 py-10 text-center text-[0.875rem] text-ink-3\">\n {t(\"check.noPreview\")}\n </p>\n )}\n </>\n ) : (\n <p className=\"px-4 py-14 text-center text-[0.875rem] text-ink-3\">\n {t(\"check.noFile\")}\n </p>\n )}\n </div>\n <div className=\"grid grid-cols-2 gap-x-3 gap-y-2 sm:grid-cols-3\">\n {labelled.map((c) => (\n <div\n key={c.id}\n className={cn(\n \"min-w-0\",\n c.type === \"text\" && c.format?.style === \"multiline\" && \"col-span-full\",\n )}\n >\n <div className=\"px-1 pb-0.5 text-[0.6875rem] text-ink-3\">{c.name}</div>\n <CellInput\n boxed\n column={c}\n value={current.cells[c.id]}\n onCommit={(value) => void patch(current.id, { [c.id]: value })}\n />\n </div>\n ))}\n </div>\n {error ? <p className=\"text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nconst LIST_FORMAT_LABEL: Partial<Record<Format, string>> = {\n xlsx: \"Excel\",\n csv: \"CSV\",\n json: \"JSON\",\n md: \"Markdown\",\n zip: \"ZIP\",\n};\n\nexport function ListDownloads({ runId, list }: { runId: string; list: ShownList }) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {list.formats.map((f) => (\n <a\n key={f}\n href={withBase(`${runBase(runId)}/lists/${list.def.id}/download?format=${f}`)}\n className=\"inline-flex h-9 items-center rounded-full bg-paper-2 px-3.5 font-medium text-[0.8125rem] text-ink-2 transition hover:bg-paper-3 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n {LIST_FORMAT_LABEL[f] ?? f}\n </a>\n ))}\n </div>\n );\n}\n\n// --- what the wizard keeps -------------------------------------------------------\n\ninterface StoreSummary {\n lists: { id: string; title: string; rows: number }[];\n files: StoreFile[];\n connections: ConnectionView[];\n keepsSignIns: boolean;\n}\n\n/** Everything the wizard keeps for this person between runs, and the way to delete it. */\nexport function StoreButton({ runId }: { runId: string }) {\n const [open, setOpen] = useState(false);\n const [data, setData] = useState<StoreSummary | null>(null);\n const [confirm, setConfirm] = useState(false);\n useEffect(() => {\n if (open) {\n setConfirm(false);\n void api.get<StoreSummary>(`${runBase(runId)}/store`).then(setData);\n }\n }, [open, runId]);\n const empty =\n data &&\n !data.files.length &&\n !data.connections.length &&\n !data.keepsSignIns &&\n data.lists.every((l) => !l.rows);\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"inline-flex items-center gap-1.5 text-[0.8125rem] text-ink-4 transition hover:text-ink-2 coarse:min-h-11\"\n >\n <Database className=\"size-3.5\" /> {t(\"store.open\")}\n </button>\n <Dialog open={open} onClose={() => setOpen(false)} title={t(\"store.title\")} wide>\n {!data ? (\n <div className=\"flex justify-center py-8 text-ink-4\">\n <Spinner />\n </div>\n ) : (\n <div className=\"flex flex-col gap-5 text-[0.875rem]\">\n <p className=\"text-ink-3\">{t(\"store.explain\")}</p>\n {empty ? <p className=\"text-ink-2\">{t(\"store.empty\")}</p> : null}\n {data.lists.some((l) => l.rows) ? (\n <ul className=\"flex flex-col gap-1\">\n {data.lists\n .filter((l) => l.rows)\n .map((l) => (\n <li key={l.id} className=\"flex justify-between gap-3\">\n <span>{l.title}</span>\n <span className=\"text-ink-3 tabular-nums\">\n {t(\"store.rows\", { n: l.rows })}\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n {data.connections.map((c) => (\n <div key={c.id} className=\"flex items-center gap-2\">\n <Link2 className=\"size-4 text-ink-3\" /> {c.account?.label}\n </div>\n ))}\n {data.keepsSignIns ? (\n <div className=\"flex items-center gap-2\">\n <Check className=\"size-4 text-ink-3\" /> {t(\"store.signIns\")}\n </div>\n ) : null}\n {data.files.length ? (\n <div>\n <div className=\"mb-1 text-ink-3\">\n {t(\"store.files\", {\n n: data.files.length,\n size: formatBytes(data.files.reduce((n, f) => n + f.size, 0)),\n })}\n </div>\n <ul className=\"max-h-56 overflow-y-auto rounded-lg ring-1 ring-border-soft\">\n {data.files.map((f) => (\n <li key={f.path} className=\"border-border-soft border-b last:border-0\">\n <a\n href={withBase(`${runBase(runId)}/store/files/${f.path}`)}\n className=\"flex items-center gap-2 px-3 py-2 text-[0.8125rem] hover:bg-paper-2 coarse:min-h-11\"\n title={f.source ?? undefined}\n >\n <FileText className=\"size-3.5 shrink-0 text-ink-3\" />\n <span className=\"min-w-0 flex-1 truncate\">{f.path}</span>\n <span className=\"text-ink-4 tabular-nums\">{formatBytes(f.size)}</span>\n </a>\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n <div className=\"flex items-center justify-between gap-3 pt-1\">\n {empty ? (\n <span />\n ) : confirm ? (\n <Button\n variant=\"secondary\"\n onClick={async () => {\n await api.del(`${runBase(runId)}/store`);\n setData(await api.get<StoreSummary>(`${runBase(runId)}/store`));\n setConfirm(false);\n }}\n >\n <Trash2 className=\"size-4\" /> {t(\"store.confirmDelete\")}\n </Button>\n ) : (\n <Button variant=\"ghost\" onClick={() => setConfirm(true)}>\n <Trash2 className=\"size-4\" /> {t(\"store.delete\")}\n </Button>\n )}\n <Button onClick={() => setOpen(false)}>{t(\"common.close\")}</Button>\n </div>\n </div>\n )}\n </Dialog>\n </>\n );\n}\n","import { type AudioValue, isAudioValue } from \"@engenty/wizards-shared/definition\";\nimport { FileAudio, Mic, RotateCcw, Square } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { stamp } from \"./camera\";\nimport { canUseMedia } from \"./device\";\nimport { api, appCall, appCan, runBase, runnerEnv } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, Spinner } from \"./ui.js\";\n\nconst MAX_SECONDS = 300;\n\nfunction recordingType(): string | undefined {\n if (typeof MediaRecorder === \"undefined\") {\n return undefined;\n }\n // A phone that writes the note down itself reads AAC in an .m4a, not WebM or Ogg.\n const types = appCan(\"transcribe\")\n ? [\"audio/mp4\", \"audio/webm;codecs=opus\", \"audio/webm\", \"audio/ogg;codecs=opus\"]\n : [\"audio/webm;codecs=opus\", \"audio/mp4\", \"audio/webm\", \"audio/ogg;codecs=opus\"];\n return types.find((type) => MediaRecorder.isTypeSupported(type));\n}\n\n/** A recording written down by the app on the phone; undefined when the app cannot. */\nasync function transcribeOnDevice(file: Blob, lang: string): Promise<string | undefined> {\n if (!appCan(\"transcribe\")) {\n return undefined;\n }\n try {\n const audio = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result).split(\",\")[1] ?? \"\");\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n const result = await appCall<{ text: string } | null>(\"transcribe\", {\n audio,\n mime: file.type,\n lang,\n });\n return typeof result?.text === \"string\" ? result.text : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction clock(seconds: number): string {\n return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, \"0\")}`;\n}\n\n/**\n * A voice note: recorded here with the microphone, or — where the browser cannot record — an\n * audio file from the phone's recorder. The recording is kept as an upload; what is said in it\n * is written down on the server before the next step reads it.\n */\nexport function VoiceField({\n value,\n runId,\n onChange,\n onBusy,\n}: {\n value: unknown;\n runId: string;\n onChange: (v: AudioValue | undefined) => void;\n onBusy?: (busy: boolean) => void;\n}) {\n const note = isAudioValue(value) ? value : null;\n const [seconds, setSeconds] = useState<number | null>(null);\n const [level, setLevel] = useState(0);\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [denied, setDenied] = useState(false);\n // What was just recorded plays from memory; a note from an earlier visit plays from the server.\n const [local, setLocal] = useState<{ asset: string; url: string } | null>(null);\n const session = useRef<{ recorder: MediaRecorder; stop: () => void } | null>(null);\n const picker = useRef<HTMLInputElement>(null);\n const type = recordingType();\n const canRecord = canUseMedia && Boolean(type);\n\n useEffect(\n () => () => {\n // Leaving the page mid-recording keeps nothing and frees the microphone.\n if (session.current) {\n session.current.recorder.onstop = null;\n session.current.stop();\n }\n },\n [],\n );\n useEffect(\n () => () => {\n if (local) {\n URL.revokeObjectURL(local.url);\n }\n },\n [local],\n );\n\n const keep = async (file: File, length: number | undefined) => {\n setUploading(true);\n onBusy?.(true);\n setError(null);\n try {\n const ref = await api.upload<{ id: string }>(`${runBase(runId)}/uploads`, file);\n setLocal({ asset: ref.id, url: URL.createObjectURL(file) });\n // In the app the phone writes the note down itself; else the server does before the next step.\n const { lang } = runnerEnv();\n const transcript = await transcribeOnDevice(file, lang);\n onChange({\n asset: ref.id,\n lang,\n ...(length !== undefined ? { seconds: length } : {}),\n ...(transcript !== undefined ? { transcript } : {}),\n });\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setUploading(false);\n onBusy?.(false);\n }\n };\n\n const start = async () => {\n setError(null);\n setDenied(false);\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getUserMedia({\n audio: { echoCancellation: true, noiseSuppression: true },\n });\n } catch {\n setDenied(true);\n return;\n }\n const chunks: Blob[] = [];\n const recorder = new MediaRecorder(stream, { mimeType: type, audioBitsPerSecond: 48_000 });\n const began = Date.now();\n // The level bar shows the microphone hears something.\n const ctx = new AudioContext();\n const analyser = ctx.createAnalyser();\n analyser.fftSize = 256;\n ctx.createMediaStreamSource(stream).connect(analyser);\n const samples = new Uint8Array(analyser.fftSize);\n let frame = 0;\n const meter = () => {\n analyser.getByteTimeDomainData(samples);\n let peak = 0;\n for (const s of samples) {\n peak = Math.max(peak, Math.abs(s - 128));\n }\n setLevel(Math.min(1, peak / 64));\n setSeconds((Date.now() - began) / 1000);\n if ((Date.now() - began) / 1000 >= MAX_SECONDS) {\n stop();\n return;\n }\n frame = requestAnimationFrame(meter);\n };\n const stop = () => {\n cancelAnimationFrame(frame);\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n for (const track of stream.getTracks()) {\n track.stop();\n }\n void ctx.close().catch(() => undefined);\n session.current = null;\n setSeconds(null);\n setLevel(0);\n };\n recorder.ondataavailable = (e) => e.data.size && chunks.push(e.data);\n recorder.onstop = () => {\n const mime = (recorder.mimeType || type || \"audio/webm\").split(\";\")[0];\n const ext = mime === \"audio/mp4\" ? \"m4a\" : mime === \"audio/ogg\" ? \"ogg\" : \"webm\";\n const length = Math.max(1, Math.round((Date.now() - began) / 1000));\n void keep(new File(chunks, `sprachnotiz-${stamp()}.${ext}`, { type: mime }), length);\n };\n session.current = { recorder, stop };\n onBusy?.(true);\n recorder.start(1000);\n frame = requestAnimationFrame(meter);\n };\n\n const recording = seconds !== null;\n const fileButton = (\n <Button variant=\"secondary\" onClick={() => picker.current?.click()}>\n <FileAudio className=\"size-4\" /> {t(\"voice.pick\")}\n </Button>\n );\n\n return (\n <div>\n {recording ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-3 ring-1 ring-ember\">\n <span className=\"relative flex size-11 shrink-0 items-center justify-center\">\n <span\n className=\"absolute inset-0 rounded-full bg-rose-tint transition-transform duration-75\"\n style={{ transform: `scale(${0.7 + level * 0.5})` }}\n />\n <span className=\"relative size-3.5 animate-pulse-dot rounded-full bg-rose\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-medium text-[0.9375rem] tabular-nums\">{clock(seconds)}</div>\n <div className=\"text-[0.8125rem] text-ink-3\">\n {seconds > MAX_SECONDS - 30\n ? t(\"voice.left\", { s: Math.ceil(MAX_SECONDS - seconds) })\n : t(\"voice.recording\")}\n </div>\n </div>\n <Button onClick={() => session.current?.stop()}>\n <Square className=\"size-3.5 fill-current\" /> {t(\"voice.stop\")}\n </Button>\n </div>\n ) : uploading ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-4 text-[0.875rem] text-ink-3 ring-1 ring-input\">\n <Spinner className=\"size-4\" /> {t(\"run.uploading\")}\n </div>\n ) : note ? (\n <div className=\"rounded-xl bg-card p-3 ring-1 ring-input\">\n {/* biome-ignore lint/a11y/useMediaCaption: the person's own voice note, just recorded */}\n <audio\n controls\n preload=\"metadata\"\n src={local?.asset === note.asset ? local.url : `${runBase(runId)}/assets/${note.asset}`}\n className=\"h-11 w-full\"\n />\n {note.transcript ? (\n <p className=\"mt-2 whitespace-pre-wrap px-1 text-[0.875rem] text-ink-2 leading-relaxed\">\n {note.transcript}\n </p>\n ) : null}\n <div className=\"mt-2 flex flex-wrap items-center justify-between gap-2\">\n <span className=\"px-1 text-[0.8125rem] text-ink-3\">\n {note.seconds ? clock(note.seconds) : null}\n </span>\n <div className=\"flex gap-1\">\n {canRecord ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void start()}>\n <RotateCcw className=\"size-3.5\" /> {t(\"voice.again\")}\n </Button>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onChange(undefined)}>\n {t(\"voice.remove\")}\n </Button>\n </div>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"flex flex-wrap gap-2\">\n {canRecord ? (\n <Button\n variant=\"secondary\"\n size=\"lg\"\n onClick={() => void start()}\n className=\"w-full sm:w-auto\"\n >\n <Mic className=\"size-4\" /> {t(\"voice.start\")}\n </Button>\n ) : (\n fileButton\n )}\n {canRecord && denied ? fileButton : null}\n </div>\n {denied ? (\n <p className=\"mt-2 rounded-lg bg-amber-tint px-3 py-2 text-[0.8125rem] text-ink-2 leading-relaxed\">\n {t(\"voice.denied\")}\n </p>\n ) : (\n <p className=\"mt-2 text-[0.8125rem] text-ink-3 leading-relaxed\">\n {t(canRecord ? \"voice.why\" : \"voice.noRecorder\")}\n </p>\n )}\n </div>\n )}\n <input\n ref={picker}\n type=\"file\"\n hidden\n accept=\"audio/*\"\n capture\n onChange={(e) => {\n const file = e.target.files?.[0];\n e.target.value = \"\";\n if (file) {\n void keep(file, undefined);\n }\n }}\n />\n {error ? <div className=\"mt-2 text-[0.8125rem] text-rose\">{error}</div> : null}\n </div>\n );\n}\n","import {\n type CardOption,\n type Field,\n itemsTotals,\n MAX_FILES,\n type ModelClass,\n slotDayText,\n slotTime,\n} from \"@engenty/wizards-shared/definition\";\nimport { formatMoney } from \"@engenty/wizards-shared/numbers\";\nimport type { ClosedChoice, RunView } from \"@engenty/wizards-shared/run\";\nimport {\n Camera,\n Film,\n GripVertical,\n ImagePlus,\n Paperclip,\n Plus,\n ScanLine,\n Trash2,\n Video,\n X,\n} from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { CameraDialog, canRecordClips, shrinkImage } from \"./camera\";\nimport { canUseMedia, isTouch } from \"./device\";\nimport { api, runBase, withBase } from \"./env.js\";\nimport { choiceLabel, lang, t } from \"./i18n.js\";\nimport { LocationField } from \"./location\";\nimport { ScanDialog } from \"./scan\";\nimport { SignatureField } from \"./signature\";\nimport { ConnectionField, ListTable } from \"./store\";\nimport { cn, IconButton, Input, Label, Segmented, Select, Swatch, Switch, Textarea } from \"./ui.js\";\nimport { VoiceField } from \"./voice\";\n\nexport type Values = Record<string, unknown>;\n\nfunction ItemsField({\n field,\n value,\n values,\n onChange,\n}: {\n field: Field;\n value: unknown;\n values: Values;\n onChange: (v: unknown) => void;\n}) {\n const cols = field.columns ?? [];\n const rows = (Array.isArray(value) && value.length ? value : [{}]) as Record<string, unknown>[];\n const totals = itemsTotals(field, rows, values);\n const set = (i: number, col: string, v: string) => {\n const next = rows.map((r, j) => (j === i ? { ...r, [col]: v } : r));\n onChange(next);\n };\n const grid = cols\n .map((c) => (c.kind === \"text\" && c === cols[0] ? \"minmax(0,3fr)\" : \"minmax(0,1fr)\"))\n .join(\" \");\n return (\n <div className=\"rounded-xl bg-card p-2 ring-1 ring-input\">\n <div\n className=\"hidden gap-2 px-2 pt-1 pb-2 text-[0.75rem] text-ink-3 sm:grid\"\n style={{ gridTemplateColumns: `${grid} 36px` }}\n >\n {cols.map((c) => (\n <div key={c.id} className={c.kind === \"text\" ? \"\" : \"text-right\"}>\n {c.label}\n </div>\n ))}\n </div>\n <div className=\"flex flex-col gap-2\">\n {rows.map((row, i) => (\n // A phone shows each row as a card: the first column across, the rest side by side\n // under their labels. From tablet width up it is one table row.\n <div\n key={i}\n className=\"grid grid-cols-6 gap-2 rounded-lg bg-paper p-2 sm:bg-transparent sm:p-0 sm:[grid-template-columns:var(--cols)]\"\n style={{ \"--cols\": `${grid} 36px` } as React.CSSProperties}\n >\n {cols.map((c, ci) => (\n <label\n key={c.id}\n className={cn(\n \"flex min-w-0 flex-col gap-1 sm:col-span-1\",\n ci === 0 ? \"col-span-5\" : cols.length - 1 <= 2 ? \"col-span-3\" : \"col-span-2\",\n )}\n >\n <span className=\"px-0.5 text-[0.6875rem] text-ink-3 sm:hidden\">{c.label}</span>\n <input\n aria-label={c.label}\n placeholder={c.label}\n inputMode={c.kind === \"text\" ? \"text\" : \"decimal\"}\n autoComplete=\"off\"\n value={String(row[c.id] ?? \"\")}\n onChange={(e) => set(i, c.id, e.target.value)}\n className={cn(\n \"h-11 w-full min-w-0 rounded-md border border-transparent bg-paper-2 px-2.5 text-[0.875rem] outline-none placeholder:text-transparent focus:border-focus focus:bg-card sm:placeholder:text-ink-4\",\n c.kind !== \"text\" && \"text-right tabular-nums\",\n )}\n />\n </label>\n ))}\n <IconButton\n label={t(\"list.delete\")}\n onClick={() => onChange(rows.filter((_, j) => j !== i))}\n className=\"order-first col-start-6 row-start-1 size-11 justify-self-end self-end sm:order-none sm:col-start-auto sm:row-start-auto\"\n >\n <Trash2 className=\"size-4\" />\n </IconButton>\n </div>\n ))}\n </div>\n <div className=\"mt-2 flex flex-wrap items-end justify-between gap-3 px-2 pb-1\">\n <button\n type=\"button\"\n onClick={() => onChange([...rows, {}])}\n className=\"inline-flex h-9 items-center gap-1.5 rounded-full px-3 text-[0.8125rem] text-ink-2 hover:bg-accent coarse:h-11\"\n >\n <Plus className=\"size-4\" /> {t(\"run.addRow\")}\n </button>\n <div className=\"text-right text-[0.8125rem] tabular-nums\">\n <div className=\"text-ink-3\">\n {t(\"run.net\")} {formatMoney(totals.net, totals.currency, lang)}\n </div>\n {totals.vatRate ? (\n <div className=\"text-ink-3\">\n {t(\"run.vat\", { r: totals.vatRate })} {formatMoney(totals.vat, totals.currency, lang)}\n </div>\n ) : null}\n <div className=\"font-semibold text-[0.9375rem] text-ink\">\n {t(\"run.total\")} {formatMoney(totals.gross, totals.currency, lang)}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/** Whether a paste belongs to typing somewhere rather than to an upload field. */\nfunction typingTarget(el: Element | null): boolean {\n return Boolean(el?.closest(\"input, textarea, [contenteditable='true']\"));\n}\n\nfunction UploadField({\n field,\n value,\n runId,\n onChange,\n onBusy,\n}: {\n field: Field;\n value: unknown;\n runId: string;\n onChange: (v: unknown) => void;\n onBusy?: (busy: boolean) => void;\n}) {\n const root = useRef<HTMLDivElement>(null);\n const picker = useRef<HTMLInputElement>(null);\n const nativeCamera = useRef<HTMLInputElement>(null);\n const nativeVideo = useRef<HTMLInputElement>(null);\n const [busy, setBusy] = useState(false);\n const [names, setNames] = useState<Record<string, { name: string; mime: string }>>({});\n const [error, setError] = useState<string | null>(null);\n const [camera, setCamera] = useState(false);\n const [over, setOver] = useState(false);\n // The file being dragged to another place in the list. The ref is what the pointer handlers\n // read: a move can arrive before the state has rendered.\n const [dragging, setDragging] = useState<string | null>(null);\n const drag = useRef<string | null>(null);\n const grab = (id: string | null) => {\n drag.current = id;\n setDragging(id);\n };\n const image = field.kind === \"image\";\n const multiple = Boolean(field.multiple);\n const most = multiple ? (field.max ?? MAX_FILES) : 1;\n const withCamera = image || Boolean(field.camera) || Boolean(field.video);\n const clips = !image && Boolean(field.video);\n const ids = Array.isArray(value)\n ? (value as string[])\n : typeof value === \"string\" && value\n ? [value]\n : [];\n // The list as it is now, not as it was when an upload started: several can finish in a row.\n const current = useRef(ids);\n current.current = ids;\n const room = ids.length < most;\n\n const add = async (files: File[]) => {\n // Several picked at once arrive in whatever order the file dialog likes; by name, pictures\n // from a camera are in the order they were taken.\n const wanted = (image ? files.filter((f) => f.type.startsWith(\"image/\")) : files).sort((a, b) =>\n a.name.localeCompare(b.name, undefined, { numeric: true }),\n );\n if (!wanted.length) {\n return;\n }\n const free = most - (multiple ? current.current.length : 0);\n setBusy(true);\n onBusy?.(true);\n setError(wanted.length > free && multiple ? t(\"run.maxFiles\", { n: most }) : null);\n try {\n for (const raw of wanted.slice(0, Math.max(0, free))) {\n const file = await shrinkImage(raw);\n const ref = await api.upload<{ id: string; name: string; mime: string }>(\n `${runBase(runId)}/uploads`,\n file,\n );\n setNames((n) => ({ ...n, [ref.id]: { name: ref.name, mime: ref.mime } }));\n const next = multiple ? [...current.current, ref.id] : ref.id;\n current.current = multiple ? (next as string[]) : [ref.id];\n onChange(next);\n }\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setBusy(false);\n onBusy?.(false);\n }\n };\n const adding = useRef(add);\n adding.current = add;\n const remove = (id: string) => {\n const left = ids.filter((x) => x !== id);\n onChange(multiple ? left : undefined);\n };\n // The order is part of the answer (the rooms of a tour, the pages of a document).\n const move = (id: string, to: number) => {\n const from = current.current.indexOf(id);\n const at = Math.min(current.current.length - 1, Math.max(0, to));\n if (from < 0 || from === at) {\n return;\n }\n const next = current.current.filter((x) => x !== id);\n next.splice(at, 0, id);\n current.current = next;\n onChange(next);\n };\n const sortable = multiple && ids.length > 1;\n\n // A screenshot or a copied picture is pasted straight in: into the field the pointer is on,\n // or the page's only upload field. Typing in a text field keeps its own paste.\n useEffect(() => {\n if (!room) {\n return;\n }\n const onPaste = (e: ClipboardEvent) => {\n const files = Array.from(e.clipboardData?.files ?? []);\n const el = root.current;\n if (!files.length || !el || typingTarget(document.activeElement)) {\n return;\n }\n const fields = document.querySelectorAll(\"[data-upload-field]\");\n if (el.matches(\":hover\") || el.contains(document.activeElement) || fields.length === 1) {\n e.preventDefault();\n void adding.current(files);\n }\n };\n document.addEventListener(\"paste\", onPaste);\n return () => document.removeEventListener(\"paste\", onPaste);\n }, [room]);\n\n const tile = cn(\n \"flex flex-col items-center justify-center gap-2 rounded-xl border border-input border-dashed bg-card px-3 text-[0.875rem] text-ink-3 transition hover:border-ember hover:text-ink\",\n ids.length ? \"py-4\" : \"py-8\",\n );\n return (\n <div\n ref={root}\n data-upload-field=\"\"\n onDragOver={(e) => {\n if (room) {\n e.preventDefault();\n setOver(true);\n }\n }}\n onDragLeave={() => setOver(false)}\n onDrop={(e) => {\n setOver(false);\n if (room) {\n e.preventDefault();\n void add(Array.from(e.dataTransfer.files));\n }\n }}\n >\n {ids.length ? (\n <div className=\"mb-2 flex flex-col gap-2\">\n {ids.map((id, index) => {\n const known = names[id];\n const mime = known?.mime ?? (image ? \"image/\" : \"\");\n return (\n <div\n key={id}\n data-file-id={id}\n className={cn(\n \"flex items-center gap-3 rounded-xl bg-card p-2 ring-1 ring-input transition-shadow\",\n dragging === id && \"relative z-10 shadow-elevated ring-2 ring-ember\",\n )}\n >\n {sortable ? (\n <button\n type=\"button\"\n aria-label={t(\"run.moveFile\", { n: index + 1 })}\n title={t(\"run.moveFileHint\")}\n className={cn(\n \"-mr-1 flex h-14 w-9 shrink-0 touch-none flex-col items-center justify-center gap-0.5 rounded-lg text-ink-3 hover:bg-paper-2 hover:text-ink\",\n dragging === id ? \"cursor-grabbing\" : \"cursor-grab\",\n )}\n onPointerDown={(e) => {\n try {\n e.currentTarget.setPointerCapture(e.pointerId);\n } catch {\n // Without capture the drag still works while the pointer stays on the list.\n }\n grab(id);\n }}\n onPointerMove={(e) => {\n if (drag.current !== id) {\n return;\n }\n // The row under the pointer gives its place to the one being dragged.\n const row = document\n .elementFromPoint(e.clientX, e.clientY)\n ?.closest(\"[data-file-id]\");\n const other = row?.getAttribute(\"data-file-id\");\n if (other && other !== id && root.current?.contains(row ?? null)) {\n move(id, current.current.indexOf(other));\n }\n }}\n onPointerUp={() => grab(null)}\n onPointerCancel={() => grab(null)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowUp\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n move(id, index + (e.key === \"ArrowUp\" ? -1 : 1));\n }\n }}\n >\n <span className=\"font-medium text-[0.75rem] tabular-nums\">{index + 1}</span>\n <GripVertical className=\"size-4\" />\n </button>\n ) : null}\n {mime.startsWith(\"image/\") ? (\n <img\n src={withBase(`${runBase(runId)}/assets/${id}`)}\n alt=\"\"\n className=\"size-14 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"flex size-12 shrink-0 items-center justify-center rounded-lg bg-paper-2\">\n {mime.startsWith(\"video/\") ? (\n <Film className=\"size-5 text-ink-3\" />\n ) : (\n <Paperclip className=\"size-5 text-ink-3\" />\n )}\n </div>\n )}\n <div className=\"min-w-0 flex-1 truncate text-[0.875rem]\">{known?.name ?? \"✓\"}</div>\n <IconButton label={t(\"run.removeFile\")} onClick={() => remove(id)}>\n <X className=\"size-4\" />\n </IconButton>\n </div>\n );\n })}\n </div>\n ) : null}\n {room ? (\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => picker.current?.click()}\n className={cn(tile, \"min-w-[9rem] flex-1 px-4\", over && \"border-ember text-ink\")}\n >\n {image ? <ImagePlus className=\"size-6\" /> : <Paperclip className=\"size-6\" />}\n {busy\n ? t(\"run.uploading\")\n : ids.length\n ? t(\"run.uploadMore\")\n : t(isTouch ? \"run.uploadTouch\" : \"run.upload\")}\n </button>\n {withCamera ? (\n <button\n type=\"button\"\n onClick={() => (canUseMedia ? setCamera(true) : nativeCamera.current?.click())}\n className={cn(tile, \"w-28\")}\n >\n <Camera className=\"size-6\" />\n {t(\"run.camera\")}\n </button>\n ) : null}\n {/* Where the browser cannot record a clip itself, the phone's camera app does. */}\n {clips && !(canUseMedia && canRecordClips) ? (\n <button\n type=\"button\"\n onClick={() => nativeVideo.current?.click()}\n className={cn(tile, \"w-28\")}\n >\n <Video className=\"size-6\" />\n {t(\"camera.video\")}\n </button>\n ) : null}\n </div>\n ) : null}\n <input\n ref={picker}\n type=\"file\"\n hidden\n multiple={multiple}\n accept={image ? \"image/*\" : undefined}\n onChange={(e) => {\n void add(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n <input\n ref={nativeCamera}\n type=\"file\"\n hidden\n accept=\"image/*\"\n capture=\"environment\"\n onChange={(e) => {\n void add(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n {clips ? (\n <input\n ref={nativeVideo}\n type=\"file\"\n hidden\n accept=\"video/*\"\n capture=\"environment\"\n onChange={(e) => {\n void add(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n ) : null}\n <CameraDialog\n open={camera}\n multiple={multiple}\n video={clips}\n onClose={() => setCamera(false)}\n onCapture={(file) => add([file])}\n onNative={() => nativeCamera.current?.click()}\n />\n {multiple && (field.min || field.max) ? (\n <div className=\"mt-2 text-[0.8125rem] text-ink-3 tabular-nums\">\n {field.min && ids.length < field.min\n ? t(\"run.filesMin\", { n: ids.length, min: field.min })\n : field.max\n ? t(\"run.filesOf\", { n: ids.length, max: field.max })\n : null}\n </div>\n ) : null}\n {error ? <div className=\"mt-2 text-[0.8125rem] text-rose\">{error}</div> : null}\n </div>\n );\n}\n\n/**\n * What the keyboard should offer for a short text: a label that asks for a phone number gets the\n * number pad, a name gets the person's own from autofill. Guessed from the field's id and label.\n */\nexport function textHints(field: Field): React.InputHTMLAttributes<HTMLInputElement> {\n const key = `${field.id} ${field.label}`.toLowerCase();\n if (/telefon|phone|handy|mobil(?!it)|\\btel\\b|rückruf/.test(key)) {\n return { type: \"tel\", inputMode: \"tel\", autoComplete: \"tel\" };\n }\n if (/\\bplz\\b|postleitzahl|postal|zip/.test(key)) {\n return { inputMode: \"numeric\", autoComplete: \"postal-code\" };\n }\n if (/iban/.test(key)) {\n return { autoCapitalize: \"characters\", autoCorrect: \"off\", spellCheck: false };\n }\n if (/vorname|first.?name/.test(key)) {\n return { autoComplete: \"given-name\", autoCapitalize: \"words\" };\n }\n if (/nachname|last.?name|surname/.test(key)) {\n return { autoComplete: \"family-name\", autoCapitalize: \"words\" };\n }\n if (/firma|unternehmen|company|organi[sz]ation/.test(key)) {\n return { autoComplete: \"organization\", autoCapitalize: \"words\" };\n }\n if (/straße|strasse|street|anschrift|adresse|address/.test(key)) {\n return { autoComplete: \"street-address\", autoCapitalize: \"words\" };\n }\n if (/\\b(ort|stadt|city|town)\\b/.test(key)) {\n return { autoComplete: \"address-level2\", autoCapitalize: \"words\" };\n }\n if (/\\bname\\b|ansprechp/.test(key)) {\n return { autoComplete: \"name\", autoCapitalize: \"words\" };\n }\n return { autoCapitalize: \"sentences\" };\n}\n\n/** A short text that can also be filled by pointing the camera at a QR code or barcode. */\nfunction ScanInput({\n field,\n value,\n onChange,\n}: {\n field: Field;\n value: string;\n onChange: (v: string) => void;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"flex gap-2\">\n <Input\n value={value}\n placeholder={field.placeholder}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n onChange={(e) => onChange(e.target.value)}\n />\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"inline-flex h-11 shrink-0 items-center gap-2 rounded-lg border border-input bg-card px-3.5 font-medium text-[0.875rem] text-ink-2 transition hover:border-ember hover:text-ink\"\n >\n <ScanLine className=\"size-4\" /> {t(\"scan.button\")}\n </button>\n <ScanDialog open={open} onClose={() => setOpen(false)} onResult={onChange} />\n </div>\n );\n}\n\n/** How many days of offered times show before \"Show later times\". */\nconst SLOT_DAYS = 4;\n\n/** Offered times by calendar day, in their own offset (the business's clock), earliest first. */\nfunction slotDays(options: string[]) {\n const days = new Map<string, { label: string; times: { value: string; time: string }[] }>();\n const sorted = options\n .map((value) => ({ value, slot: slotTime(value) }))\n .filter((o) => o.slot)\n .sort((a, b) => Date.parse(a.value) - Date.parse(b.value));\n for (const { value, slot } of sorted) {\n if (!slot) {\n continue;\n }\n const day = days.get(slot.day) ?? { label: slotDayText(value, lang), times: [] };\n day.times.push({ value, time: slot.time });\n days.set(slot.day, day);\n }\n return [...days.values()];\n}\n\n/**\n * One appointment time from those offered: a small heading per day, the times under it as\n * chips. The chips are one group of radio buttons — the arrow keys move between the times shown.\n */\nfunction SlotField({\n name,\n label,\n options,\n value,\n onChange,\n disabled,\n}: {\n name: string;\n label: string;\n options: string[];\n value: string;\n onChange: (v: string) => void;\n disabled: Set<string>;\n}) {\n const days = slotDays(options);\n const chosenDay = days.findIndex((d) => d.times.some((tm) => tm.value === value));\n const [all, setAll] = useState(chosenDay >= SLOT_DAYS);\n if (!days.length) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"slot.none\")}</p>;\n }\n const shown = all ? days : days.slice(0, SLOT_DAYS);\n return (\n <div className=\"flex flex-col gap-4\">\n <fieldset className=\"flex min-w-0 flex-col gap-4\">\n <legend className=\"sr-only\">{label}</legend>\n {shown.map((day) => (\n <div key={day.label}>\n <div className=\"mb-2 font-medium text-[0.75rem] text-ink-3\">{day.label}</div>\n <div className=\"flex flex-wrap gap-2\">\n {day.times.map((tm) => (\n <label key={tm.value} className=\"relative\">\n <input\n type=\"radio\"\n name={`slot-${name}`}\n value={tm.value}\n checked={tm.value === value}\n disabled={disabled.has(tm.value)}\n aria-label={`${day.label}, ${tm.time}`}\n onChange={() => onChange(tm.value)}\n className=\"peer sr-only\"\n />\n <span\n className={cn(\n \"inline-flex h-10 cursor-pointer items-center rounded-full border px-4 text-sm tabular-nums transition coarse:h-11\",\n \"border-input bg-card text-ink-2 hover:border-ink-4 hover:text-ink\",\n \"peer-checked:border-ember peer-checked:bg-ember-tint peer-checked:text-ink\",\n \"peer-disabled:pointer-events-none peer-disabled:line-through peer-disabled:opacity-60\",\n \"peer-focus-visible:outline-[1.5px] peer-focus-visible:outline-offset-2 peer-focus-visible:outline-(--focus-line) peer-focus-visible:outline-solid\",\n )}\n >\n {tm.time}\n </span>\n </label>\n ))}\n </div>\n </div>\n ))}\n </fieldset>\n {days.length > shown.length ? (\n <button\n type=\"button\"\n onClick={() => setAll(true)}\n className=\"self-start text-[0.8125rem] text-ink-3 underline-offset-4 transition hover:text-ink hover:underline coarse:min-h-11\"\n >\n {t(\"slot.later\")}\n </button>\n ) : null}\n </div>\n );\n}\n\n/**\n * Choices drawn as cards: a picture, the title, a line under it, a price, and a page to open.\n * One or several of them, as the field is a select or a multiselect.\n */\nfunction CardChoice({\n cards,\n value,\n multi,\n runId,\n onChange,\n disabled,\n}: {\n cards: CardOption[];\n value: unknown;\n multi: boolean;\n runId: string;\n onChange: (v: unknown) => void;\n disabled: Set<string>;\n}) {\n const picked = new Set<string>(\n multi\n ? Array.isArray(value)\n ? value.map(String)\n : []\n : value === undefined || value === null || value === \"\"\n ? []\n : [String(value)],\n );\n const toggle = (v: string) => {\n if (multi) {\n onChange(picked.has(v) ? [...picked].filter((x) => x !== v) : [...picked, v]);\n } else {\n onChange(picked.has(v) ? \"\" : v);\n }\n };\n const image = (src: string) =>\n /^(https?:|data:|\\/)/.test(src) ? src : withBase(`/api/runs/${runId}/assets/${src}`);\n return (\n <div\n className=\"grid gap-3\"\n style={{ gridTemplateColumns: \"repeat(auto-fill, minmax(min(100%, 10.5rem), 1fr))\" }}\n >\n {cards.map((c) => {\n const on = picked.has(c.value);\n const shut = disabled.has(c.value);\n return (\n <div\n key={c.value}\n className={cn(\n \"flex flex-col overflow-hidden rounded-xl bg-card ring-1 ring-border-soft transition\",\n on && \"ring-2 ring-ember\",\n shut && \"opacity-50\",\n )}\n >\n {c.image ? (\n <img src={image(c.image)} alt=\"\" className=\"aspect-square w-full object-cover\" />\n ) : null}\n <div className=\"flex flex-1 flex-col gap-1 p-3\">\n <div className=\"font-medium text-[0.9375rem] leading-snug\">{c.label}</div>\n {c.subtitle ? (\n <div className=\"text-[0.8125rem] text-ink-3 leading-snug\">{c.subtitle}</div>\n ) : null}\n {c.meta ? (\n <div className=\"mt-auto pt-1 font-display font-semibold text-[0.9375rem] tabular-nums\">\n {c.meta}\n </div>\n ) : null}\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n <button\n type=\"button\"\n aria-pressed={on}\n disabled={shut}\n onClick={() => toggle(c.value)}\n className={cn(\n \"inline-flex h-9 flex-1 items-center justify-center rounded-full px-3 text-[0.8125rem] transition coarse:h-11\",\n on ? \"bg-ember text-ember-on\" : \"bg-paper-2 text-ink-2 hover:text-ink\",\n )}\n >\n {on ? t(\"cards.picked\") : t(\"cards.pick\")}\n </button>\n {c.link ? (\n <a\n href={c.link}\n target=\"_blank\"\n rel=\"noopener\"\n className=\"inline-flex h-9 items-center rounded-full px-3 text-[0.8125rem] text-ink-2 ring-1 ring-border-soft hover:text-ink coarse:h-11\"\n >\n {t(\"cards.open\")}\n </a>\n ) : null}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport function FieldInput({\n field,\n value,\n values,\n runId,\n view,\n onChange,\n onBusy,\n error,\n closed,\n}: {\n field: Field;\n value: unknown;\n values: Values;\n runId: string;\n /** Answers that lead to a step this app has no model for: shown, not to be picked. */\n closed?: ClosedChoice;\n /** The run as the server sees it: connections, stored lists and card choices come from there. */\n view?: Pick<RunView, \"connections\" | \"lists\" | \"cards\">;\n onChange: (v: unknown) => void;\n /** The field is uploading or recording: the page waits with going on. */\n onBusy?: (busy: boolean) => void;\n error?: string;\n}) {\n const str = value === undefined || value === null ? \"\" : String(value);\n const shut = new Set(closed?.values.map(String));\n let control: React.ReactNode;\n switch (field.kind) {\n case \"textarea\":\n control = (\n <Textarea\n value={str}\n placeholder={field.placeholder}\n autoCapitalize=\"sentences\"\n enterKeyHint=\"enter\"\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"number\":\n control = (\n <Input\n inputMode=\"decimal\"\n autoComplete=\"off\"\n value={str}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"select\": {\n const options = field.options ?? [];\n const cards = view?.cards?.[field.id];\n control = cards?.length ? (\n <CardChoice\n cards={cards}\n value={value}\n multi={false}\n runId={runId}\n onChange={onChange}\n disabled={shut}\n />\n ) : options.length <= 5 && options.every((o) => o.length <= 28) ? (\n <Segmented\n value={str}\n options={options}\n onChange={onChange}\n disabled={[...shut]}\n label={choiceLabel}\n />\n ) : (\n <Select\n value={str}\n placeholder=\"—\"\n onChange={onChange}\n options={options.map((o) => ({ value: o, label: choiceLabel(o), disabled: shut.has(o) }))}\n />\n );\n break;\n }\n case \"slot\":\n control = (\n <SlotField\n name={field.id}\n label={field.label}\n options={field.options ?? []}\n value={str}\n onChange={onChange}\n disabled={shut}\n />\n );\n break;\n case \"multiselect\": {\n const cards = view?.cards?.[field.id];\n control = cards?.length ? (\n <CardChoice\n cards={cards}\n value={value}\n multi\n runId={runId}\n onChange={onChange}\n disabled={shut}\n />\n ) : (\n <Segmented\n multi\n value={Array.isArray(value) ? (value as string[]) : []}\n options={field.options ?? []}\n onChange={onChange}\n label={choiceLabel}\n />\n );\n break;\n }\n case \"date\":\n control = (\n <Input\n type=\"date\"\n value={str}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-full sm:w-56\"\n />\n );\n break;\n case \"email\":\n control = (\n <Input\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={str}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"url\":\n control = (\n <Input\n type=\"url\"\n inputMode=\"url\"\n autoComplete=\"url\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={str}\n placeholder={field.placeholder ?? \"https://\"}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"toggle\":\n control = (\n <Switch\n checked={value === true}\n onChange={onChange}\n label={field.label}\n disabled={shut.has(String(value !== true))}\n />\n );\n break;\n case \"color\":\n control = (\n <div className=\"flex items-center gap-3\">\n <Swatch value={str || \"#e0531b\"} onChange={(e) => onChange(e.target.value)} />\n <Input\n value={str}\n placeholder=\"#e0531b\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-36\"\n />\n </div>\n );\n break;\n case \"image\":\n case \"file\":\n control = (\n <UploadField\n field={field}\n value={value}\n runId={runId}\n onChange={onChange}\n onBusy={onBusy}\n />\n );\n break;\n case \"items\":\n control = <ItemsField field={field} value={value} values={values} onChange={onChange} />;\n break;\n case \"connection\":\n control = (\n <ConnectionField\n runId={runId}\n connection={view?.connections.find((c) => c.id === field.connection)}\n />\n );\n break;\n case \"list\": {\n const list = view?.lists.find((l) => l.def.id === field.list);\n control = list ? <ListTable runId={runId} list={list} editable /> : null;\n break;\n }\n case \"location\":\n control = (\n <LocationField\n value={value}\n runId={runId}\n placeholder={field.placeholder}\n onChange={onChange}\n onBusy={onBusy}\n />\n );\n break;\n case \"audio\":\n // Nothing here can listen to it: the reason below stands in for the recorder.\n control = closed ? null : (\n <VoiceField value={value} runId={runId} onChange={onChange} onBusy={onBusy} />\n );\n break;\n case \"signature\":\n control = (\n <SignatureField label={field.label} value={value} runId={runId} onChange={onChange} />\n );\n break;\n default:\n control = field.scan ? (\n <ScanInput field={field} value={str} onChange={onChange} />\n ) : (\n <Input\n {...textHints(field)}\n value={str}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n }\n return (\n <div>\n {field.kind === \"toggle\" ? (\n <div className=\"flex items-start justify-between gap-6\">\n <Label hint={field.help}>{field.label}</Label>\n {control}\n </div>\n ) : (\n <>\n <Label hint={field.help} required={field.required}>\n {field.label}\n </Label>\n {control}\n </>\n )}\n {closed ? (\n <div className=\"mt-1.5 text-[0.8125rem] text-ink-3\">\n {t(\"run.closed\", {\n list: closed.classes.map((c) => t(`run.cls.${groupOf(c)}`)).join(\", \"),\n })}\n </div>\n ) : null}\n {error ? <div className=\"mt-1.5 text-[0.8125rem] text-rose\">{error}</div> : null}\n </div>\n );\n}\n\n/**\n * What a model class is called where a person reads that it is missing. A standalone site\n * names its groups directly, \"account\" among them: what only an engenty account would do.\n */\ntype ClassGroup = \"text\" | \"image\" | \"video\" | \"speech\" | \"audio\" | \"account\";\n\nfunction groupOf(cls: string): ClassGroup {\n if (cls in CLASS_GROUP) {\n return CLASS_GROUP[cls as ModelClass];\n }\n return cls === \"account\" ? \"account\" : \"text\";\n}\n\nconst CLASS_GROUP: Record<ModelClass, Exclude<ClassGroup, \"account\">> = {\n classifier: \"text\",\n standard: \"text\",\n high: \"text\",\n highest: \"text\",\n image: \"image\",\n video: \"video\",\n speech: \"speech\",\n audio: \"audio\",\n};\n","import { type AgentStep, stepShape } from \"@engenty/wizards-shared/definition\";\nimport {\n type FieldShape,\n type ListShape,\n labelOf,\n type ObjectShape,\n titleKey,\n} from \"@engenty/wizards-shared/shape\";\nimport { lang, t } from \"./i18n.js\";\nimport { cn } from \"./ui.js\";\n\n/**\n * A json result without a view of its own, drawn from the step's shape: things as cards (title,\n * a line about it, its short values), words as chips, ordered text as numbered lines, a yes/no\n * in its own words. A table only where entries are figures to compare across columns.\n */\n\ntype Entry = Record<string, unknown>;\ntype Of = ListShape[\"of\"];\n\nconst text = (v: unknown): string =>\n v === null || v === undefined ? \"\" : typeof v === \"object\" ? JSON.stringify(v) : String(v);\n\nconst sectionLabel = \"mb-1.5 font-medium text-[0.75rem] text-ink-3 uppercase tracking-[0.06em]\";\n\n/** The shape of an entry: declared, or read from the entries themselves (a table without one). */\nfunction entryShape(of: Of | undefined, rows: Entry[]): ObjectShape {\n if (of?.kind === \"object\") {\n return of;\n }\n const keys = [...new Set(rows.flatMap((r) => Object.keys(r ?? {})))];\n return {\n kind: \"object\",\n fields: Object.fromEntries(\n keys.map((k) => {\n const values = rows.map((r) => r?.[k]).filter((v) => v !== null && v !== undefined);\n const kind = values.every((v) => typeof v === \"number\")\n ? (\"number\" as const)\n : values.every((v) => typeof v === \"boolean\")\n ? (\"yesno\" as const)\n : (\"text\" as const);\n const long = kind === \"text\" && values.some((v) => String(v).length > 80);\n return [k, kind === \"text\" ? { kind, long } : { kind }];\n }),\n ),\n };\n}\n\n/** Entries that are figures: at least three numbers and more numbers than words. */\nfunction figures(shape: ObjectShape): boolean {\n const fields = Object.values(shape.fields);\n const numbers = fields.filter((f) => f.kind === \"number\").length;\n return numbers >= 3 && numbers > fields.length / 2;\n}\n\nfunction leafText(f: FieldShape | Of, v: unknown, root: Entry): string {\n if (v === null || v === undefined || v === \"\") {\n return \"\";\n }\n switch (f.kind) {\n case \"number\":\n return `${typeof v === \"number\" ? v.toLocaleString(lang) : text(v)}${f.unit ? ` ${f.unit}` : \"\"}`;\n case \"yesno\":\n return v ? (f.yes ?? t(\"run.yes\")) : (f.no ?? t(\"run.no\"));\n case \"ref\": {\n const list = root[f.to];\n const hit = Array.isArray(list)\n ? (list as Entry[]).find((e) => e && text(e.id) === text(v))\n : undefined;\n return hit ? text(hit.title ?? hit.name ?? hit.label ?? v) : text(v);\n }\n default:\n return text(v);\n }\n}\n\nfunction Chips({ items }: { items: string[] }) {\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {items.map((x, i) => (\n <span\n key={i}\n className=\"rounded-full bg-card px-2.5 py-0.5 text-[0.8125rem] text-ink-2 ring-1 ring-border-soft\"\n >\n {x}\n </span>\n ))}\n </div>\n );\n}\n\n/** A list of values: short ones as chips, sentences as a list. */\nfunction Leaves({ of, values, root }: { of: Of; values: unknown[]; root: Entry }) {\n const items = values.map((v) => leafText(of, v, root)).filter(Boolean);\n return items.every((x) => x.length <= 32) ? (\n <Chips items={items} />\n ) : (\n <ul className=\"flex list-disc flex-col gap-1 pl-5 text-[0.9375rem]\">\n {items.map((x, i) => (\n <li key={i} className=\"break-words\">\n {x}\n </li>\n ))}\n </ul>\n );\n}\n\nfunction FigureTable({ shape, rows, root }: { shape: ObjectShape; rows: Entry[]; root: Entry }) {\n const cols = Object.entries(shape.fields);\n return (\n <div className=\"overflow-x-auto rounded-lg ring-1 ring-border-soft\">\n <table className=\"w-full text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {cols.map(([k, f]) => (\n <th\n key={k}\n className={cn(\n \"whitespace-nowrap px-3 py-2 text-left font-medium\",\n f.kind === \"number\" && \"text-right\",\n )}\n >\n {labelOf(k, f)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((r, i) => (\n <tr key={i} className=\"border-border-soft border-t\">\n {cols.map(([k, f]) => (\n <td\n key={k}\n className={cn(\"px-3 py-2 tabular-nums\", f.kind === \"number\" && \"text-right\")}\n >\n {leafText(f, r?.[k], root)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/** Nested entries inside a card: numbered lines when they are text, else their titles. */\nfunction Nested({ shape, rows, root }: { shape: ObjectShape; rows: Entry[]; root: Entry }) {\n const fields = Object.entries(shape.fields);\n const main = fields.find(([, f]) => f.kind === \"text\" && f.long)?.[0] ?? titleKey(shape);\n const rest = fields.filter(([k, f]) => k !== main && k !== \"id\" && f.kind !== \"list\");\n const ordered = Boolean(fields.find(([, f]) => f.kind === \"text\" && f.long));\n const List = ordered ? \"ol\" : \"ul\";\n return (\n <List className=\"flex flex-col gap-1.5 text-[0.875rem]\">\n {rows.map((r, i) => {\n // The first value reads as the line, the rest beside it, quieter.\n const parts = [\n main ? text(r?.[main]) : \"\",\n ...rest.map(([k, f]) => leafText(f, r?.[k], root)),\n ].filter(Boolean);\n return (\n <li key={i} className={cn(ordered && \"grid grid-cols-[1.25rem_1fr] gap-1.5\")}>\n {ordered ? (\n <span className=\"font-semibold text-ember tabular-nums\">{i + 1}</span>\n ) : null}\n <span>\n {parts[0]}\n {parts.length > 1 ? (\n <span className=\"text-ink-3\"> · {parts.slice(1).join(\" · \")}</span>\n ) : null}\n </span>\n </li>\n );\n })}\n </List>\n );\n}\n\n/**\n * Yes/no values as tags: a yes in its own words or the field's label (\"Bald verbrauchen\"), a no\n * only where it has words of its own (\"einkaufen\") — a plain no is no news.\n */\nfunction Flags({ fields, entry }: { fields: [string, FieldShape][]; entry: Entry }) {\n const tags = fields.flatMap(([k, f]) => {\n if (f.kind !== \"yesno\" || entry[k] === undefined || entry[k] === null) {\n return [];\n }\n const words = entry[k] ? (f.yes ?? labelOf(k, f)) : f.no;\n return words ? [{ k, words, on: Boolean(entry[k]) }] : [];\n });\n return tags.length ? (\n <span className=\"flex shrink-0 flex-wrap justify-end gap-1\">\n {tags.map((tag) => (\n <span\n key={tag.k}\n className={cn(\n \"rounded-full px-2 py-0.5 text-[0.75rem]\",\n tag.on ? \"bg-second-tint text-second\" : \"bg-ember-tint text-ember-strong\",\n )}\n >\n {tag.words}\n </span>\n ))}\n </span>\n ) : null;\n}\n\n/** Small entries (no long text, no lists): one row each, in one card. */\nfunction EntryRows({ shape, rows, root }: { shape: ObjectShape; rows: Entry[]; root: Entry }) {\n const fields = Object.entries(shape.fields).filter(([k]) => k !== \"id\");\n const title = titleKey(shape);\n const flags = fields.filter(([, f]) => f.kind === \"yesno\");\n const metas = fields.filter(([k, f]) => k !== title && f.kind !== \"yesno\");\n return (\n <div className=\"divide-y divide-border-soft overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n {rows.map((r, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-2.5\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-[0.9375rem]\">{title ? text(r?.[title]) : \"\"}</div>\n <div className=\"text-[0.8125rem] text-ink-3\">\n {metas\n .map(([k, f]) => leafText(f, r?.[k], root))\n .filter(Boolean)\n .join(\" · \")}\n </div>\n </div>\n <Flags fields={flags} entry={r ?? {}} />\n </div>\n ))}\n </div>\n );\n}\n\nfunction EntryCard({ shape, entry, root }: { shape: ObjectShape; entry: Entry; root: Entry }) {\n const fields = Object.entries(shape.fields).filter(([k]) => k !== \"id\");\n const title = titleKey(shape);\n const about = fields.find(([, f]) => f.kind === \"text\" && f.long);\n const metas = fields.filter(\n ([k, f]) =>\n k !== title &&\n k !== about?.[0] &&\n (f.kind === \"number\" ||\n f.kind === \"choice\" ||\n f.kind === \"score\" ||\n f.kind === \"ref\" ||\n (f.kind === \"text\" && !f.long)),\n );\n const flags = fields.filter(([, f]) => f.kind === \"yesno\");\n const longs = fields.filter(([k, f]) => f.kind === \"text\" && f.long && k !== about?.[0]);\n const lists = fields.filter(([, f]) => f.kind === \"list\" || f.kind === \"table\");\n return (\n <article className=\"flex flex-col gap-2 rounded-xl bg-card p-4 ring-1 ring-border-soft\">\n <div className=\"flex items-start justify-between gap-3\">\n <h4 className=\"text-balance font-display font-semibold text-[1.0625rem] leading-snug\">\n {title ? text(entry[title]) : \"\"}\n </h4>\n <Flags fields={flags} entry={entry} />\n </div>\n {about ? (\n <p className=\"text-[0.875rem] text-ink-3 leading-relaxed\">{text(entry[about[0]])}</p>\n ) : null}\n {metas.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {metas\n .map(([k, f]) => leafText(f, entry[k], root))\n .filter(Boolean)\n .map((m, i) => (\n <span\n key={i}\n className=\"rounded-full bg-paper-2 px-2 py-0.5 text-[0.75rem] text-ink-2\"\n >\n {m}\n </span>\n ))}\n </div>\n ) : null}\n {longs.map(([k, f]) =>\n entry[k] ? (\n <p key={k} className=\"text-[0.875rem] leading-relaxed\">\n <span className=\"text-ink-3\">{labelOf(k, f)}: </span>\n {text(entry[k])}\n </p>\n ) : null,\n )}\n {lists.map(([k, f]) => {\n const v = entry[k];\n if (!Array.isArray(v) || !v.length) {\n return null;\n }\n return (\n <div key={k} className=\"border-border-soft border-t pt-2\">\n <div className={sectionLabel}>{labelOf(k, f)}</div>\n {f.kind === \"list\" && f.of.kind !== \"object\" ? (\n <Leaves of={f.of} values={v} root={root} />\n ) : (\n <Nested\n shape={entryShape(f.kind === \"list\" ? f.of : undefined, v as Entry[])}\n rows={v as Entry[]}\n root={root}\n />\n )}\n </div>\n );\n })}\n </article>\n );\n}\n\nfunction Entries({ of, rows, root }: { of: Of | undefined; rows: Entry[]; root: Entry }) {\n const shape = entryShape(of, rows);\n if (figures(shape)) {\n return <FigureTable shape={shape} rows={rows} root={root} />;\n }\n const rich = Object.values(shape.fields).some(\n (f) => f.kind === \"list\" || f.kind === \"table\" || (f.kind === \"text\" && f.long),\n );\n if (!rich) {\n return <EntryRows shape={shape} rows={rows} root={root} />;\n }\n return (\n <div className=\"grid grid-cols-[repeat(auto-fill,minmax(min(100%,16rem),1fr))] gap-3\">\n {rows.map((r, i) => (\n <EntryCard key={i} shape={shape} entry={r ?? {}} root={root} />\n ))}\n </div>\n );\n}\n\nexport function JsonView({ step, json }: { step: AgentStep; json: unknown }) {\n if (!json || typeof json !== \"object\" || Array.isArray(json)) {\n return <pre className=\"text-[0.8125rem]\">{JSON.stringify(json, null, 2)}</pre>;\n }\n const root = json as Entry;\n const shape = stepShape(step);\n return (\n <div className=\"flex flex-col gap-5\">\n {Object.entries(root).map(([key, v]) => {\n const f = shape.fields[key];\n const title = f ? labelOf(key, f) : key;\n let body: React.ReactNode;\n if (Array.isArray(v) && v.length && v.every((x) => x && typeof x === \"object\")) {\n body = (\n <Entries of={f?.kind === \"list\" ? f.of : undefined} rows={v as Entry[]} root={root} />\n );\n } else if (Array.isArray(v)) {\n body = (\n <Leaves of={f?.kind === \"list\" ? f.of : { kind: \"text\" }} values={v} root={root} />\n );\n } else if (v && typeof v === \"object\") {\n body = (\n <pre className=\"overflow-auto rounded-lg bg-paper-2 p-3 text-[0.75rem]\">\n {JSON.stringify(v, null, 2)}\n </pre>\n );\n } else {\n const leaf = f && f.kind !== \"list\" && f.kind !== \"table\" ? f : { kind: \"text\" as const };\n body = (\n <div className=\"whitespace-pre-wrap text-[0.9375rem] leading-relaxed\">\n {leafText(leaf, v, root)}\n </div>\n );\n }\n return (\n <section key={key}>\n <div className={sectionLabel}>{title}</div>\n {body}\n </section>\n );\n })}\n </div>\n );\n}\n","import { marked, type Token, type Tokens } from \"marked\";\nimport type { Content, TableCell, TDocumentDefinitions } from \"pdfmake/interfaces\";\nimport { t } from \"./i18n.js\";\n\n/**\n * A written output as a PDF, made in the browser. A host whose server writes no PDF (the\n * WordPress plugin: PHP, no Chromium) still hands the visitor the file the result step\n * promised: pdfmake lays it out from a content tree — a Markdown text through marked's tokens,\n * a structured output as the result page shows it (label, value, list, table) — with Roboto\n * bundled, so German, Czech or Polish read as written. The library and its fonts weigh about\n * 1.5 MB and are loaded on the first click only; the content tree itself is small and pure.\n */\n\nexport interface Written {\n /** The step's title: the document's heading and the file's name. */\n title: string;\n /** A Markdown or plain text. */\n text?: string;\n /** A structured output; its keys are named by `label`. */\n json?: unknown;\n /** What a key of the structured output is called (the step's output fields). */\n label?: (key: string) => string;\n /** The line at the foot of every page: the wizard, the date. */\n foot?: string;\n}\n\n/** A run of text with its look, as pdfmake takes it. */\ninterface Run {\n text: string;\n bold?: boolean;\n italics?: boolean;\n link?: string;\n color?: string;\n decoration?: \"underline\" | \"lineThrough\";\n}\n\nconst INK = \"#282623\";\nconst INK_3 = \"#81807e\";\nconst LINK = \"#1a5fb4\";\nconst LINE = \"#dbd9d6\";\n/** A4 less the margins: what a rule spans. */\nconst TEXT_WIDTH = 595.28 - 2 * 56;\n\nconst ENTITIES: Record<string, string> = {\n amp: \"&\",\n lt: \"<\",\n gt: \">\",\n quot: '\"',\n apos: \"'\",\n \"#39\": \"'\",\n nbsp: \" \",\n};\n\n/** marked keeps some text escaped for HTML; a PDF wants the characters. */\nfunction plain(text: string): string {\n return text.replace(/&(#x[0-9a-f]+|#\\d+|[a-z]+\\d*);/gi, (all, name: string) => {\n if (name[0] === \"#\") {\n const code =\n name[1]?.toLowerCase() === \"x\" ? Number.parseInt(name.slice(2), 16) : Number(name.slice(1));\n return Number.isFinite(code) ? String.fromCodePoint(code) : all;\n }\n return ENTITIES[name.toLowerCase()] ?? all;\n });\n}\n\n/** Tags out of a raw HTML token: its text is what a PDF can hold. */\nfunction untagged(html: string): string {\n return plain(html.replace(/<[^>]+>/g, \"\")).trim();\n}\n\n/** Inline tokens as runs: bold, italics, code, links and line breaks kept; images as their text. */\nfunction runs(tokens: Token[] | undefined, look: Omit<Run, \"text\"> = {}): Run[] {\n const out: Run[] = [];\n for (const token of tokens ?? []) {\n switch (token.type) {\n case \"text\": {\n const inner = (token as Tokens.Text).tokens;\n if (inner?.length) {\n out.push(...runs(inner, look));\n } else {\n out.push({ ...look, text: plain(token.text) });\n }\n break;\n }\n case \"escape\":\n out.push({ ...look, text: plain(token.text) });\n break;\n case \"strong\":\n out.push(...runs((token as Tokens.Strong).tokens, { ...look, bold: true }));\n break;\n case \"em\":\n out.push(...runs((token as Tokens.Em).tokens, { ...look, italics: true }));\n break;\n case \"del\":\n out.push(...runs((token as Tokens.Del).tokens, { ...look, decoration: \"lineThrough\" }));\n break;\n case \"codespan\":\n out.push({ ...look, text: plain(token.text), color: \"#3d3b38\" });\n break;\n case \"link\": {\n const link = token as Tokens.Link;\n out.push(\n ...runs(link.tokens, { ...look, link: link.href, color: LINK, decoration: \"underline\" }),\n );\n break;\n }\n case \"image\":\n out.push({ ...look, text: (token as Tokens.Image).text });\n break;\n case \"br\":\n out.push({ ...look, text: \"\\n\" });\n break;\n case \"html\":\n out.push({ ...look, text: untagged(token.text) });\n break;\n default:\n if (\"tokens\" in token && Array.isArray(token.tokens)) {\n out.push(...runs(token.tokens, look));\n } else if (\"text\" in token && typeof token.text === \"string\") {\n out.push({ ...look, text: plain(token.text) });\n }\n }\n }\n return out;\n}\n\n/** A list item: its own text without a paragraph's space under it, a nested list below. */\nfunction item(tokens: Token[]): Content {\n const parts = blocks(tokens);\n if (parts.length === 1 && typeof parts[0] === \"object\" && \"style\" in parts[0]) {\n const { style: _, ...rest } = parts[0];\n return rest as Content;\n }\n return parts.length === 1 ? parts[0] : { stack: parts };\n}\n\nfunction cell(c: Tokens.TableCell, header: boolean): TableCell {\n return {\n text: runs(c.tokens),\n alignment: c.align ?? \"left\",\n ...(header ? { style: \"th\" } : {}),\n };\n}\n\n/** Thin rules between the rows, nothing between the columns. */\nconst TABLE_LAYOUT = {\n hLineWidth: () => 0.5,\n vLineWidth: () => 0,\n hLineColor: () => LINE,\n paddingTop: () => 4,\n paddingBottom: () => 4,\n};\n\n/** Block tokens as pdfmake content. */\nfunction blocks(tokens: Token[]): Content[] {\n const out: Content[] = [];\n for (const token of tokens) {\n switch (token.type) {\n case \"space\":\n break;\n case \"heading\": {\n const depth = (token as Tokens.Heading).depth;\n out.push({\n text: runs((token as Tokens.Heading).tokens),\n style: depth <= 1 ? \"h1\" : depth === 2 ? \"h2\" : \"h3\",\n });\n break;\n }\n case \"paragraph\":\n out.push({ text: runs((token as Tokens.Paragraph).tokens), style: \"p\" });\n break;\n case \"text\":\n out.push({ text: runs([token]), style: \"p\" });\n break;\n case \"list\": {\n const list = token as Tokens.List;\n const items = list.items.map((i) => item(i.tokens));\n out.push(\n list.ordered\n ? { ol: items, style: \"list\", start: Number(list.start) || 1 }\n : { ul: items, style: \"list\" },\n );\n break;\n }\n case \"table\": {\n const table = token as Tokens.Table;\n if (!table.header.length) {\n break;\n }\n out.push({\n table: {\n headerRows: 1,\n widths: table.header.map(() => \"*\"),\n body: [\n table.header.map((c) => cell(c, true)),\n ...table.rows.map((row) => row.map((c) => cell(c, false))),\n ],\n },\n layout: TABLE_LAYOUT,\n style: \"table\",\n });\n break;\n }\n case \"code\":\n out.push({ text: plain(token.text), style: \"code\", preserveLeadingSpaces: true });\n break;\n case \"blockquote\":\n out.push({ stack: blocks((token as Tokens.Blockquote).tokens), style: \"quote\" });\n break;\n case \"hr\":\n out.push({\n canvas: [\n { type: \"line\", x1: 0, y1: 0, x2: TEXT_WIDTH, y2: 0, lineWidth: 0.5, lineColor: LINE },\n ],\n margin: [0, 6, 0, 12],\n });\n break;\n case \"html\": {\n const text = untagged(token.text);\n if (text) {\n out.push({ text, style: \"p\" });\n }\n break;\n }\n default:\n if (\"tokens\" in token && Array.isArray(token.tokens)) {\n out.push({ text: runs(token.tokens), style: \"p\" });\n } else if (\"text\" in token && typeof token.text === \"string\") {\n out.push({ text: plain(token.text), style: \"p\" });\n }\n }\n }\n return out;\n}\n\n/** A Markdown text as content. */\nexport function markdownContent(text: string): Content[] {\n return blocks(marked.lexer(text));\n}\n\n/** A structured output as the result page shows it: each key with its label, then its value. */\nexport function jsonContent(json: unknown, label: (key: string) => string = (k) => k): Content[] {\n if (!json || typeof json !== \"object\") {\n return [{ text: JSON.stringify(json, null, 2) ?? \"\", style: \"code\" }];\n }\n const out: Content[] = [];\n for (const [key, v] of Object.entries(json as Record<string, unknown>)) {\n out.push({ text: label(key), style: \"label\" });\n if (typeof v === \"boolean\") {\n out.push({ text: t(v ? \"run.yes\" : \"run.no\"), style: \"p\" });\n } else if (typeof v === \"string\" || typeof v === \"number\") {\n out.push({ text: String(v), style: \"p\" });\n } else if (Array.isArray(v) && v.every((x) => typeof x !== \"object\")) {\n out.push({ ul: v.map((x) => String(x)), style: \"list\" });\n } else if (Array.isArray(v) && v.length && typeof v[0] === \"object\") {\n const rows = v as Record<string, unknown>[];\n const cols = [...new Set(rows.flatMap((r) => Object.keys(r)))];\n out.push({\n table: {\n headerRows: 1,\n widths: cols.map(() => \"*\"),\n body: [\n cols.map((c): TableCell => ({ text: c, style: \"th\" })),\n ...rows.map((r) =>\n cols.map(\n (c): TableCell => ({\n text: r[c] === null || r[c] === undefined ? \"\" : String(r[c]),\n }),\n ),\n ),\n ],\n },\n layout: TABLE_LAYOUT,\n style: \"table\",\n });\n } else {\n out.push({ text: JSON.stringify(v, null, 2), style: \"code\" });\n }\n }\n return out;\n}\n\n/** The document: A4, the title first, the body, a foot with the page number. */\nexport function pdfDocument(written: Written): TDocumentDefinitions {\n const body =\n written.json !== undefined && written.json !== null\n ? jsonContent(written.json, written.label)\n : markdownContent(written.text ?? \"\");\n const foot = written.foot ?? \"\";\n return {\n info: { title: written.title },\n pageSize: \"A4\",\n pageMargins: [56, 60, 56, 64],\n defaultStyle: { font: \"Roboto\", fontSize: 10.5, lineHeight: 1.3, color: INK },\n styles: {\n title: { fontSize: 20, bold: true, lineHeight: 1.15, margin: [0, 0, 0, 16] },\n h1: { fontSize: 15, bold: true, margin: [0, 14, 0, 6] },\n h2: { fontSize: 13, bold: true, margin: [0, 12, 0, 5] },\n h3: { fontSize: 11, bold: true, margin: [0, 10, 0, 4] },\n p: { margin: [0, 0, 0, 7] },\n list: { margin: [0, 0, 0, 7] },\n table: { margin: [0, 2, 0, 10] },\n th: { bold: true, fillColor: \"#f3f1ee\" },\n label: { fontSize: 8, bold: true, color: INK_3, characterSpacing: 0.6, margin: [0, 8, 0, 2] },\n code: { fontSize: 9, color: \"#3d3b38\", margin: [0, 0, 0, 8] },\n quote: { italics: true, color: \"#5d5b58\", margin: [14, 0, 0, 8] },\n },\n content: [{ text: written.title, style: \"title\" }, ...body],\n footer: (page, pages) => ({\n columns: [\n { text: foot, color: INK_3, fontSize: 8.5 },\n { text: `${page} / ${pages}`, alignment: \"right\", color: INK_3, fontSize: 8.5 },\n ],\n margin: [56, 26, 56, 0],\n }),\n };\n}\n\n/** pdfmake's browser build as it is loaded: one object with the calls used here. */\ninterface PdfMake {\n addVirtualFileSystem(vfs: Record<string, string>): void;\n addFonts(fonts: Record<string, Record<string, string>>): void;\n createPdf(doc: TDocumentDefinitions): { getBlob(): Promise<Blob> };\n}\n\n/** The fonts in pdfmake's own file: Roboto in four cuts. */\nexport const ROBOTO = {\n Roboto: {\n normal: \"Roboto-Regular.ttf\",\n bold: \"Roboto-Medium.ttf\",\n italics: \"Roboto-Italic.ttf\",\n bolditalics: \"Roboto-MediumItalic.ttf\",\n },\n};\n\nlet loading: Promise<PdfMake> | null = null;\n\n/** The library with Roboto, fetched once. */\nfunction pdfMake(): Promise<PdfMake> {\n loading ??= Promise.all([\n import(\"pdfmake/build/pdfmake\") as Promise<{ default: PdfMake }>,\n import(\"pdfmake/build/vfs_fonts\") as Promise<{ default: Record<string, string> }>,\n ])\n .then(([lib, fonts]) => {\n const pdf = lib.default;\n pdf.addVirtualFileSystem(fonts.default);\n pdf.addFonts(ROBOTO);\n return pdf;\n })\n .catch((err) => {\n loading = null;\n throw err;\n });\n return loading;\n}\n\n/** A title as a file name: what no file system refuses. */\nexport function fileName(title: string): string {\n return (\n title\n .replace(/[\\\\/:*?\"<>|]+|\\p{Cc}+/gu, \"-\")\n .replace(/\\s+/g, \" \")\n .trim() || \"result\"\n );\n}\n\n/** The written output as a PDF file. */\nexport async function writePdf(written: Written): Promise<File> {\n const pdf = await pdfMake();\n const blob = await pdf.createPdf(pdfDocument(written)).getBlob();\n return new File([blob], `${fileName(written.title)}.pdf`, { type: \"application/pdf\" });\n}\n","import type { Surface, SurfaceComponent } from \"@engenty/wizards-shared/surface\";\nimport { bound } from \"@engenty/wizards-shared/surface\";\nimport { Check, ChevronRight, Clock, Lightbulb, Share2 } from \"lucide-react\";\nimport { type ReactNode, useState } from \"react\";\nimport { lang, t } from \"./i18n.js\";\nimport { cn, Dialog, Tabs as Segments } from \"./ui.js\";\n\n/**\n * A surface drawn with the runner's own components: the catalog in shared/surface.ts, nothing\n * else. Unknown components render nothing; a prop that is not there shows empty.\n */\n\nexport type SurfaceAction = { action: \"regenerate\" | \"open\"; target?: unknown };\n\n/** What the person did in a view that is kept with the run: a checklist's ticks, by component id. */\nexport type SurfaceState = Record<string, unknown>;\n\ninterface Ctx {\n byId: Map<string, SurfaceComponent>;\n data: Record<string, unknown>;\n assetUrl: (id: string) => string;\n onAction?: (a: SurfaceAction) => void;\n state: SurfaceState;\n setState: (id: string, value: unknown) => void;\n /** Opens an entry in a sheet, drawn by `view`. */\n open: (view: string, row: unknown) => void;\n}\n\n// A yes/no without words of its own reads as yes or no, never as true or false.\nconst text = (v: unknown): string =>\n v === null || v === undefined\n ? \"\"\n : typeof v === \"boolean\"\n ? t(v ? \"run.yes\" : \"run.no\")\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v);\n\nconst num = (v: unknown): number => {\n const n = typeof v === \"number\" ? v : Number(String(v ?? \"\").replace(\",\", \".\"));\n return Number.isFinite(n) ? n : 0;\n};\n\n/** A picture: an asset of the run by id, or an address. */\nfunction src(v: unknown, assetUrl: (id: string) => string): string | null {\n const s = text(v);\n if (!s) {\n return null;\n }\n return /^(https?:|data:|\\/)/.test(s) ? s : assetUrl(s);\n}\n\nfunction prop(c: SurfaceComponent, key: string, ctx: Ctx, row?: unknown): unknown {\n return bound((c as Record<string, unknown>)[key], ctx.data, row);\n}\n\n/** Chart points from rows: their `label` and `value`, or the columns a chart names instead. */\nfunction points(\n v: unknown,\n labelKey: unknown,\n valueKey: unknown,\n): { label: string; value: number }[] {\n const l = text(labelKey) || \"label\";\n const k = text(valueKey) || \"value\";\n return Array.isArray(v)\n ? v.map((p) => ({ label: text((p as any)?.[l]), value: num((p as any)?.[k]) }))\n : [];\n}\n\nfunction Children({ c, ctx, row }: { c: SurfaceComponent; ctx: Ctx; row?: unknown }) {\n const kids = c.children;\n if (!kids) {\n return null;\n }\n if (Array.isArray(kids)) {\n return (\n <>\n {kids.map((id) => (\n <Node key={id} id={id} ctx={ctx} row={row} />\n ))}\n </>\n );\n }\n const items = bound({ path: kids.path }, ctx.data, row);\n return (\n <>\n {(Array.isArray(items) ? items : []).map((item, i) => (\n <Node key={i} id={kids.componentId} ctx={ctx} row={item} />\n ))}\n </>\n );\n}\n\nconst TONES: Record<string, string> = {\n success: \"bg-second-tint text-second\",\n warning: \"bg-amber-tint text-ink-2\",\n accent: \"bg-ember-tint text-ember-strong\",\n default: \"bg-paper-2 text-ink-2\",\n};\n\nconst rows = (v: unknown): unknown[] => (Array.isArray(v) ? v : []);\n\n/** A cell of an entry by its key; an entry that is itself a value is its own label. */\nfunction cell(item: unknown, key: string): unknown {\n if (item === null || typeof item !== \"object\") {\n return key === \"\" ? item : undefined;\n }\n return (item as Record<string, unknown>)[key];\n}\n\n/** What an entry is called: its `labelKey`, else the usual keys, else the entry itself. */\nfunction labelOf(item: unknown, key: string): string {\n if (item === null || typeof item !== \"object\") {\n return text(item);\n }\n const r = item as Record<string, unknown>;\n return text(key ? r[key] : (r.label ?? r.name ?? r.title ?? r.text));\n}\n\n/** Entries under a heading per value of a key, in `order` first, the rest as they come. */\nfunction grouped(items: unknown[], by: string, order: string[]): [string, unknown[]][] {\n const groups = new Map<string, unknown[]>();\n for (const item of items) {\n const name = text(cell(item, by));\n groups.set(name, [...(groups.get(name) ?? []), item]);\n }\n const rank = (name: string) => {\n const i = order.indexOf(name);\n return i < 0 ? order.length : i;\n };\n return [...groups.entries()].sort((a, b) => rank(a[0]) - rank(b[0]));\n}\n\nconst minutes = (n: unknown) => (n ? `${text(n)} ${lang === \"de\" ? \"Min\" : \"min\"}` : \"\");\n\nfunction Metas({ items }: { items: string[] }) {\n return items.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {items.map((m, i) => (\n <span key={i} className=\"rounded-full bg-paper-2 px-2 py-0.5 text-[0.75rem] text-ink-2\">\n {m}\n </span>\n ))}\n </div>\n ) : null;\n}\n\n/** `meta`: one value or a list of them, each a literal or a path. */\nfunction metasOf(c: SurfaceComponent, ctx: Ctx, row?: unknown): string[] {\n const raw = (c as Record<string, unknown>).meta;\n return (Array.isArray(raw) ? raw : [raw])\n .map((m) => text(bound(m, ctx.data, row)))\n .filter(Boolean);\n}\n\nfunction TabsView({ c, ctx, row }: { c: SurfaceComponent; ctx: Ctx; row?: unknown }) {\n const [on, setOn] = useState(\"0\");\n const tabs = rows((c as Record<string, unknown>).tabs) as Record<string, unknown>[];\n const options = tabs.map((tab, i) => {\n const count = bound(tab?.count, ctx.data, row);\n const n = Array.isArray(count) ? count.length : count;\n const label = text(bound(tab?.label, ctx.data, row));\n return {\n id: String(i),\n label: n === undefined || n === null || n === \"\" ? label : `${label} (${text(n)})`,\n };\n });\n const child = tabs[Number(on)]?.child;\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"sticky top-2 z-10 max-w-full self-start overflow-x-auto rounded-full\">\n <Segments value={on} onChange={setOn} options={options} />\n </div>\n {typeof child === \"string\" ? <Node id={child} ctx={ctx} row={row} /> : null}\n </div>\n );\n}\n\nfunction ChecklistView({ c, ctx, row }: { c: SurfaceComponent; ctx: Ctx; row?: unknown }) {\n const p = (key: string) => prop(c, key, ctx, row);\n const [copied, setCopied] = useState(false);\n const items = rows(p(\"items\"));\n const labelKey = text(p(\"labelKey\"));\n const detailKey = text(p(\"detailKey\")) || \"amount\";\n const noteKey = text(p(\"noteKey\"));\n const noteFormat = text(p(\"noteFormat\"));\n const groupKey = text(p(\"groupKey\"));\n const order = rows(p(\"groupOrder\")).map(text);\n const ticks = (ctx.state[c.id] ?? {}) as Record<string, boolean>;\n const keyOf = (item: unknown, i: number) => `${i}:${labelOf(item, labelKey)}`;\n const done = items.filter((item, i) => ticks[keyOf(item, i)]).length;\n const indexed = items.map((item, i) => ({ item, i }));\n const groups: [string, { item: unknown; i: number }[]][] = groupKey\n ? grouped(items, groupKey, order).map(([name]) => [\n name,\n indexed.filter(({ item }) => text(cell(item, groupKey)) === name),\n ])\n : [[\"\", indexed]];\n const detailOf = (item: unknown) => text(cell(item, detailKey));\n const noteMap = p(\"noteMap\");\n const noteOf = (item: unknown) => {\n const v = noteKey ? cell(item, noteKey) : undefined;\n // A yes/no says something only in words of its own: \"da\", \"einkaufen\".\n if (typeof v === \"boolean\") {\n const words =\n noteMap && typeof noteMap === \"object\"\n ? (noteMap as Record<string, unknown>)[String(v)]\n : \"\";\n return text(words ?? \"\");\n }\n const words = Array.isArray(v) ? v.map(text).join(\", \") : text(v);\n return words && noteFormat ? noteFormat.replace(\"{}\", words) : words;\n };\n const share = async () => {\n const open = groups\n .map(([name, list]) => {\n const lines = list\n .filter(({ item, i }) => !ticks[keyOf(item, i)])\n .map(\n ({ item }) =>\n `☐ ${labelOf(item, labelKey)}${detailOf(item) ? ` – ${detailOf(item)}` : \"\"}`,\n );\n return lines.length ? [name, ...lines].filter(Boolean).join(\"\\n\") : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n try {\n if (navigator.share) {\n await navigator.share({ text: open });\n } else {\n await navigator.clipboard.writeText(open);\n setCopied(true);\n setTimeout(() => setCopied(false), 1600);\n }\n } catch {\n // Closed without sharing, or the clipboard refused: nothing to do.\n }\n };\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-1.5 flex-1 overflow-hidden rounded-full bg-paper-2\">\n <div\n className=\"h-full rounded-full bg-second transition-[width] duration-300\"\n style={{ width: `${items.length ? (done / items.length) * 100 : 0}%` }}\n />\n </div>\n <span className=\"text-[0.8125rem] text-ink-3 tabular-nums\">\n {done === items.length && items.length\n ? t(\"surface.allDone\")\n : t(\"surface.done\", { done, total: items.length })}\n </span>\n {p(\"share\") === false ? null : (\n <button\n type=\"button\"\n onClick={share}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-10\"\n >\n {copied ? <Check className=\"size-3.5\" /> : <Share2 className=\"size-3.5\" />}\n {copied ? t(\"share.copied\") : t(\"run.share\")}\n </button>\n )}\n </div>\n {groups.map(([name, list]) => (\n <section key={name} className=\"rounded-xl bg-card px-4 py-1 ring-1 ring-border-soft\">\n {name ? (\n <h4 className=\"pt-3 pb-1 font-semibold text-[0.6875rem] text-second uppercase tracking-[0.14em]\">\n {name}\n </h4>\n ) : null}\n {list.map(({ item, i }) => {\n const key = keyOf(item, i);\n const on = Boolean(ticks[key]);\n const note = noteOf(item);\n return (\n <label\n key={key}\n className=\"flex cursor-pointer items-start gap-3 border-border-soft border-b border-dashed py-2.5 last:border-0\"\n >\n <input\n type=\"checkbox\"\n checked={on}\n onChange={() => ctx.setState(c.id, { ...ticks, [key]: !on })}\n className=\"mt-0.5 size-[1.125rem] shrink-0 accent-[var(--second)] coarse:size-6\"\n />\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"text-[0.9375rem]\", on && \"text-ink-3 line-through\")}>\n {labelOf(item, labelKey)}\n {detailOf(item) ? (\n <span className=\"text-ink-3\"> · {detailOf(item)}</span>\n ) : null}\n </span>\n {note ? <span className=\"block text-[0.75rem] text-ink-3\">{note}</span> : null}\n </span>\n </label>\n );\n })}\n </section>\n ))}\n </div>\n );\n}\n\nfunction Bars({ data }: { data: { label: string; value: number }[] }) {\n const max = Math.max(1, ...data.map((d) => d.value));\n return (\n <div className=\"flex flex-col gap-1.5\">\n {data.map((d, i) => (\n <div key={i} className=\"grid grid-cols-[minmax(0,8rem)_1fr_auto] items-center gap-2\">\n <span className=\"truncate text-[0.8125rem] text-ink-2\">{d.label}</span>\n <span className=\"h-2.5 rounded-full bg-paper-2\">\n <span\n className=\"block h-full rounded-full bg-ember\"\n style={{ width: `${(d.value / max) * 100}%` }}\n />\n </span>\n <span className=\"text-[0.8125rem] tabular-nums\">{d.value.toLocaleString(lang)}</span>\n </div>\n ))}\n </div>\n );\n}\n\nfunction Line({ data }: { data: { label: string; value: number }[] }) {\n if (data.length < 2) {\n return <Bars data={data} />;\n }\n const w = 320;\n const h = 120;\n const max = Math.max(...data.map((d) => d.value));\n const min = Math.min(...data.map((d) => d.value));\n const span = max - min || 1;\n const xy = data.map((d, i) => [\n (i / (data.length - 1)) * (w - 8) + 4,\n h - 4 - ((d.value - min) / span) * (h - 8),\n ]);\n return (\n <figure>\n <svg viewBox={`0 0 ${w} ${h}`} className=\"w-full text-ember\" role=\"img\">\n <polyline\n points={xy.map(([x, y]) => `${x},${y}`).join(\" \")}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinejoin=\"round\"\n />\n {xy.map(([x, y], i) => (\n <circle key={i} cx={x} cy={y} r=\"3\" fill=\"currentColor\">\n <title>{`${data[i].label}: ${data[i].value}`}</title>\n </circle>\n ))}\n </svg>\n <figcaption className=\"mt-1 flex justify-between text-[0.75rem] text-ink-3\">\n <span>{data[0].label}</span>\n <span>{data.at(-1)?.label}</span>\n </figcaption>\n </figure>\n );\n}\n\nconst DONUT = [\n \"var(--color-ember)\",\n \"var(--color-cobalt)\",\n \"var(--color-moss)\",\n \"var(--color-amber)\",\n \"var(--color-ink-3)\",\n];\n\nfunction Donut({ data }: { data: { label: string; value: number }[] }) {\n const total = data.reduce((a, d) => a + Math.max(0, d.value), 0) || 1;\n let at = 0;\n const r = 40;\n const length = 2 * Math.PI * r;\n return (\n <div className=\"flex items-center gap-4\">\n <svg viewBox=\"0 0 100 100\" className=\"size-28 shrink-0 -rotate-90\" role=\"img\">\n {data.map((d, i) => {\n const part = (Math.max(0, d.value) / total) * length;\n const el = (\n <circle\n key={i}\n cx=\"50\"\n cy=\"50\"\n r={r}\n fill=\"none\"\n stroke={DONUT[i % DONUT.length]}\n strokeWidth=\"16\"\n strokeDasharray={`${part} ${length - part}`}\n strokeDashoffset={-at}\n >\n <title>{`${d.label}: ${d.value}`}</title>\n </circle>\n );\n at += part;\n return el;\n })}\n </svg>\n <ul className=\"flex flex-col gap-1 text-[0.8125rem]\">\n {data.map((d, i) => (\n <li key={i} className=\"flex items-center gap-2\">\n <span\n className=\"size-2.5 rounded-full\"\n style={{ background: DONUT[i % DONUT.length] }}\n />\n <span className=\"text-ink-2\">{d.label}</span>\n <span className=\"tabular-nums\">{d.value.toLocaleString(lang)}</span>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nfunction Titled({ title, children }: { title: string; children: ReactNode }) {\n return (\n <div className=\"rounded-xl bg-card p-4 ring-1 ring-border-soft\">\n {title ? <div className=\"mb-3 font-medium text-[0.875rem]\">{title}</div> : null}\n {children}\n </div>\n );\n}\n\nfunction Node({ id, ctx, row }: { id: string; ctx: Ctx; row?: unknown }) {\n const c = ctx.byId.get(id);\n if (!c) {\n return null;\n }\n const p = (key: string) => prop(c, key, ctx, row);\n switch (c.component) {\n case \"Column\":\n return (\n <div className=\"flex flex-col gap-4\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n case \"Text\": {\n const variant = text(p(\"variant\")) || \"body\";\n return (\n <p\n className={cn(\n variant === \"h3\" && \"font-display font-semibold text-[1.25rem] leading-tight\",\n variant === \"h4\" && \"font-semibold text-[1rem]\",\n variant === \"lead\" && \"font-display text-[1.0625rem] text-ink-2 leading-relaxed\",\n variant === \"body\" && \"text-[0.9375rem] leading-relaxed\",\n variant === \"muted\" && \"text-[0.8125rem] text-ink-3\",\n )}\n >\n {text(p(\"text\"))}\n </p>\n );\n }\n case \"List\":\n return (\n <div className=\"flex flex-col divide-y divide-border-soft overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n case \"Row\": {\n const image = src(p(\"image\"), ctx.assetUrl);\n const badge = text(p(\"badge\"));\n return (\n <div className=\"flex items-center gap-3 px-4 py-3\">\n {image ? (\n <img src={image} alt=\"\" className=\"size-10 shrink-0 rounded-lg object-cover\" />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[0.9375rem]\">{text(p(\"title\"))}</div>\n {p(\"subtitle\") ? (\n <div className=\"truncate text-[0.8125rem] text-ink-3\">{text(p(\"subtitle\"))}</div>\n ) : null}\n </div>\n {p(\"meta\") ? (\n <span className=\"shrink-0 text-[0.8125rem] text-ink-3 tabular-nums\">\n {text(p(\"meta\"))}\n </span>\n ) : null}\n {badge ? (\n <span\n className={cn(\n \"shrink-0 rounded-full px-2 py-0.5 text-[0.75rem]\",\n TONES[text(p(\"badgeTone\"))] ?? TONES.default,\n )}\n >\n {badge}\n </span>\n ) : null}\n </div>\n );\n }\n case \"DetailGrid\": {\n const rows = p(\"rows\");\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 rounded-xl bg-card p-4 text-[0.875rem] ring-1 ring-border-soft\">\n {(Array.isArray(rows) ? rows : []).map((r, i) => (\n <div key={i} className=\"contents\">\n <dt className=\"text-ink-3\">{text(bound((r as any)?.label, ctx.data, row))}</dt>\n <dd className=\"break-words\">{text(bound((r as any)?.value, ctx.data, row))}</dd>\n </div>\n ))}\n </dl>\n );\n }\n case \"Badge\":\n return (\n <span\n className={cn(\n \"inline-flex w-fit rounded-full px-2.5 py-0.5 text-[0.75rem]\",\n TONES[text(p(\"tone\"))] ?? TONES.default,\n )}\n >\n {text(p(\"label\"))}\n </span>\n );\n case \"Grid\": {\n const columns = Math.min(4, Math.max(1, num(p(\"columns\")) || 2));\n // The narrowest a tile gets: small tiles (figures) sit two to a phone, cards one.\n const min = Math.min(24, Math.max(6, num(p(\"min\")) || (columns > 2 ? 9 : 12)));\n return (\n <div\n className=\"grid gap-3\"\n style={{\n gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${min}rem), 1fr))`,\n }}\n >\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n }\n case \"Metric\":\n return (\n <div className=\"rounded-xl bg-card p-4 ring-1 ring-border-soft\">\n <div className=\"text-[0.75rem] text-ink-3 uppercase tracking-[0.06em]\">\n {text(p(\"label\"))}\n </div>\n <div className=\"mt-1 font-display font-semibold text-[1.5rem] tabular-nums\">\n {text(p(\"value\"))}\n </div>\n {p(\"caption\") ? (\n <div className=\"text-[0.8125rem] text-ink-3\">{text(p(\"caption\"))}</div>\n ) : null}\n </div>\n );\n case \"Table\": {\n const rows = p(\"rows\");\n const list = (Array.isArray(rows) ? rows : []) as Record<string, unknown>[];\n const declared = p(\"columns\");\n const cols: { key: string; label: string }[] = Array.isArray(declared)\n ? declared.map((d: any) => ({ key: text(d?.key), label: text(d?.label ?? d?.key) }))\n : [...new Set(list.flatMap((r) => Object.keys(r ?? {})))].map((k) => ({\n key: k,\n label: k,\n }));\n return (\n <div className=\"overflow-x-auto rounded-xl ring-1 ring-border-soft\">\n <table className=\"w-full text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {cols.map((col) => (\n <th key={col.key} className=\"px-3 py-2 text-left font-medium\">\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {list.map((r, i) => (\n <tr key={i} className=\"border-border-soft border-t\">\n {cols.map((col) => (\n <td key={col.key} className=\"px-3 py-2 tabular-nums\">\n {text(r?.[col.key])}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n }\n case \"Image\": {\n const url = src(p(\"src\"), ctx.assetUrl);\n return url ? <img src={url} alt={text(p(\"alt\"))} className=\"w-full rounded-xl\" /> : null;\n }\n case \"BarChart\":\n return (\n <Titled title={text(p(\"title\"))}>\n <Bars data={points(p(\"points\"), p(\"labelKey\"), p(\"valueKey\"))} />\n </Titled>\n );\n case \"LineChart\":\n return (\n <Titled title={text(p(\"title\"))}>\n <Line data={points(p(\"points\"), p(\"labelKey\"), p(\"valueKey\"))} />\n </Titled>\n );\n case \"DonutChart\":\n return (\n <Titled title={text(p(\"title\"))}>\n <Donut data={points(p(\"slices\"), p(\"labelKey\"), p(\"valueKey\"))} />\n </Titled>\n );\n case \"Actions\":\n return (\n <div className=\"flex flex-wrap gap-2\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n case \"Button\": {\n const action = text(p(\"action\")) as SurfaceAction[\"action\"];\n if (!ctx.onAction && action !== \"open\") {\n return null;\n }\n return (\n <button\n type=\"button\"\n onClick={() => {\n const target = p(\"target\");\n if (action === \"open\") {\n const url = src(target, ctx.assetUrl);\n if (url) {\n window.open(url, \"_blank\", \"noopener\");\n }\n return;\n }\n ctx.onAction?.({ action, target });\n }}\n className=\"inline-flex h-9 items-center rounded-full bg-paper-2 px-4 text-[0.875rem] text-ink-2 hover:text-ink coarse:h-11\"\n >\n {text(p(\"label\"))}\n </button>\n );\n }\n case \"Tabs\":\n return <TabsView c={c} ctx={ctx} row={row} />;\n case \"Card\": {\n const image = src(p(\"image\"), ctx.assetUrl);\n const eyebrow = text(p(\"eyebrow\"));\n const subtitle = text(p(\"subtitle\"));\n return (\n <article className=\"overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n {image ? <img src={image} alt=\"\" className=\"aspect-[16/9] w-full object-cover\" /> : null}\n <div className={cn(\"flex flex-col gap-1.5 px-4 py-3.5\", c.children && \"bg-paper-2/60\")}>\n {eyebrow ? (\n <div className=\"font-medium text-[0.6875rem] text-ink-3 uppercase tracking-[0.14em]\">\n {eyebrow}\n </div>\n ) : null}\n <h3 className=\"text-balance font-display font-semibold text-[1.1875rem] leading-snug\">\n {text(p(\"title\"))}\n </h3>\n {subtitle ? (\n <p className=\"text-[0.875rem] text-ink-3 leading-relaxed\">{subtitle}</p>\n ) : null}\n <Metas items={metasOf(c, ctx, row)} />\n </div>\n {c.children ? (\n <div className=\"flex flex-col gap-3 border-border-soft border-t px-4 py-3.5 empty:hidden\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n ) : null}\n </article>\n );\n }\n case \"Fold\":\n return (\n <details\n open={Boolean(p(\"open\"))}\n className=\"group border-border-soft border-t pt-3 first:border-0 first:pt-0\"\n >\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 font-display font-semibold text-[1rem] [&::-webkit-details-marker]:hidden\">\n {text(p(\"title\"))}\n <ChevronRight className=\"size-4 text-ink-3 transition-transform group-open:rotate-90 motion-reduce:transition-none\" />\n </summary>\n <div className=\"flex flex-col gap-3 pt-3\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n </details>\n );\n case \"Group\": {\n const kids = c.children;\n if (!kids || Array.isArray(kids)) {\n return null;\n }\n const items = rows(bound({ path: kids.path }, ctx.data, row));\n return (\n <div className=\"flex flex-col gap-5\">\n {grouped(items, text(p(\"by\")), rows(p(\"order\")).map(text)).map(([name, list]) => (\n <section key={name} className=\"flex flex-col gap-2\">\n {name ? (\n <h4 className=\"font-semibold text-[0.6875rem] text-second uppercase tracking-[0.14em]\">\n {name}\n </h4>\n ) : null}\n {list.map((item, i) => (\n <Node key={i} id={kids.componentId} ctx={ctx} row={item} />\n ))}\n </section>\n ))}\n </div>\n );\n }\n case \"Chips\": {\n const labelKey = text(p(\"labelKey\"));\n const flagKey = text(p(\"flagKey\"));\n const flag = text(p(\"flag\"));\n const title = text(p(\"title\"));\n return (\n <div className=\"flex flex-col gap-2\">\n {title ? <div className=\"text-[0.8125rem] text-ink-3\">{title}</div> : null}\n <div className=\"flex flex-wrap gap-1.5\">\n {rows(p(\"items\")).map((item, i) => {\n const flagged = Boolean(flagKey && cell(item, flagKey));\n return (\n <span\n key={i}\n className={cn(\n \"rounded-full px-2.5 py-1 text-[0.8125rem]\",\n flagged\n ? \"bg-amber-tint font-medium text-ink ring-1 ring-amber/60\"\n : \"bg-card text-ink-2 ring-1 ring-border-soft\",\n )}\n >\n {labelOf(item, labelKey)}\n {flagged && flag ? ` · ${flag}` : \"\"}\n </span>\n );\n })}\n </div>\n </div>\n );\n }\n case \"Checklist\":\n return <ChecklistView c={c} ctx={ctx} row={row} />;\n case \"Steps\": {\n const textKey = text(p(\"textKey\")) || \"text\";\n const minutesKey = text(p(\"minutesKey\")) || \"minutes\";\n return (\n <ol className=\"flex flex-col gap-3\">\n {rows(p(\"items\")).map((item, i) => {\n const words = typeof item === \"object\" ? text(cell(item, textKey)) : text(item);\n const time = minutes(cell(item, minutesKey));\n return (\n <li key={i} className=\"grid grid-cols-[1.5rem_1fr] gap-2\">\n <span className=\"font-display font-semibold text-[1.125rem] text-ember leading-snug\">\n {i + 1}\n </span>\n <span className=\"text-[0.9375rem] leading-relaxed\">\n {words}\n {time ? (\n <span className=\"ml-1.5 inline-flex items-center gap-1 whitespace-nowrap rounded-full bg-paper-2 px-2 py-0.5 align-[1px] text-[0.75rem] text-ink-2\">\n <Clock className=\"size-3\" />\n {time}\n </span>\n ) : null}\n </span>\n </li>\n );\n })}\n </ol>\n );\n }\n case \"Link\": {\n // The entry it opens: title, subtitle and meta read it; the eyebrow reads the row it sits in.\n const key = text(p(\"key\")) || \"id\";\n const value = text(p(\"value\"));\n const entry = rows(p(\"items\")).find((item) => text(cell(item, key)) === value);\n const view = (c as Record<string, unknown>).view;\n if (entry === undefined) {\n return null;\n }\n const at = (k: string) => bound((c as Record<string, unknown>)[k], ctx.data, entry);\n const eyebrow = text(p(\"eyebrow\"));\n const meta = metasOf(c, ctx, entry);\n return (\n <button\n type=\"button\"\n onClick={() => typeof view === \"string\" && ctx.open(view, entry)}\n className={cn(\n \"group flex w-full items-center gap-3 text-left\",\n text(p(\"look\")) === \"card\"\n ? \"rounded-xl bg-card p-4 ring-1 ring-border-soft hover:ring-ink-4\"\n : \"-mx-2 w-[calc(100%+1rem)] rounded-lg px-2 py-2 hover:bg-paper-2/70 coarse:py-3\",\n )}\n >\n <span className=\"min-w-0 flex-1\">\n {eyebrow ? (\n <span className=\"block font-semibold text-[0.6875rem] text-second uppercase tracking-[0.14em]\">\n {eyebrow}\n </span>\n ) : null}\n <span className=\"block font-display font-semibold text-[1rem] leading-snug group-hover:text-ember\">\n {text(at(\"title\"))}\n </span>\n {at(\"subtitle\") ? (\n <span className=\"block text-[0.8125rem] text-ink-3\">{text(at(\"subtitle\"))}</span>\n ) : null}\n {meta.length ? (\n <span className=\"mt-0.5 flex items-center gap-1 text-[0.75rem] text-ink-3\">\n <Clock className=\"size-3\" />\n {meta.join(\" · \")}\n </span>\n ) : null}\n </span>\n <ChevronRight className=\"size-4 shrink-0 text-ink-3\" />\n </button>\n );\n }\n case \"Callout\": {\n const tone = text(p(\"tone\")) || \"tip\";\n const title = text(p(\"title\"));\n return (\n <div\n className={cn(\n \"flex gap-2.5 rounded-xl px-4 py-3 text-[0.875rem] leading-relaxed\",\n tone === \"tip\" && \"bg-second-tint\",\n tone === \"note\" && \"bg-paper-2\",\n tone === \"warning\" && \"bg-amber-tint\",\n )}\n >\n <Lightbulb\n className={cn(\"mt-0.5 size-4 shrink-0\", tone === \"tip\" ? \"text-second\" : \"text-ink-3\")}\n />\n <p>\n {title ? <b className=\"font-semibold\">{title} </b> : null}\n {text(p(\"text\"))}\n </p>\n </div>\n );\n }\n }\n return null;\n}\n\nexport function SurfaceView({\n surface,\n assetUrl,\n onAction,\n initial,\n onState,\n}: {\n surface: Surface;\n assetUrl: (id: string) => string;\n onAction?: (a: SurfaceAction) => void;\n /** What the person did in the view last time (kept with the run). */\n initial?: SurfaceState;\n /** Keeps what the person did; without it, it lasts as long as the page. */\n onState?: (next: SurfaceState) => void;\n}) {\n const [state, setState] = useState<SurfaceState>(initial ?? {});\n const [sheet, setSheet] = useState<{ view: string; row: unknown } | null>(null);\n const ctx: Ctx = {\n byId: new Map(surface.components.map((c) => [c.id, c])),\n data: surface.data,\n assetUrl,\n onAction,\n state,\n setState: (id, value) => {\n const next = { ...state, [id]: value };\n setState(next);\n onState?.(next);\n },\n open: (view, row) => setSheet({ view, row }),\n };\n return (\n <>\n <Node id=\"root\" ctx={ctx} />\n <Dialog open={sheet !== null} onClose={() => setSheet(null)} height=\"tall\">\n {sheet ? (\n <div className=\"flex flex-col gap-4\">\n <Node id={sheet.view} ctx={ctx} row={sheet.row} />\n <button\n type=\"button\"\n onClick={() => setSheet(null)}\n className=\"h-10 self-center rounded-full bg-paper-2 px-5 text-[0.875rem] text-ink-2 hover:text-ink\"\n >\n {t(\"surface.close\")}\n </button>\n </div>\n ) : null}\n </Dialog>\n </>\n );\n}\n","import type { Format, Step } from \"@engenty/wizards-shared/definition\";\nimport { stepShape } from \"@engenty/wizards-shared/definition\";\nimport type { StepOutput } from \"@engenty/wizards-shared/run\";\nimport { labelOf } from \"@engenty/wizards-shared/shape\";\nimport DOMPurify from \"dompurify\";\nimport { Check, Copy, Download, FileText, Maximize2, Printer, Share } from \"lucide-react\";\nimport { marked } from \"marked\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { canShareFiles } from \"./device\";\nimport { appCall, appCan, appDownload, asset, standalone, withBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { JsonView } from \"./json-view.js\";\nimport { type Written, writePdf } from \"./pdf.js\";\nimport { type SurfaceAction, SurfaceView } from \"./surface\";\nimport { cn, Spinner, Textarea } from \"./ui.js\";\n\nexport function Markdown({ text, className }: { text: string; className?: string }) {\n const html = useMemo(\n () => DOMPurify.sanitize(marked.parse(text, { async: false }) as string),\n [text],\n );\n return (\n // biome-ignore lint/security/noDangerouslySetInnerHtml: model output, sanitised by DOMPurify above\n <div className={cn(\"prose-zen\", className)} dangerouslySetInnerHTML={{ __html: html }} />\n );\n}\n\n/**\n * Generated HTML in a sandboxed frame: scripts run (scrubbers, tabs, animations) but in an opaque\n * origin with no network. The frame is mounted only once its HTML is there — Chrome paints a\n * sandboxed frame whose content changes after mount blank. `page` is the layout width; the frame\n * is scaled to fit.\n */\nexport function HtmlFrame({\n src,\n page,\n height,\n fit,\n flow,\n state,\n onState,\n}: {\n src: string;\n /** Layout width in CSS px; null = the frame's own width. */\n page: number | null;\n height: number;\n /** Scale up as well as down, so a fixed-size widget fills the width. */\n fit?: boolean;\n /**\n * A widget laid out as part of the page: as wide as the page, as tall as its content says\n * (`height` until it does), never scaled. It may keep a state and share text.\n */\n flow?: boolean;\n /** What the widget kept last time (`wizard.state`). */\n state?: Record<string, unknown>;\n onState?: (state: Record<string, unknown>) => void;\n}) {\n const frame = useRef<HTMLIFrameElement>(null);\n const [tall, setTall] = useState(height);\n // The state the frame started with: later saves must not reload it.\n const [initial] = useState(() => state ?? {});\n const keep = useRef(onState);\n keep.current = onState;\n useEffect(() => {\n const listen = (e: MessageEvent) => {\n if (!frame.current || e.source !== frame.current.contentWindow) {\n return;\n }\n const msg = e.data as { wizard?: string; height?: unknown; state?: unknown; text?: unknown };\n if (msg?.wizard === \"height\" && typeof msg.height === \"number\") {\n setTall(Math.min(20_000, Math.max(120, Math.ceil(msg.height))));\n } else if (msg?.wizard === \"state\" && msg.state && typeof msg.state === \"object\") {\n keep.current?.(msg.state as Record<string, unknown>);\n } else if (msg?.wizard === \"share\" && typeof msg.text === \"string\") {\n const text = msg.text.slice(0, 10_000);\n if (navigator.share) {\n navigator.share({ text }).catch(() => undefined);\n } else {\n navigator.clipboard?.writeText(text).catch(() => undefined);\n }\n }\n };\n window.addEventListener(\"message\", listen);\n return () => window.removeEventListener(\"message\", listen);\n }, []);\n const wrap = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(0);\n useEffect(() => {\n const el = wrap.current;\n if (!el) {\n return;\n }\n const ro = new ResizeObserver(() => setWidth(el.clientWidth));\n ro.observe(el);\n setWidth(el.clientWidth);\n return () => ro.disconnect();\n }, []);\n const [html, setHtml] = useState<{ src: string; text: string } | null>(null);\n useEffect(() => {\n let alive = true;\n fetch(src, { credentials: \"include\" })\n .then((r) => (r.ok ? r.text() : \"\"))\n .then((text) => alive && setHtml({ src, text }));\n return () => {\n alive = false;\n };\n }, [src]);\n const layout = flow ? width || 360 : (page ?? Math.max(width, 900));\n const scale = flow ? 1 : width ? (fit ? width / layout : Math.min(1, width / layout)) : 1;\n const shown = flow ? tall : height;\n // The kept state goes in ahead of the widget's own scripts, so `wizard.state` is there at once.\n const doc =\n flow && html\n ? `<script>window.__WIZARD_STATE=${JSON.stringify(initial).replace(/</g, \"\\\\u003c\")}</script>${html.text}`\n : html?.text;\n return (\n <div\n ref={wrap}\n className={cn(\n \"relative overflow-hidden\",\n !flow && \"rounded-lg bg-white ring-1 ring-border-soft\",\n )}\n style={{ height: shown * scale }}\n >\n {html?.src === src ? (\n <iframe\n ref={frame}\n key={src}\n title={t(\"output.preview\")}\n srcDoc={doc}\n sandbox=\"allow-scripts allow-popups allow-popups-to-escape-sandbox\"\n className=\"absolute top-0 left-0 origin-top-left border-0\"\n style={{ width: layout, height: shown, transform: `scale(${scale})` }}\n />\n ) : (\n <div className=\"absolute inset-0 animate-pulse bg-paper-2\" />\n )}\n {flow ? null : (\n <a\n href={src}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"absolute top-3 right-3 inline-flex size-9 items-center justify-center rounded-full bg-card/90 text-ink-2 shadow-soft ring-1 ring-border-soft backdrop-blur hover:text-ink coarse:size-11\"\n aria-label={t(\"run.openFull\")}\n >\n <Maximize2 className=\"size-4\" />\n </a>\n )}\n </div>\n );\n}\n\n/**\n * Where the artwork sits inside the Commission's icon files (the half-transparent variants):\n * each leaves clear space around its shape, and the label is laid out by the shape.\n */\nconst AI_ICONS = {\n disc: { file: \"ai\", box: 566.93, x: 89.28, y: 100.72, w: 365.49, h: 365.49 },\n generated: { file: \"ai-generated\", box: 1789.84, x: 207.3, y: 144.36, w: 1384.24, h: 266.41 },\n edited: { file: \"ai-modified\", box: 1700.79, x: 231.11, y: 144.36, w: 1230.56, h: 266.41 },\n} as const;\n\n/** One of the icons, scaled so that its shape is `size` px high, with the shape at the box's corner. */\nfunction AiIcon({\n icon,\n tone,\n size,\n className,\n}: {\n icon: keyof typeof AI_ICONS;\n tone: \"white\" | \"black\";\n size: number;\n className?: string;\n}) {\n const art = AI_ICONS[icon];\n const scale = size / art.h;\n return (\n <img\n src={asset(`ai-labels/${art.file}-${tone}.svg`)}\n alt=\"\"\n draggable={false}\n className={cn(\"pointer-events-none absolute max-w-none select-none\", className)}\n style={{\n width: art.box * scale,\n height: 566.93 * scale,\n left: -art.x * scale,\n top: -art.y * scale,\n }}\n />\n );\n}\n\n/**\n * The EU's label on media a model made or changed: the round \"AI\" alone, and on hover, on focus\n * and on a tap the long form — \"AI GENERATED\" or \"AI MODIFIED\". It lies over the picture in the\n * interface and is not part of the file; the file says the same in its metadata.\n */\nexport function AiBadge({\n ai,\n className,\n}: {\n ai: \"generated\" | \"edited\" | undefined;\n /** Where on the media it sits; default: bottom left. \"static\" sets it into the text flow. */\n className?: string;\n}) {\n // A phone has no hover: a tap opens the label and the next one closes it.\n const [open, setOpen] = useState(false);\n if (!ai) {\n return null;\n }\n // Small, and of glass: the icon's ground is half transparent, the picture behind it blurred.\n const size = 18;\n const long = AI_ICONS[ai];\n const inline = className === \"static\";\n const shown = \"opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100\";\n const hidden = \"opacity-100 group-hover:opacity-0 group-focus-visible:opacity-0\";\n // Over a picture the white label reads on anything; in the text it follows the theme.\n const tones = inline\n ? ([\n [\"black\", \"dark:hidden\"],\n [\"white\", \"hidden dark:block\"],\n ] as const)\n : ([[\"white\", \"\"]] as const);\n return (\n <button\n type=\"button\"\n aria-label={t(ai === \"edited\" ? \"ai.modified\" : \"ai.generated\")}\n aria-expanded={open}\n data-open={open}\n onClick={() => setOpen((v) => !v)}\n className={cn(\n \"group block cursor-default overflow-hidden rounded-full backdrop-blur-md transition-[width] duration-200\",\n \"w-[var(--ai-disc)] hover:w-[var(--ai-long)] focus-visible:w-[var(--ai-long)] data-[open=true]:w-[var(--ai-long)]\",\n inline\n ? \"relative\"\n : cn(\"absolute shadow-[0_1px_3px_rgba(0,0,0,0.25)]\", className ?? \"bottom-2 left-2\"),\n )}\n style={\n {\n height: size,\n \"--ai-disc\": `${size}px`,\n \"--ai-long\": `${(long.w / long.h) * size}px`,\n } as React.CSSProperties\n }\n >\n {tones.map(([tone, theme]) => (\n <span key={tone} className={theme}>\n <AiIcon\n icon=\"disc\"\n tone={tone}\n size={size}\n className={cn(\"transition-opacity duration-200\", open ? \"opacity-0\" : hidden)}\n />\n <AiIcon\n icon={ai}\n tone={tone}\n size={size}\n className={cn(\"transition-opacity duration-200\", open ? \"opacity-100\" : shown)}\n />\n </span>\n ))}\n </button>\n );\n}\n\n/** What people read for a key of a step's output: its label in the step's shape. */\nfunction labelFor(step: Step, key: string): string {\n const f = step.type === \"agent\" ? stepShape(step).fields[key] : undefined;\n return f ? labelOf(key, f) : key;\n}\n\nfunction CopyButton({ text }: { text: string }) {\n const [done, setDone] = useState(false);\n return (\n <button\n type=\"button\"\n onClick={() => {\n void navigator.clipboard.writeText(text);\n setDone(true);\n setTimeout(() => setDone(false), 1500);\n }}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n {done ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {done ? t(\"share.copied\") : t(\"run.copy\")}\n </button>\n );\n}\n\n/** One step's result: the right preview for what it produced. */\nexport function OutputView({\n base,\n step,\n output,\n editable,\n draft,\n onDraft,\n picked,\n onPick,\n onSurfaceAction,\n onView,\n}: {\n /** `/api/runs/<id>` or `/api/shares/<token>` — where the output's files are served. */\n base: string;\n step: Step;\n output: StepOutput | null;\n editable?: boolean;\n draft?: string;\n onDraft?: (text: string) => void;\n /** Several results: the ones picked to be made again (from 0), and the tap that picks one. */\n picked?: number[];\n onPick?: (index: number) => void;\n /** A surface's buttons: \"regenerate\" where the review allows it. */\n onSurfaceAction?: (a: SurfaceAction) => void;\n /** Keeps what the person did in the view (ticks, a widget's state) with the run. */\n onView?: (state: Record<string, unknown>) => void;\n}) {\n if (!output) {\n return null;\n }\n const assetUrl = (id: string) => withBase(`${base}/assets/${id}`);\n // A view from the catalog stands for the step's data.\n if (output.surface) {\n return (\n <SurfaceView\n surface={output.surface}\n assetUrl={assetUrl}\n onAction={onSurfaceAction}\n initial={output.view}\n onState={onView}\n />\n );\n }\n if (step.type === \"widget\" || step.type === \"film\") {\n const film = output.assets?.find((a) => a.kind === \"video\");\n if (film) {\n const poster = output.assets?.find((a) => a.kind === \"poster\");\n const tall =\n step.type === \"film\"\n ? step.format === \"9:16\"\n : (step.size?.height ?? 0) > (step.size?.width ?? 1);\n const video = (\n <div className={cn(\"relative mx-auto\", tall ? \"w-fit\" : \"w-full\")}>\n {/* biome-ignore lint/a11y/useMediaCaption: the film's captions are part of the picture */}\n <video\n src={assetUrl(film.id)}\n poster={poster ? assetUrl(poster.id) : undefined}\n controls\n playsInline\n className={cn(\n \"rounded-lg bg-black ring-1 ring-border-soft\",\n tall ? \"max-h-[76vh]\" : \"w-full\",\n )}\n />\n <AiBadge ai={film.ai} className=\"top-2 right-2\" />\n </div>\n );\n // A film step's text is the client's own word on what it made or changed — or why not.\n return step.type === \"film\" && output.text ? (\n <div className=\"flex flex-col gap-4\">\n {video}\n <Markdown text={output.text} className=\"text-[0.875rem] text-ink-2\" />\n </div>\n ) : (\n video\n );\n }\n if (step.type === \"film\") {\n return null;\n }\n const html = output.assets?.find((a) => a.mime === \"text/html\");\n const size = step.size ?? { width: 1280, height: 720 };\n return html ? (\n <HtmlFrame\n src={assetUrl(html.id)}\n page={size.width}\n height={size.height}\n fit\n flow={step.layout === \"page\"}\n state={output.view}\n onState={onView}\n />\n ) : null;\n }\n if (step.type === \"generate\") {\n const asset = output.assets?.[0];\n if (!asset) {\n return null;\n }\n if (step.asset === \"voice\") {\n return (\n <div className=\"flex flex-col gap-3\">\n {/* biome-ignore lint/a11y/useMediaCaption: what is said stands right below */}\n <audio src={assetUrl(asset.id)} controls className=\"w-full\" />\n <AiBadge ai={asset.ai} className=\"static\" />\n {output.text ? (\n <p className=\"text-[0.875rem] text-ink-2 leading-relaxed\">{output.text}</p>\n ) : null}\n </div>\n );\n }\n const several = (output.assets?.length ?? 0) > 1;\n if (several && (step.asset === \"image\" || step.asset === \"video\")) {\n const tall = step.options?.aspectRatio === \"9:16\" || step.options?.aspectRatio === \"2:3\";\n return (\n <div className={cn(\"grid gap-3\", tall ? \"grid-cols-2 sm:grid-cols-3\" : \"sm:grid-cols-2\")}>\n {output.assets?.map((a, i) => {\n const on = picked?.includes(i);\n return (\n <figure\n key={a.id}\n className={cn(\n \"relative overflow-hidden rounded-lg bg-paper-2 ring-1 ring-border-soft\",\n on && \"ring-2 ring-ember\",\n )}\n >\n {step.asset === \"image\" ? (\n <img src={assetUrl(a.id)} alt={`${step.title} ${i + 1}`} className=\"w-full\" />\n ) : (\n // biome-ignore lint/a11y/useMediaCaption: generated clips have no caption track to offer\n <video src={assetUrl(a.id)} controls playsInline loop className=\"w-full\" />\n )}\n {onPick ? (\n <button\n type=\"button\"\n aria-pressed={on}\n onClick={() => onPick(i)}\n className={cn(\n \"absolute top-2 left-2 inline-flex h-8 items-center gap-1.5 rounded-full px-3 font-medium text-[0.75rem] shadow-soft backdrop-blur coarse:h-11\",\n on ? \"bg-ember text-ember-on\" : \"bg-card/90 text-ink-2 hover:text-ink\",\n )}\n >\n {on ? <Check className=\"size-3.5\" /> : null}\n {t(on ? \"run.pickedItem\" : \"run.pickItem\", { n: i + 1 })}\n </button>\n ) : (\n <span className=\"absolute top-2 left-2 rounded-full bg-card/90 px-2.5 py-1 font-medium text-[0.75rem] text-ink-2\">\n {i + 1}\n </span>\n )}\n <AiBadge\n ai={a.ai}\n className={step.asset === \"image\" ? \"bottom-2 left-2\" : \"top-2 right-2\"}\n />\n </figure>\n );\n })}\n </div>\n );\n }\n if (step.asset === \"image\") {\n return (\n <div className=\"relative\">\n <img\n src={assetUrl(asset.id)}\n alt={step.title}\n className=\"w-full rounded-lg bg-paper-2 ring-1 ring-border-soft\"\n />\n <AiBadge ai={asset.ai} />\n </div>\n );\n }\n if (step.asset === \"video\") {\n const tall = step.options?.aspectRatio === \"9:16\";\n return (\n <div className={cn(\"relative mx-auto\", tall ? \"w-fit\" : \"w-full\")}>\n {/* biome-ignore lint/a11y/useMediaCaption: generated clips have no caption track to offer */}\n <video\n src={assetUrl(asset.id)}\n controls\n playsInline\n loop\n className={cn(\n \"rounded-lg bg-black ring-1 ring-border-soft\",\n tall ? \"max-h-[70vh]\" : \"w-full\",\n )}\n />\n <AiBadge ai={asset.ai} className=\"top-2 left-2\" />\n </div>\n );\n }\n return step.asset === \"document\" ? (\n <HtmlFrame src={assetUrl(asset.id)} page={820} height={1100} />\n ) : (\n <HtmlFrame src={assetUrl(asset.id)} page={null} height={760} />\n );\n }\n if (step.type === \"agent\") {\n const images =\n output.assets?.filter((a) => a.kind !== \"file\" && a.mime.startsWith(\"image/\")) ?? [];\n const files = output.assets?.filter((a) => a.kind === \"file\") ?? [];\n return (\n <div className=\"flex flex-col gap-4\">\n {step.output.format === \"json\" && output.json !== undefined ? (\n <JsonView step={step} json={output.json} />\n ) : editable ? (\n <Textarea\n value={draft ?? output.text ?? \"\"}\n onChange={(e) => onDraft?.(e.target.value)}\n minRows={4}\n maxRows={24}\n />\n ) : step.output.format === \"markdown\" ? (\n <Markdown text={output.text ?? \"\"} />\n ) : (\n <div className=\"whitespace-pre-wrap text-[1rem] leading-relaxed\">{output.text}</div>\n )}\n {images.map((img) => (\n <div key={img.id} className=\"relative\">\n <img\n src={assetUrl(img.id)}\n alt=\"\"\n className=\"w-full rounded-lg ring-1 ring-border-soft\"\n />\n <AiBadge ai={img.ai} />\n </div>\n ))}\n {files.length ? (\n <ul className=\"overflow-hidden rounded-lg ring-1 ring-border-soft\">\n {files.map((f) => (\n <li key={f.id} className=\"border-border-soft border-b last:border-0\">\n <a\n href={assetUrl(f.id)}\n download={f.name}\n onClick={(e) => appDownload(e, assetUrl(f.id), f.name)}\n className=\"flex items-center gap-2 px-3 py-2 text-[0.8125rem] hover:bg-paper-2 coarse:min-h-11\"\n >\n <FileText className=\"size-3.5 shrink-0 text-ink-3\" />\n <span className=\"min-w-0 flex-1 truncate\">{f.name}</span>\n </a>\n </li>\n ))}\n </ul>\n ) : null}\n {step.output.format !== \"json\" && !editable && output.text ? (\n <div>\n <CopyButton text={output.text} />\n </div>\n ) : null}\n </div>\n );\n }\n return null;\n}\n\n/** A download format as a person reads it. */\nexport const FORMAT_LABEL: Record<Format, string> = {\n png: \"PNG\",\n mp4: \"MP4\",\n mp3: \"MP3\",\n pdf: \"PDF\",\n docx: \"Word\",\n html: \"HTML\",\n md: \"Markdown\",\n txt: \"Text\",\n csv: \"CSV\",\n xlsx: \"Excel\",\n json: \"JSON\",\n zip: \"ZIP\",\n};\n\n/** The file's name as the server sends it, for the share sheet and \"Save to Files\". */\nfunction downloadName(res: Response, fallback: string): string {\n const header = res.headers.get(\"content-disposition\") ?? \"\";\n return header.match(/filename=\"([^\"]+)\"/)?.[1] ?? fallback;\n}\n\n/** A file made in the browser, saved as a download would be. */\nfunction saveFile(file: File) {\n const url = URL.createObjectURL(file);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = file.name;\n a.rel = \"noopener\";\n document.body.append(a);\n a.click();\n a.remove();\n setTimeout(() => URL.revokeObjectURL(url), 60_000);\n}\n\n/**\n * Hands a result to the phone's share sheet as a file — Mail, WhatsApp, \"Save to Files\", \"Open\n * in …\". The file is fetched first (or made here); when that took longer than the browser lets\n * a tap wait, a second tap sends it.\n */\nfunction ShareFileButton({\n url,\n format,\n title,\n make,\n}: {\n url: string;\n format: Format;\n title?: string;\n /** The file made in the browser instead of fetched: a written output's PDF on a site. */\n make?: () => Promise<File>;\n}) {\n const [state, setState] = useState<\"idle\" | \"busy\" | \"ready\">(\"idle\");\n const file = useRef<File | null>(null);\n const share = async () => {\n if (appCan(\"share\") && !make) {\n // The app fetches the file itself and opens the native share sheet with it.\n setState(\"busy\");\n await appCall(\"share\", { url: new URL(url, location.href).href, title }).catch(\n () => undefined,\n );\n setState(\"idle\");\n return;\n }\n try {\n if (!file.current) {\n setState(\"busy\");\n if (make) {\n file.current = await make();\n } else {\n const res = await fetch(url, { credentials: \"include\" });\n if (!res.ok) {\n throw new Error(String(res.status));\n }\n const blob = await res.blob();\n file.current = new File([blob], downloadName(res, `download.${format}`), {\n type: blob.type.split(\";\")[0],\n });\n }\n }\n const data = { files: [file.current], title };\n if (!navigator.canShare(data)) {\n // A type the share sheet does not take: it is downloaded instead.\n if (make) {\n saveFile(file.current);\n } else {\n location.href = url;\n }\n setState(\"idle\");\n return;\n }\n await navigator.share(data);\n setState(\"idle\");\n } catch (err) {\n // Fetched, but the tap is too long ago for the browser: the next tap shares at once.\n setState(file.current && (err as DOMException).name === \"NotAllowedError\" ? \"ready\" : \"idle\");\n }\n };\n return (\n <button\n type=\"button\"\n onClick={() => void share()}\n disabled={state === \"busy\"}\n aria-label={t(\"run.shareFile\")}\n title={t(\"run.shareFile\")}\n className={cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-full px-3 font-medium text-[0.8125rem] transition coarse:h-11 coarse:px-4\",\n state === \"ready\"\n ? \"bg-ember-tint text-ink ring-1 ring-ember\"\n : \"bg-paper-2 text-ink-2 hover:bg-paper-3 hover:text-ink\",\n )}\n >\n {state === \"busy\" ? <Spinner className=\"size-3.5\" /> : <Share className=\"size-3.5\" />}\n {state === \"ready\" ? t(\"run.shareNow\") : t(\"run.share\")}\n </button>\n );\n}\n\nconst SHARES_FILES = appCan(\"share\") || canShareFiles();\n\nexport function DownloadButtons({\n base,\n stepId,\n formats,\n title,\n step,\n output,\n foot,\n}: {\n base: string;\n stepId: string;\n formats: Format[];\n /** Named in the share sheet. */\n title?: string;\n /** The step and its output: on a standalone host a written output's PDF is made here. */\n step?: Step;\n output?: StepOutput;\n /** The foot of a PDF made here: the wizard, the date. */\n foot?: string;\n}) {\n const href = (f: Format) => withBase(`${base}/steps/${stepId}/download?format=${f}`);\n const [busy, setBusy] = useState(false);\n const made = useRef<File | null>(null);\n // The server of a standalone host writes no PDF: a written output's PDF is made in the browser.\n const written: Written | null =\n standalone() && step?.type === \"agent\" && output && (output.text || output.json !== undefined)\n ? {\n title: title ?? step.title,\n text: output.text,\n json: step.output.format === \"json\" ? output.json : undefined,\n label: (key) => labelFor(step, key),\n foot,\n }\n : null;\n const makePdf = async () => {\n if (!written) {\n throw new Error(\"nothing written\");\n }\n made.current ??= await writePdf(written);\n return made.current;\n };\n const savePdf = async () => {\n setBusy(true);\n try {\n saveFile(await makePdf());\n } catch (err) {\n console.warn(`pdf: ${(err as Error).message}`);\n // Without the library (offline, a blocked script): the page to print stands in.\n if (formats.includes(\"html\")) {\n window.open(href(\"html\"), \"_blank\", \"noopener\");\n }\n } finally {\n setBusy(false);\n }\n };\n const look = (i: number) =>\n cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-full px-3.5 font-medium text-[0.8125rem] transition coarse:h-11 coarse:px-4\",\n i === 0\n ? \"bg-primary text-primary-foreground hover:brightness-105\"\n : \"bg-paper-2 text-ink-2 hover:bg-paper-3 hover:text-ink\",\n );\n const inBrowser = (f: Format) => f === \"pdf\" && written !== null;\n return (\n <div className=\"flex flex-wrap gap-2\">\n {formats.map((f, i) =>\n inBrowser(f) ? (\n <button\n key={f}\n type=\"button\"\n onClick={() => void savePdf()}\n disabled={busy}\n className={look(i)}\n >\n {busy ? (\n <Spinner className=\"size-3.5\" />\n ) : i === 0 ? (\n <Download className=\"size-3.5\" />\n ) : null}\n {FORMAT_LABEL[f]}\n </button>\n ) : f === \"html\" && standalone() ? (\n // On a site the HTML of a result is a page to print, opened beside the run.\n <a key={f} href={href(f)} target=\"_blank\" rel=\"noopener\" className={look(i)}>\n {i === 0 ? <Printer className=\"size-3.5\" /> : null}\n {t(\"run.print\")}\n </a>\n ) : (\n <a key={f} href={href(f)} onClick={(e) => appDownload(e, href(f))} className={look(i)}>\n {i === 0 ? <Download className=\"size-3.5\" /> : null}\n {FORMAT_LABEL[f]}\n </a>\n ),\n )}\n {SHARES_FILES && formats.length ? (\n <ShareFileButton\n key={href(formats[0])}\n url={href(formats[0])}\n format={formats[0]}\n title={title}\n make={inBrowser(formats[0]) ? makePdf : undefined}\n />\n ) : null}\n </div>\n );\n}\n","import {\n isDecidedField,\n type PageStep,\n type ResultStep,\n type ReviewStep,\n type Step,\n shownFields,\n stepShape,\n} from \"@engenty/wizards-shared/definition\";\nimport type { RunView, StepOutput } from \"@engenty/wizards-shared/run\";\nimport {\n ArrowLeft,\n ArrowRight,\n Bell,\n BellRing,\n Languages,\n Pencil,\n RefreshCw,\n RotateCcw,\n Sparkles,\n} from \"lucide-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { AskPanel } from \"./AskPanel.js\";\nimport { DataEditor, editableData, StudioData } from \"./data.js\";\nimport {\n disableNotify,\n enableNotify,\n notificationsBlocked,\n signalPerson,\n useKeyboardInset,\n useNotifyState,\n useWakeLock,\n} from \"./device\";\nimport { api, runBase, runnerEnv, withBase } from \"./env.js\";\nimport { FieldInput, type Values } from \"./fields\";\nimport { eventText, setChoiceLabels, t } from \"./i18n.js\";\nimport { DownloadButtons, OutputView } from \"./outputs\";\nimport { ListCheck, ListDownloads, ListTable, StoreButton } from \"./store\";\nimport { Button, Card, cn, LinkedText, Spinner, Textarea } from \"./ui.js\";\n\n/**\n * A run as the runner drives it: the view, and the commands a person can give. `useRun` in the\n * studio (a server-sent stream), `useLocalRun` in the WordPress plugin (one request per step).\n */\nexport interface RunSource {\n view: RunView | null;\n notFound: boolean;\n error: string | null;\n busy: boolean;\n fieldErrors: Record<string, string>;\n submitPage(stepId: string, values: Record<string, unknown>): Promise<boolean>;\n accept(\n stepId: string,\n edits?: Record<string, string | Record<string, unknown>>,\n ): Promise<boolean>;\n regenerate(stepId: string, target: string, note: string, items?: number[]): Promise<boolean>;\n back(): Promise<boolean>;\n retry(): Promise<boolean>;\n /** A finished result's text in the language the run is read in (a translated wizard). */\n translateResult?(stepId: string): Promise<boolean>;\n}\n\ntype Run = RunSource;\n\nfunction Progress({ view }: { view: RunView }) {\n const pct = Math.round(\n (Math.min(view.progress.done, view.progress.total) / Math.max(1, view.progress.total)) * 100,\n );\n return (\n <div className=\"h-[3px] w-full bg-paper-2\">\n <div\n className=\"h-full bg-ember transition-[width] duration-700 ease-out\"\n style={{ width: `${pct}%` }}\n />\n </div>\n );\n}\n\n/** Keeps what the person did in a step's view (ticks, a widget's state) with the run. */\nconst keepView = (runId: string, stepId: string) => (state: Record<string, unknown>) => {\n api.put(`${runBase(runId)}/views/${stepId}`, { state }).catch(() => undefined);\n};\n\nfunction StepHeading({\n title,\n description,\n kicker,\n}: {\n title: string;\n description?: string;\n kicker?: string | null;\n}) {\n return (\n <div className=\"kb-title mb-8\">\n {kicker ? (\n <p className=\"kb-hide mb-4 text-[0.9375rem] text-ink-2 leading-relaxed\">{kicker}</p>\n ) : null}\n <h1 className=\"wizard-title font-display font-semibold text-[1.75rem] leading-[1.15] tracking-tight sm:text-[2rem]\">\n {title}\n </h1>\n {description ? (\n <p className=\"kb-hide mt-2 text-[0.9375rem] text-ink-3 leading-relaxed\">{description}</p>\n ) : null}\n </div>\n );\n}\n\nexport function initialValues(step: PageStep, view: RunView): Values {\n const out: Values = {};\n for (const f of step.fields) {\n out[f.id] =\n view.values[f.id] ??\n view.prefill?.[f.id] ??\n f.default ??\n (f.kind === \"multiselect\" ? [] : undefined);\n }\n return out;\n}\n\n/** Text inputs of a page, in order — what Enter and the keyboard's action key walk through. */\nfunction typedInputs(form: HTMLElement): HTMLElement[] {\n return Array.from(\n form.querySelectorAll<HTMLElement>(\n 'input:not([type=\"hidden\"], [type=\"file\"], [type=\"checkbox\"], [type=\"color\"], [type=\"range\"], [disabled]), textarea:not([disabled])',\n ),\n ).filter((el) => !el.closest(\"dialog\") && el.offsetParent !== null);\n}\n\nfunction PageForm({ view, run, step }: { view: RunView; run: Run; step: PageStep }) {\n // Keyed by the page at the call site, so a page (or a page revisited) starts from the run's values.\n const [values, setValues] = useState<Values>(() => initialValues(step, view));\n // Fields still uploading or recording; going on now would leave their answer behind.\n const [pending, setPending] = useState<ReadonlySet<string>>(new Set());\n const form = useRef<HTMLFormElement>(null);\n const first = view.progress.done === 0;\n // Choices from earlier data stand in for the fixed ones; a field whose condition does not\n // hold is not shown, decided again as the person types.\n const fields = useMemo(\n () =>\n step.fields\n .filter((f) => !isDecidedField(f) || view.decidedFields?.includes(f.id))\n .map((f) => (view.options?.[f.id]?.length ? { ...f, options: view.options[f.id] } : f)),\n [step.fields, view.options, view.decidedFields],\n );\n const shown = shownFields(fields, view.known ?? {}, values);\n const submit = () => void run.submitPage(step.id, values);\n\n // The keyboard's action key says what it does: \"next\" between fields, \"go\" on the last one.\n useEffect(() => {\n if (!form.current) {\n return;\n }\n const inputs = typedInputs(form.current).filter((el) => el instanceof HTMLInputElement);\n for (const [i, el] of inputs.entries()) {\n if (el.dataset.hint || !el.hasAttribute(\"enterkeyhint\")) {\n el.dataset.hint = \"1\";\n el.setAttribute(\"enterkeyhint\", i === inputs.length - 1 ? \"go\" : \"next\");\n }\n }\n });\n\n return (\n <form\n ref={form}\n className=\"animate-rise\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!pending.size) {\n submit();\n }\n }}\n onKeyDown={(e) => {\n const el = e.target;\n if (\n e.key !== \"Enter\" ||\n e.defaultPrevented ||\n e.nativeEvent.isComposing ||\n !(el instanceof HTMLInputElement) ||\n el.closest(\"dialog\")\n ) {\n return;\n }\n // Enter walks to the next field; only on the last one it sends the page.\n const inputs = typedInputs(e.currentTarget);\n const next = inputs[inputs.indexOf(el) + 1];\n if (next) {\n e.preventDefault();\n next.focus();\n }\n }}\n >\n <StepHeading\n title={step.title}\n description={step.description}\n kicker={first ? view.wizard.intro : null}\n />\n <div className=\"flex flex-col gap-7\">\n {shown.map((f) => (\n <FieldInput\n key={f.id}\n field={f}\n value={values[f.id]}\n values={values}\n runId={view.id}\n view={view}\n error={run.fieldErrors[f.id]}\n closed={view.closed?.[f.id]}\n onChange={(v) => setValues((prev) => ({ ...prev, [f.id]: v }))}\n onBusy={(busy) =>\n setPending((prev) => {\n if (prev.has(f.id) === busy) {\n return prev;\n }\n const next = new Set(prev);\n if (busy) {\n next.add(f.id);\n } else {\n next.delete(f.id);\n }\n return next;\n })\n }\n />\n ))}\n </div>\n <Footer view={view} run={run} sticky>\n <Button type=\"submit\" size=\"lg\" busy={run.busy} disabled={pending.size > 0}>\n {step.cta || t(\"run.next\")} <ArrowRight className=\"size-4\" />\n </Button>\n </Footer>\n </form>\n );\n}\n\nfunction Footer({\n view,\n run,\n sticky,\n children,\n}: {\n view: RunView;\n run: Run;\n /** The page's primary action: on a phone it stays in reach at the bottom of the screen. */\n sticky?: boolean;\n children: React.ReactNode;\n}) {\n return (\n <div className={cn(\"mt-10 flex items-center justify-between gap-3\", sticky && \"action-bar\")}>\n {view.canBack ? (\n <Button variant=\"ghost\" onClick={() => void run.back()} disabled={run.busy}>\n <ArrowLeft className=\"size-4\" /> {t(\"run.back\")}\n </Button>\n ) : (\n <span />\n )}\n {children}\n </div>\n );\n}\n\n/** \"Tell me when it's done\": asked for with a tap, never on page load. */\nfunction NotifyToggle() {\n const state = useNotifyState();\n const [busy, setBusy] = useState(false);\n const on = state !== \"off\";\n return (\n <div className=\"mt-6 flex flex-col items-center gap-2\">\n <button\n type=\"button\"\n aria-pressed={on}\n disabled={busy}\n onClick={async () => {\n if (on) {\n disableNotify();\n return;\n }\n setBusy(true);\n await enableNotify();\n setBusy(false);\n }}\n className={cn(\n \"inline-flex h-11 items-center gap-2 rounded-full px-4 font-medium text-[0.875rem] ring-1 transition\",\n on\n ? \"bg-ember-tint text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink hover:ring-ink-4\",\n )}\n >\n {on ? <BellRing className=\"size-4 text-ember-strong\" /> : <Bell className=\"size-4\" />}\n {t(on ? \"notify.on\" : \"notify.ask\")}\n </button>\n <p className=\"max-w-xs text-[0.75rem] text-ink-4 leading-relaxed\">\n {state === \"off\"\n ? t(\"notify.why\")\n : state === \"on\"\n ? t(\"notify.onHint\")\n : t(notificationsBlocked() ? \"notify.blocked\" : \"notify.quiet\")}\n </p>\n </div>\n );\n}\n\nfunction Working({\n view,\n compact,\n awake,\n}: {\n view: RunView;\n compact?: boolean;\n /** The screen is kept on while the step works. */\n awake: boolean;\n}) {\n const started = useMemo(() => {\n const e = [...view.events]\n .reverse()\n .find((ev) => ev.type === \"step_started\" && ev.stepId === view.step?.id);\n return e ? new Date(e.at).getTime() : Date.now();\n }, [view.events, view.step?.id]);\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, []);\n const label =\n [...view.events]\n .reverse()\n .find((ev) => ev.type === \"step_started\" && ev.stepId === view.step?.id)?.message ??\n view.step?.title ??\n t(\"run.working\");\n const recent = view.events.filter(\n (ev) =>\n (ev.type === \"tool\" || ev.type === \"info\") && new Date(ev.at).getTime() >= started - 500,\n );\n const trail = recent.slice(-4);\n const { Mascot } = runnerEnv();\n // The pictures the step is about — photos it looks at, images it has just made — newest last.\n const pictures = [...new Set(recent.map((ev) => ev.asset).filter((id): id is string => !!id))];\n const latest = [...recent].reverse().find((ev) => ev.asset)?.asset;\n return (\n <div className=\"flex animate-rise flex-col items-center pt-6 text-center\">\n <Mascot\n kind={view.wizard.avatar}\n costume={view.wizard.costume}\n size={compact ? 130 : 170}\n fluffy\n />\n <h2 className=\"wizard-heading mt-4 font-display font-semibold text-[1.375rem] tracking-tight\">\n {label}\n </h2>\n <div className=\"mt-1 text-[0.8125rem] text-ink-4 tabular-nums\">\n {t(\"run.elapsed\", { s: Math.max(0, Math.round((now - started) / 1000)) })}\n </div>\n {pictures.length ? (\n <div className=\"mt-5 flex max-w-full flex-wrap justify-center gap-2\">\n {pictures.slice(-8).map((id) => (\n <img\n key={id}\n src={withBase(`${runBase(view.id)}/assets/${id}`)}\n alt=\"\"\n className={cn(\n \"size-16 animate-rise rounded-lg bg-paper-2 object-cover ring-1 ring-border-soft transition sm:size-20\",\n id === latest ? \"ring-2 ring-ember\" : \"opacity-70\",\n )}\n />\n ))}\n </div>\n ) : null}\n <div className=\"mt-6 flex min-h-[7rem] w-full max-w-sm flex-col gap-1.5\">\n {trail.map((ev, i) => (\n <div\n key={ev.id}\n className={cn(\n \"flex items-center justify-center gap-2 text-[0.8125rem] transition-opacity\",\n i === trail.length - 1 ? \"text-ink-2\" : \"text-ink-4\",\n )}\n >\n {i === trail.length - 1 ? (\n <Sparkles className=\"size-3.5 animate-breathe text-ember\" />\n ) : null}\n <span className=\"truncate\">{eventText(ev)}</span>\n </div>\n ))}\n </div>\n {compact ? null : <NotifyToggle />}\n {awake ? <p className=\"mt-3 text-[0.75rem] text-ink-4\">{t(\"run.awake\")}</p> : null}\n </div>\n );\n}\n\n/**\n * Tells the person when a step that took a while is done, or when it needs them (a sign-in, a\n * confirmation) — if they asked for it. A page in the background also marks its title.\n */\nexport function useDoneSignal(view: RunView | null) {\n const last = useRef({ running: false, since: 0, ask: null as string | null });\n useEffect(() => {\n if (!view) {\n return;\n }\n const prev = last.current;\n const running = view.status === \"running\";\n const since = running ? (prev.running ? prev.since : Date.now()) : 0;\n const tell = (body: string) => {\n if (document.visibilityState !== \"visible\" && !document.title.startsWith(\"● \")) {\n document.title = `● ${document.title}`;\n }\n void signalPerson({ title: view.wizard.title, body, tag: view.id });\n };\n if (running && view.ask && view.ask.id !== prev.ask) {\n tell(t(\"notify.needsYou\"));\n } else if (!running && prev.running && Date.now() - prev.since > 8000) {\n tell(\n view.status === \"failed\"\n ? t(\"run.failed\")\n : view.status === \"done\"\n ? t(\"notify.done\")\n : t(\"notify.next\"),\n );\n }\n last.current = { running, since, ask: view.ask?.id ?? null };\n }, [view]);\n useEffect(() => {\n const seen = () => {\n if (document.visibilityState === \"visible\" && document.title.startsWith(\"● \")) {\n document.title = document.title.slice(2);\n }\n };\n document.addEventListener(\"visibilitychange\", seen);\n return () => document.removeEventListener(\"visibilitychange\", seen);\n }, []);\n}\n\nfunction Review({\n view,\n run,\n step,\n studio,\n}: {\n view: RunView;\n run: Run;\n step: ReviewStep;\n studio?: boolean;\n}) {\n const [drafts, setDrafts] = useState<Record<string, string | Record<string, unknown>>>({});\n const [editing, setEditing] = useState<Record<string, boolean>>({});\n // What the person wants changed, and which of the shown results it is about.\n const [note, setNote] = useState(\"\");\n const made = view.shown.filter((x) => x.output);\n const [target, setTarget] = useState<string | null>(made.length === 1 ? made[0].step.id : null);\n // Steps with several results: the ones picked to be made again.\n const [picked, setPicked] = useState<Record<string, number[]>>({});\n const prompt = useRef<HTMLTextAreaElement>(null);\n const aim = made.find((x) => x.step.id === target);\n const several = aim?.step.type === \"generate\" && (aim.output?.assets?.length ?? 0) > 1;\n const send = () => {\n if (aim && note.trim()) {\n void run.regenerate(step.id, aim.step.id, note.trim(), picked[aim.step.id]);\n }\n };\n return (\n <div className=\"animate-rise\">\n <StepHeading title={step.title} description={step.description} />\n <div className=\"flex flex-col gap-6\">\n {/* A step the run skipped (a branch) has nothing to review. */}\n {view.shown\n .filter((x) => x.output)\n .map(({ step: s, output }) => {\n // A json step's data is edited by its schema, a written one as its text.\n const data = editableData(s) ? s : null;\n const editable =\n Boolean(step.edit) && s.type === \"agent\" && (s.output.format !== \"json\" || !!data);\n const draft = drafts[s.id];\n const heading = (menu: React.ReactNode) => (\n <div className=\"mb-2 flex items-center justify-between gap-3\">\n <h3 className=\"font-medium text-[0.8125rem] text-ink-3 uppercase tracking-[0.06em]\">\n {s.title}\n </h3>\n <div className=\"flex items-center\">\n {editable && !editing[s.id] ? (\n <button\n type=\"button\"\n onClick={() => setEditing((e) => ({ ...e, [s.id]: true }))}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full px-3 text-[0.8125rem] text-ink-2 hover:bg-accent hover:text-ink coarse:h-11\"\n >\n <Pencil className=\"size-3.5\" /> {t(\"run.edit\")}\n </button>\n ) : null}\n {menu}\n </div>\n </div>\n );\n const shown =\n data && output && editable && editing[s.id] ? (\n <div className=\"overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n <DataEditor\n shape={stepShape(data)}\n value={\n draft && typeof draft === \"object\"\n ? draft\n : ((output.json ?? {}) as Record<string, unknown>)\n }\n onChange={(next) => setDrafts((d) => ({ ...d, [s.id]: next }))}\n start=\"edit\"\n />\n </div>\n ) : (\n <OutputView\n base={`${runBase(view.id)}`}\n step={s}\n output={output}\n onView={keepView(view.id, s.id)}\n editable={editable && editing[s.id] && !data}\n draft={typeof draft === \"string\" ? draft : undefined}\n onDraft={(text) => setDrafts((d) => ({ ...d, [s.id]: text }))}\n picked={picked[s.id]}\n onPick={\n step.regenerate\n ? (i) => {\n // Picking a result says what the change is about.\n setTarget(s.id);\n setPicked((p) => {\n const now = p[s.id] ?? [];\n return {\n ...p,\n [s.id]: now.includes(i) ? now.filter((x) => x !== i) : [...now, i],\n };\n });\n prompt.current?.focus();\n }\n : undefined\n }\n onSurfaceAction={\n step.regenerate\n ? () => {\n setTarget(s.id);\n prompt.current?.focus();\n }\n : undefined\n }\n />\n );\n return (\n <section key={s.id}>\n {studio && data && output ? (\n <StudioData runId={view.id} step={data} output={output} header={heading}>\n {shown}\n </StudioData>\n ) : (\n <>\n {heading(null)}\n {shown}\n </>\n )}\n </section>\n );\n })}\n {view.lists.map((list) => (\n <section key={list.def.id}>\n <h3 className=\"mb-2 font-medium text-[0.8125rem] text-ink-3 uppercase tracking-[0.06em]\">\n {list.def.title}\n </h3>\n {list.def.check ? (\n <ListCheck runId={view.id} list={list} />\n ) : (\n <ListTable runId={view.id} list={list} editable />\n )}\n </section>\n ))}\n {step.regenerate && made.length ? (\n // The way to say what should be different: always there, below what it is about.\n <Card className=\"p-3\">\n {made.length > 1 ? (\n <div className=\"flex flex-wrap items-center gap-1.5 px-1 pb-2\">\n <span className=\"mr-1 text-[0.8125rem] text-ink-3\">{t(\"run.feedbackTarget\")}</span>\n {made.map(({ step: s }) => (\n <button\n key={s.id}\n type=\"button\"\n aria-pressed={target === s.id}\n onClick={() => {\n setTarget(s.id);\n prompt.current?.focus();\n }}\n className={cn(\n \"inline-flex h-8 items-center rounded-full px-3 text-[0.8125rem] ring-1 transition coarse:h-11\",\n target === s.id\n ? \"bg-ember-tint text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink\",\n )}\n >\n {s.title}\n </button>\n ))}\n </div>\n ) : null}\n <Textarea\n ref={prompt}\n minRows={2}\n maxRows={8}\n value={note}\n placeholder={t(\"run.feedbackPlaceholder\")}\n onChange={(e) => setNote(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n send();\n }\n }}\n className=\"border-0 bg-transparent shadow-none focus:ring-0\"\n />\n <div className=\"flex items-center justify-between gap-3 px-1 pt-1\">\n <span className=\"min-w-0 text-[0.75rem] text-ink-3\">\n {several\n ? picked[aim.step.id]?.length\n ? t(\"run.regeneratePicked\", {\n n: [...picked[aim.step.id]]\n .sort((x, y) => x - y)\n .map((i) => i + 1)\n .join(\", \"),\n })\n : t(\"run.regenerateAll\")\n : !aim && note.trim()\n ? t(\"run.feedbackPick\")\n : null}\n </span>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n busy={run.busy}\n disabled={!note.trim() || !aim}\n onClick={send}\n >\n <RefreshCw className=\"size-3.5\" /> {t(\"run.regenerateGo\")}\n </Button>\n </div>\n </Card>\n ) : null}\n </div>\n <Footer view={view} run={run} sticky>\n <Button\n size=\"lg\"\n busy={run.busy}\n onClick={() => void run.accept(step.id, Object.keys(drafts).length ? drafts : undefined)}\n >\n {t(\"run.accept\")} <ArrowRight className=\"size-4\" />\n </Button>\n </Footer>\n </div>\n );\n}\n\nfunction Result({\n view,\n run,\n step,\n onRestart,\n studio,\n}: {\n view: RunView;\n run: Run;\n step: ResultStep;\n onRestart?: () => void;\n studio?: boolean;\n}) {\n const made = view.shown.filter((x) => x.output);\n const { Mascot, ShareResultButton } = runnerEnv();\n return (\n <div className=\"animate-rise\">\n <div className=\"mb-8 flex flex-wrap items-center gap-x-4 gap-y-5\">\n <Mascot kind={view.wizard.avatar} costume={view.wizard.costume} size={64} />\n {/* On a phone the title keeps the row; the share button goes below it. */}\n <div className=\"min-w-0 flex-1 basis-[12rem]\">\n <h1 className=\"wizard-title text-balance font-display font-semibold text-[1.75rem] leading-tight tracking-tight sm:text-[2rem]\">\n {step.title}\n </h1>\n {step.message ? <p className=\"mt-1 text-[0.9375rem] text-ink-3\">{step.message}</p> : null}\n </div>\n {ShareResultButton && view.shown.some((x) => x.output) ? (\n <div className=\"max-sm:basis-full\">\n <ShareResultButton view={view} title={`${step.title} · ${view.wizard.title}`} />\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-col gap-6\">\n {/* A step the run skipped (a branch) has made nothing to hand over. */}\n {made.map(({ step: s, output, formats, label }) => {\n const heading = (menu: React.ReactNode) => (\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-3\">\n <h3 className=\"font-display font-semibold text-[1.0625rem]\">{label ?? s.title}</h3>\n <div className=\"flex items-center gap-1\">\n <DownloadButtons\n base={`${runBase(view.id)}`}\n stepId={s.id}\n formats={formats}\n title={label ?? s.title}\n step={s}\n output={output ?? undefined}\n foot={`${view.wizard.title} · ${new Date().toLocaleDateString(runnerEnv().lang)}`}\n />\n {menu}\n </div>\n </div>\n );\n const shown = (\n <TranslatedOutput\n view={view}\n run={run}\n step={s}\n output={output}\n onView={keepView(view.id, s.id)}\n />\n );\n return (\n <Card key={s.id} className=\"p-4 sm:p-5\">\n {studio && editableData(s) && output ? (\n <StudioData runId={view.id} step={s} output={output} header={heading}>\n {shown}\n </StudioData>\n ) : (\n <>\n {heading(null)}\n {shown}\n </>\n )}\n {output?.assets?.some((a) => a.ai) ? (\n // Whoever publishes it has to say so too; the file already does, in its metadata.\n <p className=\"mt-3 text-[0.75rem] text-ink-3 leading-relaxed\">{t(\"ai.publish\")}</p>\n ) : null}\n </Card>\n );\n })}\n {view.lists.map((list) => (\n <Card key={list.def.id} className=\"p-4 sm:p-5\">\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-3\">\n <h3 className=\"font-display font-semibold text-[1.0625rem]\">\n {list.label ?? list.def.title}\n </h3>\n <ListDownloads runId={view.id} list={list} />\n </div>\n <ListTable runId={view.id} list={list} editable />\n </Card>\n ))}\n </div>\n <Footer view={view} run={run}>\n {onRestart ? (\n <Button variant=\"secondary\" onClick={onRestart}>\n <RotateCcw className=\"size-4\" /> {t(\"run.again\")}\n </Button>\n ) : (\n <span />\n )}\n </Footer>\n </div>\n );\n}\n\nfunction Failed({ view, run }: { view: RunView; run: Run }) {\n const { Mascot } = runnerEnv();\n return (\n <div className=\"flex animate-rise flex-col items-center pt-8 text-center\">\n <Mascot kind={view.wizard.avatar} costume={view.wizard.costume} size={90} />\n <h2 className=\"wizard-heading mt-4 font-display font-semibold text-[1.375rem]\">\n {t(\"run.failed\")}\n </h2>\n <p className=\"mt-2 max-w-md text-[0.9375rem] text-ink-3\">\n <LinkedText text={view.error ?? \"\"} />\n </p>\n <div className=\"mt-8 flex gap-3\">\n {view.canBack ? (\n <Button variant=\"ghost\" onClick={() => void run.back()}>\n <ArrowLeft className=\"size-4\" /> {t(\"run.back\")}\n </Button>\n ) : null}\n <Button onClick={() => void run.retry()} busy={run.busy}>\n <RotateCcw className=\"size-4\" /> {t(\"run.retry\")}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * A result in a translated run: as it was made, with the offer to read its text in the run's\n * language; once translated, the translation with the way back to the original.\n */\nfunction TranslatedOutput({\n view,\n run,\n step,\n output,\n onView,\n}: {\n view: RunView;\n run: Run;\n step: Step;\n output: StepOutput | null;\n onView?: (state: Record<string, unknown>) => void;\n}) {\n const [original, setOriginal] = useState(false);\n const [busy, setBusy] = useState(false);\n const base = runBase(view.id);\n const translated = view.translation?.results[step.id];\n if (!(view.translation && output?.text && run.translateResult)) {\n return <OutputView base={base} step={step} output={output} onView={onView} />;\n }\n const shown = translated && !original ? { ...output, text: translated } : output;\n return (\n <>\n <OutputView base={base} step={step} output={shown} onView={onView} />\n <div className=\"mt-3 flex items-center gap-3 text-[0.8125rem] text-ink-3\">\n {translated ? (\n <>\n {original ? null : <span>{t(\"translation.machine\")}</span>}\n <button\n type=\"button\"\n className=\"underline-offset-4 hover:text-ink hover:underline coarse:min-h-11\"\n onClick={() => setOriginal((o) => !o)}\n >\n {t(original ? \"translation.showTranslated\" : \"translation.showOriginal\")}\n </button>\n </>\n ) : (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n busy={busy}\n onClick={async () => {\n setBusy(true);\n await run.translateResult?.(step.id);\n setBusy(false);\n }}\n >\n <Languages className=\"size-4\" />{\" \"}\n {busy ? t(\"translation.working\") : t(\"result.translate\")}\n </Button>\n )}\n </div>\n </>\n );\n}\nexport function RunnerBody({\n run,\n compact,\n onRestart,\n onView,\n stickyProgress,\n studio,\n}: {\n run: RunSource;\n compact?: boolean;\n /** In the studio: a json step's data can be viewed, edited and its JSON Schema read. */\n studio?: boolean;\n onRestart?: () => void;\n onView?: (view: RunView | null) => void;\n /** In a box of its own (an AI app's widget): the progress stays on top while the page scrolls. */\n stickyProgress?: boolean;\n}) {\n const { view } = run;\n setChoiceLabels(view?.translation?.labels);\n useEffect(() => {\n onView?.(view);\n }, [view, onView]);\n useKeyboardInset();\n const awake = useWakeLock(view?.status === \"running\" && !view.ask);\n useDoneSignal(view);\n if (run.notFound) {\n return <div className=\"py-24 text-center text-ink-3\">{t(\"run.notFound\")}</div>;\n }\n if (!view) {\n return (\n <div className=\"flex justify-center py-24 text-ink-4\">\n <Spinner />\n </div>\n );\n }\n const step = view.step;\n let body: React.ReactNode = null;\n if (view.status === \"running\" && view.ask) {\n body = <AskPanel key={view.ask.id} runId={view.id} ask={view.ask} />;\n } else if (view.status === \"running\") {\n body = <Working view={view} compact={compact} awake={awake} />;\n } else if (view.status === \"failed\") {\n body = <Failed view={view} run={run} />;\n } else if (view.status === \"cancelled\") {\n body = <div className=\"py-24 text-center text-ink-3\">{t(\"run.cancelled\")}</div>;\n } else if (step?.type === \"page\") {\n body = <PageForm key={step.id} view={view} run={run} step={step} />;\n } else if (step?.type === \"review\") {\n // A regenerated output is a fresh review: drafts and notes start over.\n const version = view.shown.map((x) => x.output?.at ?? \"\").join(\"|\");\n body = (\n <Review key={`${step.id}:${version}`} view={view} run={run} step={step} studio={studio} />\n );\n } else if (step?.type === \"result\") {\n body = <Result view={view} run={run} step={step} onRestart={onRestart} studio={studio} />;\n }\n // Rows beside their files need the width of the screen.\n const wide =\n step?.type === \"review\" &&\n view.status === \"waiting_input\" &&\n view.lists.some((l) => l.def.check);\n return (\n <div className=\"flex min-h-full flex-col\">\n {stickyProgress ? (\n <div className=\"sticky top-0 z-10\">\n <Progress view={view} />\n </div>\n ) : (\n <Progress view={view} />\n )}\n <div\n className={cn(\n \"safe-x kb-tight mx-auto w-full flex-1\",\n wide\n ? \"max-w-[1240px] py-8\"\n : compact\n ? \"max-w-[620px] py-8\"\n : \"max-w-[640px] py-8 sm:py-16\",\n )}\n >\n {body}\n {run.error && view.status !== \"failed\" ? (\n <div className=\"mt-4 rounded-lg bg-rose-tint px-4 py-3 text-[0.875rem] text-rose\">\n {run.error}\n </div>\n ) : null}\n {view.keeps && view.status !== \"running\" ? (\n <div className=\"mt-10 flex justify-center\">\n <StoreButton runId={view.id} />\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n","import { ApiError, api, type RunSource, runnerEnv, setChoiceLabels } from \"@engenty/wizards-runner\";\nimport type { RunView } from \"@engenty/wizards-shared/run\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\n/** Two missed pings: the stream is taken for dead. */\nconst STALE_MS = 45_000;\n\n/**\n * One run, live: the runtime's stream of the whole view, plus the commands a person gives. The\n * same as the studio's `useRun` (apps/web/src/runner/useRun.ts), on the runner's own client, so\n * it talks to whichever runtime `configureWizards` named. `prefill` starts a page's fields with\n * answers the chat already knows; the person still sees and sends the page.\n */\nexport function useWizardRun(\n runId: string | null,\n prefill: Record<string, unknown> | undefined,\n): RunSource {\n const [view, setView] = useState<RunView | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [notFound, setNotFound] = useState(false);\n const [busy, setBusy] = useState(false);\n const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});\n\n useEffect(() => {\n setView(null);\n setNotFound(false);\n if (!runId) {\n return;\n }\n const { runBase, withBase } = runnerEnv();\n let stopped = false;\n let retry = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let es: EventSource | null = null;\n let lastHeard = Date.now();\n const refresh = async () => {\n try {\n const fresh = await api.get<RunView>(runBase(runId));\n if (!stopped) {\n setView(fresh);\n }\n } catch (err) {\n if (err instanceof ApiError && err.status === 404) {\n stopped = true;\n es?.close();\n setNotFound(true);\n }\n }\n };\n const open = () => {\n clearTimeout(timer);\n es?.close();\n if (stopped) {\n return;\n }\n const stream = new EventSource(withBase(`${runBase(runId)}/stream`), {\n withCredentials: true,\n });\n es = stream;\n lastHeard = Date.now();\n stream.addEventListener(\"view\", (e) => {\n retry = 0;\n lastHeard = Date.now();\n setView(JSON.parse((e as MessageEvent).data));\n });\n stream.addEventListener(\"ping\", () => {\n lastHeard = Date.now();\n });\n stream.onerror = () => {\n stream.close();\n if (stopped || es !== stream) {\n return;\n }\n es = null;\n void refresh();\n retry = Math.min(retry + 1, 6);\n timer = setTimeout(open, 500 * 2 ** retry);\n };\n };\n const watchdog = setInterval(() => {\n if (!stopped && es && Date.now() - lastHeard > STALE_MS) {\n retry = 0;\n open();\n }\n }, 15_000);\n open();\n return () => {\n stopped = true;\n clearTimeout(timer);\n clearInterval(watchdog);\n es?.close();\n };\n }, [runId]);\n\n const command = useCallback(\n async (path: string, body?: unknown) => {\n if (!runId) {\n return false;\n }\n setBusy(true);\n setError(null);\n setFieldErrors({});\n try {\n await api.post(`${runnerEnv().runBase(runId)}/${path}`, body);\n return true;\n } catch (err) {\n if (err instanceof ApiError && err.status === 422 && Array.isArray(err.body?.fields)) {\n setFieldErrors(\n Object.fromEntries(\n err.body.fields.map((f: { field: string; message: string }) => [f.field, f.message]),\n ),\n );\n }\n setError((err as Error).message);\n return false;\n } finally {\n setBusy(false);\n }\n },\n [runId],\n );\n\n // The chat's answers start the page's fields, under what the run already holds.\n const shown = useMemo(() => {\n if (!view || !prefill || view.step?.type !== \"page\") {\n return view;\n }\n const known = Object.fromEntries(\n view.step.fields.filter((f) => f.id in prefill).map((f) => [f.id, prefill[f.id]]),\n );\n return Object.keys(known).length ? { ...view, prefill: { ...known, ...view.prefill } } : view;\n }, [view, prefill]);\n\n setChoiceLabels(view?.translation?.labels);\n return {\n view: shown,\n notFound,\n error,\n busy,\n fieldErrors,\n submitPage: (stepId, values) => command(`pages/${stepId}`, { values }),\n accept: (stepId, edits) => command(`reviews/${stepId}`, { type: \"accept\", edits }),\n regenerate: (stepId, target, note, items) =>\n command(`reviews/${stepId}`, {\n type: \"regenerate\",\n target,\n note,\n items: items?.length ? items : undefined,\n }),\n back: () => command(\"back\"),\n retry: () => command(\"retry\"),\n translateResult: (stepId) => command(\"translate-result\", { stepId }),\n };\n}\n","import {\n useGetFieldValue,\n useIsStreaming,\n useSetFieldValue,\n useTriggerAction,\n} from \"@openuidev/react-lang\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { WIZARD_COMPONENT } from \"./server.js\";\n\n/**\n * What the Wizard component keeps with its message, in OpenUI's state of the message.\n *\n * OpenUI keeps that state as the fields of forms, saves it with the message and restores it when\n * the message is shown again. An action hands the chat the fields of the form it names, or every\n * field where it names none; the chat shows them as “Form data” and gives them to the model. So\n * the run id is a field of its own, which no action names, and the action that reports the\n * result names a form that holds nothing.\n */\n\nconst runField = (token: string) => `wizard:${token}`;\nconst EMPTY_FORM = \"wizard:empty\";\n\n/**\n * The run this message shows: the one it kept, else a new one from `start`. A run starts once\n * the reply has finished streaming, as the token can be half written until then, and once per\n * message, however often React runs the effect (twice in Strict Mode).\n */\nexport function useMessageRun(\n token: string | undefined,\n start: (token: string) => Promise<string>,\n): { runId: string | null; failed: string | null } {\n const streaming = useIsStreaming();\n const getField = useGetFieldValue();\n const setField = useSetFieldValue();\n const [runId, setRunId] = useState<string | null>(null);\n const [failed, setFailed] = useState<string | null>(null);\n const started = useRef<Promise<string> | null>(null);\n\n useEffect(() => {\n if (streaming || runId || failed || !token) {\n return;\n }\n let cancelled = false;\n const take = async () => {\n // OpenUI restores the message's state in an effect of its own, which runs after this one.\n await Promise.resolve();\n if (cancelled) {\n return;\n }\n const kept = getField(undefined, runField(token));\n if (typeof kept === \"string\") {\n setRunId(kept);\n return;\n }\n started.current ??= start(token);\n const id = await started.current;\n if (!cancelled) {\n setRunId(id);\n setField(undefined, WIZARD_COMPONENT, runField(token), id, true);\n }\n };\n take().catch((err: unknown) => {\n if (!cancelled) {\n setFailed(err instanceof Error ? err.message : String(err));\n }\n });\n return () => {\n cancelled = true;\n };\n }, [streaming, runId, failed, token, getField, setField, start]);\n\n return { runId, failed };\n}\n\n/** Tells the chat something as a turn of the person, with `context` for the model. */\nexport function useReport(): (message: string, context: unknown) => void {\n const setField = useSetFieldValue();\n const trigger = useTriggerAction();\n return useCallback(\n (message, context) => {\n setField(EMPTY_FORM, undefined, \"empty\", undefined, false);\n void trigger(message, EMPTY_FORM, { type: \"continue_conversation\", params: { context } });\n },\n [setField, trigger],\n );\n}\n","import {\n api,\n configureRunner,\n type Lang,\n type MascotProps,\n RunnerBody,\n} from \"@engenty/wizards-runner\";\nimport type { PublicWizard, RunTheme, RunView } from \"@engenty/wizards-shared/run\";\nimport { defineComponent } from \"@openuidev/react-lang\";\nimport { type CSSProperties, useEffect, useRef, useState } from \"react\";\nimport { type WizardLookProps, wizardLook } from \"./look.js\";\nimport { useMessageRun, useReport } from \"./message.js\";\nimport { useWizardRun } from \"./run.js\";\nimport { WIZARD_COMPONENT, WIZARD_DESCRIPTION, type WizardProps, wizardProps } from \"./server.js\";\n\nexport interface WizardsConfig {\n /**\n * Where the runtime answers, as the browser reaches it: a path the host proxies to it\n * (`/wizards-runtime`, so the runner's cookie stays first-party) or the runtime's address.\n */\n runtime: string;\n /** The language of the runner's own words: `en` unless given. */\n lang?: Lang;\n /** The wizard's mascot above its pages; a plain dot in the wizard's colour unless given. */\n Mascot?: (props: MascotProps) => React.ReactNode;\n /**\n * The wizard's look here: `host` (your page's own `--wizard-*` variables, nothing of the\n * wizard's), `brand`, `default` or the id of a theme the wizard offers. Unless given, or one the\n * wizard does not offer: its first theme.\n */\n theme?: string;\n /** Light or dark, as your page shows; else what the theme prefers. */\n mode?: \"light\" | \"dark\";\n /** The effects of the wizard's theme the card may draw (`CARD_EFFECTS`); none unless given. */\n effects?: readonly string[];\n}\n\nlet shown: Pick<WizardsConfig, \"theme\" | \"mode\" | \"effects\"> = {};\n\n/** A plain stand-in for the studio's engenty. */\nfunction Dot({ size = 64 }: MascotProps) {\n const d = Math.min(size, 72);\n return (\n <span\n aria-hidden=\"true\"\n className=\"inline-block rounded-full bg-ember\"\n style={{ width: d * 0.6, height: d * 0.6 }}\n />\n );\n}\n\n/** Names the runtime the Wizard component talks to. Once, before the first render. */\nexport function configureWizards(config: WizardsConfig) {\n const base = config.runtime.replace(/\\/+$/, \"\");\n configureRunner({\n lang: config.lang ?? \"en\",\n runBase: (runId) => `/api/runs/${runId}`,\n withBase: (path) => `${base}${path}`,\n asset: (path) => `${base}/${path.replace(/^\\/+/, \"\")}`,\n Mascot: config.Mascot ?? Dot,\n });\n shown = { theme: config.theme, mode: config.mode, effects: config.effects };\n looks.clear();\n}\n\n/** Each wizard's look, asked once a page. */\nconst looks = new Map<string, Promise<RunTheme | null>>();\n\nfunction lookOf(token: string): Promise<RunTheme | null> {\n let found = looks.get(token);\n if (!found) {\n const query = shown.theme ? `?theme=${encodeURIComponent(shown.theme)}` : \"\";\n found = api.get<PublicWizard>(`/api/public/wizards/${encodeURIComponent(token)}${query}`).then(\n (w) => w.brand.theme,\n () => null,\n );\n looks.set(token, found);\n }\n return found;\n}\n\n/** The look of the wizard behind `token` on its card; none for `host`, or while it loads. */\nfunction useLook(token: string): WizardLookProps | null {\n const [look, setLook] = useState<RunTheme | null>(null);\n useEffect(() => {\n if (shown.theme === \"host\") {\n return;\n }\n let live = true;\n void lookOf(token).then((found) => live && setLook(found));\n return () => {\n live = false;\n };\n }, [token]);\n return look ? wizardLook(look, { mode: shown.mode, effects: shown.effects }) : null;\n}\n\n/** Starts a run of the published wizard behind `token`, as a visitor of the runtime. */\nconst startRun = (token: string) =>\n api\n .post<{ runId: string }>(`/api/public/wizards/${encodeURIComponent(token)}/runs`, {})\n .then((started) => started.runId);\n\n/** What the chat hears when a run is done: the result's texts, each cut short. */\nfunction resultContext(view: RunView) {\n const results = Object.entries(view.outputs)\n .filter(([, out]) => typeof out.text === \"string\" && out.text.trim())\n .map(([step, out]) => ({ step, text: (out.text ?? \"\").slice(0, 4000) }));\n return { wizard: view.wizard.title, runId: view.id, results };\n}\n\nfunction WizardRun({ props }: { props: WizardProps }) {\n const { runId, failed } = useMessageRun(props.wizard, startRun);\n const run = useWizardRun(runId, props.prefill);\n const report = useReport();\n const look = useLook(props.wizard);\n\n // The chat hears of a run it saw finish. A message shown again with a done run tells nothing.\n const view = run.view;\n const seenRunning = useRef(false);\n useEffect(() => {\n if (!view) {\n return;\n }\n if (view.status !== \"done\") {\n seenRunning.current = true;\n } else if (seenRunning.current) {\n seenRunning.current = false;\n report(`The wizard “${view.wizard.title}” finished.`, resultContext(view));\n }\n }, [view, report]);\n\n return (\n <div\n {...look}\n style={look?.style as CSSProperties | undefined}\n className=\"engenty-runner overflow-hidden rounded-2xl border border-paper-3 bg-paper\"\n >\n {props.note ? <p className=\"px-5 pt-4 text-[0.9375rem] text-ink-2\">{props.note}</p> : null}\n <div className=\"px-5 pb-6\">\n {failed ? (\n <p className=\"py-10 text-center text-ink-3\">{failed}</p>\n ) : (\n <RunnerBody run={run} compact />\n )}\n </div>\n </div>\n );\n}\n\n/** The component an OpenUI library gets: `Wizard(\"<token>\", \"<note>\", {prefill})`. */\nexport const Wizard = defineComponent({\n name: WIZARD_COMPONENT,\n description: WIZARD_DESCRIPTION,\n props: wizardProps,\n component: ({ props }) => <WizardRun props={props} />,\n});\n"],"mappings":"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ACnB,mBAAmB;CACnB,gBAAgB;CAChB,cAAc;CACd,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,WAAW;CACX,OAAO;EAAE,KAAK;EAAuB,OAAO;CAAuB;CACnE,WAAW;CACX,YAAY;CACZ,UAAU;CACV,WAAW;CACX,SAAS;CACT,YAAY;CACZ,mBAAmB;CACnB,mBAAmB;CACnB,gBAAgB;CAChB,wBACE;CACF,aAAa;CACb,cAAc;CACd,aAAa;CACb,eAAe;CACf,aAAa;CACb,SAAS;CACT,SAAS;CACT,cAAc;CACd,cAAc;CACd,aAAa;CACb,SAAS;CACT,gBAAgB;CAChB,YAAY;CACZ,cAAc;CACd,UAAU;CACV,mBAAmB;CACnB,cAAc;CACd,kBAAkB;CAClB,uBAAuB;CACvB,kBAAkB;CAClB,oBAAoB;CACpB,WAAW;CACX,WAAW;CACX,YAAY;CACZ,eAAe;CACf,UAAU;CACV,WAAW;CACX,eAAe;CACf,kBAAkB;CAClB,UACE;CACF,cACE;CACF,cAAc;CACd,SAAS;CACT,aAAa;CACb,WAAW;CACX,cACE;CACF,cAAc;CACd,eAAe;CACf,aAAa;CACb,aAAa;CACb,eACE;CACF,mBAAmB;CACnB,6BAA6B;CAC7B,mBAAmB;CACnB,cAAc;CACd,oBACE;CACF,yBACE;CACF,mBAAmB;CACnB,4BACE;CACF,0BAA0B;CAC1B,uBAAuB;CACvB,2BAA2B;CAC3B,qBACE;CACF,mBAAmB;CACnB,oBACE;CACF,gBAAgB;CAChB,wBACE;CACF,4BACE;CACF,2BACE;CACF,2BACE;CACF,wBAAwB;CACxB,sBAAsB;CACtB,iBAAiB;CACjB,oBAAoB;CACpB,uBACE;CACF,iBACE;CACF,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,gBAAgB;CAChB,0BAA0B;CAC1B,mBAAmB;CACnB,sBACE;CACF,0BACE;CACF,eAAe;CACf,eAAe;CACf,cAAc;CACd,aAAa;CACb,eAAe;CACf,gBAAgB;CAChB,sBAAsB;CACtB,aAAa;CACb,qBAAqB;CACrB,mBACE;CACF,oBAAoB;CACpB,iBAAiB;CACjB,qBAAqB;CACrB,iBAAiB;CACjB,cAAc;CACd,cAAc;CACd,mBAAmB;CACnB,qBAAqB;CACrB,oBAAoB;CACpB,0BAA0B;CAC1B,iBAAiB;CACjB,mBAAmB;CACnB,oBAAoB;CACpB,eAAe;CACf,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,oBAAoB;CACpB,iBAAiB;CACjB,2BAA2B;CAC3B,gBAAgB;CAChB,qBAAqB;CACrB,YAAY;EACV,KAAK;EACL,OAAO;CACT;CACA,mBAAmB;CACnB,oBAAoB;CACpB,UAAU;CACV,mBAAmB;CACnB,qBAAqB;CACrB,qBAAqB;EACnB,KAAK;EACL,OAAO;CACT;CACA,uBAAuB;CACvB,4BAA4B;CAC5B,uBAAuB;CACvB,2BACE;CACF,cAAc;CACd,eAAe;CACf,oBAAoB;CACpB,sBAAsB;CACtB,oBAAoB;CACpB,qBAAqB;CACrB,sBAAsB;EACpB,KAAK;EACL,OAAO;CACT;CACA,0BAA0B;EACxB,KAAK;EACL,OAAO;CACT;CACA,sBACE;CACF,wBAAwB;CACxB,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;EACf,KAAK;EACL,OAAO;CACT;CACA,uBACE;CACF,oBAAoB;CACpB,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,gBAAgB;EACd,KAAK;EACL,OAAO;CACT;CACA,iBAAiB;CACjB,mBAAmB;CACnB,gBAAgB;CAChB,cAAc;CACd,cAAc;CACd,gBACE;CACF,oBAAoB;CACpB,yBACE;CACF,iBAAiB;CACjB,oBAAoB;CACpB,aACE;CACF,mBAAmB;CACnB,kBAAkB;CAClB,qBAAqB;CACrB,qBAAqB;CACrB,oBAAoB;CACpB,uBAAuB;CACvB,oBAAoB;EAClB,KAAK;EACL,OAAO;CACT;CACA,kBAAkB;CAClB,sBAAsB;CACtB,oBAAoB;CACpB,sBAAsB;CACtB,sBACE;CACF,aAAa;CACb,oBACE;CACF,qBACE;CACF,mBAAmB;CACnB,kBAAkB;CAClB,2BAA2B;CAC3B,iBAAiB;CACjB,uBAAuB;CACvB,eAAe;CACf,wBAAwB;CACxB,sBACE;CACF,eACE;CACF,YAAY;CACZ,kBAAkB;CAClB,oBAAoB;CACpB,mBACE;CACF,eAAe;CACf,kBAAkB;CAClB,mBAAmB;CACnB,oBAAoB;CACpB,YAAY;CACZ,aAAa;CACb,UACE;CACF,WAAW;CACX,QAAQ;CACR,YAAY;CACZ,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,gBAAgB;CAChB,YAAY;CACZ,sBAAsB;EACpB,KAAK;EACL,OAAO;CACT;CACA,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,gBAAgB;CAChB,kBAAkB;CAClB,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CACb,iBAAiB;AACnB,GAmVaC,KAAgC;CAAE,IAAID;CAAU,IAAI;EA/U/D,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,WAAW;EACX,SAAS;EACT,SAAS;EACT,gBAAgB;GACd,KAAK;GACL,OAAO;EACT;EACA,gBAAgB;EAChB,OAAO;EACP,OAAO;EACP,QAAQ;EACR,cAAc;EACd,aAAa;EACb,cAAc;EACd,WAAW;EACX,aAAa;EACb,cAAc;EACd,gBAAgB;EAChB,OAAO;EACP,WAAW;GAAE,KAAK;GAA0B,OAAO;EAA0B;EAC7E,OAAO;EACP,QAAQ;EACR,UAAU;EACV,OAAO;EACP,WAAW;EACX,SAAS;EACT,SAAS;EACT,SAAS;EACT,UAAU;EACV,cAAc;EACd,UAAU;EACV,cAAc;EACd,aAAa;EACb,aAAa;EACb,gBAAgB;EAChB,WAAW;EACX,UAAU;EACV,MAAM;EACN,aAAa;EACb,QAAQ;EACR,SAAS;EACT,YAAY;EACZ,mBAAmB;EACnB,mBAAmB;EACnB,gBAAgB;EAChB,cAAc;EACd,eAAe;GACb,KAAK;GACL,OAAO;EACT;EACA,WAAW;EACX,OAAO;GAAE,KAAK;GAAyB,OAAO;EAA0B;EACxE,WAAW;EACX,YAAY;EACZ,UAAU;EACV,WAAW;EACX,SAAS;EACT,YAAY;EACZ,mBAAmB;EACnB,mBACE;EACF,gBAAgB;EAChB,wBACE;EACF,aAAa;EACb,cAAc;EACd,aAAa;EACb,eAAe;EACf,aAAa;EACb,SAAS;EACT,SAAS;EACT,cAAc;EACd,cAAc;EACd,aAAa;EACb,SAAS;EACT,gBAAgB;EAChB,YAAY;EACZ,cAAc;EACd,UAAU;EACV,mBAAmB;EACnB,cAAc;EACd,kBAAkB;EAClB,uBAAuB;EACvB,kBACE;EACF,oBAAoB;EACpB,WAAW;EACX,WAAW;EACX,YAAY;EACZ,eAAe;EACf,UAAU;EACV,WAAW;EACX,eAAe;EACf,kBAAkB;EAClB,UACE;EACF,cACE;EACF,cAAc;EACd,SAAS;EACT,aAAa;EACb,WACE;EACF,cACE;EACF,cACE;EACF,eAAe;EACf,aAAa;EACb,aAAa;EACb,eACE;EACF,mBAAmB;EACnB,6BAA6B;EAC7B,mBAAmB;EACnB,cAAc;EACd,oBACE;EACF,yBAAyB;EACzB,mBAAmB;EACnB,4BACE;EACF,0BACE;EACF,uBAAuB;EACvB,2BAA2B;EAC3B,qBACE;EACF,mBACE;EACF,oBACE;EACF,gBACE;EACF,wBACE;EACF,4BACE;EACF,2BACE;EACF,2BACE;EACF,wBAAwB;EACxB,sBAAsB;EACtB,iBAAiB;EACjB,oBAAoB;EACpB,uBACE;EACF,iBACE;EACF,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,gBACE;EACF,0BAA0B;EAC1B,mBAAmB;EACnB,sBACE;EACF,0BACE;EACF,eAAe;EACf,eAAe;EACf,cAAc;EACd,aAAa;EACb,eAAe;EACf,gBAAgB;EAChB,sBAAsB;EACtB,aAAa;EACb,qBACE;EACF,mBACE;EACF,oBAAoB;EACpB,iBAAiB;EACjB,qBAAqB;EACrB,iBAAiB;EACjB,cAAc;EACd,cAAc;EACd,mBAAmB;EACnB,qBAAqB;EACrB,oBAAoB;EACpB,0BAA0B;EAC1B,iBAAiB;EACjB,mBAAmB;EACnB,oBAAoB;EACpB,eAAe;EACf,YAAY;EACZ,gBAAgB;EAChB,cAAc;EACd,oBAAoB;EACpB,iBAAiB;EACjB,2BAA2B;EAC3B,gBAAgB;EAChB,qBAAqB;EACrB,YAAY;GACV,KAAK;GACL,OAAO;EACT;EACA,mBAAmB;EACnB,oBAAoB;EACpB,UAAU;EACV,mBAAmB;EACnB,qBAAqB;EACrB,qBAAqB;GACnB,KAAK;GACL,OAAO;EACT;EACA,uBAAuB;EACvB,4BAA4B;EAC5B,uBAAuB;EACvB,2BACE;EACF,cAAc;EACd,eAAe;EACf,oBAAoB;EACpB,sBAAsB;EACtB,oBAAoB;EACpB,qBAAqB;EACrB,sBAAsB;GACpB,KAAK;GACL,OAAO;EACT;EACA,0BAA0B;GACxB,KAAK;GACL,OAAO;EACT;EACA,sBACE;EACF,wBAAwB;EACxB,cAAc;EACd,gBAAgB;EAChB,gBAAgB;EAChB,iBAAiB;GACf,KAAK;GACL,OAAO;EACT;EACA,uBACE;EACF,oBAAoB;EACpB,eAAe;GACb,KAAK;GACL,OAAO;EACT;EACA,gBAAgB;GACd,KAAK;GACL,OAAO;EACT;EACA,iBAAiB;EACjB,mBAAmB;EACnB,gBAAgB;EAChB,cAAc;EACd,cAAc;EACd,gBACE;EACF,oBACE;EACF,yBACE;EACF,iBAAiB;EACjB,oBAAoB;EACpB,aACE;EACF,mBAAmB;EACnB,kBAAkB;EAClB,qBAAqB;EACrB,qBAAqB;EACrB,oBAAoB;EACpB,uBAAuB;EACvB,oBAAoB;GAClB,KAAK;GACL,OAAO;EACT;EACA,kBAAkB;EAClB,sBAAsB;EACtB,oBAAoB;EACpB,sBAAsB;EACtB,sBACE;EACF,aAAa;EACb,oBACE;EACF,qBACE;EACF,mBAAmB;EACnB,kBAAkB;EAClB,2BAA2B;EAC3B,iBAAiB;EACjB,uBAAuB;EACvB,eAAe;EACf,wBAAwB;EACxB,sBACE;EACF,eACE;EACF,YAAY;EACZ,kBAAkB;EAClB,oBAAoB;EACpB,mBACE;EACF,eAAe;EACf,kBAAkB;EAClB,mBAAmB;EACnB,oBAAoB;EACpB,YAAY;EACZ,aAAa;EACb,UACE;EACF,WAAW;EACX,QAAQ;EACR,YAAY;EACZ,YAAY;EACZ,gBAAgB;EAChB,sBAAsB;GACpB,KAAK;GACL,OAAO;EACT;EACA,eAAe;EACf,gBAAgB;EACh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;EACnB,eAAe;EACf,cAAc;EACd,eAAe;EACf,aAAa;EACb,eAAe;EACf,aAAa;EACb,kBAAkB;EAClB,oBAAoB;EACpB,gBAAgB;EAChB,qBAAqB;EACrB,qBAAqB;EACrB,qBAAqB;EACrB,gBAAgB;EAChB,mBAAmB;EACnB,gBACE;EACF,mBACE;EACF,mBAAmB;EACnB,kBAAkB;EAClB,eAAe;EACf,cAAc;EACd,mBAAmB;EACnB,cAAc;EACd,eAAe;EACf,gBAAgB;EAChB,cAAc;EACd,aACE;EACF,gBACE;EACF,oBACE;EACF,aAAa;EACb,aAAa;EACb,YAAY;EACZ,cAAc;EACd,eAAe;EACf,cAAc;EACd,eAAe;EACf,cAAc;EACd,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,gBAAgB;EAChB,kBACE;EACF,eAAe;EACf,eAAe;EACf,mBAAmB;EACnB,kBAAkB;EAClB,gBAAgB;EAChB,iBAAiB;EACjB,aAAa;EACb,mBAAmB;EACnB,cAAc;EACd,kBAAkB;EAClB,iBACE;EACF,mBAAmB;EACnB,sBACE;EACF,sBAAsB;EACtB,mBACE;EACF,oBAAoB;EACpB,oBAAoB;EACpB,cAAc;EACd,iBAAiB;EACjB,kBAAkB;EAClB,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,kBAAkB;EAClB,gBAAgB;EAChB,oBAAoB;EACpB,aAAa;EACb,cAAc;GAAE,KAAK;GAAY,OAAO;EAAY;EACpD,kBAAkB;EAClB,kBACE;EACF,oBAAoB;EACpB,kBAAkB;EAClB,qBAAqB;EACrB,iBAAiB;EACjB,aAAa;GAAE,KAAK;GAAW,OAAO;EAAW;EACjD,aAAa;EACb,aAAa;EACb,gBAAgB;EAChB,qBAAqB;EACrB,cAAc;EACd,eAAe;EACf,eAAe;EACf,oBAAoB;EACpB,wBAAwB;EACxB,uBAAuB;EACvB,eAAe;EACf,gBAAgB;EAChB,YAAY;EACZ,eAAe;EACf,qBACE;EACF,kBAAkB;EAClB,mBAAmB;EACnB,eAAe;EACf,aAAa;EACb,iBACE;EACF,kBAAkB;EAClB,aAAa;EACb,iBAAiB;EACjB,cAAc;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"}
1
+ {"version":3,"file":"index.js","names":["labelOf","id","listeners","EntryRows","Chips","labelOf","fileName","_Fragment","INK","_Fragment","_Fragment","text","labelOf","cell","_Fragment","Segments","labelOf","_Fragment","DOMPurify","columnBaseSchema","z","numberStyleSchema","numberFormatSchema","val","ctx","dateKindSchema","dateStyleSchema","timePrecisionSchema","dateFormatSchema","durationUnitSchema","durationDisplaySchema","durationFormatSchema","selectOptionSchema","selectFormatSchema","textStyleSchema","textFormatSchema","tableColumnSchema","tableColumnsSchema","seen","i","columns","id","tableColumnWireSchema","MS_HOUR","MS_MINUTE","MS_SECOND","fractionDigits","format","formatNumberCell","value","digits","grouping","locale","formatDateCell","formatClock","date","dateStyle","timePrecision","hours","minutes","seconds","precision","formatDurationCell","ms","toIsoDuration","formatTableCell","column","formatSelectCell","ids","labels","option","acc","readNumber","s","opts","n","formatBytes","bytes","formatMoney","amount","currency","key","named","leaves","LEAF_KINDS","objectAt","deeper","depth","of","list","field","f","objectsOf","out","k","shape","at","refProblem","target","root","to","outputShapeSchema","objects","keys","o","ref","problem","shapeOfFields","one","d","fields","titleKey","labelOf$1","about","base","more","CELL","shapeZod","description","meta","c","shapeJsonSchema","schema","title","CONNECTION_KINDS","cellValue","text","SURFACE_COMPONENTS","id$1","surfaceComponentSchema","surfaceComponentsSchema","isPath","v","pointer","data","part","path","bound","worded","row","raw","map","spec","ENGENTY_KINDS","ENGENTY_COSTUMES","THEME_ID","LANGS","LOCALES","isLang","localeOf","code","FIELD_KINDS","isLocationValue","lat","lng","label","isAudioValue","TOOL_IDS","PLUGIN_ID","PLUGIN_TOOL_NAME","TEXT_CLASSES","EFFORTS","ASSET_KINDS","FORMATS","ASPECT_RATIOS","VIDEO_RESOLUTIONS","itemColumnSchema","conditionSchema","whenSchema","cardsSchema","fieldSchema","fieldGroupSchema","nextRuleSchema","rule","stepBase","outputFieldSchema","pageStepSchema","pluginToolIdSchema","agentStepSchema","generateStepSchema","widgetStepSchema","FILM_FORMATS","filmStepSchema","surfaceCandidateSchema","surfaceStepSchema","step","reviewStepSchema","deliverableSchema","shareOptionSchema","resultStepSchema","stepSchema","declaredShape","stepShape","listSchema","connectionSchema","isEmptyValue","conditionsOf","when","conditionMatches","values","a","b","whenHolds","isDecidedField","shownFields","known","page","SLOT_RE","slotTime","m","iso","y","mo","h","mi","wall","slotDayText","slot","lang","itemsTotals","rows","numeric","withAmount","amountOf","round2","net","r","vatRate","parsed","vat","plurals","pluralRules","rules","form","line","count","gapText","item","fillGaps","params","gap","textOf","texts","lineText","NOTES_EN","RUN_NOTES","gapIn","table","noteText","note","own","RUNNER_TEXTS","version","listeners$1","changed","listener","setRunnerLang","next","runnerLangCode","eventText","ev","setChoiceLabels","choiceLabel","t","vars","ApiError","message","status","body","safeJson","createApi","request","res","withBase","headers","onServerError","method","file","none","ability","env","configureRunner","runnerEnv","api","asset","runBase","runId","appCan","appCall","args","appTell","appDownload","event","href","filename","standalone","cn","parts","VARIANTS","Button","forwardRef","rest","variant","disabled","busy","size","className","Spinner","children","IconButton","fieldBase","fieldWidth","Input","Swatch","props","Textarea","inner","useRef","resize","el","lh","max","maxRows","minRows","useLayoutEffect","outer","onChange","Select","placeholder","options","Segmented","selected","on","multi","x","SLIDE","Tabs","buttons","thumb","setThumb","useState","measure","observer","Switch","checked","Label","required","hint","Card","Dialog","useEffect","open","bare","height","tallest","keep","onClose","wide","LinkedText","WHEEL_EVERY_MS","LiveBrowser","image","controls","setText","hidden","setHidden","error","setError","act","err","driving","pending","timer","onWheel","e","dy","box","onBroken","action","caption","MousePointerClick","ToolButton","CornerDownLeft","ArrowUp","ArrowDown","AskPanel","ask","ConfirmPanel","LoginPanel","remember","setRemember","setBusy","answer","Icon","TriangleAlert","PencilLine","setValues","filled","LockKeyhole","ShieldCheck","isTouch","canUseMedia","useKeyboardInset","vv","reveal","update","covered","opened","useWakeLock","held","setHeld","active","lock","stopped","acquire","taken","NOTIFY_KEY","listeners","audio","wanted","setWanted","hasNotifications","appAllows","notifyState","useNotifyState","useSyncExternalStore","notificationsBlocked","enableNotify","worker","disableNotify","chime","now","freq","osc","gain","signalPerson","registration","canShareFiles","shrinkImage","bitmap","scale","canvas","blob","stamp","cameraError","name","hasTorch","track","useCameraStream","video","stream","setStream","cameras","setCameras","torchable","setTorchable","torch","setTorchOn","live","picture","facing","readTorch","devices","MediaSheet","SheetButton","SheetBar","X","camera","Flashlight","FlashlightOff","onFlip","SwitchCamera","CameraStage","actions","asking","CLIP_SECONDS","clipType","type","canRecordClips","CameraDialog","allowVideo","setFacing","mode","setMode","setTaken","recording","setRecording","recorder","deliver","onCapture","multiple","shoot","stopClip","startClip","chunks","rec","mime","ext","clock","onNative","SheetAction","Camera","Video","Check","quiet","cellField","isEntry","setIn","head","copy","obj","tableShape","flat","isTable","isRows","titleOf","entry","Words","Value","cell","word","entries","hit","Link2","EntryTable","Entries","EntryRows$1","EntryCards","Chips$1","Form","items","draft","setDraft","j","entriesIn","fresh","cols","RemoveButton","AddButton","main","short","lists","ChevronRight","Field","onClick","Trash2","Plus","what","DataEditor","offered","modes","setOwn","start","onMode","scope","useId","DataMenu","setOpen","outside","onKey","MoreVertical","fileName$1","JsonSchemaDialog","copied","setCopied","jsx","Copy","url","Download","editableData","StudioData","setSchema","saving","setSaving","output","save","menu","Database","Braces","Fragment","header","GOOD_METRES","REFINE_MS","trouble","LocationField","place","locating","setLocating","watch","typed","latest","hasPoint","supported","stop","onBusy","locate","started","best","pos","accuracy","latitude","longitude","setLabel","MapPin","ExternalLink","LocateFixed","reader","codeReader","Native","formats","detector","source","QrScanner","engine","AppScan","found","onResult","close","ScanDialog","WebScan","qrOnly","setQrOnly","miss","setMiss","photo","tick","fromPhoto","ImageUp","INK$1","OUT","draw","pen","stroke","strokes","w","last","Pad","current","all","paint","ratio","ro","done","onStrokes","SignatureField","setStrokes","accept","PenLine","Eraser","CredentialsForm","submit","connectionId","connector","onCancel","ConnectionField","setForm","link","setLink","connection","Unplug","oauth","popup","inputText","CellInput","boxed","onCommit","ListTable","def","call","run","addRow","hasDraft","editable","commitCell","rowId","columnId","storeFileUrl","safe","inline","ANSWER_TONE","ListCheck","fileColumn","statusColumn","answers","openId","statusOf","isOpen","setSelected","onlyOpen","setOnlyOpen","shown","labelled","titleColumn","restColumns","patch","move","tone","FileText","LIST_FORMAT_LABEL","ListDownloads","StoreButton","setData","confirm","setConfirm","empty","l","MAX_SECONDS","recordingType","transcribeOnDevice","result","resolve","reject","VoiceField","setSeconds","level","setLevel","uploading","setUploading","denied","setDenied","local","setLocal","session","picker","canRecord","transcript","length","began","analyser","samples","frame","meter","peak","fileButton","FileAudio","Square","RotateCcw","Mic","ItemsField","totals","set","col","grid","ci","typingTarget","UploadField","nativeCamera","nativeVideo","names","setNames","setCamera","over","setOver","dragging","setDragging","drag","grab","most","withCamera","clips","room","add","files","free","adding","remove","left","from","sortable","onPaste","tile","index","other","GripVertical","Film","Paperclip","ImagePlus","textHints","ScanInput","ScanLine","SLOT_DAYS","slotDays","days","sorted","day","SlotField","chosenDay","tm","setAll","CardChoice","picked","toggle","src","cards","shut","FieldInput","str","closed","control","view","groupOf","cls","CLASS_GROUP","FACE_WAIT_MS","faces","loadBrandFace","face","wait","fallback","loaded","failed","text$1","sectionLabel","entryShape","kind","long","figures","numbers","leafText","Chips","Leaves","FigureTable","Nested","ordered","Flags","tags","words","tag","EntryRows","flags","metas","EntryCard","longs","JsonView","json","leaf","INK","INK_3","LINK","LINE","TEXT_WIDTH","ENTITIES","plain","untagged","html","runs","token","tokens","look","blocks","_","cell$1","TABLE_LAYOUT","markdownContent","marked","jsonContent","pdfDocument","written","foot","pages","ROBOTO","loading","pdfMake","lib","fonts","pdf","fileName","writePdf","num","assetUrl","prop","points","labelKey","valueKey","p","Children","kids","Node","TONES","labelOf","grouped","groups","by","rank","order","Metas","metasOf","TabsView","setOn","tabs","tab","child","ChecklistView","detailKey","noteKey","noteFormat","groupKey","ticks","keyOf","indexed","detailOf","noteMap","noteOf","lines","Share2","Bars","Line","min","span","xy","DONUT","Donut","total","Titled","badge","declared","eyebrow","subtitle","flagKey","flag","flagged","textKey","minutesKey","time","Clock","Lightbulb","SurfaceView","state","setState","initial","sheet","setSheet","surface","onState","Markdown","useMemo","HtmlFrame","tall","setTall","listen","msg","wrap","width","setWidth","setHtml","alive","layout","flow","fit","doc","Maximize2","AI_ICONS","AiIcon","art","icon","AiBadge","ai","tones","theme","labelFor","CopyButton","setDone","OutputView","onSurfaceAction","onView","film","poster","onPick","images","onDraft","img","FORMAT_LABEL","downloadName","saveFile","ShareFileButton","share","make","Share","SHARES_FILES","DownloadButtons","stepId","made","makePdf","savePdf","inBrowser","Printer","Progress","pct","keepView","StepHeading","kicker","initialValues","typedInputs","PageForm","setPending","first","inputs","prev","Footer","ArrowRight","sticky","ArrowLeft","NotifyToggle","BellRing","Bell","Working","setNow","recent","trail","pictures","Mascot","compact","Sparkles","awake","useDoneSignal","running","since","tell","Review","drafts","setDrafts","editing","setEditing","setNote","setTarget","setPicked","prompt","aim","several","send","heading","Pencil","studio","RefreshCw","Result","ShareResultButton","TranslatedOutput","onRestart","Failed","original","setOriginal","translated","Languages","RunnerBody","stickyProgress","BUILT_IN_THEMES","SHIPPED_FONTS","hex","themeColorsSchema","themeShapeSchema","themeEffectSchema","fontName","SANS","SERIF","SERIFS","serifFamily","family","shippedLike","shippedFontSlug","shippedFontStylesheet","fontStack","lookColours","sheets","loadShippedFont","runtime","loadLookFonts","CARD_EFFECTS","RADIUS","wizardLook","colours","style","effects","STALE_MS","useWizardRun","setView","notFound","setNotFound","fieldErrors","setFieldErrors","retry","es","lastHeard","refresh","watchdog","command","useCallback","prefill","runField","EMPTY_FORM","useMessageRun","streaming","useIsStreaming","getField","useGetFieldValue","setField","useSetFieldValue","setRunId","setFailed","cancelled","kept","WIZARD_COMPONENT","useReport","trigger","useTriggerAction","Dot","configureWizards","config","looks","lookOf","query","useLook","setLook","startRun","resultContext","results","WizardRun","report","seenRunning","Wizard","defineComponent","WIZARD_DESCRIPTION","wizardProps","WizardSpec","addWizard","loadWizards","wizardRules"],"sources":["../../../shared/src/engenty/data-tables/columns.ts","../../../shared/src/engenty/data-tables/columns-format.ts","../../../shared/src/numbers.ts","../../../shared/src/shape.ts","../../../shared/src/store.ts","../../../shared/src/surface.ts","../../../shared/src/definition.ts","../../../shared/src/texts.ts","../../../shared/src/run.ts","../../../shared/src/runner-texts.ts","../../../runner/src/i18n.ts","../../../runner/src/api.ts","../../../runner/src/env.ts","../../../runner/src/ui.tsx","../../../runner/src/browser-live.tsx","../../../runner/src/AskPanel.tsx","../../../runner/src/device.ts","../../../runner/src/camera.tsx","../../../runner/src/data.tsx","../../../runner/src/location.tsx","../../../runner/src/scan.tsx","../../../runner/src/signature.tsx","../../../runner/src/store.tsx","../../../runner/src/voice.tsx","../../../runner/src/fields.tsx","../../../runner/src/fonts.ts","../../../runner/src/json-view.tsx","../../../runner/src/pdf.ts","../../../runner/src/surface.tsx","../../../runner/src/outputs.tsx","../../../runner/src/RunnerView.tsx","../../../shared/src/theme.ts","../../src/openui/fonts.ts","../../src/openui/look.ts","../../src/openui/run.ts","../../src/openui/message.ts","../../src/openui/Wizard.tsx"],"sourcesContent":["// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\n/**\n * Space-table column definitions.\n *\n * A table is a small database, not a CSV dump: every column has a type and a\n * display format. Agents create the definition; row writes are validated\n * against it.\n */\nimport { z } from \"zod\";\n\nconst COLUMN_ID = /^[a-z][a-z0-9_]*$/;\n\nconst columnBaseSchema = z.object({\n description: z.string().max(1024).optional(),\n /**\n * Where the cell is edited. Omit to use the type default:\n * single-line text and booleans are in-field; everything else is a popout.\n */\n edit: z.enum([\"inline\", \"popout\"]).optional(),\n id: z\n .string()\n .min(1)\n .max(64)\n .regex(COLUMN_ID, \"column id must be a lowercase slug (a-z, 0-9, _)\"),\n name: z.string().min(1).max(128),\n required: z.boolean().optional(),\n});\n\nexport const numberStyleSchema = z.enum([\n \"integer\",\n \"decimal\",\n \"percent\",\n \"currency\",\n]);\nexport type NumberStyle = z.infer<typeof numberStyleSchema>;\n\nexport const numberFormatSchema = z\n .object({\n currency: z\n .string()\n .regex(/^[A-Z]{3}$/, \"currency must be an ISO 4217 code\")\n .optional(),\n fractionDigits: z.number().int().min(0).max(8).optional(),\n grouping: z.boolean().optional(),\n style: numberStyleSchema,\n })\n .superRefine((val, ctx) => {\n if (val.style === \"currency\" && !val.currency) {\n ctx.addIssue({\n code: \"custom\",\n message: \"currency style needs an ISO 4217 code\",\n path: [\"currency\"],\n });\n }\n if (val.style !== \"currency\" && val.currency) {\n ctx.addIssue({\n code: \"custom\",\n message: \"currency is only valid on currency columns\",\n path: [\"currency\"],\n });\n }\n });\nexport type NumberFormat = z.infer<typeof numberFormatSchema>;\n\nexport const dateKindSchema = z.enum([\"date\", \"datetime\", \"time\"]);\nexport type DateKind = z.infer<typeof dateKindSchema>;\n\nexport const dateStyleSchema = z.enum([\"short\", \"medium\", \"long\", \"iso\"]);\nexport type DateStyle = z.infer<typeof dateStyleSchema>;\n\n/** `hours` is clock time with no minutes — `14` or `14:30` both store as `14:00`. */\nexport const timePrecisionSchema = z.enum([\"hours\", \"minutes\", \"seconds\"]);\nexport type TimePrecision = z.infer<typeof timePrecisionSchema>;\n\nexport const dateFormatSchema = z.object({\n dateStyle: dateStyleSchema.optional(),\n kind: dateKindSchema,\n timePrecision: timePrecisionSchema.optional(),\n});\nexport type DateFormat = z.infer<typeof dateFormatSchema>;\n\nexport const durationUnitSchema = z.enum([\n \"milliseconds\",\n \"seconds\",\n \"minutes\",\n \"hours\",\n \"days\",\n]);\nexport type DurationUnit = z.infer<typeof durationUnitSchema>;\n\nexport const durationDisplaySchema = z.enum([\n \"hms\",\n \"hours\",\n \"minutes\",\n \"decimal-hours\",\n \"iso\",\n]);\nexport type DurationDisplay = z.infer<typeof durationDisplaySchema>;\n\nexport const durationFormatSchema = z.object({\n display: durationDisplaySchema,\n /** Unit a writer typically types; stored value is always milliseconds. */\n inputUnit: durationUnitSchema,\n});\nexport type DurationFormat = z.infer<typeof durationFormatSchema>;\n\nexport const selectOptionSchema = z.object({\n id: z.string().min(1).max(64),\n label: z.string().min(1).max(128),\n});\nexport type SelectOption = z.infer<typeof selectOptionSchema>;\n\nexport const selectFormatSchema = z.object({\n /** Values outside `options` are kept as-is instead of rejected. */\n allowCustom: z.boolean(),\n multiple: z.boolean().optional(),\n options: z.array(selectOptionSchema).max(200),\n});\nexport type SelectFormat = z.infer<typeof selectFormatSchema>;\n\nexport const textStyleSchema = z.enum([\"single\", \"multiline\", \"markdown\"]);\nexport type TextStyle = z.infer<typeof textStyleSchema>;\n\nexport const textFormatSchema = z.object({\n /** `single` is one line; `multiline` is plain wrapping text; `markdown` is inline marks. */\n style: textStyleSchema.default(\"single\"),\n});\nexport type TextFormat = z.infer<typeof textFormatSchema>;\n\nexport const tableColumnSchema = z.discriminatedUnion(\"type\", [\n columnBaseSchema.extend({\n format: textFormatSchema.optional(),\n type: z.literal(\"text\"),\n }),\n columnBaseSchema.extend({\n format: numberFormatSchema,\n type: z.literal(\"number\"),\n }),\n columnBaseSchema.extend({\n format: dateFormatSchema,\n type: z.literal(\"date\"),\n }),\n columnBaseSchema.extend({\n format: durationFormatSchema,\n type: z.literal(\"duration\"),\n }),\n columnBaseSchema.extend({\n format: selectFormatSchema,\n type: z.literal(\"select\"),\n }),\n columnBaseSchema.extend({ type: z.literal(\"boolean\") }),\n]);\nexport type TableColumn = z.infer<typeof tableColumnSchema>;\n\nexport type ColumnEdit = NonNullable<TableColumn[\"edit\"]>;\n\nexport function textColumnStyle(column: TableColumn): TextStyle {\n return column.type === \"text\" ? (column.format?.style ?? \"single\") : \"single\";\n}\n\n/** Where this cell is edited. Explicit `edit` wins; otherwise type defaults. */\nexport function columnEdit(column: TableColumn): ColumnEdit {\n if (column.edit) {\n return column.edit;\n }\n if (column.type === \"boolean\") {\n return \"inline\";\n }\n if (column.type === \"text\" && textColumnStyle(column) === \"single\") {\n return \"inline\";\n }\n return \"popout\";\n}\n\nexport const tableColumnsSchema = z\n .array(tableColumnSchema)\n .min(1)\n .max(64)\n .superRefine((columns, ctx) => {\n const seen = new Set<string>();\n for (let i = 0; i < columns.length; i++) {\n const id = columns[i]?.id;\n if (!id) {\n continue;\n }\n if (seen.has(id)) {\n ctx.addIssue({\n code: \"custom\",\n message: `duplicate column id \"${id}\"`,\n path: [i, \"id\"],\n });\n }\n seen.add(id);\n }\n });\n\n/**\n * The shape a MODEL is shown for `columns`, as opposed to the one we validate.\n *\n * `tableColumnsSchema` is a six-branch discriminated union that repeats the\n * whole column base per branch. As a tool's JSON Schema that came to 14.7 KB —\n * on its own 5% of a copilot prompt, resent on every model call of every run,\n * whether or not a table is in play. The union earns that as a *contract*; it\n * does not earn it as a *hint*.\n *\n * So the wire shape is one flat object with every format key optional, and the\n * tool re-parses the result with `tableColumnsSchema` before doing anything.\n * Validation is unchanged and the error the model gets back is the strict\n * schema's own; only the advertisement shrinks. Per-type rules live in the\n * tool description, which the model reads anyway.\n */\nexport const tableColumnWireSchema = z.object({\n description: z.string().optional(),\n edit: z.enum([\"inline\", \"popout\"]).optional(),\n format: z\n .object({\n allowCustom: z.boolean().optional(),\n currency: z.string().optional(),\n dateStyle: z.enum([\"short\", \"medium\", \"long\", \"iso\"]).optional(),\n display: durationDisplaySchema.optional(),\n fractionDigits: z.number().int().optional(),\n grouping: z.boolean().optional(),\n inputUnit: durationUnitSchema.optional(),\n kind: dateKindSchema.optional(),\n multiple: z.boolean().optional(),\n options: z.array(selectOptionSchema).optional(),\n // `style` spans text and number columns; which values are legal follows\n // from `type`, and the strict schema is what decides.\n style: z\n .enum([\n \"single\",\n \"multiline\",\n \"markdown\",\n \"integer\",\n \"decimal\",\n \"percent\",\n \"currency\",\n ])\n .optional(),\n timePrecision: timePrecisionSchema.optional(),\n })\n .optional(),\n id: z.string(),\n name: z.string(),\n required: z.boolean().optional(),\n type: z.enum([\"text\", \"number\", \"date\", \"duration\", \"select\", \"boolean\"]),\n});\n\nexport const tableColumnsWireSchema = z.array(tableColumnWireSchema);\nexport type TableColumnWire = z.infer<typeof tableColumnWireSchema>;\n\nexport const DATA_TABLE_ARTIFACT_TYPE = \"database\" as const;\nexport const DATA_TABLE_MIME_TYPE = \"application/vnd.engenty.database+json\";\n\nexport const dataTableHandleSchema = z.object({\n table_id: z.string().uuid(),\n});\nexport type DataTableHandle = z.infer<typeof dataTableHandleSchema>;\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport type {\n DateFormat,\n DurationFormat,\n NumberFormat,\n TableColumn,\n} from \"./columns.js\";\n\nconst MS_HOUR = 3_600_000;\nconst MS_MINUTE = 60_000;\nconst MS_SECOND = 1000;\n\nfunction fractionDigits(format: NumberFormat): number {\n if (format.fractionDigits !== undefined) {\n return format.fractionDigits;\n }\n return format.style === \"integer\" ? 0 : 2;\n}\n\nexport function formatNumberCell(\n value: unknown,\n format: NumberFormat,\n locale = \"en\"\n): string {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return \"\";\n }\n const digits = fractionDigits(format);\n const grouping = format.grouping !== false;\n if (format.style === \"percent\") {\n return new Intl.NumberFormat(locale, {\n maximumFractionDigits: digits,\n minimumFractionDigits: digits,\n style: \"percent\",\n useGrouping: grouping,\n }).format(value);\n }\n if (format.style === \"currency\" && format.currency) {\n return new Intl.NumberFormat(locale, {\n currency: format.currency,\n maximumFractionDigits: digits,\n minimumFractionDigits: digits,\n style: \"currency\",\n useGrouping: grouping,\n }).format(value);\n }\n return new Intl.NumberFormat(locale, {\n maximumFractionDigits: digits,\n minimumFractionDigits: digits,\n useGrouping: grouping,\n }).format(value);\n}\n\nexport function formatDateCell(\n value: unknown,\n format: DateFormat,\n locale = \"en\"\n): string {\n if (typeof value !== \"string\" || value.length === 0) {\n return \"\";\n }\n if (format.kind === \"time\") {\n return formatClock(value, format.timePrecision ?? \"minutes\");\n }\n if (format.dateStyle === \"iso\") {\n return format.kind === \"date\" ? value.slice(0, 10) : value;\n }\n const date =\n format.kind === \"date\" ? new Date(`${value}T00:00:00`) : new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n const dateStyle = format.dateStyle ?? \"medium\";\n if (format.kind === \"date\") {\n return new Intl.DateTimeFormat(locale, { dateStyle }).format(date);\n }\n const timePrecision = format.timePrecision ?? \"minutes\";\n return new Intl.DateTimeFormat(locale, {\n dateStyle,\n timeStyle: timePrecision === \"hours\" ? \"short\" : \"medium\",\n }).format(date);\n}\n\nfunction formatClock(\n value: string,\n precision: NonNullable<DateFormat[\"timePrecision\"]>\n): string {\n const [hours = \"0\", minutes = \"00\", seconds = \"00\"] = value.split(\":\");\n if (precision === \"hours\") {\n return `${hours.padStart(2, \"0\")}:00`;\n }\n if (precision === \"minutes\") {\n return `${hours.padStart(2, \"0\")}:${minutes.padStart(2, \"0\")}`;\n }\n return `${hours.padStart(2, \"0\")}:${minutes.padStart(2, \"0\")}:${seconds.padStart(2, \"0\")}`;\n}\n\nexport function formatDurationCell(\n value: unknown,\n format: DurationFormat\n): string {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return \"\";\n }\n const ms = Math.max(0, Math.round(value));\n if (format.display === \"iso\") {\n return toIsoDuration(ms);\n }\n if (format.display === \"minutes\") {\n return `${Math.round(ms / MS_MINUTE)} min`;\n }\n if (format.display === \"hours\") {\n return `${(ms / MS_HOUR).toFixed(2)} h`;\n }\n if (format.display === \"decimal-hours\") {\n return (ms / MS_HOUR).toFixed(2);\n }\n const hours = Math.floor(ms / MS_HOUR);\n const minutes = Math.floor((ms % MS_HOUR) / MS_MINUTE);\n const seconds = Math.floor((ms % MS_MINUTE) / MS_SECOND);\n return `${hours}:${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`;\n}\n\nfunction toIsoDuration(ms: number): string {\n const hours = Math.floor(ms / MS_HOUR);\n const minutes = Math.floor((ms % MS_HOUR) / MS_MINUTE);\n const seconds = Math.floor((ms % MS_MINUTE) / MS_SECOND);\n const dayPart = hours >= 24 ? `P${Math.floor(hours / 24)}D` : \"P\";\n const h = hours % 24;\n return `${dayPart}T${h}H${minutes}M${seconds}S`;\n}\n\nexport function formatTableCell(\n column: TableColumn,\n value: unknown,\n locale = \"en\"\n): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n switch (column.type) {\n case \"number\":\n return formatNumberCell(value, column.format, locale);\n case \"date\":\n return formatDateCell(value, column.format, locale);\n case \"duration\":\n return formatDurationCell(value, column.format);\n case \"boolean\":\n return value === true ? \"true\" : value === false ? \"false\" : \"\";\n case \"select\":\n return formatSelectCell(column, value);\n default:\n return String(value);\n }\n}\n\nfunction formatSelectCell(\n column: Extract<TableColumn, { type: \"select\" }>,\n value: unknown\n): string {\n const ids = Array.isArray(value) ? value : [value];\n const labels = column.format.options.reduce<Record<string, string>>(\n (acc, option) => {\n acc[option.id] = option.label;\n return acc;\n },\n {}\n );\n return ids\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .map((id) => labels[id] ?? id)\n .join(\", \");\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\n\n/**\n * Numbers as people write and read them: what a phone's number pad, a table cell or a document\n * gives, and an amount or a file's size as a page shows it. The server, the studio and the runner read and\n * show them the same way.\n */\n\n/**\n * A number as a person types it: digits with at most one decimal mark, a point or a comma\n * alike, as a phone's number pad gives it in either language (`1.5`, `1,5`, `89,90`). There are\n * no thousands separators: `1.234` and `1,234` are 1.234, and anything with two marks\n * (`1.234,50`, `1.234.567`) is no number, since only the writer's language could say which mark\n * is which. Text that is not typed (a document, a website) is read by a model into numbers\n * before it gets here. With `units`, what stands around the number is dropped (`38 h`,\n * `19 %`); without, anything but the number makes it none. Null where there is no number.\n */\nexport function readNumber(value: unknown, opts: { units?: boolean } = {}): number | null {\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? value : null;\n }\n if (typeof value !== \"string\") {\n return null;\n }\n const s = opts.units ? value.replace(/[^\\d,.-]/g, \"\") : value.trim();\n if (!/^-?(\\d+([.,]\\d*)?|[.,]\\d+)$/.test(s)) {\n return null;\n }\n const n = Number(s.replace(\",\", \".\"));\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * A file's size for a list, in decimal units as the operating systems show them: `1 KB` for\n * anything below a kilobyte but nothing (`0 KB`), `340 KB`, `2.4 MB`, `1.2 GB`.\n */\nexport function formatBytes(bytes: number): string {\n if (!(bytes > 0)) {\n return \"0 KB\";\n }\n if (bytes < 999_500) {\n return `${Math.max(1, Math.round(bytes / 1000))} KB`;\n }\n if (bytes < 999_950_000) {\n return `${(bytes / 1_000_000).toFixed(1)} MB`;\n }\n return `${(bytes / 1_000_000_000).toFixed(1)} GB`;\n}\n\n/** An amount in a currency, as the language writes it (`1.234,50 €`); an unknown currency code as `1234.50 XYZ`. */\nexport function formatMoney(amount: number, currency: string, locale: string): string {\n try {\n return new Intl.NumberFormat(locale, { style: \"currency\", currency }).format(amount);\n } catch {\n return `${amount.toFixed(2)} ${currency}`;\n }\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { z } from \"zod\";\n\n/**\n * What an agent step's json output holds, in the kinds wizards already use: `output.schema`.\n * Text, numbers, yes/no, a choice, an entry of another list by its id (`ref`), and lists — of\n * these or of objects (entries) with lists of their own — every one with a label. The runtime builds the model's JSON Schema from\n * it, the admin shows and edits the data by it, downloads and views read it.\n *\n * `output.fields`, the short form, compiles to the same shape (`shapeOfFields`); two kinds exist\n * only there: `score` (a decision's levels) and `table` (rows of text or numbers, columns named\n * or picked by the model).\n */\n\n/** Objects nest at most this deep, the step's own object counted. */\nexport const MAX_SHAPE_DEPTH = 4;\n/** At most this many keys in all objects together. */\nexport const MAX_SHAPE_KEYS = 100;\n\ninterface Named {\n /** What people read: a column's head, a part's title, \"add …\". Without one, the key. */\n label?: string;\n /** What the model is to put there. */\n description?: string;\n}\n\nexport type TextShape = Named & { kind: \"text\"; long?: boolean };\nexport type NumberShape = Named & { kind: \"number\"; unit?: string };\nexport type YesNoShape = Named & { kind: \"yesno\"; yes?: string; no?: string };\nexport type ChoiceShape = Named & { kind: \"choice\"; options: string[] };\n/** An entry of a top-level list of the same output, by its `id`. */\nexport type RefShape = Named & { kind: \"ref\"; to: string };\nexport type LeafShape = TextShape | NumberShape | YesNoShape | ChoiceShape | RefShape;\nexport type ListShape = Named & { kind: \"list\"; of: LeafShape | ObjectShape };\nexport interface ObjectShape extends Named {\n kind: \"object\";\n fields: Record<string, FieldShape>;\n}\n/** `fields` only: a decision's levels, lowest first. */\nexport type ScoreShape = Named & { kind: \"score\"; options: string[] };\n/** `fields` only: rows of text or numbers; without columns the model picks them. */\nexport type TableShape = Named & { kind: \"table\"; columns?: string[] };\nexport type FieldShape = LeafShape | ListShape | ScoreShape | TableShape;\n\nconst key = z\n .string()\n .regex(/^[a-zA-Z][a-zA-Z0-9_]{0,40}$/, \"keys are letters, digits and _ and start with a letter\");\n\nconst named = {\n label: z.string().min(1).optional(),\n description: z.string().optional(),\n};\n\nconst leaves = [\n z.object({ kind: z.literal(\"text\"), ...named, long: z.boolean().optional() }),\n z.object({ kind: z.literal(\"number\"), ...named, unit: z.string().optional() }),\n z.object({\n kind: z.literal(\"yesno\"),\n ...named,\n yes: z.string().optional(),\n no: z.string().optional(),\n }),\n z.object({\n kind: z.literal(\"choice\"),\n ...named,\n options: z.array(z.string().min(1)).min(2).max(40),\n }),\n z.object({ kind: z.literal(\"ref\"), ...named, to: key }),\n] as const;\n\nconst LEAF_KINDS = \"text, number, yesno, choice, ref\";\n\n/**\n * The shape of an object `depth` deep, built level by level instead of recursively: JSON Schema\n * of the definition takes no $ref, and the depth is part of the schema. Objects are the entries\n * of lists (and the step's own); a field holding one object would only add a level.\n */\nfunction objectAt(depth: number): z.ZodObject {\n const deeper: z.ZodObject | undefined = depth < MAX_SHAPE_DEPTH ? objectAt(depth + 1) : undefined;\n const of = deeper\n ? z.discriminatedUnion(\"kind\", [...leaves, deeper], {\n error: `A list holds ${LEAF_KINDS} or object.`,\n })\n : z.discriminatedUnion(\"kind\", [...leaves], {\n error: `A list this deep holds ${LEAF_KINDS}: objects nest at most ${MAX_SHAPE_DEPTH} deep.`,\n });\n const list = z.object({ kind: z.literal(\"list\"), ...named, of });\n const field = z.discriminatedUnion(\"kind\", [...leaves, list], {\n error: `\"kind\" is one of ${LEAF_KINDS}, list.`,\n });\n return z.object({\n kind: z.literal(\"object\"),\n ...named,\n fields: z\n .record(key, field)\n .refine((f) => Object.keys(f).length > 0, { message: \"An object has fields.\" }),\n });\n}\n\n/** Every object of a shape with where it sits, the shape's own first. */\nfunction objectsOf(shape: ObjectShape, at: (string | number)[] = []) {\n const out: { shape: ObjectShape; at: (string | number)[] }[] = [{ shape, at }];\n for (const [k, f] of Object.entries(shape.fields)) {\n if (f.kind === \"list\" && f.of.kind === \"object\") {\n out.push(...objectsOf(f.of, [...at, \"fields\", k, \"of\"]));\n }\n }\n return out;\n}\n\n/** The list a `ref` points into: a top-level list of objects with an `id`. Null when it is fine. */\nfunction refProblem(root: ObjectShape, to: string): string | null {\n const target = root.fields[to];\n if (target?.kind !== \"list\" || target.of.kind !== \"object\") {\n return `\"ref\" to \"${to}\": that is no list of objects at the top of the schema.`;\n }\n return target.of.fields.id?.kind === \"text\"\n ? null\n : `\"ref\" to \"${to}\": its entries need an \"id\" text field to be pointed at.`;\n}\n\n/** `output.schema`: what the step returns. */\nexport const outputShapeSchema = (objectAt(1) as unknown as z.ZodType<ObjectShape>).superRefine(\n (shape, ctx) => {\n const objects = objectsOf(shape);\n const keys = objects.reduce((n, o) => n + Object.keys(o.shape.fields).length, 0);\n if (keys > MAX_SHAPE_KEYS) {\n ctx.addIssue({\n code: \"custom\",\n message: `A schema has at most ${MAX_SHAPE_KEYS} keys in all; this one has ${keys}.`,\n });\n }\n for (const o of objects) {\n for (const [k, f] of Object.entries(o.shape.fields)) {\n const ref = f.kind === \"ref\" ? f : f.kind === \"list\" && f.of.kind === \"ref\" ? f.of : null;\n const problem = ref ? refProblem(shape, ref.to) : null;\n if (problem) {\n ctx.addIssue({ code: \"custom\", message: problem, path: [...o.at, \"fields\", k] });\n }\n }\n }\n },\n);\n\n/** An output field as `output.fields` writes it. */\ninterface ShortField {\n id: string;\n kind: string;\n description?: string;\n columns?: string[];\n options?: string[];\n}\n\n/** The short form as a shape: a field per key, a list of text, a table as it is. */\nexport function shapeOfFields(fields: ShortField[]): ObjectShape {\n const one = (f: ShortField): FieldShape => {\n const d = f.description ? { description: f.description } : {};\n switch (f.kind) {\n case \"number\":\n return { kind: \"number\", ...d };\n case \"list\":\n return { kind: \"list\", ...d, of: { kind: \"text\" } };\n case \"yesno\":\n return { kind: \"yesno\", ...d };\n case \"choice\":\n return { kind: \"choice\", ...d, options: f.options ?? [] };\n case \"score\":\n return { kind: \"score\", ...d, options: f.options ?? [] };\n case \"table\":\n return { kind: \"table\", ...d, ...(f.columns?.length ? { columns: f.columns } : {}) };\n default:\n return { kind: \"text\", ...d };\n }\n };\n return { kind: \"object\", fields: Object.fromEntries(fields.map((f) => [f.id, one(f)])) };\n}\n\n/** The key of an entry's title: its first short text other than its `id`. */\nexport function titleKey(shape: ObjectShape): string | undefined {\n return Object.entries(shape.fields).find(\n ([k, f]) => k !== \"id\" && f.kind === \"text\" && !f.long,\n )?.[0];\n}\n\n/** What people read for a key. */\nexport function labelOf(key: string, shape: FieldShape | ListShape[\"of\"]): string {\n return shape.label ?? key;\n}\n\n/**\n * What the model reads about a value beside its title: its description (without label: its key),\n * its unit, a score's order, where a ref points. Undefined where the title says it all.\n */\nfunction about(k: string, s: FieldShape | ListShape[\"of\"]): string | undefined {\n const base = s.description ?? (s.label ? \"\" : k);\n const more =\n s.kind === \"number\" && s.unit\n ? `in ${s.unit}`\n : s.kind === \"score\"\n ? \"lowest to highest\"\n : s.kind === \"ref\"\n ? `the id of an entry of \"${s.to}\"`\n : \"\";\n return (base && more ? `${base} (${more})` : base || more) || undefined;\n}\n\nconst CELL = z.union([z.string(), z.number(), z.null()]);\n\n/** The data a shape describes, as Zod: what a model's answer is checked against. */\nexport function shapeZod(shape: FieldShape | ListShape[\"of\"], k = \"data\"): z.ZodType {\n const description = about(k, shape);\n const meta = {\n ...(shape.label ? { title: shape.label } : {}),\n ...(description ? { description } : {}),\n };\n switch (shape.kind) {\n case \"text\":\n case \"ref\":\n return z.string().meta(meta);\n case \"number\":\n return z.number().meta(meta);\n case \"yesno\":\n return z.boolean().meta(meta);\n case \"choice\":\n case \"score\":\n return z.enum(shape.options as [string, ...string[]]).meta(meta);\n case \"list\":\n return z.array(shapeZod(shape.of, k)).meta(meta);\n case \"object\":\n return z\n .object(\n Object.fromEntries(Object.entries(shape.fields).map(([n, f]) => [n, shapeZod(f, n)])),\n )\n .meta(meta);\n case \"table\":\n return (\n shape.columns?.length\n ? z.array(z.object(Object.fromEntries(shape.columns.map((c) => [c, CELL]))))\n : // Free columns come as columns + rows, which a strict schema takes; stored as records.\n z.object({ columns: z.array(z.string()), rows: z.array(z.array(CELL)) })\n ).meta(meta);\n }\n}\n\n/**\n * The data as JSON Schema (draft 2020-12): every key required, no other keys — what a model's\n * structured output takes, and what developers read.\n */\nexport function shapeJsonSchema(shape: ObjectShape, title?: string): Record<string, unknown> {\n const schema = z.toJSONSchema(shapeZod(shape), { target: \"draft-2020-12\" }) as Record<\n string,\n unknown\n >;\n return title && !shape.label ? { ...schema, title } : schema;\n}\n\n/** A table cell as a table takes it: a list joined by spaces, anything else as text. */\nfunction fitCell(value: unknown): string | number | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\" || typeof value === \"number\") {\n return value;\n }\n if (Array.isArray(value) && value.every((v) => typeof v === \"string\" || typeof v === \"number\")) {\n return value.join(\" \");\n }\n return typeof value === \"boolean\" ? String(value) : JSON.stringify(value);\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n Boolean(v) && typeof v === \"object\" && !Array.isArray(v);\n\n/**\n * Data a model wrote itself, fitted to the shape before it is checked: a number where text\n * belongs as text, a number written as text as a number; in a table a cell's list joined and a\n * missing column empty. Lists stay lists everywhere else.\n */\nexport function fitData(shape: FieldShape | ListShape[\"of\"], value: unknown): unknown {\n switch (shape.kind) {\n case \"text\":\n case \"ref\":\n return typeof value === \"number\" ? String(value) : value;\n case \"number\":\n return typeof value === \"string\" && value.trim() && Number.isFinite(Number(value))\n ? Number(value)\n : value;\n case \"list\":\n return Array.isArray(value) ? value.map((v) => fitData(shape.of, v)) : value;\n case \"object\":\n if (!isRecord(value)) {\n return value;\n }\n return {\n ...value,\n ...Object.fromEntries(\n Object.entries(shape.fields)\n .filter(([k]) => k in value)\n .map(([k, f]) => [k, fitData(f, value[k])]),\n ),\n };\n case \"table\": {\n const columns = shape.columns;\n return columns?.length && Array.isArray(value)\n ? value.map((row) =>\n isRecord(row) ? Object.fromEntries(columns.map((c) => [c, fitCell(row[c])])) : row,\n )\n : value;\n }\n default:\n return value;\n }\n}\n\n/** Tables with free columns come back as columns + rows and are stored as records. */\nexport function recordsOf(shape: FieldShape | ListShape[\"of\"], value: unknown): unknown {\n if (shape.kind === \"table\" && !shape.columns?.length && isRecord(value)) {\n const t = value as { columns?: string[]; rows?: unknown[][] };\n if (t.columns && t.rows) {\n const columns = t.columns;\n return t.rows.map((row) => Object.fromEntries(columns.map((c, i) => [c, row[i] ?? null])));\n }\n }\n if (shape.kind === \"object\" && isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => {\n const f = shape.fields[k];\n return [k, f ? recordsOf(f, v) : v];\n }),\n );\n }\n if (shape.kind === \"list\" && Array.isArray(value)) {\n return value.map((v) => recordsOf(shape.of, v));\n }\n return value;\n}\n\n/** What a value of a shape is, in a word or two: \"list of Rezept\", \"choice: a | b\". */\nfunction kindLine(s: FieldShape | ListShape[\"of\"]): string {\n switch (s.kind) {\n case \"choice\":\n case \"score\":\n return `${s.kind}: ${s.options.join(\" | \")}`;\n case \"ref\":\n return `ref → /${s.to}[].id`;\n case \"table\":\n return s.columns?.length ? `table: ${s.columns.join(\", \")}` : \"table\";\n case \"list\":\n return s.of.kind === \"object\" ? \"list of entries\" : `list of ${s.of.kind}`;\n default:\n return s.kind;\n }\n}\n\n/** The shape as lines of paths a model binds to: \"/recipes[]/title (text): Titel\". */\nexport function shapeLines(shape: ObjectShape, at = \"\"): string[] {\n const out: string[] = [];\n for (const [k, f] of Object.entries(shape.fields)) {\n const path = `${at}/${k}`;\n const words = [f.label, f.description].filter(Boolean).join(\" — \");\n out.push(`- ${path} (${kindLine(f)})${words ? `: ${words}` : \"\"}`);\n if (f.kind === \"list\" && f.of.kind === \"object\") {\n out.push(...shapeLines(f.of, `${path}[]`));\n }\n }\n return out;\n}\n\n/**\n * The shape at a path: keys of objects, an index (digits) into a list. `any` where the data can\n * hold anything (a table's row), undefined where the shape has nothing.\n */\nexport function shapeAt(\n shape: FieldShape | ListShape[\"of\"],\n path: string[],\n): FieldShape | ListShape[\"of\"] | \"any\" | undefined {\n let at: FieldShape | ListShape[\"of\"] = shape;\n for (const part of path) {\n if (at.kind === \"object\") {\n const next: FieldShape | undefined = at.fields[part];\n if (!next) {\n return undefined;\n }\n at = next;\n } else if (at.kind === \"list\" && /^\\d+$/.test(part)) {\n at = at.of;\n } else if (at.kind === \"table\") {\n // A row, and in it whatever columns the model wrote.\n return /^\\d+$/.test(part) ? \"any\" : undefined;\n } else {\n return undefined;\n }\n }\n return at;\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { coerceRowValues, mergeRowValues, type TableColumn } from \"./engenty/data-tables/index.js\";\nimport { readNumber } from \"./numbers.js\";\n\n/**\n * What a wizard keeps between runs for one person: lists (tabular data), files and connected\n * accounts. The wizard definition says which lists and connections exist; the content belongs\n * to the person who ran it.\n */\n\n/** A list is an engenty data table: typed columns, rows of cells keyed by column id. */\nexport interface ListDef {\n id: string;\n title: string;\n description?: string;\n columns: TableColumn[];\n /** Column whose value identifies a row: saving a row with a known key updates it. */\n key?: string;\n /**\n * The rows are gone through one by one in a review: `file` holds the path of a kept file\n * shown beside the row, `status` is a select whose options are the answers (first = open).\n */\n check?: { file?: string; status?: string };\n /** Every run reads and writes the same rows; kept as a table of the space, not per person. */\n shared?: boolean;\n}\n\nexport interface ListRow {\n id: string;\n cells: Record<string, unknown>;\n updatedAt: string;\n}\n\nexport interface StoreFile {\n path: string;\n mime: string;\n size: number;\n /** Where the file came from, in words: \"E-Mail von billing@notion.so, 3.9.2026\". */\n source: string | null;\n updatedAt: string;\n}\n\nexport const STORE_LIMITS = {\n fileBytes: 15_000_000,\n totalBytes: 200_000_000,\n files: 2000,\n rowsPerList: 5000,\n};\n\n/** Kinds of accounts a wizard can ask the person to connect. */\nexport const CONNECTION_KINDS = [\"mail\"] as const;\nexport type ConnectionKind = (typeof CONNECTION_KINDS)[number];\n\n/** An account the person connects: a built-in kind, or one of the project's imported connectors. */\nexport interface ConnectionDef {\n id: string;\n kind?: ConnectionKind;\n /** Id of an imported connector of the project. */\n connector?: string;\n /** Imported connectors: the actions steps may call. Default: every action that only reads. */\n actions?: string[];\n /**\n * Imported connectors: per action, run it without asking (\"allow\") or ask the person first\n * (\"ask\"). Default: reading is allowed, changing asks; deleting always asks.\n */\n policy?: Record<string, \"allow\" | \"ask\">;\n title?: string;\n description?: string;\n /**\n * Share targets only (never in a wizard definition): the connectors the person can pick from,\n * and the provider is asked for no more than `actions` need — a target that sends never asks\n * for the right to read.\n */\n target?: { connectors: string[] };\n}\n\n/** A connector the person can pick for a connection: an OAuth sign-in or a credentials form. */\nexport interface ConnectorOption {\n id: string;\n name: string;\n auth: \"oauth2\" | \"api_key\";\n /** `api_key` connectors: the form, in order. */\n fields?: {\n key: string;\n label: string;\n secret?: boolean;\n placeholder?: string;\n required?: boolean;\n }[];\n /** Shown under the form: where to get the values. */\n hint?: string;\n}\n\nexport interface ConnectionView {\n id: string;\n kind: ConnectionKind | null;\n /** The imported connector behind the connection, if it is one. */\n connector: string | null;\n title: string | null;\n description: string | null;\n /** Set when the person has connected an account. */\n account: { connector: string; label: string; connectedAt: string } | null;\n connectors: ConnectorOption[];\n}\n\n/** One list as a Markdown table of raw cell values — what a model reads. */\nexport function listAsMarkdown(def: ListDef, rows: ListRow[], limit = 200): string {\n if (!rows.length) {\n return \"(empty)\";\n }\n const cols = def.columns;\n const cell = (v: unknown) =>\n v === null || v === undefined\n ? \"\"\n : (Array.isArray(v) ? v.join(\", \") : String(v)).replace(/\\|/g, \"\\\\|\").replace(/\\s+/g, \" \");\n const head = `| ${cols.map((c) => c.id).join(\" | \")} |\\n|${cols.map(() => \" --- \").join(\"|\")}|`;\n const body = rows\n .slice(0, limit)\n .map((r) => `| ${cols.map((c) => cell(r.cells[c.id])).join(\" | \")} |`);\n const more = rows.length > limit ? [`… ${rows.length - limit} more rows`] : [];\n return [head, ...body, ...more].join(\"\\n\");\n}\n\n/**\n * When the first row saved now is stamped, in milliseconds: after every row the list already\n * holds, so a list reads in the order its rows came — also when two saves fall in one\n * millisecond. The rows of one save follow it a millisecond apart.\n */\nexport function firstRowAt(existing: { createdAt: Date }[]): number {\n return existing.reduce((at, row) => Math.max(at, row.createdAt.getTime() + 1), Date.now());\n}\n\n/** The key a row is matched on: trimmed and lower-cased, so \"Notion \" and \"notion\" are one row. */\nexport function rowKey(def: ListDef, cells: Record<string, unknown>): string | null {\n if (!def.key) {\n return null;\n }\n const raw = cells[def.key];\n const key = raw === null || raw === undefined ? \"\" : String(raw).trim().toLowerCase();\n return key || null;\n}\n\n/** A new row's cells, typed by the list's columns. Throws `TableColumnValueError` on a bad value. */\nexport function newCells(def: ListDef, input: Record<string, unknown>): Record<string, unknown> {\n return coerceRowValues(def.columns, input);\n}\n\n/** An existing row's cells with some columns changed; cells of columns the list no longer has are dropped. */\nexport function patchCells(\n def: ListDef,\n current: Record<string, unknown>,\n patch: Record<string, unknown>,\n): Record<string, unknown> {\n const known = new Set(def.columns.map((c) => c.id));\n const kept = Object.fromEntries(Object.entries(current).filter(([id]) => known.has(id)));\n return mergeRowValues(def.columns, kept, patch);\n}\n\n/**\n * What a person typed into a cell, as the value sent for its column; the runtime still checks it\n * against the column. Blank is null; a number or a duration (in the column's input unit) is read\n * as people write it (\"12,5\"); a date and time from the browser's picker, in local time, becomes\n * ISO. What cannot be read goes as typed, for the runtime to refuse and name.\n */\nexport function cellValue(column: TableColumn, text: string): unknown {\n if (text.trim() === \"\") {\n return null;\n }\n switch (column.type) {\n case \"number\":\n case \"duration\":\n return readNumber(text) ?? text;\n case \"boolean\":\n return text === \"true\";\n case \"date\": {\n if (column.format.kind !== \"datetime\") {\n return text;\n }\n const at = new Date(text);\n return Number.isNaN(at.getTime()) ? text : at.toISOString();\n }\n default:\n return text;\n }\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { z } from \"zod\";\nimport { type FieldShape, type ListShape, type ObjectShape, shapeAt } from \"./shape.js\";\n\n/**\n * Surfaces: views composed from a small catalog of native components, bound to a run's data and\n * rendered by the runner itself — themed, on phones, no iframe and nothing to pay per run. A\n * surface is data, not code: only catalog components render, so it needs no sandbox. Between the\n * plain table a review shows and a widget, which is free HTML. As engenty-pro's A2UI catalog\n * (`engenty:core/v1`), kept to what a wizard's result needs.\n *\n * A surface is a flat list of components with ids; the one with id \"root\" is drawn, containers\n * name their children by id. A prop may be a literal or `{ \"path\": \"/json/pointer\" }` into the\n * surface's data. A `List`, `Table` or `Group` repeats over an array: inside a repeated row, a\n * path without a leading slash reads the row (\"name\"), one with a slash the whole data. A path\n * may turn what it reads into words: `map` looks the value up (`{ \"true\": \"im Kühlschrank\" }`),\n * `format` sets it into a text (\"{} Min\").\n */\n\nexport const SURFACE_COMPONENTS = [\n \"Column\",\n \"Text\",\n \"List\",\n \"Row\",\n \"DetailGrid\",\n \"Badge\",\n \"Grid\",\n \"Metric\",\n \"Table\",\n \"Image\",\n \"BarChart\",\n \"LineChart\",\n \"DonutChart\",\n \"Actions\",\n \"Button\",\n \"Tabs\",\n \"Card\",\n \"Fold\",\n \"Group\",\n \"Chips\",\n \"Checklist\",\n \"Steps\",\n \"Link\",\n \"Callout\",\n] as const;\nexport type SurfaceComponentName = (typeof SURFACE_COMPONENTS)[number];\n\n/** Components that hold others by id. */\nconst CONTAINERS: ReadonlySet<string> = new Set([\n \"Column\",\n \"List\",\n \"Grid\",\n \"Actions\",\n \"Card\",\n \"Fold\",\n \"Group\",\n]);\n\n/** The props each component needs. */\nconst REQUIRED: Partial<Record<SurfaceComponentName, string[]>> = {\n Text: [\"text\"],\n Row: [\"title\"],\n DetailGrid: [\"rows\"],\n Badge: [\"label\"],\n Metric: [\"label\", \"value\"],\n Table: [\"rows\"],\n Image: [\"src\"],\n BarChart: [\"points\"],\n LineChart: [\"points\"],\n DonutChart: [\"slices\"],\n Button: [\"label\", \"action\"],\n Tabs: [\"tabs\"],\n Card: [\"title\"],\n Fold: [\"title\", \"children\"],\n Group: [\"children\", \"by\"],\n Chips: [\"items\"],\n Checklist: [\"items\"],\n Steps: [\"items\"],\n Link: [\"title\", \"items\", \"value\", \"view\"],\n Callout: [\"text\"],\n};\n\nexport const SURFACE_ACTIONS = [\"regenerate\", \"open\"] as const;\n\nconst id = z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,40}$/, \"ids are letters, digits, _ and -\");\n\n/** One component: its id, its kind, its children (ids, or a template repeated over an array). */\nexport const surfaceComponentSchema = z.looseObject({\n id,\n component: z.enum(SURFACE_COMPONENTS),\n children: z\n .union([z.array(z.string()), z.object({ path: z.string(), componentId: z.string() })])\n .optional(),\n});\nexport type SurfaceComponent = z.infer<typeof surfaceComponentSchema>;\n\nexport const surfaceComponentsSchema = z.array(surfaceComponentSchema).min(1).max(200);\n\n/** What a run shows: the components and the data they are bound to. */\nexport interface Surface {\n components: SurfaceComponent[];\n data: Record<string, unknown>;\n}\n\nexport interface SurfaceIssue {\n message: string;\n}\n\nconst isPath = (v: unknown): v is { path: string } =>\n Boolean(v && typeof v === \"object\" && !Array.isArray(v) && typeof (v as any).path === \"string\");\n\n/**\n * The ids a component draws: its children, the views of its tabs. A Link's view is drawn only\n * when it is opened, so it is no part of the tree.\n */\nfunction childIds(c: SurfaceComponent): string[] {\n const kids = c.children;\n const ids = Array.isArray(kids) ? [...kids] : kids ? [kids.componentId] : [];\n const tabs = (c as Record<string, unknown>).tabs;\n if (Array.isArray(tabs)) {\n for (const tab of tabs) {\n const child = (tab as Record<string, unknown> | null)?.child;\n if (typeof child === \"string\") {\n ids.push(child);\n }\n }\n }\n return ids;\n}\n\n/** Every `{ path }` in a component's props, with whether it reads a repeated row. */\nfunction pathsOf(c: SurfaceComponent): string[] {\n const out: string[] = [];\n const walk = (v: unknown) => {\n if (isPath(v)) {\n out.push(v.path);\n } else if (Array.isArray(v)) {\n v.forEach(walk);\n } else if (v && typeof v === \"object\") {\n Object.values(v).forEach(walk);\n }\n };\n for (const [key, value] of Object.entries(c)) {\n if (key !== \"id\" && key !== \"component\") {\n walk(\n key === \"children\" && !Array.isArray(value) && isPath(value) ? { path: value.path } : value,\n );\n }\n }\n return out;\n}\n\n/** Props naming a key of the entries a component's `items` (or chart's points) holds. */\nconst ENTRY_KEYS = [\n \"labelKey\",\n \"valueKey\",\n \"flagKey\",\n \"detailKey\",\n \"noteKey\",\n \"groupKey\",\n \"textKey\",\n \"minutesKey\",\n] as const;\n\ntype Shape = FieldShape | ListShape[\"of\"];\n\n/** A path as parts: \"/days/0/label\" from the data, \"meals.slot\" from the entry. */\nconst partsOf = (path: string) =>\n (path.startsWith(\"/\") ? path.slice(1) : path)\n .split(/[./]/)\n .filter(Boolean)\n .map((p) => p.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n\n/**\n * The paths a surface reads, followed through the step's schema from \"root\": a repeated child\n * reads an entry of the list its path names, a Link's view the entry it opens. Every path has to\n * be in the schema, every key a component names in its entries.\n */\nfunction shapeIssues(byId: Map<string, SurfaceComponent>, root: ObjectShape): SurfaceIssue[] {\n const issues: SurfaceIssue[] = [];\n /** The entry drawn: its shape, \"any\" where it can hold anything, undefined outside a list. */\n type Entry = Shape | \"any\" | undefined;\n const seen = new Map<string, Set<Entry>>();\n /** The shape a path reads where `entry` is drawn; \"any\": unchecked. */\n const resolve = (path: string, entry: Entry): Shape | \"any\" | undefined => {\n if (path.startsWith(\"/\")) {\n return shapeAt(root, partsOf(path));\n }\n if (entry === \"any\") {\n return \"any\";\n }\n return entry ? shapeAt(entry, partsOf(path)) : undefined;\n };\n const say = (c: SurfaceComponent, path: string, entry: Entry) =>\n issues.push({\n message:\n !path.startsWith(\"/\") && !entry\n ? `\"${c.id}\" reads \"${path}\" outside a repeated entry; from the data it is \"/${path.replace(/\\./g, \"/\")}\".`\n : `\"${c.id}\" reads \"${path}\", which no data provides.`,\n });\n /** The entries of a list a prop binds, or undefined (and an issue) where it is no list. */\n const entriesOf = (c: SurfaceComponent, value: unknown, entry: Entry): Entry => {\n if (!isPath(value)) {\n return \"any\";\n }\n const at = resolve(value.path, entry);\n if (at === \"any\") {\n return \"any\";\n }\n if (at?.kind === \"list\") {\n return at.of;\n }\n if (at?.kind === \"table\") {\n return at.columns?.length\n ? {\n kind: \"object\",\n fields: Object.fromEntries(at.columns.map((k) => [k, { kind: \"text\" }])),\n }\n : \"any\";\n }\n if (at) {\n issues.push({ message: `\"${c.id}\" reads \"${value.path}\" as a list; it is ${at.kind}.` });\n } else {\n say(c, value.path, entry);\n }\n return undefined;\n };\n const hasKey = (shape: Entry, k: string) =>\n shape === \"any\" || shape === undefined || shape.kind !== \"object\" || k in shape.fields;\n\n const visit = (cid: string, entry: Entry) => {\n const c = byId.get(cid);\n const done = seen.get(cid) ?? new Set();\n if (!c || done.has(entry)) {\n return;\n }\n done.add(entry);\n seen.set(cid, done);\n const props = c as Record<string, unknown>;\n // What the component's items, rows or points hold, for the keys it names in them.\n const listProp = [\"items\", \"rows\", \"points\", \"slices\"].find((k) => isPath(props[k]));\n const items = listProp ? entriesOf(c, props[listProp], entry) : undefined;\n for (const k of ENTRY_KEYS) {\n const named = props[k];\n if (typeof named === \"string\" && items && !hasKey(items, named)) {\n issues.push({\n message: `\"${c.id}\": \"${k}\" names \"${named}\", which its entries do not have.`,\n });\n }\n }\n if (c.component === \"Table\" && Array.isArray(props.columns) && items) {\n for (const col of props.columns as { key?: unknown }[]) {\n if (typeof col?.key === \"string\" && !hasKey(items, col.key)) {\n issues.push({ message: `\"${c.id}\": no column \"${col.key}\" in its rows.` });\n }\n }\n }\n // A Link: title, subtitle and meta read the entry it opens, the rest the entry it sits in.\n const opened = c.component === \"Link\" ? items : undefined;\n if (c.component === \"Link\" && typeof props.key === \"string\" && !hasKey(opened, props.key)) {\n issues.push({ message: `\"${c.id}\": its items have no \"${props.key}\".` });\n }\n for (const [k, value] of Object.entries(props)) {\n if (k === \"id\" || k === \"component\" || k === \"children\" || k === listProp) {\n continue;\n }\n const reads = c.component === \"Link\" && (k === \"title\" || k === \"subtitle\" || k === \"meta\");\n const scope = reads ? opened : entry;\n const paths: string[] = [];\n const walk = (v: unknown) => {\n if (isPath(v)) {\n paths.push(v.path);\n } else if (Array.isArray(v)) {\n v.forEach(walk);\n } else if (v && typeof v === \"object\") {\n Object.values(v).forEach(walk);\n }\n };\n walk(value);\n for (const path of paths) {\n if (resolve(path, scope) === undefined) {\n say(c, path, scope);\n }\n }\n }\n const kids = c.children;\n if (Array.isArray(kids)) {\n for (const k of kids) {\n visit(k, entry);\n }\n } else if (kids) {\n const of = entriesOf(c, { path: kids.path }, entry);\n if (of !== undefined) {\n if (c.component === \"Group\" && typeof props.by === \"string\" && !hasKey(of, props.by)) {\n issues.push({\n message: `\"${c.id}\": \"by\" names \"${props.by}\", which its entries do not have.`,\n });\n }\n visit(kids.componentId, of);\n }\n }\n const tabs = props.tabs;\n if (Array.isArray(tabs)) {\n for (const tab of tabs) {\n const child = (tab as Record<string, unknown> | null)?.child;\n if (typeof child === \"string\") {\n visit(child, entry);\n }\n }\n }\n if (c.component === \"Link\" && typeof props.view === \"string\" && opened !== undefined) {\n visit(props.view, opened);\n }\n };\n if (byId.has(\"root\")) {\n visit(\"root\", undefined);\n }\n return issues;\n}\n\n/**\n * What can be wrong with a surface: an unknown or missing component, no root, a child that is\n * not there, an id twice, a loop, a prop missing, and — given the data keys a run will provide,\n * or the step's schema — a path into data nothing provides.\n */\nexport function validateSurface(raw: unknown, data?: string[] | ObjectShape): SurfaceIssue[] {\n const dataKeys = Array.isArray(data) ? data : undefined;\n const parsed = surfaceComponentsSchema.safeParse(raw);\n if (!parsed.success) {\n return parsed.error.issues.map((i) => ({ message: `${i.path.join(\".\")}: ${i.message}` }));\n }\n const components = parsed.data;\n const issues: SurfaceIssue[] = [];\n const byId = new Map<string, SurfaceComponent>();\n for (const c of components) {\n if (byId.has(c.id)) {\n issues.push({ message: `Duplicate component id \"${c.id}\".` });\n }\n byId.set(c.id, c);\n }\n if (!byId.has(\"root\")) {\n issues.push({ message: 'A surface has a component with id \"root\".' });\n }\n for (const c of components) {\n for (const prop of REQUIRED[c.component] ?? []) {\n if ((c as Record<string, unknown>)[prop] === undefined) {\n issues.push({ message: `${c.component} \"${c.id}\" needs \"${prop}\".` });\n }\n }\n const action = (c as Record<string, unknown>).action;\n if (action !== undefined && !(SURFACE_ACTIONS as readonly unknown[]).includes(action)) {\n issues.push({\n message: `\"${c.id}\": action is one of ${SURFACE_ACTIONS.join(\", \")}.`,\n });\n }\n const children = c.children;\n if (children && !CONTAINERS.has(c.component) && c.component !== \"Table\") {\n issues.push({ message: `${c.component} \"${c.id}\" holds no children.` });\n }\n if (c.component === \"Group\" && (!children || Array.isArray(children))) {\n issues.push({\n message: `Group \"${c.id}\" repeats over a list: children { \"path\", \"componentId\" }.`,\n });\n }\n const tabs = (c as Record<string, unknown>).tabs;\n if (c.component === \"Tabs\" && !(Array.isArray(tabs) && tabs.length >= 2)) {\n issues.push({ message: `Tabs \"${c.id}\" needs at least two tabs: [{ label, child }].` });\n }\n const view = (c as Record<string, unknown>).view;\n const ids = [...childIds(c), ...(typeof view === \"string\" ? [view] : [])];\n for (const child of ids) {\n if (!byId.has(child)) {\n issues.push({ message: `\"${c.id}\" names a child \"${child}\" that is not there.` });\n }\n }\n if (dataKeys) {\n for (const path of pathsOf(c)) {\n const key = path.startsWith(\"/\") ? path.split(\"/\")[1] : null;\n if (key !== null && !dataKeys.includes(key)) {\n issues.push({ message: `\"${c.id}\" reads \"${path}\", which no data provides.` });\n }\n }\n }\n }\n // A child that holds its parent would draw forever.\n const seen = new Set<string>();\n const loops = (cid: string, stack: Set<string>): boolean => {\n if (stack.has(cid)) {\n return true;\n }\n if (seen.has(cid)) {\n return false;\n }\n seen.add(cid);\n const c = byId.get(cid);\n const kids = c ? childIds(c) : [];\n const next = new Set(stack).add(cid);\n return kids.some((k) => loops(k, next));\n };\n if (byId.has(\"root\") && loops(\"root\", new Set())) {\n issues.push({ message: \"Components hold each other in a loop.\" });\n return issues;\n }\n return data && !Array.isArray(data) ? [...issues, ...shapeIssues(byId, data)] : issues;\n}\n\n/** A JSON pointer into data: \"/suppliers/0/name\". */\nexport function pointer(data: unknown, path: string): unknown {\n let at: unknown = data;\n for (const part of path.split(\"/\").slice(1)) {\n if (at === null || typeof at !== \"object\") {\n return undefined;\n }\n at = (at as Record<string, unknown>)[part.replace(/~1/g, \"/\").replace(/~0/g, \"~\")];\n }\n return at;\n}\n\n/**\n * A prop's value: a literal as it is, a path read from the data — or, without a leading slash,\n * from the row a List or Table repeats over.\n */\nexport function bound(value: unknown, data: unknown, row?: unknown): unknown {\n if (!isPath(value)) {\n return value;\n }\n const raw = value.path.startsWith(\"/\")\n ? pointer(data, value.path)\n : row === undefined\n ? undefined\n : pointer(row, `/${value.path.replace(/\\./g, \"/\")}`);\n return worded(raw, value as { map?: unknown; format?: unknown });\n}\n\n/** A value turned into words as its path says: looked up in `map`, set into `format`. */\nexport function worded(raw: unknown, spec: { map?: unknown; format?: unknown }): unknown {\n let v = raw;\n const map = spec.map;\n if (map && typeof map === \"object\" && !Array.isArray(map)) {\n const key = String(v);\n if (Object.hasOwn(map, key)) {\n v = (map as Record<string, unknown>)[key];\n }\n }\n if (typeof spec.format === \"string\" && v !== undefined && v !== null && v !== \"\") {\n v = spec.format.replace(\"{}\", Array.isArray(v) ? v.join(\", \") : String(v));\n }\n return v;\n}\n\n/** What a model needs to compose a surface: the catalog, briefly. */\nexport const SURFACE_GUIDE = `A surface is a flat JSON array of components; the one with id \"root\" is drawn. Containers list their children by id.\nComponents and props (a prop may be a literal or {\"path\": \"/key/...\"} into the data):\n- Column { children: [ids] } — vertical stack (use for root); Column and Grid may also repeat one component per entry: children {\"path\", \"componentId\"}\n- Text { text, variant?: \"h3\"|\"h4\"|\"lead\"|\"body\"|\"muted\" } — \"lead\": the one opening line in the wizard's voice\n- List { children: {\"path\": \"/rows\", \"componentId\": \"<a Row id>\"} } — one Row per array entry; inside, paths without \"/\" read the entry (\"name\")\n- Row { title, subtitle?, meta?, badge?, image? }\n- DetailGrid { rows: [{ label, value }] } — label/value facts\n- Badge { label, tone?: \"default\"|\"success\"|\"warning\"|\"accent\" }\n- Grid { children: [ids], columns?: 2|3|4, min?: rem } — tiles side by side; min: the narrowest a tile gets (14 for cards, so a phone shows one)\n- Metric { label, value, caption? } — a key figure\n- Table { rows: {\"path\": \"/rows\"}, columns?: [{ key, label }] }\n- Image { src: an asset id or {\"path\": ...}, alt? }\n- BarChart / LineChart { title?, points: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n- DonutChart { title?, slices: [{ label, value }] or {\"path\": ...}, labelKey?, valueKey? }\n (labelKey / valueKey: the columns of bound rows that hold the label and the number, e.g. \"name\", \"price\")\n- Actions { children: [Button ids] } / Button { label, action: \"regenerate\"|\"open\" }\n- Tabs { tabs: [{ label, count?, child: id }] } — two to four views of one result; count may bind a list (shows its length)\n- Card { title, eyebrow?, subtitle?, meta?: [values], image?, children?: [ids] } — one thing: a day, a recipe, an offer\n- Fold { title, open?, children: [ids] } — details that open on a tap\n- Group { children: {\"path\", \"componentId\"}, by: \"<key>\", order?: [values] } — entries under a heading per value of a key\n- Chips { items, labelKey?, flagKey?, flag? } — short things at a glance; flagKey marks some (\"bald\")\n- Checklist { items, labelKey?, detailKey?, noteKey?, noteFormat?, noteMap?, groupKey?, groupOrder?, share? } — things to get or do; ticks are kept; a yes/no note needs noteMap: {\"true\": \"da\", \"false\": \"einkaufen\"}\n- Steps { items, textKey?, minutesKey? } — ordered work, numbered, with times\n- Link { title, subtitle?, eyebrow?, meta?, look?: \"row\"|\"card\", items: {\"path\": \"/recipes\"}, key?: \"id\", value: {\"path\": \"recipe_id\"}, view: id } — opens the entry of items whose key is value in a sheet, drawn by view; title, subtitle and meta read that entry, eyebrow the row the Link sits in\n- Callout { text, title?, tone?: \"tip\"|\"note\"|\"warning\" }\nA path may put its value into words: {\"path\": \"in_fridge\", \"map\": {\"true\": \"da\", \"false\": \"einkaufen\"}}, {\"path\": \"minutes\", \"format\": \"{} Min\"}.\nDesign it like an app, not a report: lead with a headline, the key figure or the chips; one Card per thing, never a Table of things; ordered work is Steps, things to get are a Checklist, sets are grouped by their key. A Table only for figures people compare across columns.\nKeep it small: what the person needs to see first, then the details. Never invent numbers: bind them by path.`;\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { z } from \"zod\";\nimport { tableColumnsSchema } from \"./engenty/data-tables/index.js\";\nimport { readNumber } from \"./numbers.js\";\nimport { type ObjectShape, outputShapeSchema, shapeOfFields } from \"./shape.js\";\nimport { isShareTargetId } from \"./sharing.js\";\nimport { CONNECTION_KINDS } from \"./store.js\";\nimport { type SurfaceComponent, surfaceComponentsSchema, validateSurface } from \"./surface.js\";\n\n/** The engenty avatars a wizard can wear. Same cast as engenty's ui-core. */\nexport const ENGENTY_KINDS = [\n \"round\",\n \"drop\",\n \"dome\",\n \"flame\",\n \"oval\",\n \"bean\",\n \"pebble\",\n \"sprout\",\n \"tower\",\n \"wedge\",\n] as const;\nexport type EngentyKind = (typeof ENGENTY_KINDS)[number];\n\n/** The Halloween costumes a wizard's engenty can wear. Same list as the web app's engenty figures. */\nexport const ENGENTY_COSTUMES = [\"witch\", \"devil\", \"bat\", \"pumpkin\"] as const;\n\n/** A theme's id: `halloween`, or `@owner/halloween` for a theme from the catalog (theme.ts). */\nexport const THEME_ID = /^(@[a-z0-9-]{1,39}\\/)?[a-z0-9][a-z0-9-]{0,47}$/;\nexport type EngentyCostume = (typeof ENGENTY_COSTUMES)[number];\n\n// --- languages -------------------------------------------------------------------------------\n\n/**\n * The languages engenty speaks: the studio, the runner, the mails, a wizard's own words. A\n * language joins once its strings are written; English is the one every string has, and what a\n * language still lacks is said in English.\n */\nexport const LANGS = [\"en\", \"de\"] as const;\nexport type Lang = (typeof LANGS)[number];\n\n/** Each language's name, in that language: what a switch or a menu shows. */\nexport const LANG_NAMES: Record<Lang, string> = { en: \"English\", de: \"Deutsch\" };\n\n/** The locale amounts and dates are written in for a language. */\nexport const LOCALES: Record<Lang, string> = { en: \"en-GB\", de: \"de-DE\" };\n\n/** The locale speech is heard and spoken in for a language (recognition, voices). */\nexport const SPEECH_LOCALES: Record<Lang, string> = { en: \"en-US\", de: \"de-DE\" };\n\nexport function isLang(value: unknown): value is Lang {\n return typeof value === \"string\" && (LANGS as readonly string[]).includes(value);\n}\n\n/** The language of a tag such as \"de-AT\", \"fr\" or \"pt_BR\", where engenty speaks it. */\nexport function langOf(tag: string | null | undefined): Lang | null {\n const code = tag?.trim().toLowerCase().split(/[-_]/)[0];\n return isLang(code) ? code : null;\n}\n\n/**\n * The main language of each European country. It holds languages engenty does not speak yet:\n * `langOf` passes over them until they join `LANGS`.\n */\nconst COUNTRY_LANGUAGE: Record<string, string> = {\n AT: \"de\",\n BE: \"nl\",\n BG: \"bg\",\n CH: \"de\",\n CY: \"el\",\n CZ: \"cs\",\n DE: \"de\",\n DK: \"da\",\n EE: \"et\",\n ES: \"es\",\n FI: \"fi\",\n FR: \"fr\",\n GB: \"en\",\n GR: \"el\",\n HR: \"hr\",\n HU: \"hu\",\n IE: \"en\",\n IS: \"is\",\n IT: \"it\",\n LI: \"de\",\n LT: \"lt\",\n LU: \"fr\",\n LV: \"lv\",\n MC: \"fr\",\n MT: \"en\",\n NL: \"nl\",\n NO: \"nb\",\n PL: \"pl\",\n PT: \"pt\",\n RO: \"ro\",\n RS: \"sr\",\n SE: \"sv\",\n SI: \"sl\",\n SK: \"sk\",\n SM: \"it\",\n UA: \"uk\",\n VA: \"it\",\n};\n\n/**\n * The languages a wizard is offered in when its author picks one: English, German and the main\n * languages of Europe. A wizard may name any other real language by its code as well.\n */\nexport const WIZARD_LANGS: readonly string[] = [\n ...new Set([\"en\", \"de\", ...Object.values(COUNTRY_LANGUAGE)]),\n];\n\n/** The country of each European time zone (IANA names, as `Intl` gives them). */\nconst ZONE_COUNTRY: Record<string, string> = {\n \"Europe/Amsterdam\": \"NL\",\n \"Europe/Athens\": \"GR\",\n \"Europe/Belgrade\": \"RS\",\n \"Europe/Berlin\": \"DE\",\n \"Europe/Bratislava\": \"SK\",\n \"Europe/Brussels\": \"BE\",\n \"Europe/Bucharest\": \"RO\",\n \"Europe/Budapest\": \"HU\",\n \"Europe/Busingen\": \"DE\",\n \"Europe/Copenhagen\": \"DK\",\n \"Europe/Dublin\": \"IE\",\n \"Europe/Helsinki\": \"FI\",\n \"Europe/Kiev\": \"UA\",\n \"Europe/Kyiv\": \"UA\",\n \"Europe/Lisbon\": \"PT\",\n \"Europe/Ljubljana\": \"SI\",\n \"Europe/London\": \"GB\",\n \"Europe/Luxembourg\": \"LU\",\n \"Europe/Madrid\": \"ES\",\n \"Europe/Malta\": \"MT\",\n \"Europe/Monaco\": \"MC\",\n \"Europe/Oslo\": \"NO\",\n \"Europe/Paris\": \"FR\",\n \"Europe/Prague\": \"CZ\",\n \"Europe/Riga\": \"LV\",\n \"Europe/Rome\": \"IT\",\n \"Europe/San_Marino\": \"SM\",\n \"Europe/Sofia\": \"BG\",\n \"Europe/Stockholm\": \"SE\",\n \"Europe/Tallinn\": \"EE\",\n \"Europe/Vaduz\": \"LI\",\n \"Europe/Vatican\": \"VA\",\n \"Europe/Vienna\": \"AT\",\n \"Europe/Vilnius\": \"LT\",\n \"Europe/Warsaw\": \"PL\",\n \"Europe/Zagreb\": \"HR\",\n \"Europe/Zurich\": \"CH\",\n \"Atlantic/Canary\": \"ES\",\n \"Atlantic/Madeira\": \"PT\",\n \"Atlantic/Reykjavik\": \"IS\",\n \"Asia/Nicosia\": \"CY\",\n};\n\n/**\n * The person's own language beside English: the first of their languages (the browser's, in\n * its order) that engenty speaks, else the main language of the country their time zone lies\n * in; null where neither names one.\n */\nexport function localLang(languages: readonly string[], timeZone?: string | null): Lang | null {\n for (const tag of languages) {\n const found = langOf(tag);\n if (found && found !== \"en\") {\n return found;\n }\n }\n const country = timeZone ? ZONE_COUNTRY[timeZone] : undefined;\n const found = country ? langOf(COUNTRY_LANGUAGE[country]) : null;\n return found === \"en\" ? null : found;\n}\n\n/**\n * A language a wizard can be translated into: any language, by its two- or three-letter code\n * (\"fr\", \"it\", \"pl\"), not only those of `LANGS`.\n */\nexport const LANG_CODE = /^[a-z]{2,3}$/;\n\n/** The code of a tag such as \"fr-CA\" or \"pt_BR\"; null where it names no language. */\nexport function langCodeOf(tag: string | null | undefined): string | null {\n const code = tag?.trim().toLowerCase().split(/[-_]/)[0] ?? \"\";\n return LANG_CODE.test(code) ? code : null;\n}\n\n/**\n * A real language, as the platform's own language data knows it: \"it\" and \"nb\" are, \"xx\" is\n * not. The schema only checks the shape of a code; this checks that it names a language.\n */\nexport function isRealLanguage(code: string): boolean {\n if (!LANG_CODE.test(code)) {\n return false;\n }\n try {\n return Boolean(new Intl.DisplayNames([\"en\"], { type: \"language\", fallback: \"none\" }).of(code));\n } catch {\n return false;\n }\n}\n\n/** The language engenty's own strings are read in for any language: itself where they are written, else English. */\nexport function textLang(code: string): Lang {\n return isLang(code) ? code : \"en\";\n}\n\n/**\n * The language the person reads, for a wizard translated on request: the first of their\n * languages (the browser's, in its order), else the main language of the country their time\n * zone lies in. Any language, not only one engenty's own strings are written in.\n */\nexport function viewerLang(languages: readonly string[], timeZone?: string | null): string | null {\n for (const tag of languages) {\n const code = langCodeOf(tag);\n if (code) {\n return code;\n }\n }\n const country = timeZone ? ZONE_COUNTRY[timeZone] : undefined;\n return country ? langCodeOf(COUNTRY_LANGUAGE[country]) : null;\n}\n\n/** A language's name in that language, as a switch shows it: \"Italiano\", \"Polski\". */\nexport function langName(code: string): string {\n if (isLang(code)) {\n return LANG_NAMES[code];\n }\n try {\n const name = new Intl.DisplayNames([code], { type: \"language\" }).of(code) ?? code;\n return name.charAt(0).toLocaleUpperCase(code) + name.slice(1);\n } catch {\n return code.toUpperCase();\n }\n}\n\n/** A language's name in English, for a model told what to write in: \"Italian\". */\nexport function langNameEn(code: string): string {\n try {\n return new Intl.DisplayNames([\"en\"], { type: \"language\" }).of(code) ?? code;\n } catch {\n return code;\n }\n}\n\n/** The locale amounts, dates and plural forms are written in for any language. */\nexport function localeOf(code: string): string {\n return isLang(code) ? LOCALES[code] : code;\n}\n\n/** The locale speech is recognised and read aloud in for any language. */\nexport function speechLocaleOf(code: string): string {\n return isLang(code) ? SPEECH_LOCALES[code] : code;\n}\n\nexport const FIELD_KINDS = [\n \"text\",\n \"textarea\",\n \"number\",\n \"select\",\n \"multiselect\",\n \"date\",\n \"email\",\n \"url\",\n \"toggle\",\n \"color\",\n \"image\",\n \"file\",\n \"items\",\n \"connection\",\n \"list\",\n \"location\",\n \"audio\",\n \"signature\",\n \"slot\",\n] as const;\nexport type FieldKind = (typeof FIELD_KINDS)[number];\n\n/**\n * How a field is answered without the page's form: `typed` as text, `tapped` from its choices,\n * `value` as a plain value (a colour, line items, a place), `device` only with the person's\n * device or account (a file, a recording, a signature, a connection, a kept list). The chat\n * types and taps; an AI client over MCP gives every way but `device`.\n */\nexport type FieldWay = \"typed\" | \"tapped\" | \"value\" | \"device\";\n\nexport const FIELD_WAYS: Record<FieldKind, FieldWay> = {\n text: \"typed\",\n textarea: \"typed\",\n number: \"typed\",\n date: \"typed\",\n email: \"typed\",\n url: \"typed\",\n select: \"tapped\",\n multiselect: \"tapped\",\n slot: \"tapped\",\n toggle: \"tapped\",\n color: \"value\",\n items: \"value\",\n location: \"value\",\n image: \"device\",\n file: \"device\",\n audio: \"device\",\n signature: \"device\",\n connection: \"device\",\n list: \"device\",\n};\n\n/**\n * What a `location` field holds: where the person stands (from the device), a place they typed,\n * or both — the label is then the address of the position.\n */\nexport interface LocationValue {\n lat?: number;\n lng?: number;\n /** Radius in metres the device vouches for. */\n accuracy?: number;\n label?: string;\n}\n\n/** What an `audio` field holds: the recording, and what is said in it once it was listened to. */\nexport interface AudioValue {\n /** Upload id of the recording. */\n asset: string;\n seconds?: number;\n transcript?: string;\n /** The language the runner was in when the note was taken: what it is most likely spoken in. */\n lang?: Lang;\n}\n\nexport function isLocationValue(v: unknown): v is LocationValue {\n if (!v || typeof v !== \"object\" || Array.isArray(v)) {\n return false;\n }\n const { lat, lng, label } = v as LocationValue;\n return (\n (typeof lat === \"number\" && typeof lng === \"number\") ||\n (typeof label === \"string\" && label.trim().length > 0)\n );\n}\n\nexport function isAudioValue(v: unknown): v is AudioValue {\n return Boolean(\n v &&\n typeof v === \"object\" &&\n typeof (v as AudioValue).asset === \"string\" &&\n (v as AudioValue).asset,\n );\n}\n\n/** A position the way a person reads it: \"Hauptplatz 1, Graz (47.07071, 15.43950, ±12 m)\". */\nexport function locationText(v: LocationValue): string {\n const point =\n typeof v.lat === \"number\" && typeof v.lng === \"number\"\n ? `${v.lat.toFixed(5)}, ${v.lng.toFixed(5)}${v.accuracy ? `, ±${Math.round(v.accuracy)} m` : \"\"}`\n : \"\";\n const label = v.label?.trim() ?? \"\";\n return label && point ? `${label} (${point})` : label || point;\n}\n\n/** A field takes at most this many files. */\nexport const MAX_FILES = 30;\n\nexport const TOOL_IDS = [\n \"web_search\",\n \"web_fetch\",\n \"browser\",\n \"sandbox\",\n \"image\",\n \"http\",\n \"pages\",\n \"code\",\n] as const;\n\n/**\n * A tool a plugin of the runtime adds: `<plugin id>.<tool name>`. A wizard that names one runs\n * only where that plugin is installed.\n */\nexport const PLUGIN_ID = /^[a-z][a-z0-9-]{0,39}$/;\nexport const PLUGIN_TOOL_NAME = /^[a-z][a-z0-9_]{0,39}$/;\nexport type PluginToolId = `${string}.${string}`;\n\n/** The plugin and the tool a step's tool id names, or null for one of the built-in tools. */\nexport function pluginToolOf(id: string): { plugin: string; tool: string } | null {\n const [plugin, tool, ...rest] = id.split(\".\");\n return tool !== undefined &&\n rest.length === 0 &&\n PLUGIN_ID.test(plugin) &&\n PLUGIN_TOOL_NAME.test(tool)\n ? { plugin, tool }\n : null;\n}\n\n/**\n * The kinds of model a step can ask for. A step names a class; which model serves it is bound\n * outside the wizard (the model-gateway, or the settings of a runtime that runs alone).\n */\nexport const TEXT_CLASSES = [\"classifier\", \"standard\", \"high\", \"highest\"] as const;\nexport type TextClass = (typeof TEXT_CLASSES)[number];\nexport const MODEL_CLASSES = [...TEXT_CLASSES, \"image\", \"video\", \"audio\", \"speech\"] as const;\nexport type ModelClass = (typeof MODEL_CLASSES)[number];\n/** How hard the model should think, where the bound model can be told. */\nexport const EFFORTS = [\"low\", \"medium\", \"high\"] as const;\nexport type Effort = (typeof EFFORTS)[number];\nexport type ToolId = (typeof TOOL_IDS)[number];\n\nexport const ASSET_KINDS = [\"image\", \"video\", \"voice\", \"document\", \"dashboard\"] as const;\nexport type AssetKind = (typeof ASSET_KINDS)[number];\n\nexport const FORMATS = [\n \"png\",\n \"mp4\",\n \"mp3\",\n \"pdf\",\n \"docx\",\n \"html\",\n \"md\",\n \"txt\",\n \"csv\",\n \"xlsx\",\n \"json\",\n \"zip\",\n] as const;\nexport type Format = (typeof FORMATS)[number];\n\nexport const ASPECT_RATIOS = [\"1:1\", \"16:9\", \"9:16\", \"4:5\", \"3:2\", \"2:3\"] as const;\n\n/** What a video model renders at: 720p unless the step asks for less. Never more. */\nexport const VIDEO_RESOLUTIONS = [\"720p\", \"480p\"] as const;\nexport type VideoResolution = (typeof VIDEO_RESOLUTIONS)[number];\n\nconst id = z\n .string()\n .regex(/^[a-zA-Z][a-zA-Z0-9_]{0,40}$/, \"ids are letters, digits and _ and start with a letter\");\n\nexport const itemColumnSchema = z.object({\n id,\n label: z.string().min(1),\n kind: z.enum([\"text\", \"number\", \"money\"]),\n});\n\nexport const CONDITION_OPS = [\n \"equals\",\n \"notEquals\",\n \"in\",\n \"notEmpty\",\n \"empty\",\n \"gt\",\n \"lt\",\n \"contains\",\n] as const;\nexport type ConditionOp = (typeof CONDITION_OPS)[number];\n\n/**\n * One test on what the run knows: an answer by field id, an output of an agent step as\n * \"steps.<step>.<field>\", or how many rows a stored list has as \"lists.<list>.count\".\n */\nexport const conditionSchema = z.object({\n field: z.string(),\n op: z.enum(CONDITION_OPS),\n value: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]).optional(),\n});\nexport type Condition = z.infer<typeof conditionSchema>;\n\n/** One condition, or several that must all hold. */\nexport const whenSchema = z.union([conditionSchema, z.array(conditionSchema).min(1)]);\nexport type When = z.infer<typeof whenSchema>;\n\n/** What a card of a choice shows: the columns of the table the choices come from. */\nexport const cardsSchema = z.object({\n label: z.string().min(1),\n value: z.string().optional(),\n image: z.string().optional(),\n subtitle: z.string().optional(),\n meta: z.string().optional(),\n link: z.string().optional(),\n});\nexport type CardsDef = z.infer<typeof cardsSchema>;\n\n/** A choice drawn as a card, as the runner gets it. */\nexport interface CardOption {\n value: string;\n label: string;\n image?: string;\n subtitle?: string;\n meta?: string;\n link?: string;\n}\n\nexport const fieldSchema = z.object({\n id,\n label: z.string().min(1),\n kind: z.enum(FIELD_KINDS),\n required: z.boolean().optional(),\n placeholder: z.string().optional(),\n help: z.string().optional(),\n /**\n * Choices for select / multiselect. slot: the appointment times offered, as ISO 8601 date-times\n * with their offset (\"2026-10-12T09:00:00+02:00\").\n */\n options: z.array(z.string()).optional(),\n default: z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]).optional(),\n /** Line-item columns for `items`. A row's amount is the product of its number and money columns. */\n columns: z.array(itemColumnSchema).optional(),\n /** VAT for `items`: a fixed rate in percent, or the id of a number/select field holding it. */\n vat: z.object({ rate: z.number().optional(), field: z.string().optional() }).optional(),\n currency: z.string().optional(),\n /** image / file: several files; the value is then a list, in the order the person put them. */\n multiple: z.boolean().optional(),\n /** image / file with `multiple`: how many files at least and at most (up to 30). */\n min: z.number().int().min(1).max(MAX_FILES).optional(),\n max: z.number().int().min(1).max(MAX_FILES).optional(),\n /** file: also offer the camera, for documents the person only has on paper. Images always offer it. */\n camera: z.boolean().optional(),\n /** file: the camera also records short video clips. */\n video: z.boolean().optional(),\n /**\n * file: a recording (video or audio) is listened to before the next step runs — what is said,\n * piece by piece between pauses, with exact times. Read as {{field.speech}}.\n */\n listen: z.boolean().optional(),\n /** text: also fill it by scanning a QR code or barcode with the camera. */\n scan: z.boolean().optional(),\n /** connection: id of the wizard connection the person connects here. */\n connection: z.string().optional(),\n /** list: id of the wizard list shown here for the person to check and correct. */\n list: z.string().optional(),\n /**\n * What the field starts with, from an earlier step: \"steps.<id>\" or \"steps.<id>.<key>\". An\n * `items` field takes a table whose columns are its column ids; the person corrects it.\n */\n prefill: z.string().optional(),\n /**\n * The field is shown only while this holds. It reads an answer of this page (decided as the\n * person types) or anything known before the page. A hidden field is not asked and not kept.\n */\n when: whenSchema.optional(),\n /**\n * select / multiselect / slot: the choices come from earlier data — a list output\n * (\"steps.<id>.<key>\"), a column of a table output (\"steps.<id>.<key>.<column>\") or a column\n * of a stored list (\"lists.<id>.<column>\"). `options` stand in while that data is empty.\n */\n optionsFrom: z.string().optional(),\n /**\n * select / multiselect with `optionsFrom` naming a table output (\"steps.<id>.<key>\"): each row\n * is a choice drawn as a card. The columns that hold what the card shows; `value` (default:\n * `label`) is what the answer holds, `link` a page the card opens.\n */\n cards: cardsSchema.optional(),\n /**\n * The field is shown when a decision, made as the run reaches the page, finds this statement\n * true of the run (\"The complaint is about a damaged article\").\n */\n ask: z.string().min(1).optional(),\n /** The id of one of the page's `groups`: of a group's fields a decision shows one (or none). */\n group: z.string().optional(),\n});\nexport type Field = z.infer<typeof fieldSchema>;\n\nexport const fieldGroupSchema = z.object({\n id,\n /** What the decision picks: \"How should we reach the person?\" */\n instructions: z.string().min(1),\n /** True when showing none of the group's fields is a valid answer. */\n optional: z.boolean().optional(),\n});\n\nexport const nextRuleSchema = z\n .object({\n /** The rule holds when this holds … */\n when: whenSchema.optional(),\n /**\n * … or, instead, when a decision finds this statement true of the run (\"The person wants a\n * refund\"). All `ask` rules of a step are decided together, after no `when` rule matched.\n */\n ask: z.string().min(1).optional(),\n /**\n * A step id, or \"end\". A rule with neither `when` nor `ask` is the step's \"otherwise\": where\n * the run goes when no other rule holds, in place of the next step in the list.\n */\n goto: z.string(),\n /**\n * How often this rule may send the run on in one run; afterwards it is skipped. Meant for a\n * branch back to an earlier step (a loop), which without it is taken at most ten times.\n */\n max: z.number().int().min(1).max(50).optional(),\n })\n .refine((rule) => rule.when === undefined || rule.ask === undefined, {\n message: 'A branch has \"when\" or \"ask\", not both.',\n });\nexport type NextRule = z.infer<typeof nextRuleSchema>;\n\nconst stepBase = {\n id,\n title: z.string().min(1),\n description: z.string().optional(),\n next: z.array(nextRuleSchema).optional(),\n};\n\nexport const outputFieldSchema = z\n .object({\n id,\n kind: z.enum([\"text\", \"number\", \"list\", \"table\", \"yesno\", \"choice\", \"score\"]),\n /** What the field holds; for `yesno`, `choice` and `score` the question it answers. */\n description: z.string().optional(),\n /** Table only: the exact column keys every row has — what a widget reads. */\n columns: z.array(z.string().min(1)).optional(),\n /** Choice: the options, one of which is the answer. Score: the levels, lowest first. */\n options: z.array(z.string().min(1)).min(2).max(40).optional(),\n })\n .refine(\n (field) =>\n (field.kind !== \"choice\" && field.kind !== \"score\") || Boolean(field.options?.length),\n { message: \"A choice or score field lists its options.\", path: [\"options\"] },\n )\n .refine((field) => field.kind !== \"score\" || (field.options?.length ?? 0) <= 10, {\n message: \"A score has at most ten levels.\",\n path: [\"options\"],\n });\n\nexport const pageStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"page\"),\n fields: z.array(fieldSchema).min(1),\n /** Fields of which a decision shows one: see `group` on a field. */\n groups: z.array(fieldGroupSchema).max(6).optional(),\n cta: z.string().optional(),\n});\n\n/** A plugin's tool as a step names it: `<plugin>.<tool>`. */\nconst pluginToolIdSchema = z.templateLiteral([\n z.string().regex(PLUGIN_ID),\n \".\",\n z.string().regex(PLUGIN_TOOL_NAME),\n]);\n\nexport const agentStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"agent\"),\n /** What the agent does. A template: {{field}}, {{steps.id}}, {{brand.name}}. Empty with `call`. */\n instructions: z.string().default(\"\"),\n /**\n * One tool of a plugin, called once with these inputs and no model: its answer is the step's\n * json output, as it is. For data a later page shows unchanged (free appointment times), where\n * a model would only copy it. String inputs are templates; a filled-in whole number or\n * true/false is passed as one, an empty one is left out.\n */\n call: z\n .object({\n tool: pluginToolIdSchema,\n input: z.record(z.string(), z.unknown()).default({}),\n })\n .optional(),\n tools: z.array(z.union([z.enum(TOOL_IDS), pluginToolIdSchema])).default([]),\n /** Ids of project MCP servers this step may use. */\n mcp: z.array(z.string()).optional(),\n /** Ids of wizard connections (the person's accounts) this step may use. */\n connections: z.array(z.string()).optional(),\n output: z\n .object({\n format: z.enum([\"text\", \"markdown\", \"json\"]),\n /** The short form: one level of keys. A step has `fields` or `schema`, not both. */\n fields: z.array(outputFieldSchema).optional(),\n /**\n * json only: nested data (lists of entries with lists of their own), in the kinds of\n * `shape.ts`. Objects nest at most four deep, a hundred keys in all.\n */\n schema: outputShapeSchema.optional(),\n /**\n * json only: a view of the result from the surface catalog, bound to the step's own fields;\n * reviews and the result show it instead of a plain table. Components: written once, the\n * same every run, nothing to pay. `true`: a model composes one each run.\n */\n surface: z.union([z.boolean(), surfaceComponentsSchema]).optional(),\n })\n .default({ format: \"markdown\" }),\n /** The kind of model the step needs; default `high`. The model itself is bound elsewhere. */\n model: z.enum(TEXT_CLASSES).optional(),\n effort: z.enum(EFFORTS).optional(),\n /** Shown to the person while it works. */\n /**\n * One run of the step per entry, at most twenty: the rows of a table output\n * (\"steps.<id>.<key>\"), the entries of a list output, or the rows of a stored list\n * (\"lists.<id>\"). The instructions read the entry as {{item.<column>}}, {{index}}, {{count}}.\n * The output is a table: the entry's columns and the step's output fields, one row per entry.\n */\n each: z.string().optional(),\n working: z.string().optional(),\n});\n\nexport const generateStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"generate\"),\n asset: z.enum(ASSET_KINDS),\n /** For image/video the visual prompt; for document/dashboard the brief. A template. */\n prompt: z.string().min(1),\n options: z\n .object({\n aspectRatio: z.enum(ASPECT_RATIOS).optional(),\n /** Video length in seconds. */\n duration: z.number().optional(),\n /** Video: the height the model renders at; default 720p, the most there is. */\n resolution: z.enum(VIDEO_RESOLUTIONS).optional(),\n style: z.string().optional(),\n /** Document flavour, steers the layout. */\n template: z.enum([\"invoice\", \"offer\", \"briefing\", \"letter\", \"report\", \"free\"]).optional(),\n })\n .optional(),\n /**\n * The image the image/video model starts from: an earlier image field, or an earlier step\n * that made images.\n */\n referenceImage: z.string().optional(),\n /**\n * Image / video: one result per entry instead of one. Names an image field with several\n * uploads, an earlier step that made several images, or a table of an earlier agent step\n * (\"steps.<id>.<key>\"). The prompt reads the entry as {{item.<column>}}, {{index}}, {{count}};\n * `referenceImage` gives each entry its own image when it holds as many.\n */\n each: z.string().optional(),\n /** For document/dashboard: the kind of model that writes it; default `high`. */\n model: z.enum(TEXT_CLASSES).optional(),\n effort: z.enum(EFFORTS).optional(),\n working: z.string().optional(),\n});\n\nexport const widgetStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"widget\"),\n /** Workspace path of the widget's HTML. Written once; every run only brings new data. */\n entry: z.string().min(1),\n /** What the widget gets as `wizard.data`: key → a field id, steps.id, steps.id.key, brand.name or today. */\n data: z.record(z.string(), z.string()).default({}),\n /** Workspace path of example data (JSON) for previews before any run. */\n sample: z.string().optional(),\n /**\n * How the run shows it: `fixed` (default) at `size`, scaled to the page; `page` as a part of\n * the page, as wide as it and as tall as its content — a result people scroll and use, not a\n * picture. PNG/PDF/MP4 still render at `size`.\n */\n layout: z.enum([\"fixed\", \"page\"]).optional(),\n /** The size the widget is designed for; previews scale it, PNG/PDF/MP4 render at it. */\n size: z\n .object({\n width: z.number().int().min(200).max(3840),\n height: z.number().int().min(200).max(3840),\n })\n .optional(),\n /**\n * The result is a film: the timeline is rendered to an MP4 with sound when the step runs,\n * and that video is what the person sees and downloads.\n */\n video: z.boolean().optional(),\n working: z.string().optional(),\n});\n\n/** Formats a film step makes; the composition is drawn for this frame. */\nexport const FILM_FORMATS = [\"16:9\", \"9:16\", \"1:1\"] as const;\nexport type FilmFormat = (typeof FILM_FORMATS)[number];\n\nexport const FILM_SIZES: Record<FilmFormat, { width: number; height: number }> = {\n \"16:9\": { width: 1920, height: 1080 },\n \"9:16\": { width: 1080, height: 1920 },\n \"1:1\": { width: 1080, height: 1080 },\n};\n\n/**\n * A film the AI client installed on this machine makes in a folder of its own: it writes the\n * composition as code (HTML, CSS, JS) with the skills it is given, looks at its frames and fixes\n * them; the runtime renders the MP4. It runs on the person's subscription, never on credits.\n */\nexport const filmStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"film\"),\n /** What the film is: story, look, what to use. A template. */\n brief: z.string().min(1),\n /**\n * Skill packages the client reads: platform packages (\"hyperframes\") or a folder of the\n * workspace with a SKILL.md (\"skills/<name>\").\n */\n skills: z.array(z.string().min(1)).max(12).default([\"hyperframes\"]),\n /**\n * A style kit in the workspace — a showreel made once with its rules, helpers and stills, as\n * a .zip — unpacked as `showcase/`: the bar every film of this wizard is made to.\n */\n kit: z.string().optional(),\n /**\n * What the film is made from: name → a field id or \"steps.<id>\". Files (uploads, voice lines,\n * pictures) are copied into `input/<name>/`, text is written to `input/<name>.md`.\n */\n inputs: z.record(z.string(), z.string()).default({}),\n format: z.enum(FILM_FORMATS).default(\"16:9\"),\n /**\n * \"steps.<id>\" of an earlier film step: this film starts from that one's finished code and\n * lays it out for its own format — scenes, timing and sound stay. Made from scratch when that\n * step did not run.\n */\n from: z.string().optional(),\n /** About how long the film runs, in seconds. */\n seconds: z.number().int().min(3).max(600).optional(),\n /** The kind of model; default `standard` — the kit carries the craft. */\n model: z.enum(TEXT_CLASSES).optional(),\n effort: z.enum(EFFORTS).optional(),\n working: z.string().optional(),\n});\n\n/** A piece a decided surface may show: its components (the first has the piece's id) and what it shows. */\nexport const surfaceCandidateSchema = z.object({\n id,\n /** What this piece shows, for the decision: \"A chart of prices per supplier\". */\n description: z.string().min(1),\n components: surfaceComponentsSchema,\n /** Pieces of a group exclude each other: the decision shows one (or none, if optional). */\n group: z.string().optional(),\n /** Always shown: a title, the main list. */\n required: z.boolean().optional(),\n});\n\nexport const surfaceStepSchema = z\n .object({\n ...stepBase,\n type: z.literal(\"surface\"),\n /** A view from the surface catalog, written once like a widget; every run brings new data. */\n components: surfaceComponentsSchema.optional(),\n /**\n * Instead of `components`: pieces a decision picks from per run (no chart when there is\n * nothing to chart), drawn in this order under one column.\n */\n candidates: z.array(surfaceCandidateSchema).max(16).optional(),\n groups: z.array(fieldGroupSchema).max(6).optional(),\n /** What the surface reads as data: key → a field id, steps.id, steps.id.key, lists.id, brand.name or today. */\n data: z.record(z.string(), z.string()).default({}),\n working: z.string().optional(),\n })\n .refine((step) => Boolean(step.components) !== Boolean(step.candidates), {\n message: 'A surface step has either \"components\" or \"candidates\".',\n });\n\n/**\n * The components of a decided surface for the pieces kept: one root column holding them in\n * their order. Every piece kept is the same as all of them for the validator.\n */\nexport function assembleSurface(\n candidates: { id: string; components: SurfaceComponent[] }[],\n kept: Iterable<string>,\n): SurfaceComponent[] {\n const keep = new Set(kept);\n const chosen = candidates.filter((c) => keep.has(c.id));\n return [\n { id: \"root\", component: \"Column\", children: chosen.map((c) => c.components[0]?.id ?? c.id) },\n ...chosen.flatMap((c) => c.components),\n ];\n}\n\nexport const reviewStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"review\"),\n /** Step ids whose output is shown. */\n show: z.array(z.string()).min(1),\n edit: z.boolean().optional(),\n regenerate: z.boolean().optional(),\n});\n\nexport const deliverableSchema = z.object({\n from: z.string(),\n label: z.string().optional(),\n formats: z.array(z.enum(FORMATS)).min(1),\n});\n\n/** One share target the result offers, with what its form starts with. */\nexport const shareOptionSchema = z.object({\n /** \"email\", \"slack\", \"browser\", \"storage:<connector>\" or \"connector:<connector>\". */\n target: z.string().min(1),\n /** How the result names it, e.g. \"Auf LinkedIn posten\". Default: the target's own name. */\n label: z.string().optional(),\n /** Prefills the target's form by field id. Templates: {{field}}, {{steps.id}}, {{brand.name}}. */\n values: z.record(z.string(), z.string()).optional(),\n});\nexport type ShareOption = z.infer<typeof shareOptionSchema>;\n\nexport const resultStepSchema = z.object({\n ...stepBase,\n type: z.literal(\"result\"),\n message: z.string().optional(),\n deliverables: z.array(deliverableSchema),\n /**\n * Where the person can send or publish the result besides the link and the downloads. Left\n * out: the targets that need no model. An empty list: none.\n */\n share: z.array(shareOptionSchema).max(12).optional(),\n});\n\nexport const stepSchema = z.discriminatedUnion(\"type\", [\n pageStepSchema,\n agentStepSchema,\n generateStepSchema,\n widgetStepSchema,\n surfaceStepSchema,\n filmStepSchema,\n reviewStepSchema,\n resultStepSchema,\n]);\nexport type Step = z.infer<typeof stepSchema>;\nexport type PageStep = z.infer<typeof pageStepSchema>;\nexport type SurfaceStep = z.infer<typeof surfaceStepSchema>;\nexport type AgentStep = z.infer<typeof agentStepSchema>;\n\n/**\n * A decision: a step on the classifier class that uses no tools and whose output is only\n * yes/no and choice fields. It is answered in one call, which a model that only decides\n * (no text) can take.\n */\nexport function isDecisionStep(step: AgentStep): boolean {\n const fields = step.output.fields ?? [];\n return (\n !step.call &&\n !step.output.schema &&\n step.model === \"classifier\" &&\n step.output.format === \"json\" &&\n fields.length > 0 &&\n fields.every((f) => f.kind === \"yesno\" || f.kind === \"choice\" || f.kind === \"score\") &&\n !step.each &&\n step.tools.length === 0 &&\n !step.mcp?.length &&\n !step.connections?.length\n );\n}\n\n/**\n * What an agent step's json output holds: its schema, or its fields as one. Undefined when it\n * names neither (the model then returns one table).\n */\nexport function declaredShape(step: AgentStep): ObjectShape | undefined {\n if (step.output.schema) {\n return step.output.schema;\n }\n return step.output.fields?.length ? shapeOfFields(step.output.fields) : undefined;\n}\n\n/** What an agent step's json output holds: its declared shape, or else one table. */\nexport function stepShape(step: AgentStep): ObjectShape {\n return (\n declaredShape(step) ?? {\n kind: \"object\",\n fields: { data: { kind: \"table\", description: \"The result as a table\" } },\n }\n );\n}\n\n/** The top-level keys of an agent step's output: what `steps.<id>.<key>` may name. */\nexport function outputKeys(step: AgentStep): string[] {\n return Object.keys(declaredShape(step)?.fields ?? {});\n}\nexport type GenerateStep = z.infer<typeof generateStepSchema>;\nexport type WidgetStep = z.infer<typeof widgetStepSchema>;\nexport type FilmStep = z.infer<typeof filmStepSchema>;\nexport type ReviewStep = z.infer<typeof reviewStepSchema>;\nexport type ResultStep = z.infer<typeof resultStepSchema>;\nexport type StepType = Step[\"type\"];\n\nexport const listSchema = z.object({\n id,\n title: z.string().min(1),\n description: z.string().optional(),\n /** engenty data-table columns: `{ id, name, type, format }`. */\n columns: tableColumnsSchema,\n /** Column that identifies a row; saving a row with a known key updates it. */\n key: z.string().optional(),\n /**\n * The person goes through the rows one by one in a review: `file` is the column holding the\n * path of a kept file, shown beside the row; `status` a select column whose options are the\n * answers — the first one means \"not looked at yet\".\n */\n check: z.object({ file: z.string().optional(), status: z.string().optional() }).optional(),\n /**\n * The list is the wizard's, not one person's: every run reads and writes the same rows, and\n * the studio shows it under Space → Data. It is never shown to the person running the wizard,\n * who would see what others gave.\n */\n shared: z.boolean().optional(),\n});\n\nexport const connectionSchema = z.object({\n id,\n /** A built-in kind of account … */\n kind: z.enum(CONNECTION_KINDS).optional(),\n /** … or the id of one of the project's imported connectors. */\n connector: z.string().optional(),\n /** Imported connectors: the actions steps may call. Default: every action that only reads. */\n actions: z.array(z.string()).max(200).optional(),\n /** Imported connectors, per action: \"allow\" runs it without asking, \"ask\" asks the person first. */\n policy: z.record(z.string(), z.enum([\"allow\", \"ask\"])).optional(),\n title: z.string().optional(),\n description: z.string().optional(),\n});\n\n/** The version of the definition this app writes and reads; raised only by a breaking change. */\nexport const DEFINITION_VERSION = 1 as const;\n\nexport const wizardSchema = z.object({\n version: z.literal(DEFINITION_VERSION).default(DEFINITION_VERSION),\n title: z.string().min(1),\n description: z.string().default(\"\"),\n avatar: z.enum(ENGENTY_KINDS).default(\"round\"),\n /** A costume the avatar wears; none without one. */\n costume: z.enum(ENGENTY_COSTUMES).optional(),\n /** Shown on the first page above the first question. */\n intro: z.string().optional(),\n /**\n * The language the wizard speaks to people: its texts, the runner's words, its numbers and\n * dates, by its two-letter code (\"en\", \"de\", \"it\"). Any language, not only those engenty's own\n * strings are written in; `validateWizard` checks it names a real one. Without one it is read\n * from the wizard's own words (`wizardLang`).\n */\n lang: z\n .string()\n .regex(/^[a-z]{2}$/)\n .optional(),\n /** Tabular data the wizard keeps between runs, per person — or for all runs (`shared`). */\n lists: z.array(listSchema).max(12).optional(),\n /** Accounts the person connects; kept between runs, per person. */\n connections: z.array(connectionSchema).max(12).optional(),\n /** How the wizard's pages look, over its space's brand: colours, typefaces, effects, CSS. */\n /**\n * The themes the wizard offers, in its order: ids of the space's themes, or `brand`, `host`\n * and `default`. The place that shows the wizard picks one; its own pages take the first the\n * space has. Without any: the space's brand.\n */\n themes: z.array(z.string().regex(THEME_ID)).max(8).optional(),\n steps: z.array(stepSchema).min(1),\n});\nexport type WizardDefinition = z.infer<typeof wizardSchema>;\n\nexport const INTERACTIVE: ReadonlySet<StepType> = new Set([\"page\", \"review\", \"result\"]);\n\n/** Which formats each producing step can be downloaded in. */\nexport function formatsFor(step: Step): Format[] {\n if (step.type === \"generate\") {\n switch (step.asset) {\n case \"image\":\n return step.each ? [\"png\", \"zip\"] : [\"png\"];\n case \"video\":\n return step.each ? [\"mp4\", \"zip\"] : [\"mp4\"];\n case \"voice\":\n return [\"mp3\"];\n case \"document\":\n return [\"pdf\", \"docx\", \"html\", \"md\", \"png\"];\n case \"dashboard\":\n return [\"html\", \"pdf\", \"png\"];\n }\n }\n if (step.type === \"film\") {\n return [\"mp4\"];\n }\n if (step.type === \"widget\") {\n return step.video ? [\"mp4\", \"png\"] : [\"html\", \"png\", \"pdf\", \"mp4\", \"json\"];\n }\n if (step.type === \"surface\") {\n return [\"json\"];\n }\n if (step.type === \"agent\") {\n if (step.output.format === \"json\") {\n // Nested data reads as a document too.\n return step.output.schema\n ? [\"json\", \"csv\", \"xlsx\", \"md\", \"pdf\", \"zip\"]\n : [\"json\", \"csv\", \"xlsx\", \"md\", \"zip\"];\n }\n return [\"md\", \"txt\", \"docx\", \"pdf\", \"html\", \"zip\"];\n }\n return [];\n}\n\n/** Formats a stored list can be downloaded in; zip = the kept files its rows name, with the list. */\nexport const LIST_FORMATS: Format[] = [\"xlsx\", \"csv\", \"json\", \"md\", \"zip\"];\n\nconst LIST_REF = /^lists\\.([a-zA-Z][a-zA-Z0-9_]*)$/;\n\n/** \"lists.providers\" → \"providers\"; anything else → null. */\nexport function listRef(ref: string): string | null {\n return ref.match(LIST_REF)?.[1] ?? null;\n}\n\nexport const DEFAULT_WIDGET_SIZE = { width: 1280, height: 720 };\n\nexport function widgetSize(step: WidgetStep) {\n return step.size ?? DEFAULT_WIDGET_SIZE;\n}\n\n/** A widget data reference without braces: \"{{steps.x}}\" and \"steps.x\" mean the same. */\nexport function dataRef(raw: string): string {\n return raw\n .trim()\n .replace(/^\\{\\{\\s*/, \"\")\n .replace(/\\s*\\}\\}$/, \"\");\n}\n\nexport interface ValidationIssue {\n stepId?: string;\n message: string;\n}\n\nconst TEMPLATE_RE = /\\{\\{\\s*([^}]+?)\\s*\\}\\}/g;\n\nexport function templateRefs(template: string): string[] {\n return [...template.matchAll(TEMPLATE_RE)].map((m) => m[1]);\n}\n\n/**\n * Structural checks the schema cannot express: ids, references between steps,\n * templates naming things that exist by the time the step runs.\n */\nexport function validateWizard(def: WizardDefinition, files?: string[]): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const stepIds = new Set<string>();\n const fieldIds = new Set<string>();\n const seenSteps = new Set<string>();\n const seenFields = new Set<string>();\n const listIds = new Set<string>();\n const sharedLists = new Set<string>();\n const connectionIds = new Set<string>();\n const notShown = (id: string) =>\n `List \"${id}\" is shared: every run writes it, so the person running the wizard never sees it.`;\n\n if (def.lang && !isRealLanguage(def.lang)) {\n issues.push({\n message: `\"${def.lang}\" isn't a language code. Use a two-letter code such as \"en\", \"de\" or \"it\".`,\n });\n }\n\n if (def.themes && new Set(def.themes).size !== def.themes.length) {\n issues.push({ message: \"A theme is named twice in themes.\" });\n }\n\n for (const list of def.lists ?? []) {\n if (listIds.has(list.id)) {\n issues.push({ message: `Duplicate list id \"${list.id}\".` });\n }\n listIds.add(list.id);\n if (list.shared) {\n sharedLists.add(list.id);\n if (list.check) {\n issues.push({ message: `${notShown(list.id)} It cannot be checked row by row.` });\n }\n }\n if (list.key && !list.columns.some((c) => c.id === list.key)) {\n issues.push({ message: `List \"${list.id}\": key \"${list.key}\" is not one of its columns.` });\n }\n for (const [role, column] of Object.entries(list.check ?? {})) {\n const found = list.columns.find((c) => c.id === column);\n if (!found) {\n issues.push({\n message: `List \"${list.id}\": check.${role} \"${column}\" is not one of its columns.`,\n });\n } else if (role === \"status\" && found.type !== \"select\") {\n issues.push({ message: `List \"${list.id}\": check.status \"${column}\" must be a select.` });\n }\n }\n }\n for (const connection of def.connections ?? []) {\n if (connectionIds.has(connection.id)) {\n issues.push({ message: `Duplicate connection id \"${connection.id}\".` });\n }\n connectionIds.add(connection.id);\n if (Boolean(connection.kind) === Boolean(connection.connector)) {\n issues.push({\n message: `Connection \"${connection.id}\" needs either \"kind\" or \"connector\", not both.`,\n });\n }\n }\n\n for (const step of def.steps) {\n if (stepIds.has(step.id)) {\n issues.push({ stepId: step.id, message: `Duplicate step id \"${step.id}\".` });\n }\n stepIds.add(step.id);\n if (step.type === \"page\") {\n for (const field of step.fields) {\n if (fieldIds.has(field.id)) {\n issues.push({ stepId: step.id, message: `Duplicate field id \"${field.id}\".` });\n }\n fieldIds.add(field.id);\n if (\n (field.kind === \"select\" || field.kind === \"multiselect\" || field.kind === \"slot\") &&\n !field.options?.length &&\n !field.optionsFrom\n ) {\n issues.push({ stepId: step.id, message: `Field \"${field.id}\" needs options.` });\n }\n if (field.kind === \"slot\") {\n const wrong = (field.options ?? []).find((o) => !slotTime(o));\n if (wrong !== undefined) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"${wrong}\" is not a date and time with its offset, like \"2026-10-12T09:00:00+02:00\".`,\n });\n }\n }\n if (field.kind === \"items\" && !field.columns?.length) {\n issues.push({ stepId: step.id, message: `Field \"${field.id}\" needs columns.` });\n }\n if (field.kind === \"connection\" && !connectionIds.has(field.connection ?? \"\")) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" needs \"connection\": the id of one of the wizard's connections.`,\n });\n }\n if (field.kind === \"list\" && !listIds.has(field.list ?? \"\")) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" needs \"list\": the id of one of the wizard's lists.`,\n });\n } else if (field.kind === \"list\" && sharedLists.has(field.list ?? \"\")) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": ${notShown(field.list ?? \"\")}`,\n });\n }\n if (field.min !== undefined || field.max !== undefined) {\n if ((field.kind !== \"image\" && field.kind !== \"file\") || !field.multiple) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"min\" and \"max\" count the files of an image or file field with \"multiple\".`,\n });\n } else if (field.min !== undefined && field.max !== undefined && field.min > field.max) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": min is larger than max.`,\n });\n }\n }\n if (field.scan && field.kind !== \"text\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"scan\" fills a text field; kind is \"${field.kind}\".`,\n });\n }\n if (field.listen && field.kind !== \"file\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"listen\" belongs to a file field; kind is \"${field.kind}\".`,\n });\n }\n if (field.video && field.kind !== \"file\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"video\" belongs to a file field; kind is \"${field.kind}\".`,\n });\n }\n }\n }\n }\n\n const last = def.steps.at(-1);\n if (last?.type !== \"result\") {\n issues.push({ message: \"The last step must be a result step.\" });\n }\n\n const checkTemplate = (step: Step, template: string) => {\n for (const ref of templateRefs(template)) {\n const [head, second] = ref.split(\".\");\n if (head === \"steps\") {\n if (!second || !seenSteps.has(second)) {\n issues.push({\n stepId: step.id,\n message: `\"{{${ref}}}\" refers to a step that has not run before \"${step.id}\".`,\n });\n }\n } else if (head === \"brand\" || head === \"facts\" || head === \"today\" || head === \"notes\") {\n // provided by the runner\n } else if (head === \"item\" || head === \"index\" || head === \"count\") {\n if ((step.type !== \"generate\" && step.type !== \"agent\") || !step.each) {\n issues.push({\n stepId: step.id,\n message: `\"{{${ref}}}\" only exists in a generate or agent step with \"each\".`,\n });\n }\n } else if (head === \"lists\") {\n if (!second || !listIds.has(second)) {\n issues.push({ stepId: step.id, message: `\"{{${ref}}}\" refers to an unknown list.` });\n }\n } else if (!seenFields.has(head)) {\n issues.push({\n stepId: step.id,\n message: `\"{{${ref}}}\" refers to a field that is not asked before \"${step.id}\".`,\n });\n }\n }\n };\n\n /**\n * What a condition may read before `step`: an answer asked earlier, an output field of an\n * earlier agent step (\"steps.<step>.<field>\", the step itself for a branch), or how many rows\n * a stored list has (\"lists.<list>.count\").\n */\n const knownBefore = (step: Step, ref: string, self = false): boolean => {\n if (seenFields.has(ref)) {\n return true;\n }\n const [head, from, key, ...more] = ref.split(\".\");\n if (head === \"lists\") {\n return key === \"count\" && more.length === 0 && listIds.has(from ?? \"\");\n }\n // `steps.<step>.<field>.p`: how probable the decision's answer is.\n const probability = more.length === 1 && more[0] === \"p\";\n if (head !== \"steps\" || !key || (more.length > 0 && !probability)) {\n return false;\n }\n if (!(seenSteps.has(from) || (self && from === step.id))) {\n return false;\n }\n const source = def.steps.find((s) => s.id === from);\n return (\n source?.type === \"agent\" &&\n (!probability || isDecisionStep(source)) &&\n (outputKeys(source).includes(key) || (Boolean(source.each) && key === \"rows\" && !probability))\n );\n };\n\n const conditionIssues = (stepId: string, c: Condition): ValidationIssue[] => {\n if ((c.op === \"gt\" || c.op === \"lt\") && typeof c.value !== \"number\") {\n return [{ stepId, message: `\"${c.op}\" on \"${c.field}\" compares with a number value.` }];\n }\n if (c.op === \"in\" && !Array.isArray(c.value)) {\n return [{ stepId, message: `\"in\" on \"${c.field}\" needs a list of values.` }];\n }\n if (c.op !== \"empty\" && c.op !== \"notEmpty\" && c.value === undefined) {\n return [{ stepId, message: `\"${c.op}\" on \"${c.field}\" needs a value.` }];\n }\n return [];\n };\n\n /** Why an `optionsFrom` reference finds nothing, or null when it is fine. */\n const optionsFromProblem = (raw: string, cards?: CardsDef): string | null => {\n const [head, from, key, column, ...more] = dataRef(raw).split(\".\");\n if (head === \"lists\" && from && key && !column) {\n const list = def.lists?.find((l) => l.id === from);\n if (!list) {\n return `\"optionsFrom\" names an unknown list \"${from}\".`;\n }\n if (sharedLists.has(from)) {\n return notShown(from);\n }\n return list.columns.some((c) => c.id === key)\n ? null\n : `\"optionsFrom\": list \"${from}\" has no column \"${key}\".`;\n }\n if (head === \"steps\" && from && key && more.length === 0) {\n const source = seenSteps.has(from) ? def.steps.find((s) => s.id === from) : undefined;\n // An agent step with `each` hands on one table, `rows`: the entry's columns and its fields.\n if (source?.type === \"agent\" && source.each && key === \"rows\") {\n return column ? null : `\"optionsFrom\": \"${from}.rows\" is a table; name one of its columns.`;\n }\n const out = source?.type === \"agent\" ? declaredShape(source)?.fields[key] : undefined;\n if (!out) {\n return `\"optionsFrom\" names \"${from}.${key}\", which is not an output of an earlier agent step.`;\n }\n // The keys of a table's rows, or of a list's entries; undefined: any (free columns).\n const columns =\n out.kind === \"table\"\n ? out.columns?.length\n ? out.columns\n : undefined\n : out.kind === \"list\" && out.of.kind === \"object\"\n ? Object.keys(out.of.fields)\n : null;\n if (columns === null) {\n if (column || cards) {\n return column\n ? `\"optionsFrom\": \"${from}.${key}\" is not a table with the column \"${column}\".`\n : `\"cards\": \"${from}.${key}\" is not a table.`;\n }\n return out.kind === \"list\"\n ? null\n : `\"optionsFrom\": \"${from}.${key}\" is not a list (a table takes a column, or \"cards\").`;\n }\n if (column) {\n return !columns || columns.includes(column)\n ? null\n : `\"optionsFrom\": \"${from}.${key}\" is not a table with the column \"${column}\".`;\n }\n if (cards) {\n const missing = Object.values(cards).find((c) => columns && !columns.includes(c));\n return missing ? `\"cards\": \"${from}.${key}\" has no column \"${missing}\".` : null;\n }\n return `\"optionsFrom\": \"${from}.${key}\" is not a list (a table takes a column, or \"cards\").`;\n }\n return `\"optionsFrom\" is \"steps.<id>.<key>\", \"steps.<id>.<key>.<column>\" or \"lists.<id>.<column>\".`;\n };\n\n for (const step of def.steps) {\n switch (step.type) {\n case \"page\": {\n const groups = new Set<string>();\n for (const g of step.groups ?? []) {\n if (groups.has(g.id)) {\n issues.push({ stepId: step.id, message: `Duplicate field group \"${g.id}\".` });\n }\n groups.add(g.id);\n if (!step.fields.some((f) => f.group === g.id)) {\n issues.push({ stepId: step.id, message: `Field group \"${g.id}\" has no fields.` });\n }\n }\n const decided = step.fields.some((f) => f.ask || f.group);\n if (decided && step.fields.length > MAX_DECIDED_FIELDS) {\n issues.push({\n stepId: step.id,\n message: `A page whose fields are decided has at most ${MAX_DECIDED_FIELDS} fields.`,\n });\n }\n for (const field of step.fields) {\n if (field.ask && field.group) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" has \"ask\" or \"group\", not both.`,\n });\n }\n if (field.group && !groups.has(field.group)) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\" names an unknown group \"${field.group}\".`,\n });\n }\n }\n for (const field of step.fields) {\n for (const c of conditionsOf(field.when)) {\n const own = step.fields.some((f) => f.id === c.field && f.id !== field.id);\n if (!own && !knownBefore(step, c.field)) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"when\" reads \"${c.field}\", which is neither on this page nor known before it.`,\n });\n }\n issues.push(...conditionIssues(step.id, c));\n }\n if (field.optionsFrom) {\n const problem =\n field.kind !== \"select\" && field.kind !== \"multiselect\" && field.kind !== \"slot\"\n ? `\"optionsFrom\" fills the choices of a select, multiselect or slot; kind is \"${field.kind}\".`\n : field.cards && field.kind === \"slot\"\n ? '\"cards\" draws the choices of a select or multiselect, not of a slot.'\n : optionsFromProblem(field.optionsFrom, field.cards);\n if (problem) {\n issues.push({ stepId: step.id, message: `Field \"${field.id}\": ${problem}` });\n }\n } else if (field.cards) {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": \"cards\" needs \"optionsFrom\" naming a table output.`,\n });\n }\n if (field.prefill) {\n const ref = dataRef(field.prefill);\n if (ref.split(\".\")[0] !== \"steps\") {\n issues.push({\n stepId: step.id,\n message: `Field \"${field.id}\": prefill names an earlier step (\"steps.<id>.<key>\").`,\n });\n } else {\n checkTemplate(step, `{{${ref}}}`);\n }\n }\n seenFields.add(field.id);\n }\n break;\n }\n case \"agent\":\n checkTemplate(step, step.instructions);\n if (step.call) {\n checkTemplate(step, JSON.stringify(step.call.input));\n if (step.each) {\n issues.push({ stepId: step.id, message: 'A step with \"call\" runs once: no \"each\".' });\n }\n if (step.output.format !== \"json\") {\n issues.push({\n stepId: step.id,\n message: 'A step with \"call\" keeps the tool\\'s answer: output format \"json\".',\n });\n }\n } else if (!step.instructions.trim()) {\n issues.push({ stepId: step.id, message: \"An AI step needs instructions.\" });\n }\n for (const c of step.connections ?? []) {\n if (!connectionIds.has(c)) {\n issues.push({ stepId: step.id, message: `Step uses unknown connection \"${c}\".` });\n }\n }\n if (step.output.surface && step.output.format !== \"json\") {\n issues.push({\n stepId: step.id,\n message: 'A step composes a view (\"surface\") of json output only.',\n });\n }\n if (step.output.schema) {\n if (step.output.fields?.length) {\n issues.push({\n stepId: step.id,\n message: 'Output has \"fields\" or \"schema\", not both.',\n });\n }\n if (step.output.format !== \"json\" || step.call) {\n issues.push({\n stepId: step.id,\n message: step.call\n ? 'A step with \"call\" keeps the tool\\'s answer as it is: no \"schema\".'\n : 'A \"schema\" describes json output: output format \"json\".',\n });\n }\n }\n if (Array.isArray(step.output.surface)) {\n // A step with `each` hands over its entries as `rows`.\n for (const issue of validateSurface(\n step.output.surface,\n step.each ? [\"rows\"] : declaredShape(step),\n )) {\n issues.push({ stepId: step.id, message: `View: ${issue.message}` });\n }\n }\n if (step.each) {\n const ref = dataRef(step.each);\n const list = ref.match(/^lists\\.([a-zA-Z][a-zA-Z0-9_]*)$/)?.[1];\n if (list) {\n if (!listIds.has(list)) {\n issues.push({ stepId: step.id, message: `each names an unknown list \"${list}\".` });\n }\n } else if (ref.startsWith(\"steps.\") && ref.split(\".\").length === 3) {\n checkTemplate(step, `{{${ref}}}`);\n } else {\n issues.push({\n stepId: step.id,\n message: `each \"${step.each}\" is \"steps.<id>.<key>\" (a table or list output) or \"lists.<id>\".`,\n });\n }\n }\n break;\n case \"generate\":\n checkTemplate(step, step.prompt);\n checkTemplate(step, step.options?.style ?? \"\");\n if (\n step.referenceImage &&\n !seenFields.has(step.referenceImage) &&\n !seenSteps.has(step.referenceImage)\n ) {\n issues.push({\n stepId: step.id,\n message: `referenceImage \"${step.referenceImage}\" is not an earlier field or step.`,\n });\n }\n if (step.each) {\n const ref = dataRef(step.each);\n if (step.asset !== \"image\" && step.asset !== \"video\") {\n issues.push({ stepId: step.id, message: `\"each\" is for image and video steps.` });\n } else if (ref.startsWith(\"steps.\")) {\n checkTemplate(step, `{{${ref}}}`);\n } else if (!seenFields.has(ref) && !seenSteps.has(ref)) {\n issues.push({\n stepId: step.id,\n message: `each \"${step.each}\" is not an earlier field, step or \"steps.<id>.<key>\".`,\n });\n }\n }\n break;\n case \"widget\":\n for (const [key, ref] of Object.entries(step.data)) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n issues.push({\n stepId: step.id,\n message: `Widget data key \"${key}\" is not an identifier.`,\n });\n }\n checkTemplate(step, `{{${dataRef(ref)}}}`);\n }\n if (files && !files.includes(step.entry)) {\n issues.push({\n stepId: step.id,\n message: `Widget entry \"${step.entry}\" is not in the workspace.`,\n });\n }\n if (files && step.sample && !files.includes(step.sample)) {\n issues.push({\n stepId: step.id,\n message: `Widget sample \"${step.sample}\" is not in the workspace.`,\n });\n }\n break;\n case \"surface\": {\n for (const [key, ref] of Object.entries(step.data)) {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {\n issues.push({\n stepId: step.id,\n message: `Surface data key \"${key}\" is not an identifier.`,\n });\n }\n const list = listRef(dataRef(ref));\n if (list) {\n if (!listIds.has(list)) {\n issues.push({\n stepId: step.id,\n message: `Surface data reads an unknown list \"${list}\".`,\n });\n }\n } else {\n checkTemplate(step, `{{${dataRef(ref)}}}`);\n }\n }\n const groups = new Set((step.groups ?? []).map((g) => g.id));\n for (const c of step.candidates ?? []) {\n if (c.components[0]?.id !== c.id) {\n issues.push({\n stepId: step.id,\n message: `Surface piece \"${c.id}\": its first component carries the piece's id.`,\n });\n }\n if (c.group && !groups.has(c.group)) {\n issues.push({\n stepId: step.id,\n message: `Surface piece \"${c.id}\" names an unknown group \"${c.group}\".`,\n });\n }\n }\n const components =\n step.components ??\n assembleSurface(\n step.candidates ?? [],\n (step.candidates ?? []).map((c) => c.id),\n );\n for (const issue of validateSurface(components, Object.keys(step.data))) {\n issues.push({ stepId: step.id, message: `Surface: ${issue.message}` });\n }\n break;\n }\n case \"film\":\n checkTemplate(step, step.brief);\n for (const [name, ref] of Object.entries(step.inputs)) {\n if (!/^[a-z][a-z0-9-]{0,40}$/.test(name)) {\n issues.push({\n stepId: step.id,\n message: `Film input \"${name}\" is not a folder name (lowercase letters, digits, -).`,\n });\n }\n const r = dataRef(ref);\n if (r.startsWith(\"steps.\")) {\n checkTemplate(step, `{{${r}}}`);\n } else if (!seenFields.has(r)) {\n issues.push({\n stepId: step.id,\n message: `Film input \"${name}\": \"${ref}\" is not an earlier field or \"steps.<id>\".`,\n });\n }\n }\n if (step.from) {\n const id = dataRef(step.from).replace(/^steps\\./, \"\");\n if (!seenSteps.has(id) || def.steps.find((s) => s.id === id)?.type !== \"film\") {\n issues.push({\n stepId: step.id,\n message: `Film from \"${step.from}\" is not an earlier film step (\"steps.<id>\").`,\n });\n }\n }\n if (step.kit && !step.kit.endsWith(\".zip\")) {\n issues.push({ stepId: step.id, message: `Film kit \"${step.kit}\" is a .zip.` });\n } else if (files && step.kit && !files.includes(step.kit)) {\n issues.push({\n stepId: step.id,\n message: `Film kit \"${step.kit}\" is not in the workspace.`,\n });\n }\n for (const skill of step.skills) {\n if (skill.startsWith(\"skills/\") && files && !files.includes(`${skill}/SKILL.md`)) {\n issues.push({\n stepId: step.id,\n message: `Skill \"${skill}\" has no SKILL.md in the workspace.`,\n });\n }\n }\n break;\n case \"review\":\n for (const ref of step.show) {\n const list = listRef(ref);\n if (list ? !listIds.has(list) : !seenSteps.has(ref)) {\n issues.push({\n stepId: step.id,\n message: `Review shows unknown ${list ? \"list\" : \"step\"} \"${ref}\".`,\n });\n } else if (list && sharedLists.has(list)) {\n issues.push({ stepId: step.id, message: notShown(list) });\n }\n }\n break;\n case \"result\":\n for (const d of step.deliverables) {\n const list = listRef(d.from);\n if (list ? !listIds.has(list) : !seenSteps.has(d.from)) {\n issues.push({\n stepId: step.id,\n message: `Deliverable from unknown ${list ? \"list\" : \"step\"} \"${d.from}\".`,\n });\n } else if (list && sharedLists.has(list)) {\n issues.push({ stepId: step.id, message: notShown(list) });\n }\n }\n for (const option of step.share ?? []) {\n if (!isShareTargetId(option.target)) {\n issues.push({\n stepId: step.id,\n message: `Unknown share target \"${option.target}\": use email, slack, browser, storage:<connector> or connector:<connector>.`,\n });\n }\n for (const value of Object.values(option.values ?? {})) {\n checkTemplate(step, value);\n }\n }\n break;\n }\n if ((step.next ?? []).filter(isOtherwise).length > 1) {\n issues.push({\n stepId: step.id,\n message: 'A step has at most one \"otherwise\" branch (one without \"when\" and \"ask\").',\n });\n }\n for (const rule of step.next ?? []) {\n if (rule.goto !== \"end\" && !stepIds.has(rule.goto)) {\n issues.push({ stepId: step.id, message: `Branch goes to unknown step \"${rule.goto}\".` });\n }\n // A branch reads what the person answered (on any page), an output field of this or an\n // earlier agent step, or the row count of a stored list.\n for (const c of conditionsOf(rule.when)) {\n if (!fieldIds.has(c.field) && !knownBefore(step, c.field, true)) {\n issues.push({ stepId: step.id, message: `Branch reads unknown field \"${c.field}\".` });\n }\n issues.push(...conditionIssues(step.id, c));\n }\n }\n seenSteps.add(step.id);\n }\n return issues;\n}\n\n/** Parse + validate in one go. */\nexport function parseWizard(\n input: unknown,\n files?: string[],\n):\n | { ok: true; wizard: WizardDefinition; issues: ValidationIssue[] }\n | { ok: false; issues: ValidationIssue[] } {\n const parsed = wizardSchema.safeParse(input);\n if (!parsed.success) {\n return { ok: false, issues: shapeIssues(parsed.error, input) };\n }\n const issues = validateWizard(parsed.data, files);\n return { ok: true, wizard: parsed.data, issues };\n}\n\nfunction stepLabel(raw: unknown, index: number): string {\n const steps = (raw as { steps?: unknown[] } | null)?.steps;\n const id = (steps?.[index] as { id?: unknown } | undefined)?.id;\n return typeof id === \"string\" ? `steps[${index}] \"${id}\"` : `steps[${index}]`;\n}\n\n/** Where the shape is wrong, a step named by its id: `steps[2] \"draft\".title: …`. */\nexport function shapeIssues(error: z.ZodError, raw: unknown): ValidationIssue[] {\n return error.issues.map((i) => {\n const [head, index, ...rest] = i.path;\n const where =\n head === \"steps\" && typeof index === \"number\"\n ? [stepLabel(raw, index), ...rest].join(\".\")\n : i.path.join(\".\");\n return { message: `${where || \"wizard\"}: ${i.message}` };\n });\n}\n\n/**\n * What branch rules can read in a run: the person's answers by field id, and the structured\n * output of the steps run so far as `steps.<step>.<field>`.\n */\nexport function branchValues(\n values: Record<string, unknown>,\n outputs: Record<string, { json?: unknown; decided?: Record<string, number> }>,\n /** Rows per stored list, read as `lists.<list>.count`. */\n listCounts: Record<string, number> = {},\n): Record<string, unknown> {\n const out: Record<string, unknown> = { ...values };\n for (const [list, count] of Object.entries(listCounts)) {\n out[`lists.${list}.count`] = count;\n }\n for (const [stepId, output] of Object.entries(outputs)) {\n if (output.json && typeof output.json === \"object\" && !Array.isArray(output.json)) {\n for (const [key, value] of Object.entries(output.json)) {\n out[`steps.${stepId}.${key}`] = value;\n }\n }\n for (const [key, p] of Object.entries(output.decided ?? {})) {\n out[`steps.${stepId}.${key}.p`] = p;\n }\n }\n return out;\n}\n\n/** A branch back to an earlier step without `max` is taken at most this often in one run. */\nexport const DEFAULT_LOOP_MAX = 10;\n\n/** How a run counts the times it took a branch: \"<step>→<goto>\". */\nexport function loopKey(stepId: string, goto: string): string {\n return `${stepId}→${goto}`;\n}\n\n/** Whether a rule may still send the run on: one with `max`, or one back, stops after so many. */\nexport function ruleOpen(\n def: WizardDefinition,\n stepId: string,\n rule: NextRule,\n loops: Record<string, number> = {},\n): boolean {\n const from = def.steps.findIndex((s) => s.id === stepId);\n const to =\n rule.goto === \"end\" ? def.steps.length : def.steps.findIndex((s) => s.id === rule.goto);\n const max = rule.max ?? (to >= 0 && to <= from ? DEFAULT_LOOP_MAX : Number.POSITIVE_INFINITY);\n return (loops[loopKey(stepId, rule.goto)] ?? 0) < max;\n}\n\n/**\n * Where a run goes after a step: the first open `when` rule that holds (`rule` is its index in\n * `next`), else a decision over the open `ask` rules, else the next step in the list. `cursor`\n * null = the end.\n */\nexport type RuleOutcome =\n | { kind: \"go\"; cursor: string | null; rule: number | null }\n | { kind: \"decide\"; rules: number[] };\n\nexport function followRules(\n def: WizardDefinition,\n stepId: string,\n values: Record<string, unknown>,\n loops: Record<string, number> = {},\n): RuleOutcome {\n const index = def.steps.findIndex((s) => s.id === stepId);\n const step = def.steps[index];\n if (!step) {\n return { kind: \"go\", cursor: null, rule: null };\n }\n const rules = step.next ?? [];\n for (const [i, rule] of rules.entries()) {\n if (ruleOpen(def, stepId, rule, loops) && ruleMatches(rule, values)) {\n return { kind: \"go\", cursor: rule.goto === \"end\" ? null : rule.goto, rule: i };\n }\n }\n const asks = rules.flatMap((rule, i) =>\n rule.ask && ruleOpen(def, stepId, rule, loops) ? [i] : [],\n );\n if (asks.length) {\n return { kind: \"decide\", rules: asks };\n }\n return { kind: \"go\", ...otherwiseOf(def, stepId, loops) };\n}\n\n/** A rule with neither a condition nor a statement: where the run goes when no other rule holds. */\nexport function isOtherwise(rule: NextRule): boolean {\n return rule.when === undefined && rule.ask === undefined;\n}\n\n/**\n * Where a step goes when none of its rules holds: its \"otherwise\" rule (`rule` is its index in\n * `next`), else the next step in the list. `cursor` null = the end.\n */\nexport function otherwiseOf(\n def: WizardDefinition,\n stepId: string,\n loops: Record<string, number> = {},\n): { cursor: string | null; rule: number | null } {\n const index = def.steps.findIndex((s) => s.id === stepId);\n const rules = def.steps[index]?.next ?? [];\n const i = rules.findIndex((r) => isOtherwise(r) && ruleOpen(def, stepId, r, loops));\n if (i >= 0) {\n return { cursor: rules[i].goto === \"end\" ? null : rules[i].goto, rule: i };\n }\n return { cursor: def.steps[index + 1]?.id ?? null, rule: null };\n}\n\n/** The step after `step` by its `when` rules alone. `null` = the end. */\nexport function nextStepId(\n def: WizardDefinition,\n stepId: string,\n values: Record<string, unknown>,\n): string | null {\n const outcome = followRules(def, stepId, values);\n if (outcome.kind === \"go\") {\n return outcome.cursor;\n }\n const index = def.steps.findIndex((s) => s.id === stepId);\n return def.steps[index + 1]?.id ?? null;\n}\n\nfunction isEmptyValue(v: unknown): boolean {\n return v === undefined || v === null || v === \"\" || (Array.isArray(v) && v.length === 0);\n}\n\n/** The conditions of a rule or a field, as a list: one, several, or none. */\nexport function conditionsOf(when: When | undefined): Condition[] {\n return when === undefined ? [] : Array.isArray(when) ? when : [when];\n}\n\nexport function conditionMatches(c: Condition, values: Record<string, unknown>): boolean {\n const v = values[c.field];\n switch (c.op) {\n case \"empty\":\n return isEmptyValue(v);\n case \"notEmpty\":\n return !isEmptyValue(v);\n case \"equals\":\n return String(v) === String(c.value);\n case \"notEquals\":\n return String(v) !== String(c.value);\n case \"in\":\n return Array.isArray(c.value) && c.value.map(String).includes(String(v));\n case \"gt\":\n case \"lt\": {\n const a = readNumber(v);\n const b = readNumber(c.value);\n return a !== null && b !== null && (c.op === \"gt\" ? a > b : a < b);\n }\n case \"contains\":\n if (Array.isArray(v)) {\n return v.map(String).includes(String(c.value));\n }\n return (\n typeof v === \"string\" &&\n c.value !== undefined &&\n v.toLowerCase().includes(String(c.value).toLowerCase())\n );\n }\n}\n\n/** Whether every condition holds; no conditions hold trivially. */\nexport function whenHolds(when: When | undefined, values: Record<string, unknown>): boolean {\n return conditionsOf(when).every((c) => conditionMatches(c, values));\n}\n\n/** Whether a `when` rule holds. An `ask` rule never holds here: a decision takes it (see decide). */\nexport function ruleMatches(rule: NextRule, values: Record<string, unknown>): boolean {\n return rule.when !== undefined && whenHolds(rule.when, values);\n}\n\n/** A page with decided fields has at most this many; it shows at most MAX_SHOWN_FIELDS of them. */\nexport const MAX_DECIDED_FIELDS = 12;\nexport const MAX_SHOWN_FIELDS = 5;\n\n/** Whether a field is shown only when a decision keeps it. */\nexport function isDecidedField(field: Field): boolean {\n return Boolean(field.ask || field.group);\n}\n\n/**\n * The fields of a page that are shown: those whose `when` holds on what was known before the\n * page (`known`) and what the page holds so far (`page`). A hidden field's value does not count\n * for the fields after it.\n */\nexport function shownFields(\n fields: Field[],\n known: Record<string, unknown>,\n page: Record<string, unknown>,\n): Field[] {\n const values = { ...known, ...page };\n const out: Field[] = [];\n for (const field of fields) {\n if (whenHolds(field.when, values)) {\n out.push(field);\n } else {\n delete values[field.id];\n }\n }\n return out;\n}\n\n/** The references the `when` of a page's fields read outside the page: what the page must know. */\nexport function pageNeeds(fields: Field[]): string[] {\n const own = new Set(fields.map((f) => f.id));\n return [\n ...new Set(\n fields.flatMap((f) => conditionsOf(f.when).map((c) => c.field)).filter((r) => !own.has(r)),\n ),\n ];\n}\n\n/** At most this many choices come from data. */\nexport const MAX_DATA_OPTIONS = 100;\n\n/**\n * The choices an `optionsFrom` reference finds in a run: the entries of a list output, one\n * column of a table output, or one column of a stored list — as text, without duplicates and\n * empties. Empty when the data is not there (yet).\n */\nexport function optionsFromData(\n ref: string,\n outputs: Record<string, { json?: unknown }>,\n lists: Record<string, { rows: { cells: Record<string, unknown> }[] }> = {},\n cards?: CardsDef,\n): string[] {\n if (cards) {\n return cardsFromData(ref, outputs, cards).map((c) => c.value);\n }\n const [head, id, key, column, ...more] = dataRef(ref).split(\".\");\n let raw: unknown[] = [];\n if (head === \"lists\" && id && key && !column) {\n raw = (lists[id]?.rows ?? []).map((r) => r.cells[key]);\n } else if (head === \"steps\" && id && key && more.length === 0) {\n const json = outputs[id]?.json as Record<string, unknown> | undefined;\n const value = json && typeof json === \"object\" ? json[key] : undefined;\n if (Array.isArray(value)) {\n raw = column\n ? value.map((row) =>\n row && typeof row === \"object\" ? (row as Record<string, unknown>)[column] : undefined,\n )\n : value;\n }\n }\n const seen = new Set<string>();\n for (const v of raw) {\n if (v === null || v === undefined || typeof v === \"object\") {\n continue;\n }\n const text = String(v).trim().slice(0, 200);\n if (text) {\n seen.add(text);\n }\n if (seen.size >= MAX_DATA_OPTIONS) {\n break;\n }\n }\n return [...seen];\n}\n\n/** The rows of a table output as cards: what `optionsFrom` with `cards` finds in the run. */\nexport function cardsFromData(\n ref: string,\n outputs: Record<string, { json?: unknown }>,\n cards: CardsDef,\n): CardOption[] {\n const [head, id, key, ...more] = dataRef(ref).split(\".\");\n if (head !== \"steps\" || !id || !key || more.length) {\n return [];\n }\n const json = outputs[id]?.json as Record<string, unknown> | undefined;\n const rows = json && typeof json === \"object\" ? json[key] : undefined;\n if (!Array.isArray(rows)) {\n return [];\n }\n const cell = (row: Record<string, unknown>, column: string | undefined, max = 200) => {\n const v = column ? row[column] : undefined;\n if (v === null || v === undefined || typeof v === \"object\") {\n return \"\";\n }\n return String(v).trim().slice(0, max);\n };\n const out: CardOption[] = [];\n const seen = new Set<string>();\n for (const raw of rows) {\n if (!raw || typeof raw !== \"object\") {\n continue;\n }\n const row = raw as Record<string, unknown>;\n const label = cell(row, cards.label);\n const value = cell(row, cards.value) || label;\n if (!value || seen.has(value)) {\n continue;\n }\n seen.add(value);\n const card: CardOption = { value, label: label || value };\n const image = cell(row, cards.image, 2000);\n const link = cell(row, cards.link, 2000);\n const subtitle = cell(row, cards.subtitle, 300);\n const meta = cell(row, cards.meta, 80);\n if (/^(https?:|data:|\\/)/.test(image) || /^[a-zA-Z0-9_-]{6,64}$/.test(image)) {\n card.image = image;\n }\n if (/^https?:\\/\\//.test(link)) {\n card.link = link;\n }\n if (subtitle) {\n card.subtitle = subtitle;\n }\n if (meta) {\n card.meta = meta;\n }\n out.push(card);\n if (out.length >= MAX_DATA_OPTIONS) {\n break;\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Appointment times\n\nconst SLOT_RE =\n /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$/;\n\n/** An offered appointment time read on its own clock: the offset it was written with. */\nexport interface SlotTime {\n /** The calendar day there: \"2026-10-12\". */\n day: string;\n /** The time of day there: \"09:00\". */\n time: string;\n /** That day and time as if it were UTC — to name the weekday and month without moving it. */\n wall: Date;\n}\n\n/**\n * A slot option as day and time in its own offset (the business's time zone, not the reader's).\n * Null when it is not an ISO 8601 date-time with an offset.\n */\nexport function slotTime(iso: string): SlotTime | null {\n const m = SLOT_RE.exec(iso.trim());\n if (!m) {\n return null;\n }\n const [, y, mo, d, h, mi] = m.map(Number);\n const wall = new Date(Date.UTC(y, mo - 1, d, h, mi));\n if (\n wall.getUTCMonth() !== mo - 1 ||\n wall.getUTCDate() !== d ||\n h > 23 ||\n mi > 59 ||\n !Number.isFinite(Date.parse(iso))\n ) {\n return null;\n }\n return { day: `${m[1]}-${m[2]}-${m[3]}`, time: `${m[4]}:${m[5]}`, wall };\n}\n\n/** The weekday and date of a slot's day: \"Montag, 12. Oktober\" / \"Monday, 12 October\". */\nexport function slotDayText(iso: string, lang = \"en\"): string {\n const slot = slotTime(iso);\n if (!slot) {\n return iso;\n }\n const locale = localeOf(lang);\n const weekday = slot.wall.toLocaleDateString(locale, { weekday: \"long\", timeZone: \"UTC\" });\n const date = slot.wall.toLocaleDateString(locale, {\n day: \"numeric\",\n month: \"long\",\n timeZone: \"UTC\",\n });\n return `${weekday}, ${date}`;\n}\n\n/** A chosen slot as a person reads it back: \"Di 13.10.2026, 10:30\" / \"Tue 13/10/2026, 10:30\". */\nexport function slotText(iso: string, lang = \"en\"): string {\n const slot = slotTime(iso);\n if (!slot) {\n return iso;\n }\n const locale = localeOf(lang);\n const weekday = slot.wall\n .toLocaleDateString(locale, { weekday: \"short\", timeZone: \"UTC\" })\n .replace(/\\.$/, \"\");\n const date = slot.wall.toLocaleDateString(locale, {\n day: \"2-digit\",\n month: \"2-digit\",\n year: \"numeric\",\n timeZone: \"UTC\",\n });\n return `${weekday} ${date}, ${slot.time}`;\n}\n\n/**\n * The slot among `options` that is the same moment as `value`, written as offered — so an answer\n * in another offset (\"…T07:00:00Z\" for \"…T09:00:00+02:00\") picks the offered time.\n */\nexport function offeredSlot(value: string, options: string[]): string | undefined {\n if (options.includes(value)) {\n return value;\n }\n const at = slotTime(value) ? Date.parse(value) : Number.NaN;\n return Number.isFinite(at) ? options.find((o) => slotTime(o) && Date.parse(o) === at) : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Line items\n\nexport interface ItemsTotals {\n rows: Record<string, unknown>[];\n net: number;\n vatRate: number;\n vat: number;\n gross: number;\n currency: string;\n}\n\nexport function itemsTotals(\n field: Field,\n value: unknown,\n values: Record<string, unknown>,\n): ItemsTotals {\n const rows = Array.isArray(value) ? (value as Record<string, unknown>[]) : [];\n const numeric = (field.columns ?? []).filter((c) => c.kind !== \"text\");\n const withAmount = rows.map((row) => {\n const amount = numeric.length ? numeric.reduce((acc, c) => acc * amountOf(row[c.id]), 1) : 0;\n return { ...row, amount: round2(amount) };\n });\n const net = round2(withAmount.reduce((a, r) => a + (r.amount as number), 0));\n let vatRate = field.vat?.rate ?? 0;\n if (field.vat?.field) {\n const raw = values[field.vat.field];\n const parsed = readNumber(raw, { units: true });\n if (parsed !== null) {\n vatRate = parsed;\n }\n }\n const vat = round2((net * vatRate) / 100);\n return {\n rows: withAmount,\n net,\n vatRate,\n vat,\n gross: round2(net + vat),\n currency: field.currency ?? \"EUR\",\n };\n}\n\n/** A typed amount as a number: a phone's number pad in German gives \"89,90\". */\nfunction amountOf(v: unknown): number {\n return readNumber(v) ?? 0;\n}\n\nfunction round2(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nexport function allFields(def: WizardDefinition): Field[] {\n return def.steps.flatMap((s) => (s.type === \"page\" ? s.fields : []));\n}\n\nconst GERMAN =\n /\\b(und|der|die|das|ist|nicht|für|mit|ein|eine|wird|zu|dein|deine|ihr|wir|was|wie|oder)\\b|[äöüß]/gi;\nconst ENGLISH = /\\b(and|the|is|not|for|with|a|an|your|you|we|what|how|or|to|of)\\b/gi;\n\n/**\n * The language a wizard speaks to people: the one it names, else read from its own words\n * (titles, labels, intro) — English where they are not clearly German.\n */\nexport function wizardLang(def: WizardDefinition): string {\n if (def.lang) {\n return def.lang;\n }\n const text = [\n def.title,\n def.description,\n def.intro,\n ...def.steps.flatMap((s) => [\n s.title,\n s.description,\n ...(s.type === \"page\" ? s.fields.flatMap((f) => [f.label, f.help, f.placeholder]) : []),\n ]),\n ]\n .filter(Boolean)\n .join(\" \");\n const de = text.match(GERMAN)?.length ?? 0;\n const en = text.match(ENGLISH)?.length ?? 0;\n return de > en ? \"de\" : \"en\";\n}\n\n// --- can this app read a definition? ---------------------------------------------------------\n// The schema drops what it does not know. A definition written for a newer app would be read\n// without complaint and run wrongly, so it counts only when nothing of it is lost.\n\nfunction keepsAll(given: unknown, read: unknown): boolean {\n if (Array.isArray(given)) {\n return Array.isArray(read) && given.every((v, i) => keepsAll(v, read[i]));\n }\n if (given && typeof given === \"object\") {\n return (\n Boolean(read) &&\n typeof read === \"object\" &&\n Object.entries(given).every(\n ([k, v]) => v === undefined || (k in (read as object) && keepsAll(v, (read as never)[k])),\n )\n );\n }\n return true;\n}\n\n/** True when this app's schema reads the definition without losing anything of it. */\nexport function readable(definition: unknown): boolean {\n const parsed = wizardSchema.safeParse(definition);\n return parsed.success && keepsAll(definition, parsed.data);\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport { type Lang, localeOf } from \"./definition.js\";\n\n/**\n * A line with a form for each plural category of its `{count}` (or `{n}`, `Intl.PluralRules`):\n * \"one\" and \"other\" in English and German, more in languages that need them.\n */\nexport interface Plural {\n zero?: string;\n one?: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\n/** A line of a string table: plain, or with plural forms. */\nexport type Line = string | Plural;\n\n/**\n * A string table: each language's lines by key. English has every line; another language may\n * lack some, and those are said in English. A new language needs only its own table.\n */\nexport type Texts<K extends string> = { en: Record<K, Line> } & {\n [L in Exclude<Lang, \"en\">]: Partial<Record<K, Line>>;\n};\n\n/** What fills a line's gaps: words, a number (written the language's way), or a list of them. */\nexport type Gap = string | number | readonly Gap[];\n\nconst plurals = new Map<string, Intl.PluralRules>();\n\n/** The plural rules of a language: any language, by its code. */\nexport function pluralRules(lang: string): Intl.PluralRules {\n let rules = plurals.get(lang);\n if (!rules) {\n rules = new Intl.PluralRules(localeOf(lang));\n plurals.set(lang, rules);\n }\n return rules;\n}\n\nfunction form(line: Line, lang: string, count: unknown): string {\n if (typeof line === \"string\") {\n return line;\n }\n if (typeof count !== \"number\") {\n return line.other;\n }\n return line[pluralRules(lang).select(count)] ?? line.other;\n}\n\n/** A gap's words in a language: numbers as the language writes them, lists joined. */\nexport function gapText(value: Gap, lang: string): string {\n if (typeof value === \"number\") {\n return value.toLocaleString(localeOf(lang));\n }\n if (Array.isArray(value)) {\n return value.map((item) => gapText(item, lang)).join(\", \");\n }\n return value as string;\n}\n\n/** Fills `{name}` gaps; a gap with nothing for it stays as it is. */\nexport function fillGaps(\n text: string,\n lang: string,\n params?: Record<string, Gap | undefined>,\n): string {\n return text.replace(/\\{(\\w+)\\}/g, (gap, key: string) => {\n const value = params?.[key];\n return value === undefined ? gap : gapText(value, lang);\n });\n}\n\n/**\n * A line of a table in a language, its gaps filled and its plural form picked by `{count}`\n * (or `{n}`);\n * the English line where the language lacks one.\n */\nexport function textOf<K extends string>(\n texts: Texts<K>,\n key: K,\n lang: Lang,\n params?: Record<string, Gap | undefined>,\n): string {\n const line = (texts[lang] as Partial<Record<K, Line>>)[key] ?? texts.en[key];\n if (line === undefined) {\n return key;\n }\n return fillGaps(form(line, lang, params?.count ?? params?.n), lang, params);\n}\n\n/**\n * A string table of one language outside `LANGS`, translated on request: lines by key, a plural\n * line with the forms of that language's plural categories.\n */\nexport type TextTable = Record<string, Line>;\n\n/** A line of a table, in a language: its gaps filled and its plural form picked. */\nexport function lineText(\n line: Line,\n lang: string,\n params?: Record<string, Gap | undefined>,\n): string {\n return fillGaps(form(line, lang, params?.count ?? params?.n), lang, params);\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport {\n type CardOption,\n type EngentyCostume,\n type Format,\n isLang,\n type Lang,\n type ModelClass,\n type Step,\n type WizardDefinition,\n} from \"./definition.js\";\nimport type { ShareJobView } from \"./sharing.js\";\nimport type { ConnectionView, ListDef, ListRow } from \"./store.js\";\nimport type { Surface } from \"./surface.js\";\nimport { type Gap, type Line, lineText, type Texts, type TextTable, textOf } from \"./texts.js\";\nimport type { ThemeColours, ThemeEffect, ThemeShape } from \"./theme.js\";\n\nexport type RunStatus = \"waiting_input\" | \"running\" | \"done\" | \"failed\" | \"cancelled\";\n\nexport interface AssetRef {\n id: string;\n /** image | video | html | text | json */\n kind: string;\n mime: string;\n name: string;\n /**\n * Media a model made (\"generated\") or changed (\"edited\"). Shown with a label wherever it is\n * displayed; the file itself carries the marking in its metadata (EU AI Act, Art. 50).\n */\n ai?: \"generated\" | \"edited\";\n}\n\nexport interface StepOutput {\n text?: string;\n json?: unknown;\n /** A decision step: how probable each answer is (1 or 0 where a language model answered). */\n decided?: Record<string, number>;\n /** A view from the surface catalog and the data it is bound to. */\n surface?: Surface;\n assets?: AssetRef[];\n /**\n * What the person did in the step's view, kept with the run: a checklist's ticks by component\n * id, a widget's own state (`wizard.save`).\n */\n view?: Record<string, unknown>;\n /** Widgets: what loading it with this run's data showed. */\n widget?: {\n /** Seconds of animation the widget registered for video export; null = a still widget. */\n duration: number | null;\n errors: string[];\n };\n at: string;\n}\n\nexport interface RunState {\n values: Record<string, unknown>;\n outputs: Record<string, StepOutput>;\n /** Interactive steps answered, oldest first — \"back\" pops this. */\n history: string[];\n /** Regenerate notes per step. */\n notes: Record<string, string>;\n /** Steps that make several results: the entries (from 0) to make again; the others stay. */\n redo?: Record<string, number[]>;\n /** The step whose `ask` branches are being decided; the run waits on that decision. */\n deciding?: string;\n /** What decided `ask` branches answered, by step. */\n decisions?: Record<string, BranchDecision>;\n /** Pages whose fields a decision chose: the field ids kept, by page. */\n pages?: Record<string, { shown: string[] }>;\n /** How often each branch was taken, by \"<step>→<goto>\": loops stop at the rule's max. */\n loops?: Record<string, number>;\n /** File fields with `listen`: what is said in the recording, piece by piece with its times. */\n heard?: Record<string, { start: number; end: number; text: string }[]>;\n /**\n * A test run's own copy of the wizard's memory: the pages it wrote, by title. The wizard's\n * pages stay as they are; the copy goes with the run.\n */\n memory?: Record<string, string>;\n /**\n * Finished results translated on request, by language and step: the text the person reads in\n * place of the step's own (`StepOutput.text`); the step's output stays as it was made.\n */\n translated?: Record<string, Record<string, string>>;\n}\n\n/** What a decision over a step's `ask` branches found. */\nexport interface BranchDecision {\n /** The index of the rule in the step's `next`, or null: none of them, go on. */\n rule: number | null;\n source: \"systemone\" | \"llm\";\n probabilities?: Record<string, number>;\n at: string;\n}\n\n/** A branch decision as the studio sees it: with the step's branches it was made over. */\nexport interface ShownDecision extends BranchDecision {\n over: NonNullable<Step[\"next\"]>;\n}\n\ninterface AskBase {\n id: string;\n stepId: string;\n /** Why the wizard asks, in the person's language. */\n reason: string;\n at: string;\n}\n\n/**\n * A running step asks the person to sign in on a page the wizard's browser has open. What the\n * person types goes into that page; the model never sees it.\n */\nexport interface LoginAsk extends AskBase {\n kind: \"login\";\n site: { host: string; title: string };\n /** Inputs found on the page, to fill here instead of clicking into the picture. */\n fields: { id: string; label: string; secret: boolean }[];\n}\n\n/** A running step wants to change something in one of the person's accounts and asks first. */\nexport interface ConfirmAsk extends AskBase {\n kind: \"confirm\";\n /** The connected service, e.g. \"Notion\". */\n service: string;\n action: { id: string; summary: string; destructive: boolean };\n /** What would be sent, as readable JSON. */\n input: string;\n /** Asked for this one thing: there is nothing to allow for the rest of the run. */\n once?: boolean;\n}\n\n/** What a running step asks the person; the step waits for the answer. */\nexport type RunAsk = LoginAsk | ConfirmAsk;\n\n/** A question as a step puts it; the runner adds id, step and time. */\nexport type AskInput =\n | Omit<LoginAsk, \"id\" | \"stepId\" | \"at\">\n | Omit<ConfirmAsk, \"id\" | \"stepId\" | \"at\">;\n\n/**\n * `fill` and `done` answer a sign-in (remember = keep the sign-in); `done` also allows a change\n * (remember = allow that action for the rest of the run); `skip` declines either.\n */\nexport type AskAnswer =\n | { type: \"fill\"; values: Record<string, string>; remember?: boolean }\n | { type: \"done\"; remember?: boolean }\n | { type: \"skip\" };\n\n/** One thing the person does in the wizard's browser while it waits for them. */\nexport type BrowserAct =\n /** Where on the picture, as a share of its width and height (0–1). */\n | { type: \"click\"; fx: number; fy: number }\n | { type: \"type\"; text: string }\n | { type: \"key\"; key: \"Enter\" | \"Tab\" | \"Backspace\" | \"Escape\" }\n | { type: \"scroll\"; dy: number };\n\n/** A stored list the current step shows. */\nexport interface ShownList {\n def: ListDef;\n rows: ListRow[];\n formats: Format[];\n label: string | null;\n}\n\n/**\n * What a step reports while it works, in words for each language: the runtime writes the English\n * line into the run's log, a runner shows it in the language the person reads. The runtime's\n * answers to the person running a shared wizard (a refusal, a failure) are notes too: it answers\n * them in the wizard's language.\n */\nconst NOTES_EN = {\n entry: \"Entry {n} of {total}\",\n deciding: \"Deciding what to do next…\",\n choosingFields: \"Choosing the right questions…\",\n batchDone: \"{done} of {total} done\",\n editing: \"Editing {n} of {total}\",\n filming: \"Filming {n} of {total}\",\n clipsRendering: {\n one: \"Rendering {count} clip – this takes a few minutes.\",\n other: \"Rendering {count} clips – this takes a few minutes.\",\n },\n videoRendering: \"Rendering the video – this usually takes 1–3 minutes.\",\n photo: \"Looking at photo {n} of {total}\",\n // An entry a step has just written, while it writes the rest: \"Rezepte: Shakshuka mit Feta\".\n found: \"{label}: {name}\",\n listen: \"Listening to “{label}”…\",\n listenFailed: \"“{label}” couldn’t be transcribed.\",\n filmCutting: \"Cutting the film – this takes about a minute.\",\n filmProgress: \"{pct} % cut\",\n filmError: \"The film reports: {detail}\",\n widgetError: \"The widget reports an error: {detail}\",\n mcpConnected: \"Connected to {names}\",\n mcpUnreachable: \"MCP server unreachable: {detail}\",\n reads: \"Reading {name}\",\n readsMany: { one: \"Reading {count} document\", other: \"Reading {count} documents\" },\n opens: \"Opening {name}\",\n clicks: \"Clicking in the browser\",\n clicksOn: \"Clicking “{name}”\",\n types: \"Typing in the browser\",\n typesText: \"Typing “{text}”\",\n selects: \"Choosing “{option}”\",\n scrolls: \"Scrolling\",\n presses: \"Pressing {key}\",\n goesBack: \"Going back a page\",\n waitsForPage: \"Waiting for the page\",\n fastLoop: \"Doing in the browser: {goal}\",\n personDrives: \"You’re driving the browser – the wizard waits\",\n agentDrives: \"The wizard carries on in the browser\",\n looksAtPage: \"Looking at the page\",\n waitsForSignIn: \"Waiting for you to sign in to {name}\",\n downloads: \"Downloading {name}\",\n attaches: \"Attaching {name}\",\n runs: \"Running: {command}\",\n python: \"Running Python\",\n runsProgram: \"Working through the data in one go\",\n drawing: \"Drawing an image\",\n writesPage: \"Writing the page “{title}”\",\n searchesDocuments: \"Searching the documents: {query}\",\n searchesKnowledge: \"Searching knowledge: {query} – {relevant} of {candidates} fit\",\n listsKnowledge: \"Listing knowledge\",\n searchesMail: \"Searching {label}\",\n savesReceipts: {\n one: \"Saving {count} receipt from {label}\",\n other: \"Saving {count} receipts from {label}\",\n },\n remembers: \"Remembering {title}\",\n files: { one: \"Filing {count} file\", other: \"Filing {count} files\" },\n filmSetup: \"Setting up the folder for the film\",\n filmClient: \"{client} is working on the film – this usually takes 10–40 minutes.\",\n filmTask: \"On the film: {task}\",\n filmLooks: \"Looking at frames of the film\",\n filmFix: \"The film didn’t render – Claude Code is fixing it\",\n filmResume: \"Picking the film up where it stopped\",\n wizardUnavailable: \"This wizard isn’t available right now.\",\n translationFailed: \"This wizard can’t be translated right now. It’s shown as it was written.\",\n translationOff: \"This wizard is only offered as it was written.\",\n translationPlaceholder:\n \"The translation of “{text}” needs every placeholder in curly brackets the original has.\",\n wizardLimit: \"This wizard has reached its limit for today. Try again tomorrow.\",\n guestBudget: \"This page has reached its limit for today. Try again tomorrow.\",\n confirmHuman: \"Confirm that you’re a person.\",\n tooManyRuns: \"You’ve started a lot of runs just now. Try again in an hour.\",\n clientRefused: \"This app may not start runs here.\",\n clientLimit: \"This app has started a lot of runs just now. Try again later.\",\n runOver: \"The run is over.\",\n runBusy: \"The wizard is working right now.\",\n pageOutdated: \"This page is out of date.\",\n noStepBefore: \"There is no step before this one.\",\n checkFields: \"Check the marked fields.\",\n talkOff: \"Live conversations aren’t turned on for this wizard.\",\n talkKeyRefused: \"The conversation couldn’t start: the OpenAI API key was refused.\",\n talkFailed: \"The conversation couldn’t start ({status}).\",\n talkNoSecret: \"The conversation couldn’t start: no access key came back.\",\n tryLater: \"Try again later.\",\n recordingTooLarge: \"The recording can be 10 MB at most.\",\n fileTooLarge: \"Choose a file of {mb} MB or less.\",\n uploadNotPicture: \"This file isn’t a picture that can be read. Choose a PNG, JPEG, WebP or GIF.\",\n uploadPictureTooLarge: \"This picture is too large. Choose one of {mp} megapixels or less.\",\n uploadNotItsType: \"This file holds something other than its type says. Choose the file again.\",\n uploadSvgNotUsable: \"This SVG can’t be used. Save it again as a plain SVG, or choose a PNG.\",\n askClosed: \"This question is no longer open.\",\n noBrowser: \"The wizard has no browser open right now.\",\n notWaiting: \"The wizard isn’t waiting for you right now.\",\n pageActFailed: \"That didn’t work on the page.\",\n linkGone: \"This link has expired or was withdrawn.\",\n connected: \"Connected. You can close this window.\",\n connectFailed: \"Connecting didn’t work. Try again.\",\n connectCancelled: \"Connecting was cancelled.\",\n appleOff:\n \"Apple Intelligence is turned off on this Mac. Turn it on in System Settings → Apple Intelligence & Siri.\",\n appleLoading:\n \"Apple is still loading the model for Apple Intelligence onto this Mac. Try again in a moment.\",\n appleMissing: \"The helper for Apple Intelligence (wizards-apple) is missing from this install.\",\n appleOs: \"Apple Intelligence needs macOS 26 or later.\",\n appleDevice: \"Apple Intelligence only works on a Mac with Apple silicon.\",\n appleBusy: \"Apple Intelligence isn’t taking more requests right now. Try again in a moment.\",\n appleTooLong:\n \"The text is too long for Apple Intelligence on this Mac (4,096 tokens for question and answer). Choose another model for this class under Settings → Models.\",\n appleRefused: \"Apple Intelligence turned the request down: Apple’s content rules don’t allow it.\",\n appleLanguage: \"Apple Intelligence doesn’t understand the language of this request.\",\n appleFormat: \"Apple Intelligence can’t answer in this format: {detail}\",\n appleFailed: \"Apple Intelligence: {detail}\",\n appleNoFfmpeg:\n \"Apple Intelligence can’t read {type}, and without ffmpeg the recording can’t be converted. Install ffmpeg or record as MP4 in the browser.\",\n appleNotConverted: \"Apple Intelligence couldn’t convert the recording: {detail}\",\n connectorAlreadyExistsSpace: \"The connector “{id}” already exists in this space.\",\n connectorNotExist: \"This connector doesn’t exist.\",\n fieldMissing: \"“{label}” is missing.\",\n mailServerNotExist:\n \"The mail server{host} doesn’t exist. Enter the IMAP server. For Gmail and Google Workspace, it’s imap.gmail.com.\",\n mailServerNotResponding:\n \"The mail server{host} isn’t responding. Check the IMAP server and port.\",\n connectingNotWork: \"Connecting didn’t work{host}: {detail}\",\n connectEngentyAccountFirst:\n \"Connect your engenty account first (Settings → Account). Then you can connect Google here.\",\n engentyAccountNotReached: \"Your engenty account can’t be reached right now. Try again later.\",\n googleNoLongerAccepts: \"Google no longer accepts this connection. Connect the account again.\",\n googleNotConnectedThrough: \"Google can’t be connected through your engenty account right now.\",\n stepNeedsToolPlugin:\n \"This step needs the tool “{id}”. The plugin “{plugin}” isn’t installed here.\",\n clientNotSignedIn: \"{name} isn’t signed in on this computer. Sign in under Settings → Models.\",\n clientNotInstalled:\n \"{name} isn’t installed on this computer. Install it under Settings → Models.\",\n clientNoCredit: \"The account {name} is signed in with has no credit or quota left.\",\n clientAccountNotServed:\n \"{name} no longer serves the account it is signed in with. Sign it in with another account, or choose another way under Settings → Models.\",\n anthropicAccountClaudeCode:\n \"The Anthropic account Claude Code is signed in with has no credit. Sign Claude Code in with your subscription under Settings → Models.\",\n chatgptAccountCodexSigned:\n \"The ChatGPT account Codex is signed in with has used up its quota. Try again later or choose another client.\",\n builtTerminalNotAvailable:\n \"The built-in terminal isn’t available on this computer. Run the command in your own terminal.\",\n terminalNoLongerExists: \"This terminal no longer exists.\",\n imageTypeNotReadable: \"Images of type {mime} can’t be read (PNG, JPEG and WebP work).\",\n fileNotReadable: \"“{name}” ({mime}) can’t be read.\",\n creditsNotSignedIn: \"This is set to run on credits, but you’re not signed in to an account.\",\n accountNoLongerSigned:\n \"The account is no longer signed in. Sign in again under Settings → Account.\",\n modelNotUsedYet:\n \"The model “{ref}” can’t be used yet. Add an API key under Settings → Models, or sign in to an account.\",\n noModelForImages: \"No model is set up for images.\",\n noModelForVideos: \"No model is set up for videos.\",\n noModelForSpeech: \"No model is set up for speech.\",\n noOpenaiApiKey: \"No OpenAI API key is set for voice conversations (Settings → Models).\",\n modelNotAvailableAccount: \"This model isn’t available with your account.\",\n accountNoModelSet: \"Your account has no model set up for this.\",\n claudeCodeMakesFilms:\n \"Claude Code makes films on this computer, using your subscription. Set it up as an AI subscription under Settings → Models.\",\n macNeedsFfmpegTranscribe:\n \"This Mac needs ffmpeg to transcribe recordings from Chrome or Firefox (WebM, Ogg). Safari and the app don’t. Install ffmpeg, e.g. with “brew install ffmpeg”.\",\n fieldRequired: \"Required\",\n chooseAtLeast: \"Choose at least {min}\",\n chooseAtMost: \"At most {max} – remove some\",\n enterNumber: \"Enter a number\",\n invalidChoice: \"Invalid choice\",\n timeNotOffered: \"This time isn’t offered\",\n notValidEmailAddress: \"Not a valid email address\",\n notValidUrl: \"Not a valid URL\",\n wizardRunOutCredits: \"This wizard has run out of credits for now. Try again later.\",\n providerCreditLow:\n \"Your credit with the model provider isn’t enough for this (videos need a minimum balance there). Top up there and try again.\",\n aiServiceBusyRight: \"The AI service is busy right now. Try again in a moment.\",\n stepTookTooLong: \"The step took too long. Try again.\",\n aiServiceNotReached: \"The AI service can’t be reached right now. Try again later.\",\n notAvailableNow: \"That isn’t available here right now.\",\n fileNotFound: \"File not found\",\n connectFirst: \"Connect first\",\n noEntriesStepWork: \"There are no entries for this step to work on.\",\n stepNotReturnResult: \"The step didn’t return a result.\",\n documentNotCreated: \"The document couldn’t be created.\",\n stepMissingSourcesImages: \"This step is missing its sources (images or scenes).\",\n noTextReadAloud: \"There is no text to read aloud.\",\n wizardStillErrors: \"The wizard still has errors.\",\n noLanguageModelSet: \"No language model is set up here.\",\n creditsUsedUp: \"Your credits are used up.\",\n chooseFile: \"Choose a file.\",\n pageNotReached: \"The page can’t be reached.\",\n unknownEntry: \"Unknown entry.\",\n chooseWizardFileMb: \"Choose a wizard file ({PACKAGE_EXTENSION}) of 30 MB or less.\",\n recordingMbMost: \"The recording can be 10 MB at most.\",\n onlyFinishedResultsShared: \"Only finished results can be shared.\",\n gradientFailed: \"Couldn’t make a gradient from that. Try describing it differently.\",\n onlyOneSpaceAllowed: \"Only one space is allowed here.\",\n mostSpaces: {\n one: \"You can have at most {count} space here.\",\n other: \"You can have at most {count} spaces here.\",\n },\n twoEntriesSameKey: \"Two entries have the same key.\",\n pageSlugInvalid: \"A page address holds lower-case letters a–z, digits and hyphens.\",\n pageSlugTaken: \"Another space of your team has this address.\",\n pageTaken: \"The page is already at “{space}”.\",\n notDeleteLastSpace: \"You can’t delete the last space.\",\n notFound: \"This doesn’t exist or was deleted.\",\n categoryNeedsName: \"A category needs a name.\",\n unknownCategoryType: \"Unknown type “{type}”.\",\n spaceMostCategories: {\n one: \"A space can have at most {count} category.\",\n other: \"A space can have at most {count} categories.\",\n },\n categoryAlreadyExists: \"The category “{name}” already exists.\",\n onlyChoiceCategoriesValues: \"Only choice categories have values.\",\n onlyValuesOneCategory: \"Only values of one category can be merged.\",\n templateNeedsNewerVersion:\n \"This template needs a newer version of engenty wizards. Update engenty wizards first.\",\n chatNotExist: \"This chat doesn’t exist.\",\n unknownRunner: \"There’s no runner “{unknown}” here.\",\n leastOneRunnerStay: \"At least one runner has to stay on.\",\n linkOpenRunnerTurned: \"The link has to open a runner that’s turned on.\",\n jobNotExistAlready: \"This job doesn’t exist or has already finished.\",\n accountAlreadySpace: \"This account already has a space here.\",\n accountAlreadySpaces: {\n one: \"This account already has {count} space here.\",\n other: \"This account already has {count} spaces here.\",\n },\n roomMostPublishedWizards: {\n one: \"There’s room for at most {count} published wizard here.\",\n other: \"There’s room for at most {count} published wizards here.\",\n },\n spaceIdAlreadyExists:\n \"A space with this ID already exists here and didn’t come from your computer.\",\n wizardIdAlreadyBelongs: \"A wizard with this ID already belongs to another space here.\",\n idAlreadyUse: \"This ID is already in use here.\",\n wizardNotSpace: \"This wizard isn’t in the space.\",\n invalidColumns: \"Invalid columns.\",\n spaceMostTables: {\n one: \"A space can have at most {count} table.\",\n other: \"A space can have at most {count} tables.\",\n },\n tableBelongsOneWizard:\n \"This table belongs to one of the wizard’s lists. Its columns come from the wizard.\",\n entryAlreadyExists: \"This entry already exists.\",\n tableMostRows: {\n one: \"A table can have at most {count} row.\",\n other: \"A table can have at most {count} rows.\",\n },\n spaceMostPages: {\n one: \"A space can have at most {count} page.\",\n other: \"A space can have at most {count} pages.\",\n },\n pageNotSubpages: \"This page can’t have subpages.\",\n pageNotOwnSubpage: \"A page can’t be its own subpage.\",\n pageNeedsTitle: \"A page needs a title.\",\n unknownSpace: \"There’s no space “{space}”.\",\n noParentPage: \"There’s no page with the key “{parent}” to put this page under.\",\n onlyTeamAdmins:\n \"Only team admins can do that. As a member, you can edit the wizards that already exist.\",\n spaceEditedLocally: \"You edit this space in engenty wizards on your computer, not here.\",\n wizardsRunOncePublished:\n \"Wizards run here once you publish them in engenty wizards on your computer. You build and edit them there.\",\n logoImagePngSvg: \"A logo is an image (PNG, SVG, JPEG, WebP).\",\n patternImageSvgPng: \"A pattern is an image (SVG, PNG, JPEG, WebP).\",\n filesGoHere:\n \"Images, videos, audio, PDFs, fonts, Lottie and 3D models go here. Texts to look things up in go under knowledge.\",\n addressNotReached: \"The address can’t be reached.\",\n addressResponded: \"The address responded with {status}.\",\n addressLeadsWebPage: \"The address leads to a web page, not an image.\",\n addressFileTooLarge: \"The file is too large.\",\n onlyDocumentsIndex: \"Only documents are in the index.\",\n emptyTooLargeDocument: \"“{name}” is empty or too large for a document.\",\n spaceMostDocuments: {\n one: \"A space can have at most {count} document.\",\n other: \"A space can have at most {count} documents.\",\n },\n accountSignedOut: \"The account is signed out. Sign in again.\",\n cloudNotReachedRight: \"The cloud can’t be reached right now.\",\n publishWizardFirst: \"Publish the wizard first.\",\n wizardJsonUnreadable: \"This isn’t a wizard file: its wizard.json can’t be read.\",\n wizardFileComesNewer:\n \"This wizard file comes from a newer version, or it’s damaged. Update engenty wizards or export the wizard again.\",\n fileOver5Mb: \"{name} is larger than 5 MB.\",\n wizardFileTooLarge:\n \"The wizard file is too large: a workspace holds at most 200 files and 25 MB.\",\n wizardFileNotOpened:\n \"The wizard file can’t be opened. Export the wizard again and try once more.\",\n wizardJsonMissing: \"This isn’t a wizard file: wizard.json is missing.\",\n notValidFilePath: \"“{name}” isn’t a valid file path.\",\n workspaceWizardFileLarger: \"The workspace in the wizard file is larger than 25 MB.\",\n unknownTemplate: \"There’s no template “{starterId}”.\",\n wizardChangedMeantime: \"The wizard was changed in the meantime.\",\n valueNotExist: \"This value doesn’t exist.\",\n nothingFiledUnderValue: \"Nothing is filed under this value yet.\",\n filmNotRenderedNeeds:\n \"The film couldn’t be rendered. It needs ffmpeg and a timeline in the widget.\",\n signInRefused:\n \"The sign-in was refused{host}. Are the address and (app) password right? Gmail and Google Workspace need an app password and IMAP turned on.{answer}\",\n serverSaid: \" The server said: {answer}\",\n viaAccountFailed: \"Connecting through your engenty account didn’t work ({code}).\",\n pluginInvalidInput: \"“{id}” got invalid input: {path} – {problem}\",\n filmClientStopped:\n \"{name} stopped working on the film: {detail}. The work is saved. A new try carries on from there.\",\n filmWorkSaved: \"{problem} The work is saved. A new try carries on from there.\",\n filmRenderFailed: \"The film couldn’t be rendered: {detail}\",\n commandNotStarted: \"The command couldn’t start: {detail}\",\n providerKeyMissing: \"{provider} is chosen for {makes}, but no API key is set.\",\n noModelFor: \"No model is set up for {makes}.\",\n noApiKeyFor: \"No API key is set for {provider}.\",\n freeTier:\n \"Your AI Gateway key is on Vercel’s free tier, which doesn’t include {model}. Top up at Vercel ({url}) or choose another model under Settings → Models.\",\n thisModel: \"this model\",\n quoted: \"“{text}”\",\n viewErrors: \"The view has errors: {detail}\",\n blockedSteps: \"{steps}: {problem}\",\n joined: \"{first} {second}\",\n stepFailed: \"This step failed: {detail}\",\n answersMissing: \"Answers are missing or don’t fit: {answers}\",\n fieldError: \"{field} – {message}\",\n templateNeedsPlugins: {\n one: \"This template needs the plugin {plugins}: included with Pro on engenty.ai.\",\n other: \"This template needs the plugins {plugins}: included with Pro on engenty.ai.\",\n },\n pageMostChars: {\n one: \"A page can have at most {count} character.\",\n other: \"A page can have at most {count} characters.\",\n },\n chooseFileUpTo: \"Choose a file of {mb} MB or less.\",\n fontSourceNoFont: \"{family} needs a font file of the space: choose a .woff2 from the assets.\",\n roomMostFiles: {\n one: \"There’s room for at most {count} file here.\",\n other: \"There’s room for at most {count} files here.\",\n },\n makesText: \"text\",\n makesImages: \"images\",\n makesVideos: \"videos\",\n makesSpeech: \"speech\",\n makesVoiceNotes: \"voice notes\",\n} as const satisfies Record<string, Line>;\nexport type RunNoteCode = keyof typeof NOTES_EN;\n\nconst NOTES_DE: Partial<Record<RunNoteCode, Line>> = {\n entry: \"Eintrag {n} von {total}\",\n deciding: \"Entscheidet, wie es weitergeht …\",\n choosingFields: \"Wählt die passenden Fragen …\",\n batchDone: \"{done} von {total} fertig\",\n editing: \"Bearbeitet {n} von {total}\",\n filming: \"Dreht {n} von {total}\",\n clipsRendering: {\n one: \"{count} Clip wird gerendert – das dauert einige Minuten.\",\n other: \"{count} Clips werden gerendert – das dauert einige Minuten.\",\n },\n videoRendering: \"Das Video wird gerendert – das dauert meist 1–3 Minuten.\",\n photo: \"Sieht sich Foto {n} von {total} an\",\n found: \"{label}: {name}\",\n listen: \"Hört „{label}“ an …\",\n listenFailed: \"„{label}“ konnte nicht verschriftlicht werden.\",\n filmCutting: \"Der Film wird geschnitten – das dauert etwa eine Minute.\",\n filmProgress: \"{pct} % geschnitten\",\n filmError: \"Der Film meldet: {detail}\",\n widgetError: \"Das Widget meldet einen Fehler: {detail}\",\n mcpConnected: \"Verbunden mit {names}\",\n mcpUnreachable: \"MCP-Server nicht erreichbar: {detail}\",\n reads: \"Liest {name}\",\n readsMany: { one: \"Liest {count} Dokument\", other: \"Liest {count} Dokumente\" },\n opens: \"Öffnet {name}\",\n clicks: \"Klickt im Browser\",\n clicksOn: \"Klickt auf „{name}“\",\n types: \"Tippt im Browser\",\n typesText: \"Tippt „{text}“\",\n selects: \"Wählt „{option}“\",\n scrolls: \"Scrollt\",\n presses: \"Drückt {key}\",\n goesBack: \"Geht eine Seite zurück\",\n waitsForPage: \"Wartet auf die Seite\",\n fastLoop: \"Erledigt im Browser: {goal}\",\n personDrives: \"Du steuerst den Browser – der Wizard wartet\",\n agentDrives: \"Der Wizard macht im Browser weiter\",\n looksAtPage: \"Sieht sich die Seite an\",\n waitsForSignIn: \"Wartet auf deine Anmeldung bei {name}\",\n downloads: \"Lädt {name} herunter\",\n attaches: \"Hängt {name} an\",\n runs: \"Führt aus: {command}\",\n runsProgram: \"Arbeitet die Daten in einem Zug durch\",\n python: \"Führt Python aus\",\n drawing: \"Zeichnet ein Bild\",\n writesPage: \"Schreibt die Seite „{title}“\",\n searchesDocuments: \"Sucht in den Dokumenten: {query}\",\n searchesKnowledge: \"Sucht in Wissen: {query} – {relevant} von {candidates} passen\",\n listsKnowledge: \"Listet Wissen\",\n searchesMail: \"Durchsucht {label}\",\n savesReceipts: {\n one: \"Speichert {count} Beleg aus {label}\",\n other: \"Speichert {count} Belege aus {label}\",\n },\n remembers: \"Merkt sich {title}\",\n files: { one: \"Legt {count} Datei ab\", other: \"Legt {count} Dateien ab\" },\n filmSetup: \"Richtet den Arbeitsordner für den Film ein\",\n filmClient: \"{client} arbeitet am Film – das dauert meist 10–40 Minuten.\",\n filmTask: \"Am Film: {task}\",\n filmLooks: \"Sieht sich Bilder des Films an\",\n filmFix: \"Der Film ließ sich nicht rendern – Claude Code bessert nach\",\n filmResume: \"Macht dort weiter, wo der Film stehen geblieben ist\",\n wizardUnavailable: \"Dieser Wizard ist gerade nicht verfügbar.\",\n translationFailed:\n \"Dieser Wizard lässt sich gerade nicht übersetzen. Du siehst ihn so, wie er geschrieben wurde.\",\n translationOff: \"Diesen Wizard gibt es nur so, wie er geschrieben wurde.\",\n translationPlaceholder:\n \"Die Übersetzung von „{text}“ braucht jeden Platzhalter in geschweiften Klammern, den das Original hat.\",\n wizardLimit: \"Für heute ist das Limit dieses Wizards erreicht. Versuch es morgen wieder.\",\n guestBudget: \"Für heute ist das Limit dieser Seite erreicht. Versuch es morgen wieder.\",\n confirmHuman: \"Bestätige kurz, dass du ein Mensch bist.\",\n tooManyRuns: \"Du hast gerade viele Läufe gestartet. Versuch es in einer Stunde wieder.\",\n clientRefused: \"Diese App darf hier keine Läufe starten.\",\n clientLimit: \"Diese App hat gerade viele Läufe gestartet. Versuch es später wieder.\",\n runOver: \"Der Lauf ist beendet.\",\n runBusy: \"Der Wizard arbeitet gerade.\",\n pageOutdated: \"Diese Seite ist nicht mehr aktuell.\",\n noStepBefore: \"Kein vorheriger Schritt.\",\n checkFields: \"Prüf die markierten Felder.\",\n talkOff: \"Live-Gespräche sind für diesen Wizard nicht eingeschaltet.\",\n talkKeyRefused: \"Das Gespräch ließ sich nicht starten: Der OpenAI-API-Key wurde abgelehnt.\",\n talkFailed: \"Das Gespräch ließ sich nicht starten ({status}).\",\n talkNoSecret: \"Das Gespräch ließ sich nicht starten: Es kam kein Zugang zurück.\",\n tryLater: \"Versuch es später noch einmal.\",\n recordingTooLarge: \"Die Aufnahme darf höchstens 10 MB groß sein.\",\n fileTooLarge: \"Wähl eine Datei bis {mb} MB.\",\n uploadNotPicture: \"Diese Datei ist kein lesbares Bild. Wähl ein PNG, JPEG, WebP oder GIF.\",\n uploadPictureTooLarge: \"Dieses Bild ist zu groß. Wähl eins mit höchstens {mp} Megapixeln.\",\n uploadNotItsType:\n \"In dieser Datei steckt etwas anderes, als ihr Typ sagt. Wähl die Datei noch einmal.\",\n uploadSvgNotUsable: \"Dieses SVG geht nicht. Speicher es neu als einfaches SVG oder wähl ein PNG.\",\n askClosed: \"Diese Frage ist nicht mehr offen.\",\n noBrowser: \"Der Wizard hat gerade keinen Browser offen.\",\n notWaiting: \"Der Wizard wartet gerade nicht auf dich.\",\n pageActFailed: \"Das hat auf der Seite nicht geklappt.\",\n linkGone: \"Dieser Link ist abgelaufen oder wurde zurückgezogen.\",\n connected: \"Verbunden. Du kannst dieses Fenster schließen.\",\n connectFailed: \"Verbinden hat nicht geklappt. Versuch es noch einmal.\",\n connectCancelled: \"Verbinden wurde abgebrochen.\",\n appleOff:\n \"Apple Intelligence ist auf diesem Mac ausgeschaltet. Schalte es unter Systemeinstellungen → Apple Intelligence & Siri ein.\",\n appleLoading:\n \"Apple lädt das Modell für Apple Intelligence noch auf diesen Mac. Versuch es gleich noch einmal.\",\n appleMissing: \"Der Helfer für Apple Intelligence (wizards-apple) fehlt in dieser Installation.\",\n appleOs: \"Apple Intelligence braucht macOS 26 oder neuer.\",\n appleDevice: \"Apple Intelligence gibt es nur auf einem Mac mit Apple Silicon.\",\n appleBusy:\n \"Apple Intelligence nimmt gerade keine weiteren Anfragen an. Versuch es gleich noch einmal.\",\n appleTooLong:\n \"Der Text ist zu lang für Apple Intelligence auf diesem Mac (4.096 Tokens für Frage und Antwort). Wähle unter Einstellungen → Modelle ein anderes Modell für diese Klasse.\",\n appleRefused:\n \"Apple Intelligence hat die Anfrage abgelehnt: Apples Inhaltsregeln lassen sie nicht zu.\",\n appleLanguage: \"Apple Intelligence versteht die Sprache dieser Anfrage nicht.\",\n appleFormat: \"Apple Intelligence kann dieses Antwortformat nicht liefern: {detail}\",\n appleFailed: \"Apple Intelligence: {detail}\",\n appleNoFfmpeg:\n \"Apple Intelligence liest {type} nicht, und ohne ffmpeg lässt sich die Aufnahme nicht umwandeln. Installiere ffmpeg oder nimm im Browser als MP4 auf.\",\n appleNotConverted: \"Apple Intelligence konnte die Aufnahme nicht umwandeln: {detail}\",\n connectorAlreadyExistsSpace: \"Den Connector „{id}“ gibt es in diesem Space schon.\",\n connectorNotExist: \"Diesen Connector gibt es nicht.\",\n fieldMissing: \"„{label}“ fehlt.\",\n mailServerNotExist:\n \"Den Mail-Server{host} gibt es nicht. Trag den IMAP-Server ein, bei Gmail und Google Workspace imap.gmail.com.\",\n mailServerNotResponding: \"Der Mail-Server{host} antwortet nicht. Prüf IMAP-Server und Port.\",\n connectingNotWork: \"Verbinden hat nicht geklappt{host}: {detail}\",\n connectEngentyAccountFirst:\n \"Verbinde zuerst dein engenty-Konto (Einstellungen → Konto). Dann kannst du Google hier verbinden.\",\n engentyAccountNotReached:\n \"Dein engenty-Konto ist gerade nicht erreichbar. Versuch es später noch einmal.\",\n googleNoLongerAccepts: \"Google nimmt diese Verbindung nicht mehr an. Verbinde das Konto neu.\",\n googleNotConnectedThrough: \"Google lässt sich über dein engenty-Konto gerade nicht verbinden.\",\n stepNeedsToolPlugin:\n \"Dieser Schritt braucht das Werkzeug „{id}“. Das Plugin „{plugin}“ ist hier nicht installiert.\",\n clientNotSignedIn:\n \"{name} ist auf diesem Computer nicht angemeldet. Melde dich unter Einstellungen → Modelle an.\",\n clientNotInstalled:\n \"{name} ist auf diesem Computer nicht installiert. Installiere es unter Einstellungen → Modelle.\",\n clientNoCredit:\n \"Das Konto, mit dem {name} angemeldet ist, hat kein Guthaben oder Kontingent mehr.\",\n clientAccountNotServed:\n \"{name} bedient das Konto, mit dem es angemeldet ist, nicht mehr. Melde es mit einem anderen Konto an oder wähle unter Einstellungen → Modelle einen anderen Weg.\",\n anthropicAccountClaudeCode:\n \"Das Anthropic-Konto, mit dem Claude Code angemeldet ist, hat kein Guthaben. Melde Claude Code unter Einstellungen → Modelle mit deinem Abo an.\",\n chatgptAccountCodexSigned:\n \"Das Kontingent des ChatGPT-Kontos, mit dem Codex angemeldet ist, ist aufgebraucht. Versuch es später noch einmal oder wähle einen anderen Client.\",\n builtTerminalNotAvailable:\n \"Das eingebaute Terminal ist auf diesem Computer nicht verfügbar. Führe den Befehl in deinem eigenen Terminal aus.\",\n terminalNoLongerExists: \"Dieses Terminal gibt es nicht mehr.\",\n imageTypeNotReadable: \"Bilder vom Typ {mime} lassen sich nicht lesen (PNG, JPEG und WebP gehen).\",\n fileNotReadable: \"„{name}“ ({mime}) lässt sich nicht lesen.\",\n creditsNotSignedIn: \"Dafür sind Credits gewählt, aber du bist mit keinem Konto angemeldet.\",\n accountNoLongerSigned:\n \"Das Konto ist nicht mehr angemeldet. Melde dich unter Einstellungen → Konto neu an.\",\n modelNotUsedYet:\n \"Das Modell „{ref}“ lässt sich noch nicht nutzen. Hinterleg unter Einstellungen → Modelle einen API-Key oder melde dich mit einem Konto an.\",\n noModelForImages: \"Für Bilder ist kein Modell eingerichtet.\",\n noModelForVideos: \"Für Videos ist kein Modell eingerichtet.\",\n noModelForSpeech: \"Für Sprachausgabe ist kein Modell eingerichtet.\",\n noOpenaiApiKey:\n \"Für Sprachgespräche ist kein OpenAI-API-Key hinterlegt (Einstellungen → Modelle).\",\n modelNotAvailableAccount: \"Dieses Modell gibt es mit deinem Konto nicht.\",\n accountNoModelSet: \"Dafür ist bei deinem Konto kein Modell eingerichtet.\",\n claudeCodeMakesFilms:\n \"Filme macht Claude Code auf diesem Computer mit deinem Abo. Richte es unter Einstellungen → Modelle als KI-Abo ein.\",\n macNeedsFfmpegTranscribe:\n \"Aufnahmen aus Chrome oder Firefox (WebM, Ogg) schreibt dieser Mac erst mit ffmpeg auf. Safari und die App brauchen es nicht. Installiere ffmpeg, z. B. mit „brew install ffmpeg“.\",\n fieldRequired: \"Pflichtfeld\",\n chooseAtLeast: \"Wähl mindestens {min} aus\",\n chooseAtMost: \"Höchstens {max} – entferne einige\",\n enterNumber: \"Gib eine Zahl ein\",\n invalidChoice: \"Ungültige Auswahl\",\n timeNotOffered: \"Dieser Termin wird nicht angeboten\",\n notValidEmailAddress: \"Keine gültige E-Mail-Adresse\",\n notValidUrl: \"Keine gültige URL\",\n wizardRunOutCredits:\n \"Dieser Wizard hat gerade kein Guthaben mehr. Versuch es später noch einmal.\",\n providerCreditLow:\n \"Das Guthaben beim Modellanbieter reicht dafür nicht aus (Videos brauchen dort ein Mindestguthaben). Lade dort auf und versuch es noch einmal.\",\n aiServiceBusyRight: \"Der KI-Dienst ist gerade ausgelastet. Versuch es gleich noch einmal.\",\n stepTookTooLong: \"Der Schritt hat zu lange gedauert. Versuch es noch einmal.\",\n aiServiceNotReached: \"Der KI-Dienst ist gerade nicht erreichbar. Versuch es später noch einmal.\",\n notAvailableNow: \"Das ist hier gerade nicht verfügbar.\",\n fileNotFound: \"Datei nicht gefunden\",\n connectFirst: \"Verbinde zuerst\",\n noEntriesStepWork: \"Es gibt keine Einträge, für die dieser Schritt arbeiten könnte.\",\n stepNotReturnResult: \"Der Schritt hat kein Ergebnis geliefert.\",\n documentNotCreated: \"Das Dokument konnte nicht erstellt werden.\",\n stepMissingSourcesImages: \"Für diesen Schritt fehlen die Vorlagen (Bilder oder Szenen).\",\n noTextReadAloud: \"Es gibt keinen Text zum Vorlesen.\",\n wizardStillErrors: \"Der Wizard hat noch Fehler.\",\n noLanguageModelSet: \"Hier ist kein Sprachmodell eingerichtet.\",\n creditsUsedUp: \"Dein Guthaben ist aufgebraucht.\",\n chooseFile: \"Wähl eine Datei.\",\n pageNotReached: \"Die Seite ist nicht erreichbar.\",\n unknownEntry: \"Unbekannter Eintrag.\",\n chooseWizardFileMb: \"Wähl eine Wizard-Datei ({PACKAGE_EXTENSION}) bis 30 MB.\",\n recordingMbMost: \"Die Aufnahme darf höchstens 10 MB groß sein.\",\n onlyFinishedResultsShared: \"Nur fertige Ergebnisse lassen sich teilen.\",\n gradientFailed: \"Daraus ließ sich kein Verlauf machen. Beschreib ihn anders.\",\n onlyOneSpaceAllowed: \"Hier ist nur ein Space möglich.\",\n mostSpaces: {\n one: \"Hier ist höchstens {count} Space möglich.\",\n other: \"Hier sind höchstens {count} Spaces möglich.\",\n },\n twoEntriesSameKey: \"Zwei Einträge haben denselben Schlüssel.\",\n pageSlugInvalid: \"Eine Seitenadresse besteht aus Kleinbuchstaben a–z, Ziffern und Bindestrichen.\",\n pageSlugTaken: \"Ein anderer Space deines Teams hat diese Adresse.\",\n pageTaken: \"Die Seite ist schon bei „{space}“.\",\n notDeleteLastSpace: \"Der letzte Space lässt sich nicht löschen.\",\n notFound: \"Das gibt es nicht oder nicht mehr.\",\n categoryNeedsName: \"Eine Kategorie braucht einen Namen.\",\n unknownCategoryType: \"Unbekannter Typ „{type}“.\",\n spaceMostCategories: {\n one: \"Ein Space hat höchstens {count} Kategorie.\",\n other: \"Ein Space hat höchstens {count} Kategorien.\",\n },\n categoryAlreadyExists: \"Die Kategorie „{name}“ gibt es schon.\",\n onlyChoiceCategoriesValues: \"Werte gibt es nur bei Kategorien vom Typ Auswahl.\",\n onlyValuesOneCategory: \"Nur Werte einer Kategorie lassen sich zusammenführen.\",\n templateNeedsNewerVersion:\n \"Diese Vorlage braucht eine neuere Version von engenty wizards. Aktualisiere zuerst engenty wizards.\",\n chatNotExist: \"Diesen Chat gibt es nicht.\",\n unknownRunner: \"Einen Runner „{unknown}“ gibt es hier nicht.\",\n leastOneRunnerStay: \"Mindestens ein Runner muss eingeschaltet bleiben.\",\n linkOpenRunnerTurned: \"Der Link muss einen eingeschalteten Runner öffnen.\",\n jobNotExistAlready: \"Diesen Vorgang gibt es nicht, oder er ist schon beendet.\",\n accountAlreadySpace: \"Dieses Konto hat hier schon einen Space.\",\n accountAlreadySpaces: {\n one: \"Dieses Konto hat hier schon {count} Space.\",\n other: \"Dieses Konto hat hier schon {count} Spaces.\",\n },\n roomMostPublishedWizards: {\n one: \"Hier hat höchstens {count} veröffentlichter Wizard Platz.\",\n other: \"Hier haben höchstens {count} veröffentlichte Wizards Platz.\",\n },\n spaceIdAlreadyExists:\n \"Einen Space mit dieser Kennung gibt es hier schon, und er kommt nicht von deinem Computer.\",\n wizardIdAlreadyBelongs: \"Ein Wizard mit dieser Kennung gehört hier schon zu einem anderen Space.\",\n idAlreadyUse: \"Diese Kennung ist hier schon vergeben.\",\n wizardNotSpace: \"Diesen Wizard gibt es im Space nicht.\",\n invalidColumns: \"Ungültige Spalten.\",\n spaceMostTables: {\n one: \"Ein Space hat höchstens {count} Tabelle.\",\n other: \"Ein Space hat höchstens {count} Tabellen.\",\n },\n tableBelongsOneWizard:\n \"Diese Tabelle gehört zu einer Liste des Wizards. Die Spalten kommen aus dem Wizard.\",\n entryAlreadyExists: \"Diesen Eintrag gibt es schon.\",\n tableMostRows: {\n one: \"Eine Tabelle hat höchstens {count} Zeile.\",\n other: \"Eine Tabelle hat höchstens {count} Zeilen.\",\n },\n spaceMostPages: {\n one: \"Ein Space hat höchstens {count} Seite.\",\n other: \"Ein Space hat höchstens {count} Seiten.\",\n },\n pageNotSubpages: \"Diese Seite kann keine Unterseiten haben.\",\n pageNotOwnSubpage: \"Eine Seite kann nicht ihre eigene Unterseite sein.\",\n pageNeedsTitle: \"Eine Seite braucht einen Titel.\",\n unknownSpace: \"Den Space „{space}“ gibt es nicht.\",\n noParentPage: \"Es gibt keine Seite mit dem Schlüssel „{parent}“, unter die diese Seite könnte.\",\n onlyTeamAdmins:\n \"Das dürfen nur Admins des Teams. Als Mitglied bearbeitest du die Wizards, die es schon gibt.\",\n spaceEditedLocally:\n \"Diesen Space bearbeitest du in engenty wizards auf deinem Computer, nicht hier.\",\n wizardsRunOncePublished:\n \"Hier laufen die Wizards, die du in engenty wizards auf deinem Computer veröffentlichst. Gebaut und bearbeitet wird dort.\",\n logoImagePngSvg: \"Ein Logo ist ein Bild (PNG, SVG, JPEG, WebP).\",\n patternImageSvgPng: \"Ein Muster ist ein Bild (SVG, PNG, JPEG, WebP).\",\n filesGoHere:\n \"Hierher gehören Bilder, Videos, Audio, PDFs, Schriften, Lottie und 3D-Modelle. Texte zum Nachschlagen gehören ins Wissen.\",\n addressNotReached: \"Die Adresse ist nicht erreichbar.\",\n addressResponded: \"Die Adresse antwortete mit {status}.\",\n addressLeadsWebPage: \"Unter der Adresse steht eine Webseite, kein Bild.\",\n addressFileTooLarge: \"Die Datei ist zu groß.\",\n onlyDocumentsIndex: \"Nur Dokumente stehen im Index.\",\n emptyTooLargeDocument: \"„{name}“ ist leer oder zu groß für ein Dokument.\",\n spaceMostDocuments: {\n one: \"Ein Space hat höchstens {count} Dokument.\",\n other: \"Ein Space hat höchstens {count} Dokumente.\",\n },\n accountSignedOut: \"Das Konto ist abgemeldet. Melde dich neu an.\",\n cloudNotReachedRight: \"Die Cloud ist gerade nicht erreichbar.\",\n publishWizardFirst: \"Veröffentliche den Wizard zuerst.\",\n wizardJsonUnreadable: \"Das ist keine Wizard-Datei: Die wizard.json darin lässt sich nicht lesen.\",\n wizardFileComesNewer:\n \"Diese Wizard-Datei stammt aus einer neueren Version oder ist beschädigt. Aktualisiere engenty wizards oder exportiere den Wizard neu.\",\n fileOver5Mb: \"{name} ist größer als 5 MB.\",\n wizardFileTooLarge:\n \"Die Wizard-Datei ist zu groß: Ein Arbeitsbereich fasst höchstens 200 Dateien und 25 MB.\",\n wizardFileNotOpened:\n \"Die Wizard-Datei lässt sich nicht öffnen. Exportiere den Wizard neu und versuche es noch einmal.\",\n wizardJsonMissing: \"Das ist keine Wizard-Datei: Die wizard.json fehlt.\",\n notValidFilePath: \"„{name}“ ist kein gültiger Dateipfad.\",\n workspaceWizardFileLarger: \"Der Arbeitsbereich in der Wizard-Datei ist größer als 25 MB.\",\n unknownTemplate: \"Die Vorlage „{starterId}“ gibt es nicht.\",\n wizardChangedMeantime: \"Der Wizard wurde inzwischen geändert.\",\n valueNotExist: \"Diesen Wert gibt es nicht.\",\n nothingFiledUnderValue: \"Unter diesem Wert steht noch nichts.\",\n filmNotRenderedNeeds:\n \"Der Film ließ sich nicht rendern. Dafür braucht es ffmpeg und eine Zeitleiste im Widget.\",\n signInRefused:\n \"Anmeldung abgelehnt{host}. Stimmen Adresse und (App-)Passwort? Gmail und Google Workspace brauchen ein App-Passwort und eingeschaltetes IMAP.{answer}\",\n serverSaid: \" Antwort des Servers: {answer}\",\n viaAccountFailed: \"Verbinden über dein engenty-Konto hat nicht geklappt ({code}).\",\n pluginInvalidInput: \"„{id}“ bekam ungültige Angaben: {path} – {problem}\",\n filmClientStopped:\n \"{name} hat beim Film aufgehört: {detail}. Die Arbeit ist gespeichert. Ein neuer Versuch macht dort weiter.\",\n filmWorkSaved: \"{problem} Die Arbeit ist gespeichert. Ein neuer Versuch macht dort weiter.\",\n filmRenderFailed: \"Der Film ließ sich nicht rendern: {detail}\",\n commandNotStarted: \"Der Befehl konnte nicht starten: {detail}\",\n providerKeyMissing: \"Für {makes} ist {provider} gewählt, aber kein API-Key hinterlegt.\",\n noModelFor: \"Für {makes} ist kein Modell eingerichtet.\",\n noApiKeyFor: \"Für {provider} ist kein API-Key hinterlegt.\",\n freeTier:\n \"Dein AI-Gateway-Key nutzt bei Vercel die kostenlose Stufe, und die schließt {model} aus. Lade bei Vercel Guthaben auf ({url}) oder wähle unter Einstellungen → Modelle ein anderes Modell.\",\n thisModel: \"dieses Modell\",\n quoted: \"„{text}“\",\n viewErrors: \"Die Ansicht hat Fehler: {detail}\",\n stepFailed: \"Dieser Schritt hat nicht geklappt: {detail}\",\n answersMissing: \"Antworten fehlen oder passen nicht: {answers}\",\n templateNeedsPlugins: {\n one: \"Diese Vorlage braucht das Plugin {plugins}: bei Pro auf engenty.ai dabei.\",\n other: \"Diese Vorlage braucht die Plugins {plugins}: bei Pro auf engenty.ai dabei.\",\n },\n pageMostChars: \"Eine Seite hat höchstens {count} Zeichen.\",\n chooseFileUpTo: \"Wähl eine Datei bis {mb} MB.\",\n fontSourceNoFont:\n \"{family} braucht eine Schriftdatei des Space: Wähl eine .woff2 aus den Assets.\",\n roomMostFiles: {\n one: \"Hier hat höchstens {count} Datei Platz.\",\n other: \"Hier haben höchstens {count} Dateien Platz.\",\n },\n makesText: \"Text\",\n makesImages: \"Bilder\",\n makesVideos: \"Videos\",\n makesSpeech: \"Sprachausgabe\",\n makesVoiceNotes: \"Sprachnotizen\",\n};\n\nexport const RUN_NOTES: Texts<RunNoteCode> = { en: NOTES_EN, de: NOTES_DE };\n\n/** What fills a note's gaps: words, numbers, other notes (said in the same language), lists. */\nexport type NoteGap = Gap | RunNote | readonly NoteGap[];\n\n/** A line of `RUN_NOTES` with what goes into its gaps. */\nexport interface RunNote {\n code: RunNoteCode;\n params?: Record<string, NoteGap | undefined>;\n}\n\n/** What the person reads: plain words, or a note that has a line for each language. */\nexport type Said = string | RunNote;\n\n/** A note: a line of `RUN_NOTES`, said in whichever language the reader reads. */\nexport function note(code: RunNoteCode, params?: Record<string, NoteGap | undefined>): RunNote {\n return params ? { code, params } : { code };\n}\n\n/** What is said, in a language. */\nexport function saidText(said: Said, lang: Lang): string {\n return typeof said === \"string\" ? said : noteText(said, lang);\n}\n\nfunction gapIn(value: NoteGap, lang: string, table?: TextTable): Gap {\n if (Array.isArray(value)) {\n return value.map((item: NoteGap) => gapIn(item, lang, table));\n }\n if (typeof value === \"object\" && value !== null && \"code\" in value) {\n return noteText(value, lang, table);\n }\n return value as Gap;\n}\n\n/**\n * A note in a language, its gaps filled; English where the language lacks the line. A language\n * outside `LANGS` reads its lines from `table`, the notes translated on request.\n */\nexport function noteText(note: RunNote, lang: string, table?: TextTable): string {\n if (!(note.code in NOTES_EN)) {\n return \"\";\n }\n const params: Record<string, Gap | undefined> = {};\n for (const [key, value] of Object.entries(note.params ?? {})) {\n params[key] = value === undefined ? undefined : gapIn(value, lang, table);\n }\n const own = table?.[note.code];\n if (own !== undefined) {\n return lineText(own, lang, params);\n }\n return textOf(RUN_NOTES, note.code, isLang(lang) ? lang : \"en\", params);\n}\n\nexport interface RunEvent {\n id: number;\n at: string;\n stepId: string | null;\n type: \"step_started\" | \"step_done\" | \"tool\" | \"info\" | \"error\";\n /** In German, as the run's log keeps it. */\n message: string;\n /** The same as a note a runner shows in the person's language; null for free text. */\n note?: RunNote | null;\n /** A picture of the run this is about (a photo being looked at, an image just made). */\n asset?: string | null;\n}\n\nexport interface RunView {\n id: string;\n status: RunStatus;\n mode: \"test\" | \"live\";\n wizard: Pick<WizardDefinition, \"title\" | \"description\" | \"avatar\" | \"costume\" | \"intro\">;\n /** The language the wizard speaks, by its code: what is read aloud, and in which voice. */\n lang: string;\n /**\n * The run in the viewer's language (a wizard translated on request): every text of the view\n * is written in it, the choices keep their values and show `labels[value]`. Null: the\n * wizard's own words.\n */\n translation: RunTranslation | null;\n /** A live conversation can be started on this run: the runtime has a model for it and the wizard has live voice or video on (always in a test). */\n talk: boolean;\n /** The step the person is on (interactive) or the one running. */\n step: Step | null;\n /** Pages and reviews answered before it, oldest first: what a chat shows above the current step. */\n answered: Step[];\n values: Record<string, unknown>;\n /** What fields of the current page start with, from earlier steps (`prefill`). */\n prefill: Record<string, unknown>;\n /** What the `when` of the current page's fields read from before the page, by reference. */\n known?: Record<string, unknown>;\n /** Choices of the current page's fields that come from earlier data (`optionsFrom`). */\n options?: Record<string, string[]>;\n /** The same choices as cards, for fields that have `cards`. */\n cards?: Record<string, CardOption[]>;\n /** The decided fields (`ask`, `group`) of the current page that a decision kept. */\n decidedFields?: string[];\n /**\n * What decided branches answered so far, by step, with the branches decided over (test runs:\n * the studio shows them while the draft's branches are still those).\n */\n decisions?: Record<string, ShownDecision>;\n /** Choices of the current page that lead to a step without a model here, by field id. */\n closed: Record<string, ClosedChoice>;\n outputs: Record<string, StepOutput>;\n /** Steps whose outputs the current step shows, with their definitions. */\n shown: { step: Step; output: StepOutput | null; formats: Format[]; label: string | null }[];\n progress: { done: number; total: number };\n canBack: boolean;\n error: string | null;\n events: RunEvent[];\n brand: BrandView;\n /** What the running step asks the person right now. */\n ask: RunAsk | null;\n /** Stored lists the current step shows (a page's list fields, a review, the result). */\n lists: ShownList[];\n /** The wizard's connections with what the person has connected. */\n connections: ConnectionView[];\n /** The wizard keeps things for the person between runs (lists, files, accounts). */\n keeps: boolean;\n /** Set once the result is shared. */\n shareUrl: string | null;\n /** When the run and its shared link are deleted; null = kept. */\n expiresAt: string | null;\n /** The result on its way to a share target, or the last one that arrived or failed. */\n shareJob: ShareJobView | null;\n}\n\n/** How a run in the viewer's language shows. */\nexport interface RunTranslation {\n /** The language, by its code (\"fr\"): any language, not only one of `LANGS`. */\n lang: string;\n /** What a choice shows, by its value. */\n labels: Record<string, string>;\n /** A model wrote some of it; false where the author wrote every text by hand. */\n machine: boolean;\n /** Results shown in this language, by step (`RunState.translated`). */\n results: Record<string, string>;\n}\n\n/** A shared result: what `/s/<token>` shows. Never the person's answers. */\nexport interface ShareView {\n token: string;\n title: string;\n message: string | null;\n wizard: Pick<WizardDefinition, \"title\" | \"description\" | \"avatar\" | \"costume\">;\n brand: BrandView;\n shown: RunView[\"shown\"];\n createdAt: string;\n expiresAt: string | null;\n /** The wizard's public link, to make your own — when it is published and open. */\n wizardUrl: string | null;\n}\n\nexport interface BrandView {\n name: string;\n accent: string | null;\n logoUrl: string | null;\n /** How the pages look: the run page sets its tokens from it. */\n theme: RunTheme;\n}\n\n/**\n * How a wizard's pages look: its space's brand (`runTheme`) with the wizard's own style on top\n * (`themedLook`). Null: the runner's own.\n */\nexport interface RunTheme {\n /** Buttons and marks. */\n accent: string | null;\n /** What is there, done or good to know: ticks, tips, group headings. */\n second: string | null;\n /** The ground the pages stand on; its hue tints paper and ink. */\n background: string | null;\n /** Typefaces as CSS names them. */\n display: string | null;\n body: string | null;\n /** The brand fonts of the two typefaces that have a source: the page loads them from there. */\n faces: RunFontFace[];\n /** The brand stands on a dark ground. */\n dark: boolean;\n /** The theme has only dark or only light pages: the person's own setting does not change it. */\n pinned: boolean;\n /** The theme's colours for light and for dark pages; the page takes those of what it shows. */\n modes: { light: ThemeColours | null; dark: ThemeColours | null } | null;\n /** Which of the two the pages show while the person has not chosen. */\n prefer: \"light\" | \"dark\" | null;\n shape: ThemeShape | null;\n /** Effects from the runner's library (`THEME_EFFECTS`); names it does not know are skipped. */\n effects: ThemeEffect[];\n}\n\n/** A brand font as a run page loads it: from our copy of its file, or from the space's website. */\nexport interface RunFontFace {\n family: string;\n /** Ours (`/api/public/fonts/…`) or the website's: the font file or a stylesheet that holds it. */\n url: string;\n stylesheet: boolean;\n}\n\nexport interface PublicWizard {\n token: string;\n title: string;\n description: string;\n avatar: string;\n costume?: EngentyCostume;\n intro: string | null;\n brand: BrandView;\n turnstileSiteKey: string | null;\n available: boolean;\n unavailableReason: string | null;\n /**\n * The runners switched on for this wizard, the one its link opens first: what the page offers\n * beside \"Let's go\". A page runner has an address; a channel (a number, a bot) has none.\n */\n runners: { id: string; label: string; kind: \"page\" | \"channel\"; url: string | null }[];\n /** The language the wizard is written in, by its code: the page opens in it. */\n lang: string;\n /** The author offers the wizard in the viewer's language, translated on request. */\n translatable: boolean;\n /** The page in the viewer's language, where it was asked for (`?lang=`); null: the original. */\n translation: Omit<RunTranslation, \"results\"> | null;\n /**\n * What the wizard's pages ask, in order: an AI app that starts the wizard (the OpenUI\n * component) can fill in what it already knows. The person still sees and sends each page.\n */\n fields: PublicField[];\n}\n\n/** A field of a wizard's page, as `PublicWizard.fields` lists it. */\nexport interface PublicField {\n id: string;\n label: string;\n kind: string;\n options?: string[];\n required?: boolean;\n}\n\n/** The runner's own words in a language outside `LANGS`: `GET /api/public/texts/:lang`. */\nexport interface UiTexts {\n lang: string;\n /** The runner's table (`packages/shared/src/runner-texts.ts`). */\n runner: TextTable;\n /** The run notes (`RUN_NOTES`). */\n notes: TextTable;\n}\n\n/** What a step is expected to cost, in credits. `high` is the 90th percentile once measured. */\nexport interface StepEstimate {\n credits: number;\n high: number;\n /** From at least five runs of this version; otherwise from a formula. */\n measured: boolean;\n}\n\n/** What a run is expected to cost. `available` is false where no credits are involved. */\n/** A model class a wizard needs that this runtime cannot serve, with the steps that call it. */\nexport interface MissingModel {\n cls: ModelClass;\n /** Why the class cannot run, as the person reads it. */\n problem: string;\n steps: { id: string; title: string }[];\n /** A step that needs it lies on every path: the run cannot start. */\n blocking: boolean;\n}\n\n/** A page's choice whose values lead to a step this runtime has no model for. */\nexport interface ClosedChoice {\n /** The options (or a toggle's true / false) that lead there; empty = the field as a whole. */\n values: (string | boolean)[];\n /** What is missing on the way. */\n classes: ModelClass[];\n}\n\nexport interface RunEstimate {\n available: boolean;\n credits: number;\n /** Credits held when a run starts. */\n reserve: number;\n steps: Record<string, StepEstimate>;\n}\n","// SPDX-License-Identifier: FSL-1.1-MIT OR MIT\nimport type { Line, Texts } from \"./texts.js\";\n\n// Wording: docs/copy-style.md (voice, glossary, EN/DE mechanics). Write each language as its\n// own sentence, not a word-for-word copy of the other. Check with `pnpm copy:check`.\n/**\n * What the runner says to the person running a wizard, in German and English. The studio spreads\n * these into its own dictionary; a host without one (the WordPress plugin) uses them as they are.\n */\nconst de: Record<RunnerKey, Line> = {\n \"result.translate\": \"Übersetzen\",\n \"translation.working\": \"Wird übersetzt …\",\n \"translation.machine\": \"Maschinell übersetzt\",\n \"translation.showOriginal\": \"Original zeigen\",\n \"translation.showTranslated\": \"Übersetzung zeigen\",\n \"translation.failed\": \"Dieser Wizard lässt sich gerade nicht übersetzen.\",\n \"share.copied\": \"Kopiert\",\n \"surface.done\": \"{done} von {total}\",\n \"surface.allDone\": \"Alles erledigt\",\n \"surface.close\": \"Schließen\",\n \"data.view\": \"Ansicht\",\n \"data.edit\": \"Bearbeiten\",\n \"data.json\": \"JSON\",\n \"data.modes\": \"Daten zeigen als\",\n \"data.add\": \"{what} hinzufügen\",\n \"data.remove\": \"Entfernen\",\n \"data.missing\": \"{id} fehlt\",\n \"data.yes\": \"Ja\",\n \"data.no\": \"Nein\",\n \"data.menu\": \"Mehr\",\n \"data.open\": \"Daten ansehen und bearbeiten\",\n \"data.close\": \"Daten schließen\",\n \"data.save\": \"Speichern\",\n \"data.saved\": \"Gespeichert\",\n \"data.schema\": \"JSON Schema\",\n \"data.copy\": \"Kopieren\",\n \"data.download\": \"Herunterladen\",\n \"run.closed\": \"Hier gerade nicht verfügbar, dafür fehlt: {list}\",\n \"slot.later\": \"Spätere Termine zeigen\",\n \"slot.none\": \"Gerade sind keine Termine frei.\",\n \"cards.open\": \"Details\",\n \"cards.picked\": \"Ausgewählt ✓\",\n \"cards.pick\": \"Auswählen\",\n \"run.cls.text\": \"Text\",\n \"run.cls.image\": \"Bilder\",\n \"run.cls.video\": \"Videos\",\n \"run.cls.speech\": \"Sprachausgabe\",\n \"run.cls.audio\": \"Sprachnotizen\",\n \"run.cls.account\": \"ein engenty-Konto\",\n \"run.next\": \"Weiter\",\n \"run.back\": \"Zurück\",\n \"run.accept\": \"Passt so\",\n \"run.edit\": \"Bearbeiten\",\n \"run.pickItem\": \"Nr. {n}\",\n \"run.pickedItem\": \"Nr. {n} neu\",\n \"run.regeneratePicked\": \"Nur Nr. {n} wird neu erstellt.\",\n \"run.regenerateAll\":\n \"Alle werden neu erstellt. Tippe oben auf eine Nummer, um nur einzelne zu erneuern.\",\n \"check.progress\": \"{done} von {total} geprüft\",\n \"check.onlyOpen\": \"Nur offene\",\n \"check.noFile\": \"Zu dieser Zeile gibt es keine Datei.\",\n \"check.noPreview\": \"Für diese Datei gibt es keine Vorschau – öffne sie mit dem Link oben.\",\n \"check.reopen\": \"Wieder öffnen\",\n \"run.feedbackPlaceholder\": \"Passt etwas nicht? Schreib, was anders sein soll …\",\n \"run.feedbackTarget\": \"Was soll sich ändern?\",\n \"run.feedbackPick\": \"Wähle oben, was sich ändern soll.\",\n \"ai.generated\": \"KI-generiert\",\n \"ai.modified\": \"Mit KI verändert\",\n \"ai.publish\":\n \"Mit KI erstellt: Wer das veröffentlicht, muss es als KI-generiert kennzeichnen (EU AI Act, Art. 50). Die Datei trägt die Kennzeichnung bereits in ihren Metadaten.\",\n \"run.regenerateGo\": \"Neu erstellen\",\n \"run.retry\": \"Erneut versuchen\",\n \"run.again\": \"Nochmal\",\n \"run.copy\": \"Text kopieren\",\n \"run.failed\": \"Da hat etwas nicht geklappt.\",\n \"run.notFound\": \"Diesen Wizard gibt es nicht, oder er wurde gelöscht.\",\n \"run.working\": \"Einen Moment …\",\n \"run.elapsed\": \"{s} s\",\n \"run.cancelled\": \"Abgebrochen.\",\n \"run.addRow\": \"Zeile hinzufügen\",\n \"run.upload\": \"Datei wählen oder hierher ziehen\",\n \"run.uploading\": \"Lädt hoch …\",\n \"run.net\": \"Netto\",\n \"run.vat\": \"USt. {r} %\",\n \"run.total\": \"Gesamt\",\n \"run.uploadMore\": \"Weitere Datei\",\n \"run.camera\": \"Kamera\",\n \"camera.title\": \"Mit der Kamera aufnehmen\",\n \"camera.hint\": \"Gerade und gut beleuchtet ins Bild halten.\",\n \"camera.taken\": \"{n} aufgenommen\",\n \"camera.shoot\": \"Aufnehmen\",\n \"camera.done\": \"Fertig\",\n \"camera.denied\":\n \"Die Kamera ist für diese Seite nicht freigegeben. Erlaube sie in den Website-Einstellungen deines Browsers (Schloss-Symbol in der Adresszeile) – oder nimm das Foto mit der Kamera-App auf.\",\n \"connect.go\": \"Verbinden\",\n \"connect.connected\": \"Verbunden über {name}\",\n \"connect.disconnect\": \"Trennen\",\n \"connect.none\": \"Auf diesem Server ist noch kein Anbieter zum Verbinden eingerichtet.\",\n \"connect.openLink\": \"Anmeldung in neuem Tab öffnen\",\n \"list.empty\": \"Noch keine Einträge.\",\n \"list.delete\": \"Zeile löschen\",\n \"ask.typeInto\": \"Text in die Seite tippen …\",\n \"ask.hide\": \"verdeckt\",\n \"ask.up\": \"Nach oben\",\n \"ask.down\": \"Nach unten\",\n \"ask.pictureHint\":\n \"Hier siehst du live die Seite, die der Wizard geöffnet hat. Du kannst auch direkt hineinklicken und tippen.\",\n \"ask.remember\": \"Anmeldung für nächstes Mal merken\",\n \"ask.private\":\n \"Was du eingibst, geht direkt in die Seite. Die KI bekommt es nicht zu sehen. Gemerkte Anmeldungen werden verschlüsselt gespeichert.\",\n \"ask.skip\": \"Überspringen\",\n \"ask.done\": \"Ich bin angemeldet\",\n \"ask.signIn\": \"Anmelden\",\n \"ask.wants\": \"Der Wizard möchte in {service} Folgendes ausführen:\",\n \"ask.allowRest\": \"Für den Rest dieses Laufs erlauben\",\n \"ask.allow\": \"Erlauben\",\n \"ask.deny\": \"Nicht erlauben\",\n \"store.open\": \"Was dieser Wizard sich merkt\",\n \"store.title\": \"Für dich gemerkt\",\n \"store.explain\":\n \"Dieser Wizard merkt sich Listen, Dateien und verbundene Konten für deinen nächsten Lauf. Nur du siehst sie.\",\n \"store.empty\": \"Noch nichts gespeichert.\",\n \"store.rows\": { one: \"{n} Eintrag\", other: \"{n} Einträge\" },\n \"store.signIns\": \"Gemerkte Anmeldungen im Browser\",\n \"store.files\": { one: \"{n} Datei · {size}\", other: \"{n} Dateien · {size}\" },\n \"store.delete\": \"Alles löschen\",\n \"store.confirmDelete\": \"Ja, alles löschen\",\n \"common.close\": \"Schließen\",\n \"run.uploadTouch\": \"Datei wählen\",\n \"run.maxFiles\": {\n one: \"Hier geht höchstens {n} Datei – die übrigen sind weggelassen.\",\n other: \"Hier gehen höchstens {n} Dateien – die übrigen sind weggelassen.\",\n },\n \"run.filesMin\": \"{n} von mindestens {min}\",\n \"run.filesOf\": \"{n} von höchstens {max}\",\n \"run.moveFile\": \"Nr. {n} verschieben\",\n \"run.moveFileHint\": \"Ziehen, um die Reihenfolge zu ändern\",\n \"run.removeFile\": \"Entfernen\",\n \"run.awake\": \"Der Bildschirm bleibt an, solange der Wizard arbeitet.\",\n \"run.openFull\": \"Groß öffnen\",\n \"run.yes\": \"Ja\",\n \"run.no\": \"Nein\",\n \"run.share\": \"Teilen\",\n \"run.shareNow\": \"Jetzt teilen\",\n \"run.shareFile\": \"Als Datei teilen oder in einer App öffnen\",\n \"run.print\": \"Drucken\",\n \"camera.asking\": \"Dein Browser fragt gleich nach der Kamera. Das Bild bleibt in diesem Wizard.\",\n \"camera.native\": \"Kamera-App öffnen\",\n \"camera.pick\": \"Foto auswählen\",\n \"camera.torch\": \"Licht\",\n \"camera.flip\": \"Kamera wechseln\",\n \"camera.photo\": \"Foto\",\n \"camera.video\": \"Video\",\n \"camera.record\": \"Aufnahme starten\",\n \"camera.stop\": \"Aufnahme beenden\",\n \"camera.recording\": \"Nimmt auf – tippe zum Beenden.\",\n \"camera.clipHint\": \"Ein kurzer Clip, höchstens {s} Sekunden.\",\n \"camera.hintMany\": \"Seite für Seite aufnehmen, dann „Fertig“.\",\n \"scan.button\": \"Scannen\",\n \"scan.title\": \"Code scannen\",\n \"scan.asking\": \"Dein Browser fragt gleich nach der Kamera – sie liest nur den Code.\",\n \"scan.hint\": \"Halte den QR- oder Barcode in den Rahmen.\",\n \"scan.hintQr\": \"Halte den QR-Code in den Rahmen. Barcodes kann dieses Gerät hier nicht lesen.\",\n \"scan.miss\": \"Auf dem Foto war kein Code zu erkennen. Versuch es näher und schärfer.\",\n \"scan.fromPhoto\": \"Foto mit dem Code wählen\",\n \"scan.typeInstead\": \"Lieber eintippen\",\n \"location.use\": \"Meinen Standort verwenden\",\n \"location.locating\": \"Standort wird bestimmt …\",\n \"location.refining\": \"wird noch genauer …\",\n \"location.accuracy\": \"auf etwa {m} m genau\",\n \"location.map\": \"Karte\",\n \"location.remove\": \"Standort entfernen\",\n \"location.why\":\n \"Dein Browser fragt nach deinem Standort. Er wird nur für diesen Wizard verwendet. Du kannst auch einfach die Adresse eintippen.\",\n \"location.denied\":\n \"Der Standort ist für diese Seite nicht freigegeben. Erlaube ihn in den Website-Einstellungen deines Browsers (Schloss-Symbol in der Adresszeile) – oder tippe die Adresse unten ein.\",\n \"location.manual\": \"Adresse oder Ort eintippen\",\n \"location.label\": \"Adresse oder Beschreibung des Orts\",\n \"voice.start\": \"Sprachnotiz aufnehmen\",\n \"voice.stop\": \"Stopp\",\n \"voice.recording\": \"Aufnahme läuft …\",\n \"voice.left\": \"noch {s} s\",\n \"voice.again\": \"Neu aufnehmen\",\n \"voice.remove\": \"Löschen\",\n \"voice.pick\": \"Audiodatei wählen\",\n \"voice.why\":\n \"Dein Browser fragt nach dem Mikrofon. Die Aufnahme wird danach in Text umgewandelt.\",\n \"voice.denied\":\n \"Das Mikrofon ist für diese Seite nicht freigegeben. Erlaube es in den Website-Einstellungen deines Browsers – oder nimm die Notiz mit der Diktier-App auf und wähle die Datei.\",\n \"voice.noRecorder\":\n \"Dieser Browser kann hier nicht aufnehmen. Nimm die Notiz mit der Diktier-App auf und wähle die Datei.\",\n \"sign.open\": \"Hier unterschreiben\",\n \"sign.hint\": \"Mit dem Finger unterschreiben\",\n \"sign.pad\": \"Unterschriftsfeld\",\n \"sign.clear\": \"Löschen\",\n \"sign.accept\": \"Übernehmen\",\n \"sign.again\": \"Neu unterschreiben\",\n \"sign.remove\": \"Unterschrift entfernen\",\n \"notify.ask\": \"Bescheid geben, wenn es fertig ist\",\n \"notify.on\": \"Du bekommst Bescheid\",\n \"notify.why\":\n \"Mit Ton, Vibration oder einer Mitteilung. Dein Browser fragt dafür einmal um Erlaubnis.\",\n \"notify.onHint\": \"Du kannst die App wechseln – eine Mitteilung holt dich zurück.\",\n \"notify.quiet\": \"Mit Ton und Vibration, solange diese Seite offen ist.\",\n \"notify.blocked\":\n \"Mitteilungen sind für diese Seite blockiert – es gibt Ton und Vibration, solange sie offen ist. Erlauben kannst du sie in den Website-Einstellungen deines Browsers.\",\n \"notify.done\": \"Dein Ergebnis ist fertig.\",\n \"notify.next\": \"Es geht weiter – wirf einen Blick darauf.\",\n \"notify.needsYou\": \"Der Wizard braucht dich kurz.\",\n \"common.offline\": \"Keine Verbindung. Prüf dein Netz und versuch es noch einmal.\",\n \"common.retry\": \"Erneut versuchen\",\n \"common.cancel\": \"Abbrechen\",\n \"run.start\": \"Los geht’s\",\n \"run.unavailable\": \"Dieser Wizard ist gerade nicht verfügbar.\",\n \"run.resume\": \"Letzten Lauf fortsetzen\",\n \"output.preview\": \"Vorschau\",\n \"package.newer\":\n \"Diese Wizard-Datei stammt aus einer neueren Version oder ist beschädigt. Aktualisiere engenty wizards oder exportiere den Wizard neu.\",\n \"package.badJson\": \"Das ist keine Wizard-Datei: Die wizard.json darin lässt sich nicht lesen.\",\n \"package.unreadable\":\n \"Die Wizard-Datei lässt sich nicht öffnen. Exportiere den Wizard neu und versuche es noch einmal.\",\n \"package.noManifest\": \"Das ist keine Wizard-Datei: Die wizard.json fehlt.\",\n \"browser.driving\": \"Du steuerst den Browser – klick und tipp in die Seite. Der Wizard wartet.\",\n \"browser.handBack\": \"Zurückgeben\",\n \"browser.takeOver\": \"Übernehmen\",\n \"chat.above\": \"Antworte oben im Chat\",\n \"chat.badEmail\": \"Das sieht nicht nach einer E-Mail-Adresse aus.\",\n \"chat.badNumber\": \"Das sieht nicht nach einer Zahl aus.\",\n \"chat.badUrl\": \"Das sieht nicht nach einer Webadresse aus.\",\n \"chat.change\": \"Ändern\",\n \"chat.checked\": \"Geprüft\",\n \"chat.connected\": \"Verbunden\",\n \"chat.dictate\": \"Diktieren (⌘⇧M)\",\n \"chat.dictateStop\": \"Diktat beenden\",\n \"chat.file\": \"1 Datei\",\n \"chat.files\": { one: \"{n} Datei\", other: \"{n} Dateien\" },\n \"chat.listening\": \"Ich höre zu …\",\n \"chat.micDenied\":\n \"Das Mikrofon ist für diese Seite nicht freigegeben. Erlaube es in den Website-Einstellungen deines Browsers.\",\n \"chat.placeholder\": \"Deine Antwort …\",\n \"chat.readAloud\": \"Vorlesen\",\n \"chat.readAloudOff\": \"Vorlesen beenden\",\n \"chat.required\": \"Dafür brauche ich eine Antwort.\",\n \"chat.rows\": { one: \"{n} Zeile\", other: \"{n} Zeilen\" },\n \"chat.send\": \"Senden\",\n \"chat.skip\": \"Überspringen\",\n \"chat.skipped\": \"Übersprungen\",\n \"chat.transcribing\": \"Wird in Text umgewandelt …\",\n \"chat.voice\": \"Sprachnotiz\",\n \"install.add\": \"Zum Startbildschirm hinzufügen\",\n \"install.app\": \"In der App öffnen\",\n \"install.bookmark\": \"Als Lesezeichen speichern\",\n \"install.bookmark.mac\": \"Drücke ⌘ D, dann liegt dieser Wizard in deinen Lesezeichen.\",\n \"install.bookmark.pc\": \"Drücke Strg + D, dann liegt dieser Wizard in deinen Lesezeichen.\",\n \"install.ios\": \"Tippe unten auf „Teilen“ und dann auf „Zum Home-Bildschirm“.\",\n \"run.madeWith\": \"Erstellt mit engenty wizards\",\n \"run.orAs\": \"Oder: {label}\",\n \"talk.camera\": \"Kamera einschalten\",\n \"talk.cameraDenied\":\n \"Die Kamera ist für diese Seite nicht freigegeben. Erlaube sie in den Website-Einstellungen deines Browsers.\",\n \"talk.cameraOff\": \"Kamera ausschalten\",\n \"talk.connecting\": \"Verbindet …\",\n \"talk.failed\": \"Das Gespräch ließ sich nicht starten.\",\n \"talk.hint\": \"Sprich mit dem Wizard. Auf dem Bildschirm kannst du mitlesen.\",\n \"talk.joinHint\":\n \"Beim Start fragt dein Browser nach dem Mikrofon, nach der Kamera erst, wenn du sie einschaltest. Im Chat daneben kannst du mitlesen und eingeben, was sich schlecht sagen lässt.\",\n \"talk.listening\": \"Hört zu\",\n \"talk.live\": \"Im Gespräch\",\n \"talk.speaking\": \"Spricht\",\n \"talk.start\": \"Gespräch beginnen\",\n \"talk.stop\": \"Gespräch beenden\",\n \"video.cameraOff\": \"Kamera aus\",\n \"video.ended\": \"Anruf beendet\",\n \"video.flip\": \"Kamera wechseln\",\n \"video.hint\":\n \"Beim Beitreten fragt dein Browser nach Mikrofon und Kamera. Im Chat daneben kannst du mitlesen und eingeben, was sich schlecht sagen lässt.\",\n \"video.join\": \"Beitreten\",\n \"video.leave\": \"Verlassen\",\n \"video.mute\": \"Stummschalten\",\n \"video.rejoin\": \"Wieder beitreten\",\n \"video.unmute\": \"Stummschaltung aufheben\",\n \"video.you\": \"Du\",\n \"nav.language\": \"Sprache\",\n};\n\nexport type RunnerKey = keyof typeof en;\n\nconst en = {\n \"result.translate\": \"Translate\",\n \"translation.working\": \"Translating…\",\n \"translation.machine\": \"Machine-translated\",\n \"translation.showOriginal\": \"Show original\",\n \"translation.showTranslated\": \"Show translation\",\n \"translation.failed\": \"This wizard can’t be translated right now.\",\n \"share.copied\": \"Copied\",\n \"surface.done\": \"{done} of {total}\",\n \"surface.allDone\": \"All done\",\n \"surface.close\": \"Close\",\n \"data.view\": \"View\",\n \"data.edit\": \"Edit\",\n \"data.json\": \"JSON\",\n \"data.modes\": \"Show the data as\",\n \"data.add\": \"Add {what}\",\n \"data.remove\": \"Remove\",\n \"data.missing\": \"{id} is missing\",\n \"data.yes\": \"Yes\",\n \"data.no\": \"No\",\n \"data.menu\": \"More\",\n \"data.open\": \"View and edit the data\",\n \"data.close\": \"Close the data\",\n \"data.save\": \"Save\",\n \"data.saved\": \"Saved\",\n \"data.schema\": \"JSON Schema\",\n \"data.copy\": \"Copy\",\n \"data.download\": \"Download\",\n \"run.closed\": \"Not available here right now. It needs {list}.\",\n \"slot.later\": \"Show later times\",\n \"slot.none\": \"No times are free right now.\",\n \"cards.open\": \"Details\",\n \"cards.picked\": \"Chosen ✓\",\n \"cards.pick\": \"Choose\",\n \"run.cls.text\": \"text\",\n \"run.cls.image\": \"images\",\n \"run.cls.video\": \"video\",\n \"run.cls.speech\": \"speech output\",\n \"run.cls.audio\": \"voice notes\",\n \"run.cls.account\": \"an engenty account\",\n \"run.next\": \"Continue\",\n \"run.back\": \"Back\",\n \"run.accept\": \"Looks good\",\n \"run.edit\": \"Edit\",\n \"run.pickItem\": \"No. {n}\",\n \"run.pickedItem\": \"No. {n} again\",\n \"run.regeneratePicked\": \"Only no. {n} will be redone.\",\n \"run.regenerateAll\": \"Applies to all. Tap a number to redo just that one.\",\n \"check.progress\": \"{done} of {total} checked\",\n \"check.onlyOpen\": \"Open only\",\n \"check.noFile\": \"There’s no file for this row.\",\n \"check.noPreview\": \"This file has no preview – open it with the link above.\",\n \"check.reopen\": \"Open again\",\n \"run.feedbackPlaceholder\": \"Something not right? Write what should be different…\",\n \"run.feedbackTarget\": \"What should change?\",\n \"run.feedbackPick\": \"Choose above what should change.\",\n \"ai.generated\": \"AI-generated\",\n \"ai.modified\": \"AI-modified\",\n \"ai.publish\":\n \"Made with AI: whoever publishes this has to label it as AI-generated (EU AI Act, Art. 50). The file already carries the marking in its metadata.\",\n \"run.regenerateGo\": \"Recreate\",\n \"run.retry\": \"Try again\",\n \"run.again\": \"Start over\",\n \"run.copy\": \"Copy text\",\n \"run.failed\": \"Something went wrong.\",\n \"run.notFound\": \"This wizard doesn’t exist or was deleted.\",\n \"run.working\": \"One moment…\",\n \"run.elapsed\": \"{s} s\",\n \"run.cancelled\": \"Cancelled.\",\n \"run.addRow\": \"Add row\",\n \"run.upload\": \"Choose a file or drop it here\",\n \"run.uploading\": \"Uploading…\",\n \"run.net\": \"Net\",\n \"run.vat\": \"VAT {r}%\",\n \"run.total\": \"Total\",\n \"run.uploadMore\": \"Another file\",\n \"run.camera\": \"Camera\",\n \"camera.title\": \"Take a picture\",\n \"camera.hint\": \"Hold it flat and well lit.\",\n \"camera.taken\": \"{n} taken\",\n \"camera.shoot\": \"Capture\",\n \"camera.done\": \"Done\",\n \"camera.denied\":\n \"The camera isn’t allowed for this page. Allow it in your browser’s site settings (the lock icon in the address bar) – or take the photo with your camera app.\",\n \"connect.go\": \"Connect\",\n \"connect.connected\": \"Connected through {name}\",\n \"connect.disconnect\": \"Disconnect\",\n \"connect.none\": \"This server has no provider for connecting accounts yet.\",\n \"connect.openLink\": \"Click here to open the sign-in in a new tab\",\n \"list.empty\": \"No entries yet.\",\n \"list.delete\": \"Delete row\",\n \"ask.typeInto\": \"Type into the page…\",\n \"ask.hide\": \"hidden\",\n \"ask.up\": \"Scroll up\",\n \"ask.down\": \"Scroll down\",\n \"ask.pictureHint\":\n \"This is the page the wizard has open, live. You can also click and type right in it.\",\n \"ask.remember\": \"Remember this sign-in for next time\",\n \"ask.private\":\n \"What you enter goes straight into the page. The AI never sees it. Remembered sign-ins are stored encrypted.\",\n \"ask.skip\": \"Skip\",\n \"ask.done\": \"I’m signed in\",\n \"ask.signIn\": \"Sign in\",\n \"ask.wants\": \"The wizard wants to run this in {service}:\",\n \"ask.allowRest\": \"Allow for the rest of this run\",\n \"ask.allow\": \"Allow\",\n \"ask.deny\": \"Don’t allow\",\n \"store.open\": \"What this wizard remembers\",\n \"store.title\": \"Kept for you\",\n \"store.explain\":\n \"This wizard keeps lists, files and connected accounts for your next run. Only you see them.\",\n \"store.empty\": \"Nothing kept yet.\",\n \"store.rows\": { one: \"{n} entry\", other: \"{n} entries\" },\n \"store.signIns\": \"Remembered sign-ins in the browser\",\n \"store.files\": { one: \"{n} file · {size}\", other: \"{n} files · {size}\" },\n \"store.delete\": \"Delete everything\",\n \"store.confirmDelete\": \"Yes, delete everything\",\n \"common.close\": \"Close\",\n \"run.uploadTouch\": \"Choose a file\",\n \"run.maxFiles\": {\n one: \"At most {n} fits here – the rest were left out.\",\n other: \"At most {n} fit here – the rest were left out.\",\n },\n \"run.filesMin\": \"{n} of at least {min}\",\n \"run.filesOf\": \"{n} of at most {max}\",\n \"run.moveFile\": \"Move no. {n}\",\n \"run.moveFileHint\": \"Drag to change the order\",\n \"run.removeFile\": \"Remove\",\n \"run.awake\": \"The screen stays on while the wizard works.\",\n \"run.openFull\": \"Open full size\",\n \"run.yes\": \"Yes\",\n \"run.no\": \"No\",\n \"run.share\": \"Share\",\n \"run.shareNow\": \"Share now\",\n \"run.shareFile\": \"Share as a file or open in an app\",\n \"run.print\": \"Print\",\n \"camera.asking\": \"Your browser is about to ask for the camera. The picture stays in this wizard.\",\n \"camera.native\": \"Open the camera app\",\n \"camera.pick\": \"Choose a photo\",\n \"camera.torch\": \"Light\",\n \"camera.flip\": \"Switch camera\",\n \"camera.photo\": \"Photo\",\n \"camera.video\": \"Video\",\n \"camera.record\": \"Start recording\",\n \"camera.stop\": \"Stop recording\",\n \"camera.recording\": \"Recording – tap to stop.\",\n \"camera.clipHint\": \"A short clip, {s} seconds at most.\",\n \"camera.hintMany\": \"Capture page after page, then “Done”.\",\n \"scan.button\": \"Scan\",\n \"scan.title\": \"Scan a code\",\n \"scan.asking\": \"Your browser is about to ask for the camera – it only reads the code.\",\n \"scan.hint\": \"Hold the QR code or barcode inside the frame.\",\n \"scan.hintQr\": \"Hold the QR code inside the frame. This device doesn’t read barcodes here.\",\n \"scan.miss\": \"No code was found in the photo. Try closer and sharper.\",\n \"scan.fromPhoto\": \"Choose a photo of the code\",\n \"scan.typeInstead\": \"Type it instead\",\n \"location.use\": \"Use my location\",\n \"location.locating\": \"Finding your location…\",\n \"location.refining\": \"getting more accurate…\",\n \"location.accuracy\": \"accurate to about {m} m\",\n \"location.map\": \"Map\",\n \"location.remove\": \"Remove location\",\n \"location.why\":\n \"Your browser asks for your location. It’s only used for this wizard. You can also just type the address.\",\n \"location.denied\":\n \"Location isn’t allowed for this page. Allow it in your browser’s site settings (the lock icon in the address bar) – or type the address below.\",\n \"location.manual\": \"Type an address or place\",\n \"location.label\": \"Address or description of the place\",\n \"voice.start\": \"Record a voice note\",\n \"voice.stop\": \"Stop\",\n \"voice.recording\": \"Recording…\",\n \"voice.left\": \"{s} s left\",\n \"voice.again\": \"Record again\",\n \"voice.remove\": \"Delete\",\n \"voice.pick\": \"Choose an audio file\",\n \"voice.why\":\n \"Your browser asks for the microphone. The recording is turned into text afterwards.\",\n \"voice.denied\":\n \"The microphone isn’t allowed for this page. Allow it in your browser’s site settings – or record the note with your voice memo app and choose the file.\",\n \"voice.noRecorder\":\n \"This browser can’t record here. Record the note with your voice memo app and choose the file.\",\n \"sign.open\": \"Sign here\",\n \"sign.hint\": \"Sign with your finger\",\n \"sign.pad\": \"Signature pad\",\n \"sign.clear\": \"Clear\",\n \"sign.accept\": \"Use it\",\n \"sign.again\": \"Sign again\",\n \"sign.remove\": \"Remove signature\",\n \"notify.ask\": \"Tell me when it’s done\",\n \"notify.on\": \"We’ll let you know\",\n \"notify.why\": \"With a sound, a buzz or a notification. Your browser asks once for permission.\",\n \"notify.onHint\": \"You can switch apps – a notification brings you back.\",\n \"notify.quiet\": \"With a sound and a buzz while this page is open.\",\n \"notify.blocked\":\n \"Notifications are blocked for this page – you get a sound and a buzz while it’s open. You can allow them in your browser’s site settings.\",\n \"notify.done\": \"Your result is ready.\",\n \"notify.next\": \"The next step is ready – have a look.\",\n \"notify.needsYou\": \"The wizard needs you for a moment.\",\n \"common.offline\": \"No connection. Check your network and try again.\",\n \"common.retry\": \"Try again\",\n \"common.cancel\": \"Cancel\",\n \"run.start\": \"Let’s go\",\n \"run.unavailable\": \"This wizard isn’t available right now.\",\n \"run.resume\": \"Continue your last run\",\n \"output.preview\": \"Preview\",\n \"package.newer\":\n \"This wizard file comes from a newer version, or it’s damaged. Update engenty wizards or export the wizard again.\",\n \"package.badJson\": \"This isn’t a wizard file: its wizard.json can’t be read.\",\n \"package.unreadable\":\n \"The wizard file can’t be opened. Export the wizard again and try once more.\",\n \"package.noManifest\": \"This isn’t a wizard file: wizard.json is missing.\",\n \"browser.driving\":\n \"You’re in control of the browser – click and type in the page. The wizard waits.\",\n \"browser.handBack\": \"Hand back\",\n \"browser.takeOver\": \"Take over\",\n \"chat.above\": \"Answer above in the chat\",\n \"chat.badEmail\": \"That doesn’t look like an email address.\",\n \"chat.badNumber\": \"Enter a number.\",\n \"chat.badUrl\": \"That isn’t a valid address.\",\n \"chat.change\": \"Change\",\n \"chat.checked\": \"Checked\",\n \"chat.connected\": \"Connected\",\n \"chat.dictate\": \"Dictate (⌘⇧M)\",\n \"chat.dictateStop\": \"Stop dictating\",\n \"chat.file\": \"1 file\",\n \"chat.files\": { one: \"{n} file\", other: \"{n} files\" },\n \"chat.listening\": \"Listening…\",\n \"chat.micDenied\":\n \"The microphone isn’t allowed for this page. Allow it in your browser’s site settings.\",\n \"chat.placeholder\": \"Your answer…\",\n \"chat.readAloud\": \"Read aloud\",\n \"chat.readAloudOff\": \"Stop reading aloud\",\n \"chat.required\": \"I need an answer for this one.\",\n \"chat.rows\": { one: \"{n} row\", other: \"{n} rows\" },\n \"chat.send\": \"Send\",\n \"chat.skip\": \"Skip\",\n \"chat.skipped\": \"Skipped\",\n \"chat.transcribing\": \"Writing it down…\",\n \"chat.voice\": \"Voice note\",\n \"install.add\": \"Add to home screen\",\n \"install.app\": \"Open in the app\",\n \"install.bookmark\": \"Bookmark this wizard\",\n \"install.bookmark.mac\": \"Press ⌘ D to keep this wizard in your bookmarks.\",\n \"install.bookmark.pc\": \"Press Ctrl + D to keep this wizard in your bookmarks.\",\n \"install.ios\": \"Tap “Share” below, then “Add to Home Screen”.\",\n \"run.madeWith\": \"Made with engenty wizards\",\n \"run.orAs\": \"Or: {label}\",\n \"talk.camera\": \"Switch the camera on\",\n \"talk.cameraDenied\":\n \"The camera isn’t allowed for this page. Allow it in your browser’s site settings.\",\n \"talk.cameraOff\": \"Switch the camera off\",\n \"talk.connecting\": \"Connecting…\",\n \"talk.failed\": \"The conversation couldn’t start. Check your connection and try again.\",\n \"talk.hint\": \"Talk to the wizard – the screen follows along.\",\n \"talk.joinHint\":\n \"Your browser asks for the microphone when you start, and for the camera only when you switch it on. The chat beside it follows along and handles what voice can’t.\",\n \"talk.listening\": \"Listening\",\n \"talk.live\": \"In conversation\",\n \"talk.speaking\": \"Speaking\",\n \"talk.start\": \"Start talking\",\n \"talk.stop\": \"End the conversation\",\n \"video.cameraOff\": \"Camera off\",\n \"video.ended\": \"Call ended\",\n \"video.flip\": \"Switch camera\",\n \"video.hint\":\n \"Your browser asks for the microphone and camera when you join. The chat beside it follows along and handles what voice can’t.\",\n \"video.join\": \"Join\",\n \"video.leave\": \"Leave\",\n \"video.mute\": \"Mute\",\n \"video.rejoin\": \"Rejoin\",\n \"video.unmute\": \"Unmute\",\n \"video.you\": \"You\",\n \"nav.language\": \"Language\",\n};\n\n/**\n * The runner's words in each language. English has every one; another language may lack some,\n * and those are said in English.\n */\nexport const RUNNER_TEXTS = { en, de } satisfies Texts<RunnerKey>;\n","import type { Lang } from \"@engenty/wizards-shared/definition\";\nimport { noteText, type RunNote } from \"@engenty/wizards-shared/run\";\nimport { RUNNER_TEXTS, type RunnerKey } from \"@engenty/wizards-shared/runner-texts\";\nimport { lineText, type TextTable, textOf } from \"@engenty/wizards-shared/texts\";\nimport { useSyncExternalStore } from \"react\";\n\nexport type { Lang };\n/**\n * What the runner says to the person running a wizard: its table lives in shared/runner-texts,\n * where the runtime reads it too (a language outside `LANGS` is translated from its English).\n */\nexport { RUNNER_TEXTS, type RunnerKey };\n\n/** The language the runner speaks: set by the host (`configureRunner`, `setRunnerLang`). */\nexport let lang: Lang = \"en\";\n\n/**\n * A language outside `LANGS`, translated on request (`GET /api/public/texts/:lang`): its lines\n * win over `lang`'s, and what it lacks is said in English. Null: the runner speaks `lang`.\n */\nexport interface RunnerTable {\n lang: string;\n runner: TextTable;\n notes: TextTable;\n}\nlet table: RunnerTable | null = null;\nlet version = 0;\nconst listeners = new Set<() => void>();\n\nfunction changed() {\n version += 1;\n for (const listener of listeners) {\n listener();\n }\n}\n\nexport function setRunnerLang(next: Lang) {\n if (next === lang) {\n return;\n }\n lang = next;\n changed();\n}\n\n/** Speaks a translated language from its table, or `lang` again with null. */\nexport function setRunnerTable(next: RunnerTable | null) {\n if (next === table) {\n return;\n }\n table = next;\n changed();\n}\n\n/** The translated table in effect, for a host that shows the runner's words itself. */\nexport function runnerTable(): RunnerTable | null {\n return table;\n}\n\n/** The language the person reads, by its code: the translated one, else `lang`. */\nexport function runnerLangCode(): string {\n return table?.lang ?? lang;\n}\n\n/** The language, for a component that must render again when it changes. */\nexport function useRunnerLang(): string {\n useSyncExternalStore(\n (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n () => version,\n );\n return runnerLangCode();\n}\n\n/** What a run reports, in the language the person reads: its note where it has one. */\nexport function eventText(ev: { message: string; note?: RunNote | null }): string {\n return (ev.note && noteText(ev.note, runnerLangCode(), table?.notes)) || ev.message;\n}\n\n/**\n * What the choices of a translated wizard show, by value (`RunView.translation.labels`): the\n * answer keeps the value, the person reads the label.\n */\nlet labels: Record<string, string> = {};\n\nexport function setChoiceLabels(next: Record<string, string> | null | undefined) {\n labels = next ?? {};\n}\n\n/** What a choice shows: its translated label, else its value. */\nexport function choiceLabel(value: string): string {\n return labels[value] ?? value;\n}\n\n/** A string in the runner's language: its plural form by `{count}` or `{n}`, its gaps filled. */\nexport function t(key: RunnerKey, vars?: Record<string, string | number>): string {\n const own = table?.runner[key];\n if (table && own !== undefined) {\n return lineText(own, table.lang, vars);\n }\n return textOf(RUNNER_TEXTS, key, table ? \"en\" : lang, vars);\n}\n","import { lang, t } from \"./i18n.js\";\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly body: any,\n ) {\n super(message);\n }\n}\n\n/** The request never reached the server: no network, a tunnel, a phone switching cells. */\nexport function isOffline(err: unknown): boolean {\n return err instanceof ApiError && err.status === 0;\n}\n\n/** A body as JSON; one that is not (a proxy's error page) as `{ error: <the text> }`. */\nexport function safeJson(text: string) {\n try {\n return JSON.parse(text);\n } catch {\n return { error: text };\n }\n}\n\nexport interface Api {\n get<T>(path: string): Promise<T>;\n post<T>(path: string, body?: unknown): Promise<T>;\n put<T>(path: string, body?: unknown): Promise<T>;\n patch<T>(path: string, body?: unknown): Promise<T>;\n del<T>(path: string): Promise<T>;\n upload<T>(path: string, file: File): Promise<T>;\n}\n\n/**\n * JSON calls with the host's credentials; a refused call throws an `ApiError` with the server's\n * `error` and its body (`fields`, `issues`, a `code`).\n */\nexport function createApi(\n withBase: (path: string) => string,\n headers: Record<string, string> = {},\n /** Told of every answer of 500 and above, e.g. to send it to the host's log. */\n onServerError?: (line: string) => void,\n): Api {\n async function request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(withBase(path), {\n method,\n credentials: \"include\",\n headers: {\n // The server answers in the language the person picked, not the browser's.\n \"accept-language\": lang,\n ...headers,\n ...(body !== undefined && !(body instanceof FormData)\n ? { \"content-type\": \"application/json\" }\n : {}),\n },\n body: body === undefined ? undefined : body instanceof FormData ? body : JSON.stringify(body),\n }).catch(() => {\n throw new ApiError(t(\"common.offline\"), 0, null);\n });\n const text = await res.text();\n const data = text ? safeJson(text) : null;\n if (!res.ok) {\n if (res.status >= 500) {\n onServerError?.(`${method} ${path} answered ${res.status}: ${data?.error ?? \"\"}`);\n }\n // WordPress answers `{ code, message }`; a runtime `{ error, code }`.\n throw new ApiError(data?.error ?? data?.message ?? res.statusText, res.status, data);\n }\n return data as T;\n }\n return {\n get: <T>(path: string) => request<T>(\"GET\", path),\n post: <T>(path: string, body?: unknown) => request<T>(\"POST\", path, body ?? {}),\n put: <T>(path: string, body?: unknown) => request<T>(\"PUT\", path, body),\n patch: <T>(path: string, body?: unknown) => request<T>(\"PATCH\", path, body),\n del: <T>(path: string) => request<T>(\"DELETE\", path),\n upload: <T>(path: string, file: File) => {\n const form = new FormData();\n form.set(\"file\", file);\n return request<T>(\"POST\", path, form);\n },\n };\n}\n","import type { EngentyCostume } from \"@engenty/wizards-shared/definition\";\nimport type { RunView } from \"@engenty/wizards-shared/run\";\nimport type { ComponentType } from \"react\";\nimport { type Api, createApi } from \"./api.js\";\nimport { type Lang, setRunnerLang } from \"./i18n.js\";\n\n/**\n * What the runner needs of the page around it, given once by the host before anything renders:\n * the studio (apps/web) with its base path, its mobile-app bridge and its engenty; the WordPress\n * plugin with its REST routes and its own engenty. The runner itself knows no server.\n */\n\n/** What a mobile app around the page may offer (apps/web/src/lib/app.ts names them). */\nexport type AppAbility =\n | \"scan\"\n | \"share\"\n | \"download\"\n | \"keepAwake\"\n | \"notify\"\n | \"notifyPermission\"\n | \"signIn\"\n | \"run\"\n | \"transcribe\"\n | \"think\";\n\nexport interface AppBridge {\n can(ability: AppAbility): boolean;\n call<T = unknown>(ability: AppAbility, args?: unknown): Promise<T>;\n tell(ability: AppAbility, args?: unknown): void;\n /** A download link's click: the app fetches the file itself. Returns whether it took it. */\n download(event: { preventDefault(): void }, href: string, filename?: string): boolean;\n}\n\nexport interface MascotProps {\n kind: string;\n costume?: EngentyCostume;\n size?: number;\n fluffy?: boolean;\n}\n\nexport interface ShareResultProps {\n /** The finished run: what it made, its link, a share job at work. */\n view: RunView;\n title: string;\n}\n\nexport interface RunnerEnv {\n lang: Lang;\n /** The run's API: `/api/runs/<id>` on a runtime, `/wp-json/engenty/v1/local/runs/<id>` in WordPress. */\n runBase(runId: string): string;\n /** A root-relative address as the browser must request it (a base path, a remote runtime). */\n withBase(path: string): string;\n /** A file of the host's public folder (`ai-labels/…`, `icons/…`). */\n asset(path: string): string;\n /** Where the service worker for notifications lives; none where the host has none. */\n serviceWorker?: string;\n /** The mobile app's bridge; a page in a browser has none. */\n app?: AppBridge;\n /** The wizard's engenty. */\n Mascot: ComponentType<MascotProps>;\n /** The result's share button; a host without shared results has none. */\n ShareResultButton?: ComponentType<ShareResultProps>;\n /** Told of every answer of 500 and above, e.g. to send it to the host's log. */\n onServerError?: (line: string) => void;\n /** Extra headers on every request (a WordPress nonce). */\n headers?: Record<string, string>;\n /**\n * A host that runs wizards on its own (the WordPress plugin): its server writes no PDF, so the\n * runner writes one from a written output in the browser (pdf.ts); an HTML download of a\n * written output is a page to print.\n */\n standalone?: boolean;\n}\n\nconst none: AppBridge = {\n can: () => false,\n call: (ability) => Promise.reject(new Error(`the app cannot ${ability}`)),\n tell: () => undefined,\n download: () => false,\n};\n\nlet env: RunnerEnv | null = null;\n\n/** The host names its environment once, before the first render. */\nexport function configureRunner(next: RunnerEnv) {\n env = next;\n api = createApi(next.withBase, next.headers, next.onServerError);\n setRunnerLang(next.lang);\n}\n\nexport function runnerEnv(): RunnerEnv {\n if (!env) {\n throw new Error(\"configureRunner() first\");\n }\n return env;\n}\n\nexport let api: Api = createApi((path) => path);\n\nexport const withBase = (path: string) => runnerEnv().withBase(path);\nexport const asset = (path: string) => runnerEnv().asset(path);\nexport const runBase = (runId: string) => runnerEnv().runBase(runId);\n\nexport const appCan = (ability: AppAbility) => (env?.app ?? none).can(ability);\nexport const appCall = <T = unknown>(ability: AppAbility, args?: unknown) =>\n (env?.app ?? none).call<T>(ability, args);\nexport const appTell = (ability: AppAbility, args?: unknown) =>\n (env?.app ?? none).tell(ability, args);\nexport const appDownload = (event: { preventDefault(): void }, href: string, filename?: string) =>\n (env?.app ?? none).download(event, href, filename);\nexport const standalone = () => env?.standalone === true;\n","import {\n type ButtonHTMLAttributes,\n forwardRef,\n type InputHTMLAttributes,\n type ReactNode,\n type TextareaHTMLAttributes,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { t } from \"./i18n.js\";\n\nexport function cn(...parts: (string | false | null | undefined)[]): string {\n return parts.filter(Boolean).join(\" \");\n}\n\ntype Variant = \"primary\" | \"secondary\" | \"ghost\" | \"quiet\" | \"danger\";\n\nconst VARIANTS: Record<Variant, string> = {\n primary:\n \"bg-primary text-primary-foreground hover:brightness-[1.06] active:brightness-95 shadow-[0_1px_0_oklch(0%_0_0/0.08)]\",\n secondary: \"bg-card text-ink border border-border hover:bg-paper-2\",\n ghost: \"text-ink-2 hover:text-ink hover:bg-accent\",\n quiet: \"bg-paper-2 text-ink hover:bg-paper-3\",\n danger: \"text-rose hover:bg-rose-tint\",\n};\n\nexport const Button = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: Variant;\n size?: \"sm\" | \"md\" | \"lg\";\n busy?: boolean;\n }\n>(function Button(\n { variant = \"primary\", size = \"md\", busy, className, children, disabled, ...rest },\n ref,\n) {\n return (\n <button\n ref={ref}\n type=\"button\"\n data-variant={variant}\n disabled={disabled || busy}\n className={cn(\n \"inline-flex select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium transition-[background,filter,color,transform] duration-150 active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50\",\n size === \"sm\" && \"h-8 px-3 text-[0.8125rem] coarse:h-11 coarse:px-4\",\n size === \"md\" && \"h-10 px-4 text-sm coarse:h-11\",\n size === \"lg\" && \"h-12 px-6 text-[0.9375rem]\",\n VARIANTS[variant],\n variant === \"primary\" && \"wizard-button\",\n className,\n )}\n {...rest}\n >\n {busy ? <Spinner className=\"size-4\" /> : null}\n {children}\n </button>\n );\n});\n\nexport function IconButton({\n label,\n className,\n children,\n ...rest\n}: ButtonHTMLAttributes<HTMLButtonElement> & { label: string }) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n className={cn(\n \"inline-flex size-9 shrink-0 items-center justify-center rounded-full text-ink-3 transition hover:bg-accent hover:text-ink disabled:opacity-40 coarse:size-11\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n}\n\nconst fieldBase =\n \"wizard-field rounded-lg border border-input bg-card px-3.5 text-[0.9375rem] text-ink shadow-[inset_0_1px_0_oklch(0%_0_0/0.02)] outline-none transition placeholder:text-ink-4 focus:border-focus focus:ring-4 focus:ring-focus-glow disabled:opacity-60\";\n\n/** A field fills its row unless the caller gives it a width. */\nfunction fieldWidth(className?: string) {\n return /(^|\\s)w-/.test(className ?? \"\") ? null : \"w-full\";\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>(\n function Input({ className, ...rest }, ref) {\n return (\n <input\n ref={ref}\n className={cn(fieldBase, fieldWidth(className), \"h-11\", className)}\n {...rest}\n />\n );\n },\n);\n\n/** The native colour picker as a swatch; its chip sits concentric in the frame. */\nexport function Swatch(props: Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"className\">) {\n return (\n <input\n type=\"color\"\n className=\"swatch size-11 shrink-0 cursor-pointer rounded-lg border border-input bg-card p-1\"\n {...props}\n />\n );\n}\n\n/** A textarea that grows with its content. */\nexport const Textarea = forwardRef<\n HTMLTextAreaElement,\n TextareaHTMLAttributes<HTMLTextAreaElement> & { minRows?: number; maxRows?: number }\n>(function Textarea({ className, minRows = 3, maxRows = 14, onChange, ...rest }, outer) {\n const inner = useRef<HTMLTextAreaElement | null>(null);\n const resize = () => {\n const el = inner.current;\n if (!el) {\n return;\n }\n const lh = Number.parseFloat(getComputedStyle(el).lineHeight) || 22;\n el.style.height = \"auto\";\n const max = lh * maxRows + 20;\n el.style.height = `${Math.min(Math.max(el.scrollHeight, lh * minRows + 20), max)}px`;\n el.style.overflowY = el.scrollHeight > max ? \"auto\" : \"hidden\";\n };\n useLayoutEffect(resize);\n return (\n <textarea\n ref={(el) => {\n inner.current = el;\n if (typeof outer === \"function\") {\n outer(el);\n } else if (outer) {\n outer.current = el;\n }\n }}\n className={cn(\n fieldBase,\n fieldWidth(className),\n \"resize-none py-2.5 leading-[1.5]\",\n className,\n )}\n onChange={(e) => {\n resize();\n onChange?.(e);\n }}\n {...rest}\n />\n );\n});\n\nexport function Select({\n value,\n onChange,\n options,\n className,\n placeholder,\n}: {\n value: string;\n onChange: (v: string) => void;\n options: { value: string; label: string; disabled?: boolean }[];\n className?: string;\n placeholder?: string;\n}) {\n return (\n <div className={cn(\"relative\", className)}>\n <select\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className={cn(fieldBase, \"h-11 w-full appearance-none pr-9\")}\n >\n {placeholder !== undefined ? <option value=\"\">{placeholder}</option> : null}\n {options.map((o) => (\n <option key={o.value} value={o.value} disabled={o.disabled}>\n {o.label}\n </option>\n ))}\n </select>\n <svg\n className=\"-translate-y-1/2 pointer-events-none absolute top-1/2 right-3 size-4 text-ink-3\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n </div>\n );\n}\n\n/** Pills for a handful of options — calmer than a dropdown. */\nexport function Segmented({\n value,\n onChange,\n options,\n multi,\n disabled,\n label,\n}: {\n value: string | string[];\n onChange: (v: any) => void;\n options: string[];\n multi?: boolean;\n /** Options shown but not to be picked. */\n disabled?: string[];\n /** What an option shows; default: the option itself. */\n label?: (option: string) => string;\n}) {\n const selected = new Set(Array.isArray(value) ? value : value ? [value] : []);\n return (\n <div className=\"flex flex-wrap gap-2\">\n {options.map((o) => {\n const on = selected.has(o);\n return (\n <button\n key={o}\n type=\"button\"\n aria-pressed={on}\n disabled={disabled?.includes(o)}\n onClick={() => {\n if (multi) {\n const next = new Set(selected);\n if (on) {\n next.delete(o);\n } else {\n next.add(o);\n }\n onChange(options.filter((x) => next.has(x)));\n } else {\n onChange(o);\n }\n }}\n className={cn(\n \"h-10 rounded-full border px-4 text-sm transition disabled:pointer-events-none disabled:opacity-60 disabled:line-through coarse:h-11\",\n on\n ? \"border-ember bg-ember-tint text-ink\"\n : \"border-input bg-card text-ink-2 hover:border-ink-4 hover:text-ink\",\n )}\n >\n {label ? label(o) : o}\n </button>\n );\n })}\n </div>\n );\n}\n\nconst SLIDE = \"cubic-bezier(0.3, 0.7, 0.2, 1)\";\n\n/**\n * A row of tabs as one button group, in the look of the theme switch: a thumb slides to the\n * pick and takes its width. The tabs' panels are the caller's.\n */\nexport function Tabs<T extends string>({\n value,\n onChange,\n options,\n label,\n}: {\n value: T;\n onChange: (next: T) => void;\n options: { id: T; label: string }[];\n /** The group's name for a screen reader. */\n label?: string;\n}) {\n const buttons = useRef(new Map<T, HTMLButtonElement>());\n const [thumb, setThumb] = useState<{ x: number; w: number } | null>(null);\n // Measured from the picked tab, again when its width changes (fonts, a resize).\n useLayoutEffect(() => {\n const el = buttons.current.get(value);\n if (!el) {\n return;\n }\n const measure = () => setThumb({ x: el.offsetLeft, w: el.offsetWidth });\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, [value]);\n return (\n <div\n role=\"tablist\"\n aria-label={label}\n className=\"relative inline-flex items-center rounded-full bg-paper-2 p-0.5 ring-1 ring-border-soft\"\n >\n {thumb ? (\n <span\n aria-hidden=\"true\"\n className=\"absolute top-0.5 bottom-0.5 left-0 rounded-full bg-card shadow-sm motion-reduce:transition-none\"\n style={{\n width: thumb.w,\n transform: `translateX(${thumb.x}px)`,\n transition: `transform 300ms ${SLIDE}, width 300ms ${SLIDE}`,\n }}\n />\n ) : null}\n {options.map((option) => {\n const on = option.id === value;\n return (\n <button\n key={option.id}\n ref={(el) => {\n if (el) {\n buttons.current.set(option.id, el);\n } else {\n buttons.current.delete(option.id);\n }\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={on}\n onClick={() => onChange(option.id)}\n className={cn(\n \"relative h-8 whitespace-nowrap rounded-full px-4 font-medium text-[0.875rem] transition-colors motion-reduce:transition-none coarse:h-9\",\n on ? \"text-ink\" : \"text-ink-3 hover:text-ink-2\",\n )}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function Switch({\n checked,\n onChange,\n label,\n disabled,\n}: {\n checked: boolean;\n onChange: (v: boolean) => void;\n label?: string;\n disabled?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n disabled={disabled}\n onClick={() => onChange(!checked)}\n className={cn(\n // The track stays slim; the tap area around it is a full 44 px.\n \"relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition before:absolute before:-inset-x-1 before:-inset-y-2.5 before:content-[''] disabled:pointer-events-none disabled:opacity-60\",\n checked ? \"bg-primary\" : \"bg-paper-3\",\n )}\n >\n <span\n className={cn(\n \"inline-block size-5 rounded-full bg-white shadow-sm transition-transform\",\n checked ? \"translate-x-[22px]\" : \"translate-x-[2px]\",\n )}\n />\n </button>\n );\n}\n\nexport function Label({\n children,\n hint,\n required,\n}: {\n children: ReactNode;\n hint?: ReactNode;\n required?: boolean;\n}) {\n return (\n <div className=\"mb-2\">\n <div className=\"font-medium text-[0.875rem] text-ink\">\n {children}\n {required ? <span className=\"ml-1 text-ember\">*</span> : null}\n </div>\n {hint ? <div className=\"mt-0.5 text-[0.8125rem] text-ink-3\">{hint}</div> : null}\n </div>\n );\n}\n\nexport function Spinner({ className }: { className?: string }) {\n return (\n <svg className={cn(\"size-5 animate-spin\", className)} viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" strokeOpacity=\"0.2\" strokeWidth=\"3\" />\n <path d=\"M21 12a9 9 0 0 0-9-9\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n\nexport function Card({\n className,\n children,\n ...rest\n}: { className?: string; children: ReactNode } & React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n \"wizard-card rounded-xl bg-card shadow-soft ring-1 ring-border-soft\",\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/** `icon`: in place of the live dot. `title`: what the chip means, on hover. */\nexport function Chip({\n children,\n tone = \"neutral\",\n icon,\n title,\n}: {\n children: ReactNode;\n tone?: \"neutral\" | \"live\" | \"warn\" | \"ember\";\n icon?: ReactNode;\n title?: string;\n}) {\n return (\n <span\n title={title}\n className={cn(\n \"inline-flex h-6 items-center gap-1.5 whitespace-nowrap rounded-full px-2.5 font-medium text-[0.75rem]\",\n tone === \"neutral\" && \"bg-paper-2 text-ink-2\",\n tone === \"live\" && \"bg-moss-tint text-moss\",\n tone === \"warn\" && \"bg-amber-tint text-ink-2\",\n tone === \"ember\" && \"bg-ember-tint text-ember-strong\",\n )}\n >\n {icon ?? (tone === \"live\" ? <span className=\"size-1.5 rounded-full bg-moss\" /> : null)}\n {children}\n </span>\n );\n}\n\n/**\n * A centred modal on the native <dialog>; on a phone it fills the screen, with no gutter. Its\n * height does not jump while it is open: a dialog\n * with tabs, folds or lists (`height=\"tall\"`) stands at a height taken from the window and\n * scrolls inside; any other keeps the tallest height it has had, so switching to a shorter tab\n * or folding a section leaves it where it is.\n */\nexport function Dialog({\n open,\n onClose,\n title,\n children,\n wide,\n bare,\n height = \"auto\",\n}: {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n children: ReactNode;\n /** `\"page\"`: room for a document. */\n wide?: boolean | \"page\";\n /**\n * The children are the panel: the dialog itself draws no card, clips nothing (a close button\n * may sit on the panel's edge) and fills the screen of a phone.\n */\n bare?: boolean;\n /** `\"tall\"`: as tall as the window allows (up to 56 rem), whatever is in it. */\n height?: \"auto\" | \"tall\";\n}) {\n const ref = useRef<HTMLDialogElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) {\n return;\n }\n if (open && !el.open) {\n el.showModal();\n // A modal dialog focuses its first control (the close button); a field marked\n // `data-autofocus` is where typing starts instead.\n el.querySelector<HTMLElement>(\"[data-autofocus]\")?.focus();\n } else if (!open && el.open) {\n el.close();\n }\n }, [open]);\n // Open, the dialog never gets shorter than it has been — within what the window allows.\n useEffect(() => {\n const el = ref.current;\n if (!el || !open || bare || height === \"tall\") {\n return;\n }\n let tallest = 0;\n const keep = () => {\n tallest = Math.max(tallest, el.getBoundingClientRect().height);\n el.style.minHeight = `${Math.min(tallest, window.innerHeight - 32)}px`;\n };\n const observer = new ResizeObserver(keep);\n observer.observe(el);\n window.addEventListener(\"resize\", keep);\n return () => {\n observer.disconnect();\n window.removeEventListener(\"resize\", keep);\n el.style.minHeight = \"\";\n };\n }, [open, bare, height]);\n return (\n <dialog\n ref={ref}\n onClose={onClose}\n onClick={(e) => {\n if (e.target === ref.current) {\n onClose();\n }\n }}\n className={cn(\n \"m-auto p-0 text-ink backdrop:bg-[oklch(20%_0.01_60/0.28)] backdrop:backdrop-blur-[2px]\",\n // A phone: the whole screen, no gutter, clear of the notch and the home indicator.\n \"max-sm:m-0 max-sm:h-dvh max-sm:max-h-none max-sm:w-full max-sm:max-w-none\",\n bare\n ? \"w-[calc(100%-48px)] overflow-visible bg-transparent\"\n : \"max-h-[calc(100dvh-32px)] w-[calc(100%-32px)] overflow-y-auto overscroll-contain rounded-2xl bg-card shadow-overlay max-sm:rounded-none max-sm:pt-[env(safe-area-inset-top)] max-sm:pb-[env(safe-area-inset-bottom)]\",\n wide === \"page\" ? \"sm:max-w-4xl\" : wide ? \"sm:max-w-2xl\" : \"sm:max-w-md\",\n !bare && height === \"tall\" && \"sm:h-[min(calc(100dvh-32px),56rem)]\",\n )}\n >\n {open && bare ? (\n children\n ) : open ? (\n <div className=\"p-5 sm:p-7\">\n {title ? (\n <div className=\"mb-5 flex items-start justify-between gap-3\">\n <h2 className=\"min-w-0 font-display font-semibold text-xl\">{title}</h2>\n <IconButton label={t(\"common.close\")} onClick={onClose} className=\"-mt-1.5 -mr-2\">\n <svg viewBox=\"0 0 16 16\" fill=\"none\" className=\"size-4\" aria-hidden=\"true\">\n <path\n d=\"M4 4l8 8M12 4l-8 8\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </IconButton>\n </div>\n ) : null}\n {children}\n </div>\n ) : null}\n </dialog>\n );\n}\n\nexport function Empty({ children }: { children: ReactNode }) {\n return <div className=\"py-16 text-center text-ink-3\">{children}</div>;\n}\n\n/** A sentence of the server with its web addresses as links, named by their host. */\nexport function LinkedText({ text }: { text: string }) {\n return text.split(/(https?:\\/\\/[^\\s)]+)/).map((part, i) =>\n i % 2 ? (\n <a\n key={part}\n href={part}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"font-medium text-ink underline underline-offset-2\"\n >\n {new URL(part).host}\n </a>\n ) : (\n part\n ),\n );\n}\n","import type { BrowserAct } from \"@engenty/wizards-shared/run\";\nimport { ArrowDown, ArrowUp, CornerDownLeft, MousePointerClick } from \"lucide-react\";\nimport { type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { api, runBase, withBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { cn, Input } from \"./ui.js\";\n\n/** Scrolling in the page is sent at most this often; the wheel's movement in between adds up. */\nconst WHEEL_EVERY_MS = 250;\n\n/**\n * The wizard's browser, live: a picture from the run that changes as the page does. Watching,\n * it shows over the page what the wizard just did; driving, the person clicks, scrolls and\n * types in it — what they type goes into the page and no model reads it back.\n */\nexport function LiveBrowser({\n runId,\n driving,\n caption,\n action,\n hint,\n className,\n onBroken,\n}: {\n runId: string;\n driving: boolean;\n /** What the wizard just did, over the page while watching. */\n caption?: string;\n /** A button in the corner: take over, hand back. */\n action?: ReactNode;\n /** A line over the controls while driving. */\n hint?: string;\n className?: string;\n /** The stream broke off: the run let the browser go. */\n onBroken?: () => void;\n}) {\n const image = useRef<HTMLImageElement>(null);\n const controls = useRef<HTMLDivElement>(null);\n const [text, setText] = useState(\"\");\n const [hidden, setHidden] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const act = async (body: BrowserAct) => {\n setError(null);\n try {\n await api.post(`${runBase(runId)}/browser/act`, body);\n } catch (err) {\n setError((err as Error).message);\n }\n };\n\n // Taking over brings the controls under the page into view.\n useEffect(() => {\n if (driving) {\n controls.current?.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }\n }, [driving]);\n\n // The wheel scrolls the page, not the chat around it: a listener that may prevent that.\n useEffect(() => {\n const el = image.current;\n if (!(el && driving)) {\n return;\n }\n let pending = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n pending += e.deltaY;\n timer ??= setTimeout(() => {\n timer = null;\n const dy = Math.max(-2000, Math.min(2000, Math.round(pending)));\n pending = 0;\n if (dy) {\n void api\n .post(`${runBase(runId)}/browser/act`, { type: \"scroll\", dy })\n .catch(() => undefined);\n }\n }, WHEEL_EVERY_MS);\n };\n el.addEventListener(\"wheel\", onWheel, { passive: false });\n return () => {\n el.removeEventListener(\"wheel\", onWheel);\n if (timer) {\n clearTimeout(timer);\n }\n };\n }, [driving, runId]);\n\n const click = (e: React.MouseEvent<HTMLImageElement>) => {\n if (!driving) {\n return;\n }\n const box = e.currentTarget.getBoundingClientRect();\n void act({\n type: \"click\",\n fx: Math.min(1, Math.max(0, (e.clientX - box.left) / box.width)),\n fy: Math.min(1, Math.max(0, (e.clientY - box.top) / box.height)),\n });\n };\n\n return (\n <div className={className}>\n <div\n className={cn(\n \"relative aspect-[1280/900] w-full overflow-hidden rounded-xl bg-paper-2 ring-1\",\n driving ? \"ring-2 ring-ember\" : \"ring-border-soft\",\n )}\n >\n <img\n ref={image}\n src={withBase(`${runBase(runId)}/browser/live`)}\n alt=\"\"\n draggable={false}\n onClick={click}\n onError={onBroken}\n className={cn(\"size-full object-cover object-top\", driving && \"cursor-pointer\")}\n />\n {action ? <div className=\"absolute top-2 right-2\">{action}</div> : null}\n {caption && !driving ? (\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 flex items-center gap-1.5 bg-gradient-to-t from-black/75 to-transparent px-3 pt-8 pb-2 text-[0.8125rem] text-white\">\n <MousePointerClick className=\"size-3.5 shrink-0\" />\n <span className=\"truncate\">{caption}</span>\n </div>\n ) : null}\n </div>\n {driving ? (\n <div ref={controls} className=\"mt-1.5\">\n {hint ? <p className=\"mb-1.5 text-[0.8125rem] text-ink-3\">{hint}</p> : null}\n <div className=\"flex flex-wrap items-center gap-1.5 rounded-xl bg-card p-2 ring-1 ring-border-soft\">\n <Input\n type={hidden ? \"password\" : \"text\"}\n autoComplete=\"off\"\n value={text}\n placeholder={t(\"ask.typeInto\")}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void act({ type: \"type\", text }).then(() => setText(\"\"));\n }\n }}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n enterKeyHint=\"send\"\n className=\"h-9 min-w-[9rem] flex-1 basis-full text-[0.8125rem] sm:basis-0 coarse:h-11\"\n />\n <button\n type=\"button\"\n onClick={() => setHidden((h) => !h)}\n className={cn(\n \"h-9 shrink-0 rounded-md px-2.5 text-[0.75rem] coarse:h-11 coarse:px-3.5\",\n hidden ? \"bg-ember-veil text-ink\" : \"text-ink-3 hover:bg-paper-2\",\n )}\n >\n {t(\"ask.hide\")}\n </button>\n <ToolButton label=\"Enter\" onClick={() => void act({ type: \"key\", key: \"Enter\" })}>\n <CornerDownLeft className=\"size-4\" />\n </ToolButton>\n <ToolButton label={t(\"ask.up\")} onClick={() => void act({ type: \"scroll\", dy: -500 })}>\n <ArrowUp className=\"size-4\" />\n </ToolButton>\n <ToolButton label={t(\"ask.down\")} onClick={() => void act({ type: \"scroll\", dy: 500 })}>\n <ArrowDown className=\"size-4\" />\n </ToolButton>\n </div>\n {error ? <p className=\"mt-1.5 text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction ToolButton({\n label,\n onClick,\n children,\n}: {\n label: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n onClick={onClick}\n className=\"flex size-9 shrink-0 items-center justify-center rounded-md text-ink-3 hover:bg-paper-2 hover:text-ink coarse:size-11\"\n >\n {children}\n </button>\n );\n}\n","import type { AskAnswer, ConfirmAsk, LoginAsk, RunAsk } from \"@engenty/wizards-shared/run\";\nimport { LockKeyhole, PencilLine, ShieldCheck, TriangleAlert } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { LiveBrowser } from \"./browser-live.js\";\nimport { api, runBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, cn, Input, Label, Switch } from \"./ui.js\";\n\n/** What a running step asks the person: a sign-in, or leave to change something. */\nexport function AskPanel({ runId, ask }: { runId: string; ask: RunAsk }) {\n return ask.kind === \"confirm\" ? (\n <ConfirmPanel runId={runId} ask={ask} />\n ) : (\n <LoginPanel runId={runId} ask={ask} />\n );\n}\n\n/**\n * A running step wants to change something in an account the person connected. They see what\n * and with which values, and decide.\n */\nfunction ConfirmPanel({ runId, ask }: { runId: string; ask: ConfirmAsk }) {\n const [remember, setRemember] = useState(false);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const answer = async (body: AskAnswer) => {\n setBusy(true);\n setError(null);\n try {\n await api.post(`${runBase(runId)}/ask/${ask.id}`, body);\n } catch (err) {\n setError((err as Error).message);\n setBusy(false);\n }\n };\n const Icon = ask.action.destructive ? TriangleAlert : PencilLine;\n return (\n <div className=\"animate-rise\">\n <div className=\"mb-5 flex items-start gap-3\">\n <div\n className={cn(\n \"flex size-10 shrink-0 items-center justify-center rounded-full\",\n ask.action.destructive ? \"bg-rose-tint text-rose\" : \"bg-ember-tint text-ember-strong\",\n )}\n >\n <Icon className=\"size-5\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-[0.8125rem] text-ink-3\">{t(\"ask.wants\", { service: ask.service })}</p>\n <h2 className=\"wizard-heading font-display font-semibold text-[1.25rem] leading-snug tracking-tight\">\n {ask.reason}\n </h2>\n </div>\n </div>\n <pre className=\"max-h-72 overflow-auto whitespace-pre-wrap break-words rounded-xl bg-paper-2 p-4 text-[0.8125rem] leading-relaxed ring-1 ring-border-soft\">\n {ask.input}\n </pre>\n {ask.once ? null : (\n <div className=\"mt-5 flex items-center gap-4\">\n <Switch checked={remember} onChange={setRemember} label={t(\"ask.allowRest\")} />\n <span className=\"flex-1 text-[0.8125rem] text-ink-2\">{t(\"ask.allowRest\")}</span>\n </div>\n )}\n {error ? (\n <div className=\"mt-3 rounded-lg bg-rose-tint px-4 py-3 text-[0.875rem] text-rose\">\n {error}\n </div>\n ) : null}\n <div className=\"action-bar mt-6 flex items-center justify-between gap-3\">\n <Button variant=\"ghost\" disabled={busy} onClick={() => void answer({ type: \"skip\" })}>\n {t(\"ask.deny\")}\n </Button>\n <Button busy={busy} onClick={() => void answer({ type: \"done\", remember })}>\n {t(\"ask.allow\")}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * A running step asks the person to sign in on a page the wizard has open. The page is shown\n * live: they fill the form here, or click and type in the page itself (a captcha, \"continue\n * with Google\"). What they enter goes into the page — the model never gets it.\n */\nfunction LoginPanel({ runId, ask }: { runId: string; ask: LoginAsk }) {\n const [values, setValues] = useState<Record<string, string>>({});\n const [remember, setRemember] = useState(false);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const answer = async (body: AskAnswer) => {\n setBusy(true);\n setError(null);\n try {\n await api.post(`${runBase(runId)}/ask/${ask.id}`, body);\n } catch (err) {\n setError((err as Error).message);\n setBusy(false);\n }\n };\n const filled = ask.fields.some((f) => values[f.id]);\n\n return (\n <div className=\"animate-rise\">\n <div className=\"mb-5 flex items-start gap-3\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-ember-tint text-ember-strong\">\n <LockKeyhole className=\"size-5\" />\n </div>\n <div className=\"min-w-0\">\n <h2 className=\"wizard-heading font-display font-semibold text-[1.25rem] leading-snug tracking-tight\">\n {ask.reason}\n </h2>\n <p className=\"mt-0.5 truncate text-[0.8125rem] text-ink-3\">\n {ask.site.host}\n {ask.site.title ? ` · ${ask.site.title}` : \"\"}\n </p>\n </div>\n </div>\n\n <LiveBrowser runId={runId} driving />\n <p className=\"mt-2 text-[0.75rem] text-ink-4\">{t(\"ask.pictureHint\")}</p>\n\n {ask.fields.length ? (\n <form\n className=\"mt-5 flex flex-col gap-4\"\n onSubmit={(e) => {\n e.preventDefault();\n void answer({ type: \"fill\", values, remember });\n }}\n >\n {ask.fields.map((f, i) => (\n <div key={f.id}>\n <Label>{f.label}</Label>\n <Input\n autoFocus={i === 0}\n type={f.secret ? \"password\" : \"text\"}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n enterKeyHint={i === ask.fields.length - 1 ? \"go\" : \"next\"}\n value={values[f.id] ?? \"\"}\n onChange={(e) => setValues((v) => ({ ...v, [f.id]: e.target.value }))}\n />\n </div>\n ))}\n <button type=\"submit\" hidden />\n </form>\n ) : null}\n\n <div className=\"mt-5 flex items-center justify-between gap-4\">\n <Switch checked={remember} onChange={setRemember} label={t(\"ask.remember\")} />\n <span className=\"flex-1 text-[0.8125rem] text-ink-2\">{t(\"ask.remember\")}</span>\n </div>\n <p className=\"mt-3 flex items-start gap-2 text-[0.8125rem] text-ink-3\">\n <ShieldCheck className=\"mt-0.5 size-4 shrink-0 text-moss\" /> {t(\"ask.private\")}\n </p>\n {error ? (\n <div className=\"mt-3 rounded-lg bg-rose-tint px-4 py-3 text-[0.875rem] text-rose\">\n {error}\n </div>\n ) : null}\n\n <div className=\"action-bar mt-6 flex flex-wrap items-center justify-between gap-3\">\n <Button variant=\"ghost\" disabled={busy} onClick={() => void answer({ type: \"skip\" })}>\n {t(\"ask.skip\")}\n </Button>\n <div className=\"flex flex-wrap gap-2\">\n {ask.fields.length ? (\n <Button\n variant=\"secondary\"\n disabled={busy}\n onClick={() => void answer({ type: \"done\", remember })}\n >\n {t(\"ask.done\")}\n </Button>\n ) : null}\n {ask.fields.length ? (\n <Button\n busy={busy}\n disabled={!filled}\n onClick={() => void answer({ type: \"fill\", values, remember })}\n >\n {t(\"ask.signIn\")}\n </Button>\n ) : (\n <Button busy={busy} onClick={() => void answer({ type: \"done\", remember })}>\n {t(\"ask.done\")}\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n}\n","import { useEffect, useState, useSyncExternalStore } from \"react\";\nimport { appCall, appCan, appTell, asset, runnerEnv } from \"./env.js\";\n\n/** A finger as the main pointer: a phone or a tablet. */\nexport const isTouch =\n typeof window !== \"undefined\" && window.matchMedia?.(\"(pointer: coarse)\").matches === true;\n\n/** The camera, the microphone and the position only exist on https (and localhost). */\nexport const canUseMedia =\n typeof navigator !== \"undefined\" && Boolean(navigator.mediaDevices?.getUserMedia);\n\n/**\n * Keeps `--kb` on the root: how much of the page the on-screen keyboard covers. iOS lays the\n * keyboard over the page without resizing it, so a bar stuck to the bottom would hide behind it.\n */\nexport function useKeyboardInset() {\n useEffect(() => {\n const vv = window.visualViewport;\n if (!vv) {\n return;\n }\n const root = document.documentElement;\n // The field being typed in stays in sight: above the bar on the keyboard (its\n // scroll-margin, app.css), once the keyboard is up and on every move to another field.\n const reveal = () => {\n const el = document.activeElement;\n if (\n root.classList.contains(\"keyboard-open\") &&\n el instanceof HTMLElement &&\n el !== document.body\n ) {\n requestAnimationFrame(() => el.scrollIntoView({ block: \"nearest\" }));\n }\n };\n const update = () => {\n // Pinch-zoom shrinks the visual viewport too; only an unzoomed page measures the keyboard.\n const covered = vv.scale > 1.01 ? 0 : window.innerHeight - vv.height - vv.offsetTop;\n const open = covered > 80;\n const opened = open && !root.classList.contains(\"keyboard-open\");\n root.style.setProperty(\"--kb\", open ? `${Math.round(covered)}px` : \"0px\");\n root.classList.toggle(\"keyboard-open\", open);\n if (opened) {\n reveal();\n }\n };\n update();\n vv.addEventListener(\"resize\", update);\n vv.addEventListener(\"scroll\", update);\n document.addEventListener(\"focusin\", reveal);\n return () => {\n vv.removeEventListener(\"resize\", update);\n vv.removeEventListener(\"scroll\", update);\n document.removeEventListener(\"focusin\", reveal);\n root.style.removeProperty(\"--kb\");\n root.classList.remove(\"keyboard-open\");\n };\n }, []);\n}\n\n/**\n * Keeps the screen on while `active` — a phone that dims and locks mid-step freezes the page.\n * The lock ends whenever the page is hidden and is taken again when the person comes back.\n */\nexport function useWakeLock(active: boolean): boolean {\n const [held, setHeld] = useState(false);\n useEffect(() => {\n if (active && appCan(\"keepAwake\")) {\n // The app keeps the screen on; the page's lock ends whenever iOS hides the WebView.\n appTell(\"keepAwake\", true);\n setHeld(true);\n return () => {\n appTell(\"keepAwake\", false);\n setHeld(false);\n };\n }\n if (!active || !(\"wakeLock\" in navigator)) {\n return;\n }\n let lock: WakeLockSentinel | null = null;\n let stopped = false;\n const acquire = async () => {\n if (stopped || lock || document.visibilityState !== \"visible\") {\n return;\n }\n try {\n const taken = await navigator.wakeLock.request(\"screen\");\n if (stopped) {\n void taken.release().catch(() => undefined);\n return;\n }\n lock = taken;\n setHeld(true);\n taken.addEventListener(\"release\", () => {\n if (lock === taken) {\n lock = null;\n setHeld(false);\n }\n });\n } catch {\n // Low battery or a browser policy: the run goes on, the screen may dim.\n }\n };\n void acquire();\n document.addEventListener(\"visibilitychange\", acquire);\n return () => {\n stopped = true;\n document.removeEventListener(\"visibilitychange\", acquire);\n void lock?.release().catch(() => undefined);\n lock = null;\n setHeld(false);\n };\n }, [active]);\n return held;\n}\n\n// --- telling the person a long step is done ----------------------------------------------\n\nconst NOTIFY_KEY = \"wz.notify\";\nconst listeners = new Set<() => void>();\nlet audio: AudioContext | null = null;\n\nfunction wanted(): boolean {\n try {\n return localStorage.getItem(NOTIFY_KEY) === \"1\";\n } catch {\n return false;\n }\n}\n\nfunction setWanted(on: boolean) {\n try {\n if (on) {\n localStorage.setItem(NOTIFY_KEY, \"1\");\n } else {\n localStorage.removeItem(NOTIFY_KEY);\n }\n } catch {\n // private mode: the wish lasts until the page is reloaded\n }\n for (const listener of listeners) {\n listener();\n }\n}\n\nconst hasNotifications = typeof window !== \"undefined\" && \"Notification\" in window;\n\n/**\n * `off` — not asked for. `on` — a notification when the page is in the background, a sound and a\n * buzz when it is open. `quiet` — asked for, but the browser shows no notifications for this\n * page (blocked, or a phone browser without them): only sound and buzz while the page is open.\n */\nexport type NotifyState = \"off\" | \"on\" | \"quiet\";\n\n/** In the mobile app: what the person answered the app's own question. */\nlet appAllows: boolean | null = null;\n\nfunction notifyState(): NotifyState {\n if (!wanted()) {\n return \"off\";\n }\n if (appCan(\"notify\")) {\n return appAllows === false ? \"quiet\" : \"on\";\n }\n return hasNotifications && Notification.permission === \"granted\" ? \"on\" : \"quiet\";\n}\n\nexport function useNotifyState(): NotifyState {\n return useSyncExternalStore(\n (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n notifyState,\n () => \"off\" as const,\n );\n}\n\n/** Whether the browser has blocked notifications for this page (the person can undo it there). */\nexport function notificationsBlocked(): boolean {\n if (appCan(\"notify\")) {\n return appAllows === false;\n }\n return hasNotifications && Notification.permission === \"denied\";\n}\n\n/**\n * The person asks to be told. Called from their tap: the browser's permission question and the\n * sound both need one.\n */\nexport async function enableNotify(): Promise<NotifyState> {\n setWanted(true);\n if (appCan(\"notify\")) {\n appAllows = appCan(\"notifyPermission\")\n ? await appCall<boolean>(\"notifyPermission\").catch(() => false)\n : true;\n for (const listener of listeners) {\n listener();\n }\n return notifyState();\n }\n // A sound may only play on a page the person has tapped; this is that tap.\n try {\n audio ??= new AudioContext();\n void audio.resume();\n } catch {\n audio = null;\n }\n if (hasNotifications && Notification.permission === \"default\") {\n try {\n await Notification.requestPermission();\n } catch {\n // stays \"default\": sound and buzz only\n }\n }\n if (hasNotifications && Notification.permission === \"granted\") {\n // Phones only show a page's notification through a service worker.\n const worker = runnerEnv().serviceWorker;\n if (worker) {\n await navigator.serviceWorker?.register(worker).catch(() => undefined);\n }\n }\n for (const listener of listeners) {\n listener();\n }\n return notifyState();\n}\n\nexport function disableNotify() {\n setWanted(false);\n}\n\nfunction chime() {\n const ctx = audio;\n if (ctx?.state !== \"running\") {\n return;\n }\n const now = ctx.currentTime;\n for (const [i, freq] of [660, 880].entries()) {\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.frequency.value = freq;\n gain.gain.setValueAtTime(0, now + i * 0.16);\n gain.gain.linearRampToValueAtTime(0.18, now + i * 0.16 + 0.02);\n gain.gain.exponentialRampToValueAtTime(0.001, now + i * 0.16 + 0.32);\n osc.connect(gain).connect(ctx.destination);\n osc.start(now + i * 0.16);\n osc.stop(now + i * 0.16 + 0.34);\n }\n}\n\n/** Tells the person, in whatever way they agreed to and the device has. A no-op otherwise. */\nexport async function signalPerson(message: { title: string; body: string; tag: string }) {\n if (!wanted()) {\n return;\n }\n if (appCan(\"notify\")) {\n // The app knows whether it is in front: a buzz there, a notification otherwise.\n appTell(\"notify\", message);\n return;\n }\n if (document.visibilityState === \"visible\") {\n chime();\n navigator.vibrate?.([120, 60, 120]);\n return;\n }\n if (!hasNotifications || Notification.permission !== \"granted\") {\n return;\n }\n const options = {\n body: message.body,\n tag: message.tag,\n icon: asset(\"icons/icon-192.png\"),\n badge: asset(\"icons/icon-192.png\"),\n data: { url: location.href },\n };\n try {\n const registration = await navigator.serviceWorker?.getRegistration();\n if (registration?.active) {\n await registration.showNotification(message.title, options);\n return;\n }\n } catch {\n // falls through to the page's own notification\n }\n try {\n new Notification(message.title, options);\n } catch {\n // a phone without the service worker: the page title still says it\n }\n}\n\n/** A share sheet that takes files: phones, and desktop Safari and Chrome. */\nexport function canShareFiles(): boolean {\n if (typeof navigator === \"undefined\" || !navigator.canShare) {\n return false;\n }\n try {\n return navigator.canShare({ files: [new File([\"x\"], \"x.pdf\", { type: \"application/pdf\" })] });\n } catch {\n return false;\n }\n}\n","import { Camera, Check, Flashlight, FlashlightOff, SwitchCamera, Video, X } from \"lucide-react\";\nimport { type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { isTouch } from \"./device\";\nimport { t } from \"./i18n.js\";\nimport { cn, Spinner } from \"./ui.js\";\n\n/**\n * A photo as small as a reader needs it: phone pictures are several megabytes, which is slow to\n * upload and more than a vision model takes.\n */\nexport async function shrinkImage(file: File, max = 2400): Promise<File> {\n if (!/^image\\/(jpeg|png|webp)$/.test(file.type) || file.size < 1_200_000) {\n return file;\n }\n try {\n const bitmap = await createImageBitmap(file);\n const scale = Math.min(1, max / Math.max(bitmap.width, bitmap.height));\n const canvas = document.createElement(\"canvas\");\n canvas.width = Math.round(bitmap.width * scale);\n canvas.height = Math.round(bitmap.height * scale);\n canvas.getContext(\"2d\")?.drawImage(bitmap, 0, 0, canvas.width, canvas.height);\n const blob = await new Promise<Blob | null>((r) => canvas.toBlob(r, \"image/jpeg\", 0.86));\n return blob && blob.size < file.size\n ? new File([blob], `${file.name.replace(/\\.[^.]+$/, \"\")}.jpg`, { type: \"image/jpeg\" })\n : file;\n } catch {\n return file;\n }\n}\n\nexport function stamp(): string {\n return new Date().toISOString().slice(0, 19).replace(/[:T]/g, \"-\");\n}\n\nexport type Facing = \"environment\" | \"user\";\n/** Why there is no picture: the person (or the browser) said no, there is no camera, or it is in use. */\nexport type CameraError = \"denied\" | \"missing\" | \"busy\";\n\nfunction cameraError(err: unknown): CameraError {\n const name = (err as DOMException)?.name;\n if (name === \"NotFoundError\" || name === \"OverconstrainedError\") {\n return \"missing\";\n }\n if (name === \"NotReadableError\" || name === \"AbortError\") {\n return \"busy\";\n }\n return \"denied\";\n}\n\n/** The phone's light, where the camera track has one (Chrome on Android). */\nfunction hasTorch(track: MediaStreamTrack | undefined): boolean {\n const capabilities = track?.getCapabilities?.() as { torch?: boolean } | undefined;\n return Boolean(capabilities?.torch);\n}\n\n/**\n * The device's camera as a live picture, for as long as `active`. The browser asks for the\n * camera when this starts — callers open it from the person's tap. With `audio` the microphone\n * is asked for too; a refused microphone still gives a silent picture.\n */\nexport function useCameraStream(active: boolean, facing: Facing, audio = false) {\n const video = useRef<HTMLVideoElement>(null);\n const [stream, setStream] = useState<MediaStream | null>(null);\n const [error, setError] = useState<CameraError | null>(null);\n const [cameras, setCameras] = useState(1);\n const [torchable, setTorchable] = useState(false);\n const [torch, setTorchOn] = useState(false);\n\n useEffect(() => {\n if (!active) {\n return;\n }\n let live: MediaStream | null = null;\n let stopped = false;\n setError(null);\n setStream(null);\n setTorchable(false);\n setTorchOn(false);\n const picture = {\n facingMode: { ideal: facing },\n width: { ideal: 2560 },\n height: { ideal: 1440 },\n };\n const start = async () => {\n if (!navigator.mediaDevices?.getUserMedia) {\n throw new DOMException(\"no camera api\", \"NotAllowedError\");\n }\n try {\n live = await navigator.mediaDevices.getUserMedia({ video: picture, audio });\n } catch (err) {\n if (!audio) {\n throw err;\n }\n live = await navigator.mediaDevices.getUserMedia({ video: picture });\n }\n if (stopped) {\n for (const track of live.getTracks()) {\n track.stop();\n }\n return;\n }\n setStream(live);\n const track = live.getVideoTracks()[0];\n // Phones report the torch a moment after the picture starts.\n const readTorch = () => !stopped && setTorchable(hasTorch(track));\n readTorch();\n setTimeout(readTorch, 600);\n const devices = await navigator.mediaDevices.enumerateDevices().catch(() => []);\n if (!stopped) {\n setCameras(devices.filter((d) => d.kind === \"videoinput\").length);\n }\n };\n start().catch((err) => !stopped && setError(cameraError(err)));\n return () => {\n stopped = true;\n for (const track of live?.getTracks() ?? []) {\n track.stop();\n }\n };\n }, [active, facing, audio]);\n\n useEffect(() => {\n if (video.current && stream) {\n video.current.srcObject = stream;\n }\n }, [stream]);\n\n const setTorch = async (on: boolean) => {\n const track = stream?.getVideoTracks()[0];\n try {\n await track?.applyConstraints({ advanced: [{ torch: on } as MediaTrackConstraintSet] });\n setTorchOn(on);\n } catch {\n setTorchable(false);\n }\n };\n const mirrored = stream?.getVideoTracks()[0]?.getSettings().facingMode === \"user\";\n return { video, stream, error, cameras, torchable, torch, setTorch, mirrored };\n}\n\n/** The camera or the scanner: the whole screen on a phone, a centred sheet on a desk. */\nexport function MediaSheet({\n open,\n onClose,\n label,\n children,\n}: {\n open: boolean;\n onClose: () => void;\n label: string;\n children: ReactNode;\n}) {\n const ref = useRef<HTMLDialogElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) {\n return;\n }\n if (open && !el.open) {\n el.showModal();\n } else if (!open && el.open) {\n el.close();\n }\n }, [open]);\n return (\n <dialog ref={ref} onClose={onClose} aria-label={label} className=\"media-sheet\">\n {open ? <div className=\"flex h-full flex-col\">{children}</div> : null}\n </dialog>\n );\n}\n\nexport function SheetButton({\n label,\n onClick,\n active,\n children,\n}: {\n label: string;\n onClick: () => void;\n active?: boolean;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n aria-pressed={active}\n onClick={onClick}\n className={cn(\n \"flex size-11 shrink-0 items-center justify-center rounded-full transition\",\n active ? \"bg-white text-black\" : \"bg-white/12 text-white hover:bg-white/20\",\n )}\n >\n {children}\n </button>\n );\n}\n\n/** The top row of a media sheet: close, what this is, and the camera's switches. */\nexport function SheetBar({\n title,\n onClose,\n camera,\n onFlip,\n}: {\n title: string;\n onClose: () => void;\n camera: ReturnType<typeof useCameraStream>;\n onFlip: () => void;\n}) {\n return (\n <div className=\"safe-top\">\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <SheetButton label={t(\"common.close\")} onClick={onClose}>\n <X className=\"size-5\" />\n </SheetButton>\n <div className=\"min-w-0 flex-1 truncate text-center font-medium text-[0.9375rem]\">\n {title}\n </div>\n {camera.torchable ? (\n <SheetButton\n label={t(\"camera.torch\")}\n active={camera.torch}\n onClick={() => void camera.setTorch(!camera.torch)}\n >\n {camera.torch ? (\n <Flashlight className=\"size-5\" />\n ) : (\n <FlashlightOff className=\"size-5\" />\n )}\n </SheetButton>\n ) : null}\n {camera.stream && (camera.cameras > 1 || isTouch) ? (\n <SheetButton label={t(\"camera.flip\")} onClick={onFlip}>\n <SwitchCamera className=\"size-5\" />\n </SheetButton>\n ) : (\n <span className=\"size-11\" />\n )}\n </div>\n </div>\n );\n}\n\n/** The live picture with what to say while there is none: the browser is asking, or it said no. */\nexport function CameraStage({\n camera,\n asking,\n children,\n actions,\n}: {\n camera: ReturnType<typeof useCameraStream>;\n /** One sentence shown while the browser asks for the camera. */\n asking: string;\n children?: ReactNode;\n /** Ways on when there is no camera. */\n actions?: ReactNode;\n}) {\n return (\n <div className=\"relative min-h-0 flex-1 overflow-hidden\">\n <video\n ref={camera.video}\n autoPlay\n playsInline\n muted\n className={cn(\n \"absolute inset-0 size-full object-contain\",\n camera.mirrored && \"-scale-x-100\",\n )}\n />\n {camera.error ? (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-5 bg-black px-8 text-center\">\n <p className=\"max-w-sm text-[0.9375rem] text-white/85 leading-relaxed\">\n {t(`camera.${camera.error}` as \"camera.denied\")}\n </p>\n {actions}\n </div>\n ) : camera.stream ? (\n children\n ) : (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-4 px-8 text-center text-white/75\">\n <Spinner />\n <p className=\"max-w-xs text-[0.875rem] leading-relaxed\">{asking}</p>\n </div>\n )}\n </div>\n );\n}\n\nconst CLIP_SECONDS = 30;\n\nfunction clipType(): string | undefined {\n if (typeof MediaRecorder === \"undefined\") {\n return undefined;\n }\n // MP4 plays everywhere a clip may later be opened; WebM is what older Chrome and Firefox record.\n return [\n \"video/mp4;codecs=avc1.42E01E,mp4a.40.2\",\n \"video/mp4\",\n \"video/webm;codecs=vp9,opus\",\n \"video/webm;codecs=vp8,opus\",\n \"video/webm\",\n ].find((type) => MediaRecorder.isTypeSupported(type));\n}\n\n/** Whether this browser can record a clip itself; otherwise the phone's camera app does it. */\nexport const canRecordClips = Boolean(clipType());\n\n/**\n * Takes pictures with the device's camera: one, or several in a row (the pages of a document),\n * and short clips when the field takes video. Front and back camera, and the torch where the\n * device has one.\n */\nexport function CameraDialog({\n open,\n multiple,\n video: allowVideo,\n onClose,\n onCapture,\n onNative,\n}: {\n open: boolean;\n multiple: boolean;\n /** Also record clips of up to half a minute. */\n video?: boolean;\n onClose: () => void;\n onCapture: (file: File) => Promise<void> | void;\n /** Opens the phone's own camera app instead — the way on when the browser has no camera for us. */\n onNative?: () => void;\n}) {\n const [facing, setFacing] = useState<Facing>(\"environment\");\n const [mode, setMode] = useState<\"photo\" | \"video\">(\"photo\");\n const [taken, setTaken] = useState(0);\n const [busy, setBusy] = useState(false);\n const [recording, setRecording] = useState<number | null>(null);\n const recorder = useRef<MediaRecorder | null>(null);\n const camera = useCameraStream(open, facing, mode === \"video\");\n\n useEffect(() => {\n if (open) {\n setTaken(0);\n setMode(\"photo\");\n setRecording(null);\n }\n }, [open]);\n\n const deliver = async (file: File) => {\n setBusy(true);\n try {\n await onCapture(file);\n setTaken((n) => n + 1);\n if (!multiple) {\n onClose();\n }\n } finally {\n setBusy(false);\n }\n };\n\n const shoot = async () => {\n const el = camera.video.current;\n if (!el?.videoWidth) {\n return;\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = el.videoWidth;\n canvas.height = el.videoHeight;\n canvas.getContext(\"2d\")?.drawImage(el, 0, 0);\n const blob = await new Promise<Blob | null>((r) => canvas.toBlob(r, \"image/jpeg\", 0.9));\n if (blob) {\n await deliver(new File([blob], `foto-${stamp()}.jpg`, { type: \"image/jpeg\" }));\n }\n };\n\n const stopClip = () => {\n if (recorder.current?.state === \"recording\") {\n recorder.current.stop();\n }\n };\n const startClip = () => {\n const type = clipType();\n if (!camera.stream || !type) {\n return;\n }\n const chunks: Blob[] = [];\n const rec = new MediaRecorder(camera.stream, {\n mimeType: type,\n videoBitsPerSecond: 2_500_000,\n audioBitsPerSecond: 96_000,\n });\n rec.ondataavailable = (e) => e.data.size && chunks.push(e.data);\n rec.onstop = () => {\n setRecording(null);\n recorder.current = null;\n const mime = type.split(\";\")[0];\n if (chunks.length) {\n const ext = mime === \"video/mp4\" ? \"mp4\" : \"webm\";\n void deliver(new File(chunks, `video-${stamp()}.${ext}`, { type: mime }));\n }\n };\n recorder.current = rec;\n rec.start(1000);\n setRecording(0);\n };\n // The clock of a running clip; it ends by itself at the limit.\n useEffect(() => {\n if (recording === null) {\n return;\n }\n if (recording >= CLIP_SECONDS) {\n if (recorder.current?.state === \"recording\") {\n recorder.current.stop();\n }\n return;\n }\n const id = setTimeout(() => setRecording((s) => (s === null ? null : s + 1)), 1000);\n return () => clearTimeout(id);\n }, [recording]);\n // Closing the sheet mid-clip keeps nothing.\n useEffect(() => {\n if (!open && recorder.current) {\n recorder.current.onstop = null;\n recorder.current.stop();\n recorder.current = null;\n }\n }, [open]);\n\n const clock = (s: number) => `0:${String(s).padStart(2, \"0\")}`;\n return (\n <MediaSheet open={open} onClose={onClose} label={t(\"camera.title\")}>\n <SheetBar\n title={\n recording !== null\n ? `${clock(recording)} / ${clock(CLIP_SECONDS)}`\n : taken\n ? t(\"camera.taken\", { n: taken })\n : t(\"camera.title\")\n }\n onClose={onClose}\n camera={camera}\n onFlip={() => setFacing((f) => (f === \"environment\" ? \"user\" : \"environment\"))}\n />\n <CameraStage\n camera={camera}\n asking={t(\"camera.asking\")}\n actions={\n <div className=\"flex flex-col gap-2\">\n {onNative ? (\n <SheetAction\n onClick={() => {\n onClose();\n onNative();\n }}\n >\n <Camera className=\"size-4\" /> {t(isTouch ? \"camera.native\" : \"camera.pick\")}\n </SheetAction>\n ) : null}\n <SheetAction quiet onClick={onClose}>\n {t(\"common.close\")}\n </SheetAction>\n </div>\n }\n />\n <div className={cn(\"safe-bottom px-4 pt-3\", camera.error && \"invisible\")}>\n {allowVideo && canRecordClips && recording === null ? (\n <div className=\"mb-3 flex justify-center gap-1 text-[0.8125rem]\">\n {([\"photo\", \"video\"] as const).map((m) => (\n <button\n key={m}\n type=\"button\"\n aria-pressed={mode === m}\n onClick={() => setMode(m)}\n className={cn(\n \"h-9 rounded-full px-4 font-medium transition\",\n mode === m ? \"bg-white text-black\" : \"text-white/70 hover:text-white\",\n )}\n >\n {t(m === \"photo\" ? \"camera.photo\" : \"camera.video\")}\n </button>\n ))}\n </div>\n ) : null}\n <div className=\"grid grid-cols-[1fr_auto_1fr] items-center gap-3\">\n <span className=\"text-[0.8125rem] text-white/70 leading-snug\">\n {recording !== null\n ? t(\"camera.recording\")\n : mode === \"video\"\n ? t(\"camera.clipHint\", { s: CLIP_SECONDS })\n : multiple\n ? t(\"camera.hintMany\")\n : t(\"camera.hint\")}\n </span>\n <button\n type=\"button\"\n aria-label={\n mode === \"photo\"\n ? t(\"camera.shoot\")\n : recording === null\n ? t(\"camera.record\")\n : t(\"camera.stop\")\n }\n disabled={!camera.stream || busy}\n onClick={() =>\n mode === \"photo\" ? void shoot() : recording === null ? startClip() : stopClip()\n }\n className=\"flex size-[72px] items-center justify-center rounded-full border-4 border-white transition active:scale-95 disabled:opacity-40\"\n >\n {busy ? (\n <Spinner className=\"text-white\" />\n ) : mode === \"photo\" ? (\n <span className=\"size-[54px] rounded-full bg-white\" />\n ) : recording === null ? (\n <span className=\"flex size-[54px] items-center justify-center rounded-full bg-[#e5484d]\">\n <Video className=\"size-6 text-white\" />\n </span>\n ) : (\n <span className=\"size-7 rounded-md bg-[#e5484d]\" />\n )}\n </button>\n <div className=\"flex justify-end\">\n {multiple && taken && recording === null ? (\n <SheetAction onClick={onClose}>\n <Check className=\"size-4\" /> {t(\"camera.done\")}\n </SheetAction>\n ) : null}\n </div>\n </div>\n </div>\n </MediaSheet>\n );\n}\n\nexport function SheetAction({\n onClick,\n quiet,\n children,\n}: {\n onClick: () => void;\n quiet?: boolean;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"inline-flex h-11 items-center justify-center gap-2 rounded-full px-5 font-medium text-[0.875rem] transition\",\n quiet ? \"text-white/75 hover:text-white\" : \"bg-white text-black hover:bg-white/90\",\n )}\n >\n {children}\n </button>\n );\n}\n","import { type AgentStep, stepShape } from \"@engenty/wizards-shared/definition\";\nimport type { StepOutput } from \"@engenty/wizards-shared/run\";\nimport {\n type FieldShape,\n type ListShape,\n labelOf,\n type ObjectShape,\n shapeJsonSchema,\n titleKey,\n} from \"@engenty/wizards-shared/shape\";\nimport {\n Braces,\n Check,\n ChevronRight,\n Copy,\n Database,\n Download,\n Link2,\n MoreVertical,\n Plus,\n Trash2,\n X,\n} from \"lucide-react\";\nimport { type ReactNode, useEffect, useId, useRef, useState } from \"react\";\nimport { api, runBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, cn, Dialog, Tabs } from \"./ui.js\";\n\n/**\n * A json step's data, shown and edited by its schema: lists of flat entries are tables as in\n * Space → Data; entries that hold lists of their own are cards that open; lists of words are\n * chips; a link to another list shows that entry's title. Ansicht · Bearbeiten · JSON.\n */\n\ntype Path = (string | number)[];\nexport type DataMode = \"view\" | \"edit\" | \"json\";\ntype Shape = FieldShape | ListShape[\"of\"];\ntype Entry = Record<string, unknown>;\n\ninterface Ctx {\n root: Entry;\n shape: ObjectShape;\n edit: boolean;\n /** Prefix of the ids entries get, so two editors on one page do not meet. */\n scope: string;\n set: (path: Path, value: unknown) => void;\n open: (id: string) => void;\n}\n\nconst cellField =\n \"w-full min-w-0 rounded-md bg-transparent px-2 py-1.5 text-[0.875rem] outline-none transition placeholder:text-ink-4 hover:bg-accent focus:bg-paper focus:ring-1 focus:ring-ring\";\n\nconst caption = \"font-medium text-[0.6875rem] text-ink-3 uppercase tracking-[0.08em]\";\n\nconst isEntry = (v: unknown): v is Entry =>\n Boolean(v) && typeof v === \"object\" && !Array.isArray(v);\n\nfunction setIn(value: unknown, path: Path, next: unknown): unknown {\n if (!path.length) {\n return next;\n }\n const [head, ...rest] = path;\n if (Array.isArray(value)) {\n const copy = [...value];\n copy[head as number] = setIn(copy[head as number], rest, next);\n return copy;\n }\n const obj = (value ?? {}) as Entry;\n return { ...obj, [head]: setIn(obj[head], rest, next) };\n}\n\n/** A table's rows as entries of text fields: its columns, or the keys its rows have. */\nfunction tableShape(columns: string[] | undefined, rows: unknown[]): ObjectShape {\n const keys = columns?.length\n ? columns\n : [...new Set(rows.filter(isEntry).flatMap((r) => Object.keys(r)))];\n return { kind: \"object\", fields: Object.fromEntries(keys.map((k) => [k, { kind: \"text\" }])) };\n}\n\n/** Fields that fit in a table cell: no lists of entries, no long text. */\nconst flat = (s: Shape) =>\n s.kind !== \"object\" &&\n s.kind !== \"table\" &&\n !(s.kind === \"list\" && s.of.kind === \"object\") &&\n !(s.kind === \"text\" && s.long);\n\nconst isTable = (s: ObjectShape) => Object.values(s.fields).every(flat);\n\n/** Entries without lists of their own but with long text: numbered rows (steps of a recipe). */\nconst isRows = (s: ObjectShape) =>\n Object.values(s.fields).every(\n (f) => f.kind !== \"table\" && !(f.kind === \"list\" && f.of.kind === \"object\"),\n );\n\n/** An entry's name: its first short text. */\nfunction titleOf(shape: ObjectShape, entry: Entry): string {\n const key = titleKey(shape);\n return key ? String(entry[key] ?? \"\") : \"\";\n}\n\nfunction Words({ text }: { text: string }) {\n return <span className=\"whitespace-pre-wrap\">{text}</span>;\n}\n\n/** One value by its kind, shown or edited in place. */\nfunction Value({\n shape,\n value,\n path,\n ctx,\n cell,\n}: {\n shape: Shape;\n value: unknown;\n path: Path;\n ctx: Ctx;\n cell?: boolean;\n}) {\n switch (shape.kind) {\n case \"text\":\n if (!ctx.edit) {\n return <Words text={value === null || value === undefined ? \"\" : String(value)} />;\n }\n return shape.long ? (\n <textarea\n className={cn(cellField, \"field-sizing-content max-h-60 resize-none\")}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n />\n ) : (\n <input\n className={cellField}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n />\n );\n case \"number\":\n return ctx.edit ? (\n <span className=\"flex items-center gap-1\">\n <input\n type=\"number\"\n className={cn(cellField, \"text-right tabular-nums\", cell && \"w-20\")}\n value={value === undefined || value === null ? \"\" : Number(value)}\n onChange={(e) => ctx.set(path, e.target.value === \"\" ? null : Number(e.target.value))}\n />\n {shape.unit ? <span className=\"text-[0.8125rem] text-ink-3\">{shape.unit}</span> : null}\n </span>\n ) : (\n <span className=\"tabular-nums\">\n {value === null || value === undefined\n ? \"\"\n : `${value}${shape.unit ? ` ${shape.unit}` : \"\"}`}\n </span>\n );\n case \"yesno\": {\n const word = value ? (shape.yes ?? t(\"data.yes\")) : (shape.no ?? t(\"data.no\"));\n return ctx.edit ? (\n <label className=\"flex items-center gap-2 px-2 py-1.5 text-[0.8125rem] text-ink-2\">\n <input\n type=\"checkbox\"\n checked={Boolean(value)}\n onChange={(e) => ctx.set(path, e.target.checked)}\n className=\"size-4 accent-[var(--second)]\"\n />\n {word}\n </label>\n ) : (\n <span\n className={cn(\n \"inline-flex rounded-full px-2 py-0.5 text-[0.75rem]\",\n value ? \"bg-second-tint text-second\" : \"bg-paper-2 text-ink-3\",\n )}\n >\n {word}\n </span>\n );\n }\n case \"choice\":\n case \"score\":\n return ctx.edit ? (\n <select\n className={cellField}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n >\n {[...new Set([String(value ?? \"\"), ...shape.options])].map((o) => (\n <option key={o} value={o}>\n {o}\n </option>\n ))}\n </select>\n ) : (\n <span>{String(value ?? \"\")}</span>\n );\n case \"ref\": {\n const target = ctx.shape.fields[shape.to];\n const fields: ObjectShape =\n target?.kind === \"list\" && target.of.kind === \"object\"\n ? target.of\n : { kind: \"object\", fields: {} };\n const list = (Array.isArray(ctx.root[shape.to]) ? ctx.root[shape.to] : []) as unknown[];\n const entries = list.filter(isEntry);\n const hit = entries.find((e) => e.id === value);\n if (ctx.edit) {\n return (\n <select\n className={cellField}\n value={String(value ?? \"\")}\n onChange={(e) => ctx.set(path, e.target.value)}\n >\n {hit ? null : <option value={String(value ?? \"\")}>{String(value ?? \"\")}</option>}\n {entries.map((e) => (\n <option key={String(e.id)} value={String(e.id)}>\n {titleOf(fields, e) || String(e.id)}\n </option>\n ))}\n </select>\n );\n }\n return hit ? (\n <button\n type=\"button\"\n onClick={() => ctx.open(String(hit.id))}\n className=\"inline-flex items-center gap-1 text-left text-ember-strong hover:underline\"\n >\n <Link2 className=\"size-3.5 shrink-0\" />\n {titleOf(fields, hit) || String(hit.id)}\n </button>\n ) : (\n <span className=\"text-rose\">{t(\"data.missing\", { id: String(value ?? \"\") })}</span>\n );\n }\n case \"table\": {\n const rows = Array.isArray(value) ? value : [];\n return (\n <EntryTable shape={tableShape(shape.columns, rows)} value={rows} path={path} ctx={ctx} />\n );\n }\n case \"list\":\n if (shape.of.kind === \"object\") {\n const of = shape.of;\n const Entries = isTable(of) ? EntryTable : isRows(of) ? EntryRows : EntryCards;\n return <Entries shape={of} value={value} path={path} ctx={ctx} />;\n }\n return <Chips value={value} path={path} ctx={ctx} />;\n case \"object\":\n return <Form shape={shape} value={value} path={path} ctx={ctx} />;\n }\n}\n\nfunction Chips({ value, path, ctx }: { value: unknown; path: Path; ctx: Ctx }) {\n const items = Array.isArray(value) ? value.map(String) : [];\n const [draft, setDraft] = useState(\"\");\n return (\n <span className=\"flex flex-wrap items-center gap-1\">\n {items.map((item, i) => (\n <span\n key={`${item}-${i}`}\n className=\"inline-flex items-center gap-1 rounded-full bg-paper-2 px-2 py-0.5 text-[0.75rem]\"\n >\n {item}\n {ctx.edit ? (\n <button\n type=\"button\"\n aria-label={t(\"data.remove\")}\n onClick={() =>\n ctx.set(\n path,\n items.filter((_, j) => j !== i),\n )\n }\n className=\"text-ink-3 hover:text-ink\"\n >\n <X className=\"size-3\" />\n </button>\n ) : null}\n </span>\n ))}\n {ctx.edit ? (\n <input\n className=\"w-20 rounded-full bg-transparent px-2 py-0.5 text-[0.75rem] outline-none ring-1 ring-border-soft focus:ring-ring\"\n placeholder=\"+\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && draft.trim()) {\n e.preventDefault();\n ctx.set(path, [...items, draft.trim()]);\n setDraft(\"\");\n }\n }}\n />\n ) : null}\n </span>\n );\n}\n\ninterface EntriesProps {\n shape: ObjectShape;\n value: unknown;\n path: Path;\n ctx: Ctx;\n}\n\nconst entriesIn = (value: unknown) => (Array.isArray(value) ? value : []).filter(isEntry);\n\n/** A new entry: an id where the entries have one, so a link can point at it. */\nconst fresh = (shape: ObjectShape): Entry =>\n shape.fields.id ? { id: `n${Date.now().toString(36)}` } : {};\n\n/** Flat entries: a table as in Space → Data. */\nfunction EntryTable({ shape, value, path, ctx }: EntriesProps) {\n const rows = entriesIn(value);\n const cols = Object.entries(shape.fields);\n return (\n <div className=\"overflow-x-auto rounded-lg ring-1 ring-border-soft\">\n <table className=\"w-full border-collapse text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {cols.map(([key, f]) => (\n <th key={key} className=\"whitespace-nowrap px-3 py-2 text-left font-medium\">\n {labelOf(key, f)}\n </th>\n ))}\n {ctx.edit ? <th className=\"w-8\" /> : null}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, i) => (\n <tr key={i} className=\"group border-border-soft border-t\">\n {cols.map(([key, f]) => (\n <td key={key} className={cn(\"align-top\", ctx.edit ? \"p-0.5\" : \"px-3 py-2\")}>\n <Value shape={f} value={row[key]} path={[...path, i, key]} ctx={ctx} cell />\n </td>\n ))}\n {ctx.edit ? (\n <td className=\"p-0.5 align-middle\">\n <RemoveButton\n onClick={() =>\n ctx.set(\n path,\n rows.filter((_, j) => j !== i),\n )\n }\n />\n </td>\n ) : null}\n </tr>\n ))}\n </tbody>\n </table>\n {ctx.edit ? (\n <AddButton what={shape.label} onClick={() => ctx.set(path, [...rows, fresh(shape)])} />\n ) : null}\n </div>\n );\n}\n\n/** Entries with long text and no lists: numbered rows, the long text first, the rest beside it. */\nfunction EntryRows({ shape, value, path, ctx }: EntriesProps) {\n const rows = entriesIn(value);\n const fields = Object.entries(shape.fields);\n const main = fields.filter(([, f]) => f.kind === \"text\" && f.long);\n const rest = fields.filter(([, f]) => !(f.kind === \"text\" && f.long));\n return (\n <div className=\"overflow-hidden rounded-lg ring-1 ring-border-soft\">\n <ol>\n {rows.map((row, i) => (\n <li\n key={i}\n className=\"grid grid-cols-[1.75rem_1fr_auto] items-start gap-2 border-border-soft border-t px-3 py-2 first:border-0\"\n >\n <span className=\"pt-1.5 font-display font-semibold text-ember-strong tabular-nums\">\n {i + 1}\n </span>\n <div className={cn(\"flex min-w-0 flex-col\", !ctx.edit && \"pt-1\")}>\n {main.map(([key, f]) => (\n <Value key={key} shape={f} value={row[key]} path={[...path, i, key]} ctx={ctx} />\n ))}\n </div>\n <div\n className={cn(\n \"flex items-center gap-2 text-[0.8125rem] text-ink-3\",\n !ctx.edit && \"pt-1\",\n )}\n >\n {rest.map(([key, f]) => (\n <Value\n key={key}\n shape={f}\n value={row[key]}\n path={[...path, i, key]}\n ctx={ctx}\n cell\n />\n ))}\n {ctx.edit ? (\n <RemoveButton\n onClick={() =>\n ctx.set(\n path,\n rows.filter((_, j) => j !== i),\n )\n }\n />\n ) : null}\n </div>\n </li>\n ))}\n </ol>\n {ctx.edit ? (\n <AddButton what={shape.label} onClick={() => ctx.set(path, [...rows, fresh(shape)])} />\n ) : null}\n </div>\n );\n}\n\n/** Entries that hold lists of their own: one card each, opened to show and edit everything. */\nfunction EntryCards({ shape, value, path, ctx }: EntriesProps) {\n const entries = entriesIn(value);\n const fields = Object.entries(shape.fields);\n // The summary line: every short value but the title, then how many each list holds.\n const title = titleKey(shape);\n const short = fields.filter(\n ([key, f]) =>\n key !== title &&\n key !== \"id\" &&\n ((f.kind === \"text\" && !f.long) || f.kind === \"number\" || f.kind === \"choice\"),\n );\n const lists = fields.filter(([, f]) => f.kind === \"list\" && f.of.kind === \"object\");\n return (\n <div className=\"flex flex-col gap-2\">\n {entries.map((entry, i) => {\n const id = typeof entry.id === \"string\" ? entry.id : undefined;\n return (\n <details\n key={i}\n id={id ? `${ctx.scope}-${id}` : undefined}\n className=\"group rounded-xl bg-card ring-1 ring-border-soft open:ring-ink-4/40\"\n >\n <summary className=\"flex cursor-pointer list-none items-center gap-3 px-4 py-3 [&::-webkit-details-marker]:hidden\">\n <ChevronRight className=\"size-4 shrink-0 text-ink-3 transition-transform group-open:rotate-90\" />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium text-[0.9375rem]\">\n {titleOf(shape, entry) || `${shape.label ?? \"\"} ${i + 1}`.trim()}\n </span>\n <span className=\"flex flex-wrap gap-x-2 text-[0.75rem] text-ink-3\">\n {short.map(([key, f]) =>\n entry[key] === undefined || entry[key] === \"\" ? null : (\n <span key={key}>\n {f.kind === \"number\" && f.unit\n ? `${entry[key]} ${f.unit}`\n : String(entry[key])}\n </span>\n ),\n )}\n {lists.map(([key, f]) => (\n <span key={key}>\n {Array.isArray(entry[key]) ? (entry[key] as unknown[]).length : 0}{\" \"}\n {labelOf(key, f)}\n </span>\n ))}\n </span>\n </span>\n {ctx.edit ? (\n <RemoveButton\n onClick={() =>\n ctx.set(\n path,\n entries.filter((_, j) => j !== i),\n )\n }\n />\n ) : null}\n </summary>\n <div className=\"border-border-soft border-t px-4 py-4\">\n <Form shape={shape} value={entry} path={[...path, i]} ctx={ctx} />\n </div>\n </details>\n );\n })}\n {ctx.edit ? (\n <AddButton what={shape.label} onClick={() => ctx.set(path, [...entries, fresh(shape)])} />\n ) : null}\n </div>\n );\n}\n\n/** An entry's fields: short ones side by side, long text and lists across the width. */\nfunction Form({ shape, value, path, ctx }: EntriesProps) {\n const obj = isEntry(value) ? value : {};\n const wide = (f: Shape) =>\n f.kind === \"list\" ||\n f.kind === \"object\" ||\n f.kind === \"table\" ||\n (f.kind === \"text\" && Boolean(f.long));\n return (\n <div className=\"grid grid-cols-[repeat(auto-fill,minmax(10rem,1fr))] gap-x-4 gap-y-4\">\n {Object.entries(shape.fields).map(([key, f]) => (\n <Field\n key={key}\n title={labelOf(key, f)}\n wide={wide(f)}\n count={Array.isArray(obj[key]) ? (obj[key] as unknown[]).length : null}\n >\n <Value shape={f} value={obj[key]} path={[...path, key]} ctx={ctx} />\n </Field>\n ))}\n </div>\n );\n}\n\nfunction Field({\n title,\n wide,\n count,\n children,\n}: {\n title: string;\n wide: boolean;\n count: number | null;\n children: ReactNode;\n}) {\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1.5 text-[0.875rem]\", wide && \"col-span-full\")}>\n <span className={caption}>\n {title}\n {count !== null ? <span className=\"ml-1 text-ink-4\">{count}</span> : null}\n </span>\n {children}\n </div>\n );\n}\n\nfunction RemoveButton({ onClick }: { onClick: () => void }) {\n return (\n <button\n type=\"button\"\n aria-label={t(\"data.remove\")}\n onClick={(e) => {\n e.preventDefault();\n onClick();\n }}\n className=\"grid size-7 place-items-center rounded-md text-ink-3 hover:bg-accent hover:text-rose\"\n >\n <Trash2 className=\"size-3.5\" />\n </button>\n );\n}\n\nfunction AddButton({ what, onClick }: { what?: string; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className=\"flex w-full items-center gap-1.5 border-border-soft border-t px-3 py-2 text-[0.8125rem] text-ink-3 hover:bg-accent hover:text-ink\"\n >\n <Plus className=\"size-3.5\" /> {t(\"data.add\", { what: what ?? \"\" }).trim()}\n </button>\n );\n}\n\n/**\n * The data of one step: a bar with the parts to jump to and Ansicht · Bearbeiten · JSON, then\n * the parts. `mode` and `onMode` hold the bar's choice from outside where given.\n */\nexport function DataEditor({\n shape,\n value,\n onChange,\n mode: held,\n onMode,\n modes = [\"view\", \"edit\", \"json\"],\n start,\n}: {\n shape: ObjectShape;\n value: Entry;\n onChange?: (next: Entry) => void;\n mode?: DataMode;\n onMode?: (mode: DataMode) => void;\n /** The modes offered; without `onChange` there is no edit. */\n modes?: DataMode[];\n /** The mode it opens in. */\n start?: DataMode;\n}) {\n const offered = onChange ? modes : modes.filter((m) => m !== \"edit\");\n const [own, setOwn] = useState<DataMode>(\n start && offered.includes(start) ? start : (offered[0] ?? \"view\"),\n );\n const mode = held ?? own;\n const setMode = onMode ?? setOwn;\n const scope = useId().replace(/[^a-zA-Z0-9_-]/g, \"\");\n const ctx: Ctx = {\n root: value,\n shape,\n edit: mode === \"edit\" && Boolean(onChange),\n scope,\n set: (path, next) => onChange?.(setIn(value, path, next) as Entry),\n open: (id) => {\n const el = document.getElementById(`${scope}-${id}`) as HTMLDetailsElement | null;\n if (el) {\n el.open = true;\n el.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n },\n };\n const parts = Object.entries(shape.fields);\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-border-soft border-b px-3 py-2\">\n <div className=\"flex min-w-0 flex-wrap gap-1\">\n {parts.length > 1\n ? parts.map(([key, f]) => (\n <a\n key={key}\n href={`#${scope}-part-${key}`}\n className=\"rounded-full px-2.5 py-1 text-[0.8125rem] text-ink-2 hover:bg-accent\"\n >\n {labelOf(key, f)}\n {Array.isArray(value[key]) ? (\n <span className=\"ml-1 text-ink-4 tabular-nums\">\n {(value[key] as unknown[]).length}\n </span>\n ) : null}\n </a>\n ))\n : null}\n </div>\n {offered.length > 1 ? (\n <Tabs<DataMode>\n value={mode}\n onChange={setMode}\n label={t(\"data.modes\")}\n options={offered.map((id) => ({ id, label: t(`data.${id}`) }))}\n />\n ) : null}\n </div>\n {mode === \"json\" ? (\n <pre className=\"max-h-[36rem] overflow-auto p-4 font-mono text-[0.75rem] text-ink-2 leading-relaxed\">\n {JSON.stringify(value, null, 2)}\n </pre>\n ) : (\n <div className=\"flex flex-col gap-7 p-4 sm:p-5\">\n {parts.map(([key, f]) => (\n <section\n key={key}\n id={`${scope}-part-${key}`}\n className=\"flex scroll-mt-4 flex-col gap-2\"\n >\n <h3 className=\"flex items-baseline gap-2 font-display font-semibold text-[1rem]\">\n {labelOf(key, f)}\n {Array.isArray(value[key]) ? (\n <span className=\"font-normal font-sans text-[0.8125rem] text-ink-4 tabular-nums\">\n {(value[key] as unknown[]).length}\n </span>\n ) : null}\n </h3>\n <div className=\"text-[0.9375rem] leading-relaxed\">\n <Value shape={f} value={value[key]} path={[key]} ctx={ctx} />\n </div>\n </section>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/** A ⋮ menu of a step's output: a few entries for whoever builds or keeps the wizard. */\nexport function DataMenu({\n items,\n}: {\n items: { label: string; icon: ReactNode; onClick: () => void }[];\n}) {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (!open) {\n return;\n }\n const outside = (e: MouseEvent) => {\n if (!ref.current?.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && setOpen(false);\n document.addEventListener(\"mousedown\", outside);\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"mousedown\", outside);\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [open]);\n return (\n <div ref={ref} className=\"relative\">\n <button\n type=\"button\"\n aria-label={t(\"data.menu\")}\n title={t(\"data.menu\")}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n className={cn(\n \"grid size-8 place-items-center rounded-full text-ink-3 transition hover:bg-accent hover:text-ink coarse:size-11\",\n open && \"bg-accent text-ink\",\n )}\n >\n <MoreVertical className=\"size-4\" />\n </button>\n {open ? (\n <div\n role=\"menu\"\n className=\"absolute top-full right-0 z-50 mt-1 w-60 animate-rise rounded-xl bg-card p-1.5 shadow-overlay ring-1 ring-border-soft\"\n >\n {items.map((item) => (\n <button\n key={item.label}\n type=\"button\"\n role=\"menuitem\"\n className=\"flex w-full items-center gap-3 rounded-lg px-3 py-2 text-left text-[0.875rem] text-ink-2 transition hover:bg-accent hover:text-ink\"\n onClick={() => {\n setOpen(false);\n item.onClick();\n }}\n >\n {item.icon}\n {item.label}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\n/** A file name from a title: \"Menüplan\" → \"menueplan\". */\nfunction fileName(title: string): string {\n return (\n title\n .toLowerCase()\n .replace(/ä/g, \"ae\")\n .replace(/ö/g, \"oe\")\n .replace(/ü/g, \"ue\")\n .replace(/ß/g, \"ss\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\") || \"output\"\n );\n}\n\n/** The JSON Schema (draft 2020-12) a json step's data has: shown, copied or downloaded. */\nexport function JsonSchemaDialog({\n shape,\n title,\n open,\n onClose,\n}: {\n shape: ObjectShape;\n title: string;\n open: boolean;\n onClose: () => void;\n}) {\n const [copied, setCopied] = useState(false);\n const text = open ? JSON.stringify(shapeJsonSchema(shape, title), null, 2) : \"\";\n const download = () => {\n const url = URL.createObjectURL(new Blob([text], { type: \"application/schema+json\" }));\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${fileName(title)}.schema.json`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n };\n return (\n <Dialog\n open={open}\n onClose={onClose}\n title={`${t(\"data.schema\")} · ${title}`}\n wide\n height=\"tall\"\n >\n <div className=\"flex min-h-0 flex-1 flex-col gap-3\">\n <pre className=\"min-h-0 flex-1 overflow-auto rounded-lg bg-paper-2 p-3 font-mono text-[0.75rem] text-ink-2 leading-relaxed\">\n {text}\n </pre>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n void navigator.clipboard.writeText(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n }}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n {copied ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {copied ? t(\"share.copied\") : t(\"data.copy\")}\n </button>\n <button\n type=\"button\"\n onClick={download}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n <Download className=\"size-3.5\" /> {t(\"data.download\")}\n </button>\n </div>\n </div>\n </Dialog>\n );\n}\n\n/** A json step whose data can be edited by its shape: not one run per entry, not a tool's answer. */\nexport function editableData(step: { type: string }): step is AgentStep {\n const s = step as AgentStep;\n return s.type === \"agent\" && s.output.format === \"json\" && !s.each && !s.call;\n}\n\n/**\n * A json step's output in the studio: its ⋮ menu (the data to view and edit, the JSON Schema)\n * goes into the header, the data takes the place of the view while it is open. Saved edits go\n * to the run like a review's do, checked against the step's schema.\n */\nexport function StudioData({\n runId,\n step,\n output,\n header,\n children,\n}: {\n runId: string;\n step: AgentStep;\n output: StepOutput;\n header: (menu: ReactNode) => ReactNode;\n children: ReactNode;\n}) {\n const shape = stepShape(step);\n const [open, setOpen] = useState(false);\n const [schema, setSchema] = useState(false);\n const [draft, setDraft] = useState<Entry | null>(null);\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const value = draft ?? (isEntry(output.json) ? output.json : {});\n const save = async () => {\n if (!draft) {\n return;\n }\n setSaving(true);\n setError(null);\n try {\n await api.put(`${runBase(runId)}/outputs/${step.id}`, { json: draft });\n setDraft(null);\n setOpen(false);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setSaving(false);\n }\n };\n const menu = (\n <DataMenu\n items={[\n {\n label: t(open ? \"data.close\" : \"data.open\"),\n icon: <Database className=\"size-4 shrink-0\" />,\n onClick: () => {\n setOpen((o) => !o);\n setDraft(null);\n },\n },\n {\n label: t(\"data.schema\"),\n icon: <Braces className=\"size-4 shrink-0\" />,\n onClick: () => setSchema(true),\n },\n ]}\n />\n );\n return (\n <>\n {header(menu)}\n {open ? (\n <div className=\"overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n <DataEditor shape={shape} value={value} onChange={setDraft} />\n {draft ? (\n <div className=\"flex items-center justify-end gap-2 border-border-soft border-t px-3 py-2\">\n {error ? <span className=\"mr-auto text-[0.8125rem] text-rose\">{error}</span> : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setDraft(null)}>\n {t(\"common.cancel\")}\n </Button>\n <Button size=\"sm\" busy={saving} onClick={() => void save()}>\n {t(\"data.save\")}\n </Button>\n </div>\n ) : null}\n </div>\n ) : (\n children\n )}\n <JsonSchemaDialog\n shape={shape}\n title={step.title}\n open={schema}\n onClose={() => setSchema(false)}\n />\n </>\n );\n}\n","import { isLocationValue, type LocationValue } from \"@engenty/wizards-shared/definition\";\nimport { ExternalLink, LocateFixed, MapPin, X } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { api, runBase } from \"./env.js\";\nimport { lang, t } from \"./i18n.js\";\nimport { Button, IconButton, Input } from \"./ui.js\";\n\n/** Good enough for an address; the device keeps refining until then or until it has tried long enough. */\nconst GOOD_METRES = 25;\nconst REFINE_MS = 9000;\n\ntype Trouble = \"denied\" | \"unavailable\" | \"timeout\";\n\nfunction trouble(err: GeolocationPositionError): Trouble {\n return err.code === err.PERMISSION_DENIED\n ? \"denied\"\n : err.code === err.TIMEOUT\n ? \"timeout\"\n : \"unavailable\";\n}\n\n/**\n * Where the person is: the device's position on their tap, with how exact it is, and an address\n * line they can correct — or type alone, when the device gives no position.\n */\nexport function LocationField({\n value,\n runId,\n placeholder,\n onChange,\n onBusy,\n}: {\n value: unknown;\n runId: string;\n placeholder?: string;\n onChange: (v: LocationValue | undefined) => void;\n onBusy?: (busy: boolean) => void;\n}) {\n const place = isLocationValue(value) ? value : null;\n const [locating, setLocating] = useState(false);\n const [error, setError] = useState<Trouble | null>(null);\n const watch = useRef<number | null>(null);\n // The address line is the server's suggestion until the person types in it.\n const typed = useRef(Boolean(place?.label));\n const latest = useRef(place);\n latest.current = place;\n const hasPoint = place?.lat !== undefined && place.lng !== undefined;\n const supported = typeof navigator !== \"undefined\" && \"geolocation\" in navigator;\n\n const stop = () => {\n if (watch.current !== null) {\n navigator.geolocation.clearWatch(watch.current);\n watch.current = null;\n }\n setLocating(false);\n onBusy?.(false);\n };\n useEffect(\n () => () => {\n if (watch.current !== null) {\n navigator.geolocation.clearWatch(watch.current);\n }\n },\n [],\n );\n\n const name = async (lat: number, lng: number) => {\n try {\n const { label } = await api.post<{ label: string | null }>(`${runBase(runId)}/geocode`, {\n lat,\n lng,\n language: lang,\n });\n const now = latest.current;\n if (label && !typed.current && now?.lat === lat && now.lng === lng) {\n onChange({ ...now, label });\n }\n } catch {\n // the coordinates stand on their own\n }\n };\n\n const locate = () => {\n setError(null);\n setLocating(true);\n onBusy?.(true);\n const started = Date.now();\n let best = Number.POSITIVE_INFINITY;\n watch.current = navigator.geolocation.watchPosition(\n (pos) => {\n const { latitude, longitude, accuracy } = pos.coords;\n if (accuracy < best) {\n best = accuracy;\n const lat = Math.round(latitude * 1e6) / 1e6;\n const lng = Math.round(longitude * 1e6) / 1e6;\n const label = typed.current ? latest.current?.label : undefined;\n const next = { lat, lng, accuracy: Math.round(accuracy), ...(label ? { label } : {}) };\n latest.current = next;\n onChange(next);\n }\n if (best <= GOOD_METRES || Date.now() - started > REFINE_MS) {\n stop();\n const now = latest.current;\n if (now?.lat !== undefined && now.lng !== undefined) {\n void name(now.lat, now.lng);\n }\n }\n },\n (err) => {\n stop();\n // A fix already taken stays; only a first try that fails is reported.\n if (best === Number.POSITIVE_INFINITY) {\n setError(trouble(err));\n }\n },\n { enableHighAccuracy: true, timeout: 15_000, maximumAge: 10_000 },\n );\n };\n\n const setLabel = (label: string) => {\n typed.current = label.trim().length > 0;\n const next = { ...(hasPoint ? place : {}), label };\n onChange(hasPoint || label.trim() ? next : undefined);\n };\n\n return (\n <div className=\"flex flex-col gap-3\">\n {hasPoint ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-3 ring-1 ring-input\">\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-moss-tint text-moss\">\n <MapPin className=\"size-5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium text-[0.9375rem] tabular-nums\">\n {place.lat?.toFixed(5)}, {place.lng?.toFixed(5)}\n </div>\n <div className=\"flex flex-wrap items-center gap-x-3 text-[0.8125rem] text-ink-3\">\n <span>\n {locating\n ? t(\"location.refining\")\n : place.accuracy\n ? t(\"location.accuracy\", { m: place.accuracy })\n : null}\n </span>\n <a\n href={`https://www.openstreetmap.org/?mlat=${place.lat}&mlon=${place.lng}#map=17/${place.lat}/${place.lng}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 underline-offset-2 hover:text-ink hover:underline coarse:-my-3 coarse:min-h-11 coarse:min-w-11\"\n >\n {t(\"location.map\")} <ExternalLink className=\"size-3\" />\n </a>\n </div>\n </div>\n <IconButton\n label={t(\"location.remove\")}\n onClick={() => {\n stop();\n typed.current = false;\n onChange(undefined);\n }}\n >\n <X className=\"size-4\" />\n </IconButton>\n </div>\n ) : supported ? (\n <div>\n <Button\n variant=\"secondary\"\n size=\"lg\"\n busy={locating}\n onClick={locate}\n className=\"w-full sm:w-auto\"\n >\n {locating ? null : <LocateFixed className=\"size-4\" />}\n {locating ? t(\"location.locating\") : t(\"location.use\")}\n </Button>\n {error ? (\n <p className=\"mt-2 rounded-lg bg-amber-tint px-3 py-2 text-[0.8125rem] text-ink-2 leading-relaxed\">\n {t(`location.${error}` as \"location.denied\")}\n </p>\n ) : (\n <p className=\"mt-2 text-[0.8125rem] text-ink-3 leading-relaxed\">{t(\"location.why\")}</p>\n )}\n </div>\n ) : null}\n <Input\n value={place?.label ?? \"\"}\n placeholder={placeholder ?? t(hasPoint ? \"location.label\" : \"location.manual\")}\n autoComplete=\"street-address\"\n enterKeyHint=\"done\"\n aria-label={t(\"location.manual\")}\n onChange={(e) => setLabel(e.target.value)}\n />\n </div>\n );\n}\n","import { ImageUp } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n CameraStage,\n type Facing,\n MediaSheet,\n SheetAction,\n SheetBar,\n useCameraStream,\n} from \"./camera\";\nimport { appCall, appCan } from \"./env.js\";\nimport { t } from \"./i18n.js\";\n\ntype Detect = (source: HTMLVideoElement | ImageBitmap) => Promise<string | null>;\n\ninterface Reader {\n detect: Detect;\n /** The fallback reads QR codes only; the browser's own detector also reads barcodes. */\n qrOnly: boolean;\n}\n\ninterface NativeDetector {\n detect(source: ImageBitmapSource): Promise<{ rawValue: string }[]>;\n}\ninterface NativeDetectorClass {\n new (options?: { formats: string[] }): NativeDetector;\n getSupportedFormats(): Promise<string[]>;\n}\n\nlet reader: Promise<Reader> | null = null;\n\n/**\n * The browser's BarcodeDetector where it exists (Chrome on Android and macOS); elsewhere — iOS,\n * Firefox, Chrome on Windows — a small QR decoder that is only downloaded when first needed.\n */\nfunction codeReader(): Promise<Reader> {\n reader ??= (async () => {\n const Native = (window as unknown as { BarcodeDetector?: NativeDetectorClass }).BarcodeDetector;\n if (Native) {\n try {\n const formats = await Native.getSupportedFormats();\n if (formats.includes(\"qr_code\")) {\n const detector = new Native({ formats });\n return {\n qrOnly: false,\n detect: async (source) => (await detector.detect(source))[0]?.rawValue || null,\n };\n }\n } catch {\n // falls through to the decoder\n }\n }\n const { default: QrScanner } = await import(\"qr-scanner\");\n const engine = QrScanner.createQrEngine();\n return {\n qrOnly: true,\n detect: async (source) => {\n try {\n const found = await QrScanner.scanImage(source, {\n qrEngine: engine,\n returnDetailedScanResult: true,\n });\n return found.data || null;\n } catch {\n return null;\n }\n },\n };\n })();\n return reader;\n}\n\ninterface ScanProps {\n open: boolean;\n onClose: () => void;\n onResult: (text: string) => void;\n}\n\n/** In the mobile app its own scanner reads every common barcode; the page draws nothing. */\nfunction AppScan({ open, onClose, onResult }: ScanProps) {\n const found = useRef(onResult);\n found.current = onResult;\n const close = useRef(onClose);\n close.current = onClose;\n useEffect(() => {\n if (!open) {\n return;\n }\n void appCall<string | null>(\"scan\")\n .then((text) => {\n if (text) {\n found.current(text);\n }\n })\n .catch(() => undefined)\n .finally(() => close.current());\n }, [open]);\n return null;\n}\n\n/** Reads a QR code or barcode with the camera — or from a photo, when there is no camera. */\nexport function ScanDialog(props: ScanProps) {\n return appCan(\"scan\") ? <AppScan {...props} /> : <WebScan {...props} />;\n}\n\nfunction WebScan({ open, onClose, onResult }: ScanProps) {\n const [facing, setFacing] = useState<Facing>(\"environment\");\n const [qrOnly, setQrOnly] = useState(false);\n const [miss, setMiss] = useState(false);\n const photo = useRef<HTMLInputElement>(null);\n const camera = useCameraStream(open, facing);\n const found = useRef(onResult);\n found.current = onResult;\n const close = useRef(onClose);\n close.current = onClose;\n\n useEffect(() => {\n if (!open) {\n return;\n }\n setMiss(false);\n void codeReader().then((r) => setQrOnly(r.qrOnly));\n }, [open]);\n\n useEffect(() => {\n if (!open || !camera.stream) {\n return;\n }\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const tick = async () => {\n const el = camera.video.current;\n if (!stopped && el && el.readyState >= 2 && el.videoWidth) {\n const text = await (await codeReader()).detect(el).catch(() => null);\n if (text && !stopped) {\n navigator.vibrate?.(60);\n found.current(text);\n close.current();\n return;\n }\n }\n if (!stopped) {\n timer = setTimeout(tick, 200);\n }\n };\n void tick();\n return () => {\n stopped = true;\n clearTimeout(timer);\n };\n }, [open, camera.stream, camera.video]);\n\n const fromPhoto = async (file: File | undefined) => {\n if (!file) {\n return;\n }\n setMiss(false);\n const bitmap = await createImageBitmap(file).catch(() => null);\n const text = bitmap ? await (await codeReader()).detect(bitmap).catch(() => null) : null;\n if (text) {\n onResult(text);\n onClose();\n } else {\n setMiss(true);\n }\n };\n\n return (\n <MediaSheet open={open} onClose={onClose} label={t(\"scan.title\")}>\n <SheetBar\n title={t(\"scan.title\")}\n onClose={onClose}\n camera={camera}\n onFlip={() => setFacing((f) => (f === \"environment\" ? \"user\" : \"environment\"))}\n />\n <CameraStage\n camera={camera}\n asking={t(\"scan.asking\")}\n actions={\n <div className=\"flex flex-col gap-2\">\n <SheetAction onClick={() => photo.current?.click()}>\n <ImageUp className=\"size-4\" /> {t(\"scan.fromPhoto\")}\n </SheetAction>\n <SheetAction quiet onClick={onClose}>\n {t(\"scan.typeInstead\")}\n </SheetAction>\n </div>\n }\n >\n {/* The frame the code goes into. */}\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"aspect-square w-[min(68%,320px)] rounded-3xl border-2 border-white/90 shadow-[0_0_0_100vmax_rgb(0_0_0/0.35)]\" />\n </div>\n </CameraStage>\n <div className=\"safe-bottom flex flex-col items-center gap-3 px-5 pt-3 text-center\">\n <p className=\"text-[0.8125rem] text-white/75 leading-snug\">\n {miss ? t(\"scan.miss\") : qrOnly ? t(\"scan.hintQr\") : t(\"scan.hint\")}\n </p>\n {camera.stream ? (\n <SheetAction quiet onClick={() => photo.current?.click()}>\n <ImageUp className=\"size-4\" /> {t(\"scan.fromPhoto\")}\n </SheetAction>\n ) : null}\n </div>\n <input\n ref={photo}\n type=\"file\"\n hidden\n accept=\"image/*\"\n onChange={(e) => {\n void fromPhoto(e.target.files?.[0]);\n e.target.value = \"\";\n }}\n />\n </MediaSheet>\n );\n}\n","import { Eraser, PenLine, X } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { api, runBase, withBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, Dialog, IconButton } from \"./ui.js\";\n\ntype Point = { x: number; y: number };\n/** Strokes in pad units: x from 0 to 1, y from 0 to 1 — they survive a rotated phone. */\ntype Strokes = Point[][];\n\nconst INK = \"#1d1a17\";\n/** The kept picture: wide like a signature line, sharp enough for print. */\nconst OUT = { width: 1200, height: 480 };\n\nfunction draw(ctx: CanvasRenderingContext2D, strokes: Strokes, w: number, h: number, pen: number) {\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = INK;\n ctx.fillStyle = INK;\n ctx.lineWidth = pen;\n for (const stroke of strokes) {\n if (stroke.length === 1) {\n ctx.beginPath();\n ctx.arc(stroke[0].x * w, stroke[0].y * h, pen / 2, 0, Math.PI * 2);\n ctx.fill();\n continue;\n }\n ctx.beginPath();\n ctx.moveTo(stroke[0].x * w, stroke[0].y * h);\n // Curves through the midpoints: a finger's jittery samples become one smooth line.\n for (let i = 1; i < stroke.length - 1; i++) {\n const a = stroke[i];\n const b = stroke[i + 1];\n ctx.quadraticCurveTo(a.x * w, a.y * h, ((a.x + b.x) / 2) * w, ((a.y + b.y) / 2) * h);\n }\n const last = stroke[stroke.length - 1];\n ctx.lineTo(last.x * w, last.y * h);\n ctx.stroke();\n }\n}\n\nfunction Pad({ strokes, onStrokes }: { strokes: Strokes; onStrokes: (s: Strokes) => void }) {\n const canvas = useRef<HTMLCanvasElement>(null);\n const current = useRef<Point[] | null>(null);\n const all = useRef(strokes);\n all.current = strokes;\n\n const paint = () => {\n const el = canvas.current;\n const ctx = el?.getContext(\"2d\");\n if (!el || !ctx) {\n return;\n }\n const ratio = window.devicePixelRatio || 1;\n const w = Math.round(el.clientWidth * ratio);\n const h = Math.round(el.clientHeight * ratio);\n if (el.width !== w || el.height !== h) {\n el.width = w;\n el.height = h;\n }\n ctx.clearRect(0, 0, w, h);\n const live = current.current ? [...all.current, current.current] : all.current;\n draw(ctx, live, w, h, 2.4 * ratio);\n };\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: repaints whenever the strokes change\n useEffect(() => {\n paint();\n const el = canvas.current;\n if (!el) {\n return;\n }\n const ro = new ResizeObserver(paint);\n ro.observe(el);\n return () => ro.disconnect();\n }, [strokes]);\n\n const at = (e: React.PointerEvent<HTMLCanvasElement>): Point => {\n const box = e.currentTarget.getBoundingClientRect();\n return {\n x: Math.min(1, Math.max(0, (e.clientX - box.left) / box.width)),\n y: Math.min(1, Math.max(0, (e.clientY - box.top) / box.height)),\n };\n };\n\n return (\n <div className=\"relative overflow-hidden rounded-xl bg-white ring-1 ring-input\">\n <canvas\n ref={canvas}\n aria-label={t(\"sign.pad\")}\n className=\"block aspect-[5/2] w-full cursor-crosshair touch-none select-none\"\n onPointerDown={(e) => {\n e.currentTarget.setPointerCapture(e.pointerId);\n current.current = [at(e)];\n paint();\n }}\n onPointerMove={(e) => {\n if (current.current) {\n current.current.push(at(e));\n paint();\n }\n }}\n onPointerUp={() => {\n if (current.current) {\n const done = current.current;\n current.current = null;\n onStrokes([...all.current, done]);\n }\n }}\n onPointerCancel={() => {\n current.current = null;\n paint();\n }}\n />\n {/* The line to sign on. */}\n <div className=\"pointer-events-none absolute inset-x-6 bottom-[22%] border-[#1d1a17]/25 border-b\" />\n {strokes.length ? null : (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center text-[#1d1a17]/40 text-[0.875rem]\">\n {t(\"sign.hint\")}\n </div>\n )}\n </div>\n );\n}\n\nasync function picture(strokes: Strokes): Promise<File | null> {\n const canvas = document.createElement(\"canvas\");\n canvas.width = OUT.width;\n canvas.height = OUT.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n return null;\n }\n // Clear ground, dark ink: the signature sits on any paper it is placed on.\n draw(ctx, strokes, OUT.width, OUT.height, 7);\n const blob = await new Promise<Blob | null>((r) => canvas.toBlob(r, \"image/png\"));\n return blob ? new File([blob], \"unterschrift.png\", { type: \"image/png\" }) : null;\n}\n\n/** A signature drawn with the finger, a pen or the mouse; kept as a picture. */\nexport function SignatureField({\n label,\n value,\n runId,\n onChange,\n}: {\n label: string;\n value: unknown;\n runId: string;\n onChange: (v: string | undefined) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [strokes, setStrokes] = useState<Strokes>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const id = typeof value === \"string\" && value ? value : null;\n\n const accept = async () => {\n setBusy(true);\n setError(null);\n try {\n const file = await picture(strokes);\n if (!file) {\n return;\n }\n const ref = await api.upload<{ id: string }>(`${runBase(runId)}/uploads`, file);\n onChange(ref.id);\n setOpen(false);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div>\n {id ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-2 ring-1 ring-input\">\n <button\n type=\"button\"\n onClick={() => {\n setStrokes([]);\n setOpen(true);\n }}\n className=\"min-w-0 flex-1 rounded-lg bg-white px-3\"\n aria-label={t(\"sign.again\")}\n >\n <img\n src={withBase(`${runBase(runId)}/assets/${id}`)}\n alt={label}\n className=\"mx-auto h-20 object-contain\"\n />\n </button>\n <IconButton label={t(\"sign.remove\")} onClick={() => onChange(undefined)}>\n <X className=\"size-4\" />\n </IconButton>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => {\n setStrokes([]);\n setOpen(true);\n }}\n className=\"flex w-full flex-col items-center justify-center gap-2 rounded-xl border border-input border-dashed bg-card px-4 py-7 text-[0.875rem] text-ink-3 transition hover:border-ember hover:text-ink\"\n >\n <PenLine className=\"size-6\" />\n {t(\"sign.open\")}\n </button>\n )}\n <Dialog open={open} onClose={() => setOpen(false)} title={label} wide>\n <Pad strokes={strokes} onStrokes={setStrokes} />\n {error ? <p className=\"mt-2 text-[0.8125rem] text-rose\">{error}</p> : null}\n <div className=\"mt-5 flex items-center justify-between gap-3\">\n <Button variant=\"ghost\" disabled={!strokes.length || busy} onClick={() => setStrokes([])}>\n <Eraser className=\"size-4\" /> {t(\"sign.clear\")}\n </Button>\n <Button busy={busy} disabled={!strokes.length} onClick={() => void accept()}>\n {t(\"sign.accept\")}\n </Button>\n </div>\n </Dialog>\n </div>\n );\n}\n","import type { Format } from \"@engenty/wizards-shared/definition\";\nimport { formatTableCell, type TableColumn } from \"@engenty/wizards-shared/engenty/data-tables\";\nimport { formatBytes } from \"@engenty/wizards-shared/numbers\";\nimport type { ShownList } from \"@engenty/wizards-shared/run\";\nimport {\n type ConnectionView,\n type ConnectorOption,\n cellValue,\n type StoreFile,\n} from \"@engenty/wizards-shared/store\";\nimport { Check, Database, FileText, Link2, Plus, Trash2, Unplug } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { ApiError } from \"./api.js\";\nimport { api, appCall, appCan, runBase, withBase } from \"./env.js\";\nimport { lang, t } from \"./i18n.js\";\nimport { Button, cn, Dialog, IconButton, Input, Label, Spinner } from \"./ui.js\";\n\n// --- connecting an account -------------------------------------------------------\n\nfunction CredentialsForm({\n runId,\n connectionId,\n connector,\n onCancel,\n}: {\n runId: string;\n connectionId: string;\n connector: ConnectorOption;\n onCancel: () => void;\n}) {\n const [values, setValues] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const submit = async () => {\n setBusy(true);\n setError(null);\n try {\n await api.post(`${runBase(runId)}/connections/${connectionId}/credentials/${connector.id}`, {\n values,\n });\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n return (\n <div className=\"flex flex-col gap-3 rounded-xl bg-card p-4 ring-1 ring-input\">\n {(connector.fields ?? []).map((f) => (\n <div key={f.key}>\n <Label>{f.label}</Label>\n <Input\n type={f.secret ? \"password\" : \"text\"}\n autoComplete=\"off\"\n value={values[f.key] ?? \"\"}\n placeholder={f.placeholder}\n onChange={(e) => setValues((v) => ({ ...v, [f.key]: e.target.value }))}\n onKeyDown={(e) => {\n // Enter connects; it must not submit the wizard page around this form.\n if (e.key === \"Enter\") {\n e.preventDefault();\n void submit();\n }\n }}\n />\n </div>\n ))}\n {connector.hint ? <p className=\"text-[0.8125rem] text-ink-3\">{connector.hint}</p> : null}\n {error ? <p className=\"text-[0.8125rem] text-rose\">{error}</p> : null}\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {t(\"common.cancel\")}\n </Button>\n <Button size=\"sm\" busy={busy} onClick={() => void submit()}>\n {t(\"connect.go\")}\n </Button>\n </div>\n </div>\n );\n}\n\n/** The person connects an account (their mailbox) to the wizard, or sees which one is connected. */\nexport function ConnectionField({\n runId,\n connection,\n}: {\n runId: string;\n connection: ConnectionView | undefined;\n}) {\n const [form, setForm] = useState<string | null>(null);\n const [link, setLink] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n if (!connection) {\n return null;\n }\n if (connection.account) {\n const name =\n connection.connectors.find((c) => c.id === connection.account?.connector)?.name ?? \"\";\n return (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-3 ring-1 ring-input\">\n <div className=\"flex size-10 items-center justify-center rounded-full bg-moss-tint text-moss\">\n <Check className=\"size-5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate font-medium text-[0.9375rem]\">{connection.account.label}</div>\n <div className=\"text-[0.8125rem] text-ink-3\">{t(\"connect.connected\", { name })}</div>\n </div>\n <IconButton\n label={t(\"connect.disconnect\")}\n onClick={() => void api.del(`${runBase(runId)}/connections/${connection.id}`)}\n >\n <Unplug className=\"size-4\" />\n </IconButton>\n </div>\n );\n }\n const oauth = async (connector: ConnectorOption) => {\n setError(null);\n setLink(null);\n if (appCan(\"signIn\")) {\n // The app opens the system's sign-in sheet: Google refuses a sign-in inside a WebView.\n // The run's stream says when the account is connected, as with the popup.\n try {\n const { url } = await api.post<{ url: string }>(\n `${runBase(runId)}/connections/${connection.id}/oauth/${connector.id}`,\n );\n await appCall(\"signIn\", { url });\n } catch (err) {\n setError((err as Error).message);\n }\n return;\n }\n // Opened inside the click, before the address is known: a popup opened later is blocked.\n const popup = window.open(\"about:blank\", \"wizard-connect\", \"width=540,height=700\");\n try {\n const { url } = await api.post<{ url: string }>(\n `${runBase(runId)}/connections/${connection.id}/oauth/${connector.id}`,\n );\n if (popup) {\n popup.location.replace(url);\n } else {\n setLink(url);\n }\n } catch (err) {\n popup?.close();\n setError((err as Error).message);\n }\n };\n const open = connection.connectors.find((c) => c.id === form);\n if (!connection.connectors.length) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"connect.none\")}</p>;\n }\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex flex-wrap gap-2\">\n {connection.connectors.map((c) => (\n <button\n key={c.id}\n type=\"button\"\n onClick={() =>\n c.auth === \"oauth2\" ? void oauth(c) : setForm(form === c.id ? null : c.id)\n }\n className={cn(\n \"inline-flex h-11 items-center gap-2 rounded-full px-4 font-medium text-[0.875rem] ring-1 transition\",\n form === c.id\n ? \"bg-ember-veil text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink hover:ring-ember\",\n )}\n >\n <Link2 className=\"size-4\" /> {c.name}\n </button>\n ))}\n </div>\n {open ? (\n <CredentialsForm\n runId={runId}\n connectionId={connection.id}\n connector={open}\n onCancel={() => setForm(null)}\n />\n ) : null}\n {link ? (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"text-[0.875rem] text-ember underline\"\n >\n {t(\"connect.openLink\")}\n </a>\n ) : null}\n {error ? <p className=\"text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n );\n}\n\n// --- lists ---------------------------------------------------------------------\n\n/** A cell's value as the text its input shows. */\nfunction inputText(value: unknown): string {\n return value === null || value === undefined\n ? \"\"\n : Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n}\n\nfunction CellInput({\n column,\n value,\n boxed,\n onCommit,\n}: {\n column: TableColumn;\n value: unknown;\n /** On a card (phone) the input shows its own ground; in the table the cell is the frame. */\n boxed?: boolean;\n onCommit: (value: unknown) => void;\n}) {\n const [text, setText] = useState(inputText(value));\n useEffect(() => setText(inputText(value)), [value]);\n const base = cn(\n \"w-full min-w-0 rounded-md border border-transparent px-2 text-[0.8125rem] outline-none focus:border-ember focus:bg-card\",\n boxed ? \"h-11 bg-paper-2\" : \"h-9 bg-transparent hover:bg-paper-2 coarse:h-11\",\n );\n if (column.type === \"boolean\") {\n return (\n // The box stays small; the label around it is the full touch target.\n <label className=\"flex size-9 cursor-pointer items-center justify-center coarse:size-11\">\n <input\n type=\"checkbox\"\n aria-label={column.name}\n checked={value === true}\n onChange={(e) => onCommit(e.target.checked)}\n className=\"size-4 accent-[var(--ember)] coarse:size-6\"\n />\n </label>\n );\n }\n if (column.type === \"select\" && !column.format.multiple && !column.format.allowCustom) {\n return (\n <select value={text} onChange={(e) => onCommit(e.target.value || null)} className={base}>\n <option value=\"\" />\n {column.format.options.map((o) => (\n <option key={o.id} value={o.id}>\n {o.label}\n </option>\n ))}\n </select>\n );\n }\n const commit = () => {\n if (text !== inputText(value)) {\n onCommit(cellValue(column, text));\n }\n };\n return (\n <input\n aria-label={column.name}\n type={column.type === \"date\" && column.format.kind === \"date\" ? \"date\" : \"text\"}\n inputMode={column.type === \"number\" ? \"decimal\" : undefined}\n enterKeyHint=\"done\"\n autoComplete=\"off\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={commit}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n (e.target as HTMLInputElement).blur();\n }\n }}\n className={cn(base, column.type === \"number\" && \"text-right tabular-nums\")}\n />\n );\n}\n\n/** One of the wizard's stored lists: read, or edited in place by the person it belongs to. */\nexport function ListTable({\n runId,\n list,\n editable,\n}: {\n runId: string;\n list: ShownList;\n editable?: boolean;\n}) {\n const { def, rows } = list;\n const [error, setError] = useState<string | null>(null);\n const [draft, setDraft] = useState<Record<string, unknown>>({});\n const base = `${runBase(runId)}/lists/${def.id}/rows`;\n const call = async (run: () => Promise<unknown>) => {\n setError(null);\n try {\n await run();\n } catch (err) {\n setError(err instanceof ApiError ? err.message : String(err));\n }\n };\n const addRow = () =>\n call(async () => {\n await api.post(base, { cells: draft });\n setDraft({});\n });\n const hasDraft = Object.values(draft).some((v) => v !== null && v !== undefined && v !== \"\");\n if (!rows.length && !editable) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"list.empty\")}</p>;\n }\n const wide = (c: TableColumn, i: number) =>\n i === 0 || (c.type === \"text\" && c.format?.style === \"multiline\");\n const commitCell = (rowId: string, columnId: string, value: unknown) =>\n void call(() => api.patch(`${base}/${rowId}`, { cells: { [columnId]: value } }));\n return (\n <div>\n {/* A phone shows each row as a card of labelled cells; a table would scroll sideways. */}\n <div className=\"flex flex-col gap-2 sm:hidden\">\n {rows.map((row) => (\n <div key={row.id} className=\"rounded-lg bg-paper p-2 ring-1 ring-border-soft\">\n <div className=\"grid grid-cols-2 gap-x-2 gap-y-1.5\">\n {def.columns.map((c, i) => (\n <div key={c.id} className={cn(\"min-w-0\", wide(c, i) && \"col-span-2\")}>\n <div className=\"px-1 pb-0.5 text-[0.6875rem] text-ink-3\">{c.name}</div>\n {editable ? (\n <CellInput\n boxed\n column={c}\n value={row.cells[c.id]}\n onCommit={(value) => commitCell(row.id, c.id, value)}\n />\n ) : (\n <div\n className={cn(\n \"break-words px-1 text-[0.875rem]\",\n c.type === \"number\" && \"tabular-nums\",\n )}\n >\n {formatTableCell(c, row.cells[c.id], lang) || \"—\"}\n </div>\n )}\n </div>\n ))}\n </div>\n {editable ? (\n <div className=\"mt-1 flex justify-end\">\n <IconButton\n label={t(\"list.delete\")}\n onClick={() => void call(() => api.del(`${base}/${row.id}`))}\n >\n <Trash2 className=\"size-4\" />\n </IconButton>\n </div>\n ) : null}\n </div>\n ))}\n {editable ? (\n <div className=\"rounded-lg border border-input border-dashed p-2\">\n <div className=\"grid grid-cols-2 gap-x-2 gap-y-1.5\">\n {def.columns.map((c, i) => (\n <div key={c.id} className={cn(\"min-w-0\", wide(c, i) && \"col-span-2\")}>\n <div className=\"px-1 pb-0.5 text-[0.6875rem] text-ink-3\">{c.name}</div>\n <CellInput\n boxed\n column={c}\n value={draft[c.id]}\n onCommit={(value) => setDraft((d) => ({ ...d, [c.id]: value }))}\n />\n </div>\n ))}\n </div>\n <div className=\"mt-2 flex justify-end\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n // The cell being typed in commits on blur, just before this click lands.\n onClick={() => (hasDraft ? void addRow() : undefined)}\n >\n <Plus className=\"size-4\" /> {t(\"run.addRow\")}\n </Button>\n </div>\n </div>\n ) : null}\n </div>\n <div className=\"hidden overflow-x-auto rounded-lg ring-1 ring-border-soft sm:block\">\n <table className=\"w-full text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {def.columns.map((c) => (\n <th key={c.id} className=\"whitespace-nowrap px-3 py-2 text-left font-medium\">\n {c.name}\n </th>\n ))}\n {editable ? <th className=\"w-10\" /> : null}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.id} className=\"border-border-soft border-t align-top\">\n {def.columns.map((c) => (\n <td\n key={c.id}\n className={cn(\"min-w-[7.5rem]\", editable ? \"px-1 py-0.5\" : \"px-3 py-2\")}\n >\n {editable ? (\n <CellInput\n column={c}\n value={row.cells[c.id]}\n onCommit={(value) => commitCell(row.id, c.id, value)}\n />\n ) : (\n <span className={cn(c.type === \"number\" && \"tabular-nums\")}>\n {formatTableCell(c, row.cells[c.id], lang)}\n </span>\n )}\n </td>\n ))}\n {editable ? (\n <td className=\"px-1 py-0.5\">\n <IconButton\n label={t(\"list.delete\")}\n className=\"size-9\"\n onClick={() => void call(() => api.del(`${base}/${row.id}`))}\n >\n <Trash2 className=\"size-3.5\" />\n </IconButton>\n </td>\n ) : null}\n </tr>\n ))}\n {editable ? (\n <tr className=\"border-border-soft border-t bg-paper\">\n {def.columns.map((c) => (\n <td key={c.id} className=\"px-1 py-0.5\">\n <CellInput\n column={c}\n value={draft[c.id]}\n onCommit={(value) => setDraft((d) => ({ ...d, [c.id]: value }))}\n />\n </td>\n ))}\n <td className=\"px-1 py-0.5\">\n <IconButton\n label={t(\"run.addRow\")}\n className=\"size-9\"\n onClick={() => (hasDraft ? void addRow() : undefined)}\n >\n <Plus className=\"size-4\" />\n </IconButton>\n </td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n {error ? <p className=\"mt-2 text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n );\n}\n\n/** The path of a kept file as its address: shown in place for PDFs and photos. */\nfunction storeFileUrl(runId: string, path: string, inline: boolean): string {\n const safe = path.split(\"/\").map(encodeURIComponent).join(\"/\");\n return withBase(`${runBase(runId)}/store/files/${safe}${inline ? \"?inline=1\" : \"\"}`);\n}\n\nconst ANSWER_TONE = [\n \"bg-paper-3 text-ink-3\",\n \"bg-moss-tint text-moss\",\n \"bg-rose-tint text-rose\",\n \"bg-ember-tint text-ember-strong\",\n];\n\n/**\n * A list the person goes through row by row: the rows on the left, the row's kept file and its\n * cells on the right, and the answers of the list's status column as buttons. An answer saves\n * and moves on to the next open row.\n */\nexport function ListCheck({ runId, list }: { runId: string; list: ShownList }) {\n const { def, rows } = list;\n const fileColumn = def.columns.find((c) => c.id === def.check?.file);\n const statusColumn = def.columns.find((c) => c.id === def.check?.status);\n const answers = statusColumn?.type === \"select\" ? statusColumn.format.options : [];\n const openId = answers[0]?.id;\n const statusOf = (row: ShownList[\"rows\"][number]) =>\n statusColumn ? String(row.cells[statusColumn.id] ?? openId ?? \"\") : \"\";\n const isOpen = (row: ShownList[\"rows\"][number]) => !statusColumn || statusOf(row) === openId;\n const [selected, setSelected] = useState<string | null>(\n () => (rows.find(isOpen) ?? rows[0])?.id ?? null,\n );\n const [onlyOpen, setOnlyOpen] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const base = `${runBase(runId)}/lists/${def.id}/rows`;\n const current = rows.find((r) => r.id === selected) ?? rows[0];\n const shown = onlyOpen ? rows.filter((r) => isOpen(r) || r.id === current?.id) : rows;\n const done = rows.filter((r) => !isOpen(r)).length;\n const labelled = def.columns.filter((c) => c !== fileColumn && c !== statusColumn);\n // A row is named by its first text cell; the next two cells (a date, an amount) stand below.\n const named = labelled.filter((c) => c.id !== def.key);\n const titleColumn = named.find((c) => c.type === \"text\") ?? named[0];\n const restColumns = named.filter((c) => c !== titleColumn);\n const patch = async (rowId: string, cells: Record<string, unknown>) => {\n setError(null);\n try {\n await api.patch(`${base}/${rowId}`, { cells });\n } catch (err) {\n setError(err instanceof ApiError ? err.message : String(err));\n }\n };\n const move = (step: number) => {\n const at = shown.findIndex((r) => r.id === current?.id);\n const next = shown[Math.min(shown.length - 1, Math.max(0, at + step))];\n if (next) {\n setSelected(next.id);\n }\n };\n const answer = async (id: string) => {\n if (!current || !statusColumn) {\n return;\n }\n const at = rows.findIndex((r) => r.id === current.id);\n // The next row still open, looking onward from this one and then from the top.\n const next = [...rows.slice(at + 1), ...rows.slice(0, at)].find(isOpen);\n await patch(current.id, { [statusColumn.id]: id });\n if (next && id !== openId) {\n setSelected(next.id);\n }\n };\n // Arrow keys walk the list and digits answer, as long as nobody is typing in a cell.\n const keys = (e: React.KeyboardEvent) => {\n if ((e.target as HTMLElement).closest(\"input, textarea, select\")) {\n return;\n }\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n move(e.key === \"ArrowDown\" ? 1 : -1);\n } else if (/^[1-9]$/.test(e.key) && answers[Number(e.key)]) {\n e.preventDefault();\n void answer(answers[Number(e.key)].id);\n }\n };\n if (!rows.length) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"list.empty\")}</p>;\n }\n const path = fileColumn && current ? String(current.cells[fileColumn.id] ?? \"\").trim() : \"\";\n const ext = path.split(\".\").pop()?.toLowerCase() ?? \"\";\n const tone = (row: ShownList[\"rows\"][number]) =>\n ANSWER_TONE[\n Math.min(\n Math.max(\n 0,\n answers.findIndex((a) => a.id === statusOf(row)),\n ),\n 3,\n )\n ];\n return (\n <div className=\"grid gap-4 lg:grid-cols-[minmax(280px,360px)_minmax(0,1fr)]\" onKeyDown={keys}>\n <div className=\"flex min-h-0 flex-col\">\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <span className=\"text-[0.8125rem] text-ink-3 tabular-nums\">\n {t(\"check.progress\", { done, total: rows.length })}\n </span>\n {statusColumn ? (\n <button\n type=\"button\"\n aria-pressed={onlyOpen}\n onClick={() => setOnlyOpen((v) => !v)}\n className={cn(\n \"inline-flex h-8 items-center rounded-full px-3 text-[0.8125rem] ring-1 transition coarse:h-11\",\n onlyOpen\n ? \"bg-ember-tint text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink\",\n )}\n >\n {t(\"check.onlyOpen\")}\n </button>\n ) : null}\n </div>\n <ul className=\"flex max-h-[38vh] flex-col gap-1.5 overflow-y-auto p-0.5 pr-1 lg:max-h-[calc(100vh-15rem)]\">\n {shown.map((row) => (\n <li key={row.id}>\n <button\n type=\"button\"\n onClick={() => setSelected(row.id)}\n aria-current={row.id === current?.id}\n className={cn(\n \"flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-left ring-1 transition\",\n row.id === current?.id\n ? \"bg-card shadow-soft ring-ember\"\n : \"bg-paper ring-border-soft hover:bg-card\",\n )}\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium text-[0.875rem]\">\n {(titleColumn &&\n formatTableCell(titleColumn, row.cells[titleColumn.id], lang)) ||\n \"—\"}\n </span>\n <span className=\"block truncate text-[0.75rem] text-ink-3 tabular-nums\">\n {restColumns\n .slice(0, 2)\n .map((c) => formatTableCell(c, row.cells[c.id], lang))\n .filter(Boolean)\n .join(\" · \")}\n </span>\n </span>\n {statusColumn ? (\n <span\n className={cn(\n \"shrink-0 rounded-full px-2 py-0.5 font-medium text-[0.6875rem]\",\n tone(row),\n )}\n >\n {answers.find((a) => a.id === statusOf(row))?.label ?? statusOf(row)}\n </span>\n ) : null}\n </button>\n </li>\n ))}\n </ul>\n </div>\n {current ? (\n <div className=\"flex min-w-0 flex-col gap-3\">\n {answers.length > 1 ? (\n <div className=\"flex flex-wrap gap-2\">\n {answers.slice(1).map((a, i) => (\n <Button\n key={a.id}\n size=\"md\"\n variant={statusOf(current) === a.id ? \"primary\" : \"secondary\"}\n onClick={() => void answer(a.id)}\n >\n {statusOf(current) === a.id ? <Check className=\"size-4\" /> : null}\n {a.label}\n <kbd className=\"ml-1 hidden rounded bg-black/10 px-1.5 text-[0.6875rem] lg:inline\">\n {i + 1}\n </kbd>\n </Button>\n ))}\n {statusOf(current) !== openId ? (\n <Button size=\"md\" variant=\"ghost\" onClick={() => void answer(openId ?? \"\")}>\n {t(\"check.reopen\")}\n </Button>\n ) : null}\n </div>\n ) : null}\n <div className=\"overflow-hidden rounded-lg bg-paper-2 ring-1 ring-border-soft\">\n {path ? (\n <>\n <div className=\"flex items-center gap-2 border-border-soft border-b bg-card px-3 py-2 text-[0.8125rem]\">\n <FileText className=\"size-3.5 shrink-0 text-ink-3\" />\n <span className=\"min-w-0 flex-1 truncate\">{path.split(\"/\").pop()}</span>\n <a\n href={storeFileUrl(runId, path, ext === \"pdf\")}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"shrink-0 text-ink-2 underline-offset-2 hover:text-ink hover:underline\"\n >\n {t(\"run.openFull\")}\n </a>\n </div>\n {ext === \"pdf\" ? (\n <iframe\n key={path}\n title={path}\n src={`${storeFileUrl(runId, path, true)}#toolbar=0&navpanes=0&view=FitH`}\n className=\"h-[46vh] w-full border-0 bg-white lg:h-[calc(100vh-27rem)] lg:min-h-[360px]\"\n />\n ) : [\"png\", \"jpg\", \"jpeg\", \"webp\"].includes(ext) ? (\n <div className=\"flex max-h-[46vh] justify-center overflow-auto bg-white lg:max-h-[calc(100vh-27rem)]\">\n <img\n key={path}\n src={storeFileUrl(runId, path, true)}\n alt={path}\n className=\"max-w-full object-contain\"\n />\n </div>\n ) : (\n <p className=\"px-4 py-10 text-center text-[0.875rem] text-ink-3\">\n {t(\"check.noPreview\")}\n </p>\n )}\n </>\n ) : (\n <p className=\"px-4 py-14 text-center text-[0.875rem] text-ink-3\">\n {t(\"check.noFile\")}\n </p>\n )}\n </div>\n <div className=\"grid grid-cols-2 gap-x-3 gap-y-2 sm:grid-cols-3\">\n {labelled.map((c) => (\n <div\n key={c.id}\n className={cn(\n \"min-w-0\",\n c.type === \"text\" && c.format?.style === \"multiline\" && \"col-span-full\",\n )}\n >\n <div className=\"px-1 pb-0.5 text-[0.6875rem] text-ink-3\">{c.name}</div>\n <CellInput\n boxed\n column={c}\n value={current.cells[c.id]}\n onCommit={(value) => void patch(current.id, { [c.id]: value })}\n />\n </div>\n ))}\n </div>\n {error ? <p className=\"text-[0.8125rem] text-rose\">{error}</p> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nconst LIST_FORMAT_LABEL: Partial<Record<Format, string>> = {\n xlsx: \"Excel\",\n csv: \"CSV\",\n json: \"JSON\",\n md: \"Markdown\",\n zip: \"ZIP\",\n};\n\nexport function ListDownloads({ runId, list }: { runId: string; list: ShownList }) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {list.formats.map((f) => (\n <a\n key={f}\n href={withBase(`${runBase(runId)}/lists/${list.def.id}/download?format=${f}`)}\n className=\"inline-flex h-9 items-center rounded-full bg-paper-2 px-3.5 font-medium text-[0.8125rem] text-ink-2 transition hover:bg-paper-3 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n {LIST_FORMAT_LABEL[f] ?? f}\n </a>\n ))}\n </div>\n );\n}\n\n// --- what the wizard keeps -------------------------------------------------------\n\ninterface StoreSummary {\n lists: { id: string; title: string; rows: number }[];\n files: StoreFile[];\n connections: ConnectionView[];\n keepsSignIns: boolean;\n}\n\n/** Everything the wizard keeps for this person between runs, and the way to delete it. */\nexport function StoreButton({ runId }: { runId: string }) {\n const [open, setOpen] = useState(false);\n const [data, setData] = useState<StoreSummary | null>(null);\n const [confirm, setConfirm] = useState(false);\n useEffect(() => {\n if (open) {\n setConfirm(false);\n void api.get<StoreSummary>(`${runBase(runId)}/store`).then(setData);\n }\n }, [open, runId]);\n const empty =\n data &&\n !data.files.length &&\n !data.connections.length &&\n !data.keepsSignIns &&\n data.lists.every((l) => !l.rows);\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"inline-flex items-center gap-1.5 text-[0.8125rem] text-ink-4 transition hover:text-ink-2 coarse:min-h-11\"\n >\n <Database className=\"size-3.5\" /> {t(\"store.open\")}\n </button>\n <Dialog open={open} onClose={() => setOpen(false)} title={t(\"store.title\")} wide>\n {!data ? (\n <div className=\"flex justify-center py-8 text-ink-4\">\n <Spinner />\n </div>\n ) : (\n <div className=\"flex flex-col gap-5 text-[0.875rem]\">\n <p className=\"text-ink-3\">{t(\"store.explain\")}</p>\n {empty ? <p className=\"text-ink-2\">{t(\"store.empty\")}</p> : null}\n {data.lists.some((l) => l.rows) ? (\n <ul className=\"flex flex-col gap-1\">\n {data.lists\n .filter((l) => l.rows)\n .map((l) => (\n <li key={l.id} className=\"flex justify-between gap-3\">\n <span>{l.title}</span>\n <span className=\"text-ink-3 tabular-nums\">\n {t(\"store.rows\", { n: l.rows })}\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n {data.connections.map((c) => (\n <div key={c.id} className=\"flex items-center gap-2\">\n <Link2 className=\"size-4 text-ink-3\" /> {c.account?.label}\n </div>\n ))}\n {data.keepsSignIns ? (\n <div className=\"flex items-center gap-2\">\n <Check className=\"size-4 text-ink-3\" /> {t(\"store.signIns\")}\n </div>\n ) : null}\n {data.files.length ? (\n <div>\n <div className=\"mb-1 text-ink-3\">\n {t(\"store.files\", {\n n: data.files.length,\n size: formatBytes(data.files.reduce((n, f) => n + f.size, 0)),\n })}\n </div>\n <ul className=\"max-h-56 overflow-y-auto rounded-lg ring-1 ring-border-soft\">\n {data.files.map((f) => (\n <li key={f.path} className=\"border-border-soft border-b last:border-0\">\n <a\n href={withBase(`${runBase(runId)}/store/files/${f.path}`)}\n className=\"flex items-center gap-2 px-3 py-2 text-[0.8125rem] hover:bg-paper-2 coarse:min-h-11\"\n title={f.source ?? undefined}\n >\n <FileText className=\"size-3.5 shrink-0 text-ink-3\" />\n <span className=\"min-w-0 flex-1 truncate\">{f.path}</span>\n <span className=\"text-ink-4 tabular-nums\">{formatBytes(f.size)}</span>\n </a>\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n <div className=\"flex items-center justify-between gap-3 pt-1\">\n {empty ? (\n <span />\n ) : confirm ? (\n <Button\n variant=\"secondary\"\n onClick={async () => {\n await api.del(`${runBase(runId)}/store`);\n setData(await api.get<StoreSummary>(`${runBase(runId)}/store`));\n setConfirm(false);\n }}\n >\n <Trash2 className=\"size-4\" /> {t(\"store.confirmDelete\")}\n </Button>\n ) : (\n <Button variant=\"ghost\" onClick={() => setConfirm(true)}>\n <Trash2 className=\"size-4\" /> {t(\"store.delete\")}\n </Button>\n )}\n <Button onClick={() => setOpen(false)}>{t(\"common.close\")}</Button>\n </div>\n </div>\n )}\n </Dialog>\n </>\n );\n}\n","import { type AudioValue, isAudioValue } from \"@engenty/wizards-shared/definition\";\nimport { FileAudio, Mic, RotateCcw, Square } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { stamp } from \"./camera\";\nimport { canUseMedia } from \"./device\";\nimport { api, appCall, appCan, runBase, runnerEnv } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { Button, Spinner } from \"./ui.js\";\n\nconst MAX_SECONDS = 300;\n\nfunction recordingType(): string | undefined {\n if (typeof MediaRecorder === \"undefined\") {\n return undefined;\n }\n // A phone that writes the note down itself reads AAC in an .m4a, not WebM or Ogg.\n const types = appCan(\"transcribe\")\n ? [\"audio/mp4\", \"audio/webm;codecs=opus\", \"audio/webm\", \"audio/ogg;codecs=opus\"]\n : [\"audio/webm;codecs=opus\", \"audio/mp4\", \"audio/webm\", \"audio/ogg;codecs=opus\"];\n return types.find((type) => MediaRecorder.isTypeSupported(type));\n}\n\n/** A recording written down by the app on the phone; undefined when the app cannot. */\nasync function transcribeOnDevice(file: Blob, lang: string): Promise<string | undefined> {\n if (!appCan(\"transcribe\")) {\n return undefined;\n }\n try {\n const audio = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result).split(\",\")[1] ?? \"\");\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n const result = await appCall<{ text: string } | null>(\"transcribe\", {\n audio,\n mime: file.type,\n lang,\n });\n return typeof result?.text === \"string\" ? result.text : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction clock(seconds: number): string {\n return `${Math.floor(seconds / 60)}:${String(Math.floor(seconds % 60)).padStart(2, \"0\")}`;\n}\n\n/**\n * A voice note: recorded here with the microphone, or — where the browser cannot record — an\n * audio file from the phone's recorder. The recording is kept as an upload; what is said in it\n * is written down on the server before the next step reads it.\n */\nexport function VoiceField({\n value,\n runId,\n onChange,\n onBusy,\n}: {\n value: unknown;\n runId: string;\n onChange: (v: AudioValue | undefined) => void;\n onBusy?: (busy: boolean) => void;\n}) {\n const note = isAudioValue(value) ? value : null;\n const [seconds, setSeconds] = useState<number | null>(null);\n const [level, setLevel] = useState(0);\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [denied, setDenied] = useState(false);\n // What was just recorded plays from memory; a note from an earlier visit plays from the server.\n const [local, setLocal] = useState<{ asset: string; url: string } | null>(null);\n const session = useRef<{ recorder: MediaRecorder; stop: () => void } | null>(null);\n const picker = useRef<HTMLInputElement>(null);\n const type = recordingType();\n const canRecord = canUseMedia && Boolean(type);\n\n useEffect(\n () => () => {\n // Leaving the page mid-recording keeps nothing and frees the microphone.\n if (session.current) {\n session.current.recorder.onstop = null;\n session.current.stop();\n }\n },\n [],\n );\n useEffect(\n () => () => {\n if (local) {\n URL.revokeObjectURL(local.url);\n }\n },\n [local],\n );\n\n const keep = async (file: File, length: number | undefined) => {\n setUploading(true);\n onBusy?.(true);\n setError(null);\n try {\n const ref = await api.upload<{ id: string }>(`${runBase(runId)}/uploads`, file);\n setLocal({ asset: ref.id, url: URL.createObjectURL(file) });\n // In the app the phone writes the note down itself; else the server does before the next step.\n const { lang } = runnerEnv();\n const transcript = await transcribeOnDevice(file, lang);\n onChange({\n asset: ref.id,\n lang,\n ...(length !== undefined ? { seconds: length } : {}),\n ...(transcript !== undefined ? { transcript } : {}),\n });\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setUploading(false);\n onBusy?.(false);\n }\n };\n\n const start = async () => {\n setError(null);\n setDenied(false);\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getUserMedia({\n audio: { echoCancellation: true, noiseSuppression: true },\n });\n } catch {\n setDenied(true);\n return;\n }\n const chunks: Blob[] = [];\n const recorder = new MediaRecorder(stream, { mimeType: type, audioBitsPerSecond: 48_000 });\n const began = Date.now();\n // The level bar shows the microphone hears something.\n const ctx = new AudioContext();\n const analyser = ctx.createAnalyser();\n analyser.fftSize = 256;\n ctx.createMediaStreamSource(stream).connect(analyser);\n const samples = new Uint8Array(analyser.fftSize);\n let frame = 0;\n const meter = () => {\n analyser.getByteTimeDomainData(samples);\n let peak = 0;\n for (const s of samples) {\n peak = Math.max(peak, Math.abs(s - 128));\n }\n setLevel(Math.min(1, peak / 64));\n setSeconds((Date.now() - began) / 1000);\n if ((Date.now() - began) / 1000 >= MAX_SECONDS) {\n stop();\n return;\n }\n frame = requestAnimationFrame(meter);\n };\n const stop = () => {\n cancelAnimationFrame(frame);\n if (recorder.state !== \"inactive\") {\n recorder.stop();\n }\n for (const track of stream.getTracks()) {\n track.stop();\n }\n void ctx.close().catch(() => undefined);\n session.current = null;\n setSeconds(null);\n setLevel(0);\n };\n recorder.ondataavailable = (e) => e.data.size && chunks.push(e.data);\n recorder.onstop = () => {\n const mime = (recorder.mimeType || type || \"audio/webm\").split(\";\")[0];\n const ext = mime === \"audio/mp4\" ? \"m4a\" : mime === \"audio/ogg\" ? \"ogg\" : \"webm\";\n const length = Math.max(1, Math.round((Date.now() - began) / 1000));\n void keep(new File(chunks, `sprachnotiz-${stamp()}.${ext}`, { type: mime }), length);\n };\n session.current = { recorder, stop };\n onBusy?.(true);\n recorder.start(1000);\n frame = requestAnimationFrame(meter);\n };\n\n const recording = seconds !== null;\n const fileButton = (\n <Button variant=\"secondary\" onClick={() => picker.current?.click()}>\n <FileAudio className=\"size-4\" /> {t(\"voice.pick\")}\n </Button>\n );\n\n return (\n <div>\n {recording ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-3 ring-1 ring-ember\">\n <span className=\"relative flex size-11 shrink-0 items-center justify-center\">\n <span\n className=\"absolute inset-0 rounded-full bg-rose-tint transition-transform duration-75\"\n style={{ transform: `scale(${0.7 + level * 0.5})` }}\n />\n <span className=\"relative size-3.5 animate-pulse-dot rounded-full bg-rose\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-medium text-[0.9375rem] tabular-nums\">{clock(seconds)}</div>\n <div className=\"text-[0.8125rem] text-ink-3\">\n {seconds > MAX_SECONDS - 30\n ? t(\"voice.left\", { s: Math.ceil(MAX_SECONDS - seconds) })\n : t(\"voice.recording\")}\n </div>\n </div>\n <Button onClick={() => session.current?.stop()}>\n <Square className=\"size-3.5 fill-current\" /> {t(\"voice.stop\")}\n </Button>\n </div>\n ) : uploading ? (\n <div className=\"flex items-center gap-3 rounded-xl bg-card p-4 text-[0.875rem] text-ink-3 ring-1 ring-input\">\n <Spinner className=\"size-4\" /> {t(\"run.uploading\")}\n </div>\n ) : note ? (\n <div className=\"rounded-xl bg-card p-3 ring-1 ring-input\">\n {/* biome-ignore lint/a11y/useMediaCaption: the person's own voice note, just recorded */}\n <audio\n controls\n preload=\"metadata\"\n src={local?.asset === note.asset ? local.url : `${runBase(runId)}/assets/${note.asset}`}\n className=\"h-11 w-full\"\n />\n {note.transcript ? (\n <p className=\"mt-2 whitespace-pre-wrap px-1 text-[0.875rem] text-ink-2 leading-relaxed\">\n {note.transcript}\n </p>\n ) : null}\n <div className=\"mt-2 flex flex-wrap items-center justify-between gap-2\">\n <span className=\"px-1 text-[0.8125rem] text-ink-3\">\n {note.seconds ? clock(note.seconds) : null}\n </span>\n <div className=\"flex gap-1\">\n {canRecord ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void start()}>\n <RotateCcw className=\"size-3.5\" /> {t(\"voice.again\")}\n </Button>\n ) : null}\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onChange(undefined)}>\n {t(\"voice.remove\")}\n </Button>\n </div>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"flex flex-wrap gap-2\">\n {canRecord ? (\n <Button\n variant=\"secondary\"\n size=\"lg\"\n onClick={() => void start()}\n className=\"w-full sm:w-auto\"\n >\n <Mic className=\"size-4\" /> {t(\"voice.start\")}\n </Button>\n ) : (\n fileButton\n )}\n {canRecord && denied ? fileButton : null}\n </div>\n {denied ? (\n <p className=\"mt-2 rounded-lg bg-amber-tint px-3 py-2 text-[0.8125rem] text-ink-2 leading-relaxed\">\n {t(\"voice.denied\")}\n </p>\n ) : (\n <p className=\"mt-2 text-[0.8125rem] text-ink-3 leading-relaxed\">\n {t(canRecord ? \"voice.why\" : \"voice.noRecorder\")}\n </p>\n )}\n </div>\n )}\n <input\n ref={picker}\n type=\"file\"\n hidden\n accept=\"audio/*\"\n capture\n onChange={(e) => {\n const file = e.target.files?.[0];\n e.target.value = \"\";\n if (file) {\n void keep(file, undefined);\n }\n }}\n />\n {error ? <div className=\"mt-2 text-[0.8125rem] text-rose\">{error}</div> : null}\n </div>\n );\n}\n","import {\n type CardOption,\n type Field,\n itemsTotals,\n MAX_FILES,\n type ModelClass,\n slotDayText,\n slotTime,\n} from \"@engenty/wizards-shared/definition\";\nimport { formatMoney } from \"@engenty/wizards-shared/numbers\";\nimport type { ClosedChoice, RunView } from \"@engenty/wizards-shared/run\";\nimport {\n Camera,\n Film,\n GripVertical,\n ImagePlus,\n Paperclip,\n Plus,\n ScanLine,\n Trash2,\n Video,\n X,\n} from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { CameraDialog, canRecordClips, shrinkImage } from \"./camera\";\nimport { canUseMedia, isTouch } from \"./device\";\nimport { api, runBase, withBase } from \"./env.js\";\nimport { choiceLabel, lang, t } from \"./i18n.js\";\nimport { LocationField } from \"./location\";\nimport { ScanDialog } from \"./scan\";\nimport { SignatureField } from \"./signature\";\nimport { ConnectionField, ListTable } from \"./store\";\nimport { cn, IconButton, Input, Label, Segmented, Select, Swatch, Switch, Textarea } from \"./ui.js\";\nimport { VoiceField } from \"./voice\";\n\nexport type Values = Record<string, unknown>;\n\nfunction ItemsField({\n field,\n value,\n values,\n onChange,\n}: {\n field: Field;\n value: unknown;\n values: Values;\n onChange: (v: unknown) => void;\n}) {\n const cols = field.columns ?? [];\n const rows = (Array.isArray(value) && value.length ? value : [{}]) as Record<string, unknown>[];\n const totals = itemsTotals(field, rows, values);\n const set = (i: number, col: string, v: string) => {\n const next = rows.map((r, j) => (j === i ? { ...r, [col]: v } : r));\n onChange(next);\n };\n const grid = cols\n .map((c) => (c.kind === \"text\" && c === cols[0] ? \"minmax(0,3fr)\" : \"minmax(0,1fr)\"))\n .join(\" \");\n return (\n <div className=\"rounded-xl bg-card p-2 ring-1 ring-input\">\n <div\n className=\"hidden gap-2 px-2 pt-1 pb-2 text-[0.75rem] text-ink-3 sm:grid\"\n style={{ gridTemplateColumns: `${grid} 36px` }}\n >\n {cols.map((c) => (\n <div key={c.id} className={c.kind === \"text\" ? \"\" : \"text-right\"}>\n {c.label}\n </div>\n ))}\n </div>\n <div className=\"flex flex-col gap-2\">\n {rows.map((row, i) => (\n // A phone shows each row as a card: the first column across, the rest side by side\n // under their labels. From tablet width up it is one table row.\n <div\n key={i}\n className=\"grid grid-cols-6 gap-2 rounded-lg bg-paper p-2 sm:bg-transparent sm:p-0 sm:[grid-template-columns:var(--cols)]\"\n style={{ \"--cols\": `${grid} 36px` } as React.CSSProperties}\n >\n {cols.map((c, ci) => (\n <label\n key={c.id}\n className={cn(\n \"flex min-w-0 flex-col gap-1 sm:col-span-1\",\n ci === 0 ? \"col-span-5\" : cols.length - 1 <= 2 ? \"col-span-3\" : \"col-span-2\",\n )}\n >\n <span className=\"px-0.5 text-[0.6875rem] text-ink-3 sm:hidden\">{c.label}</span>\n <input\n aria-label={c.label}\n placeholder={c.label}\n inputMode={c.kind === \"text\" ? \"text\" : \"decimal\"}\n autoComplete=\"off\"\n value={String(row[c.id] ?? \"\")}\n onChange={(e) => set(i, c.id, e.target.value)}\n className={cn(\n \"h-11 w-full min-w-0 rounded-md border border-transparent bg-paper-2 px-2.5 text-[0.875rem] outline-none placeholder:text-transparent focus:border-focus focus:bg-card sm:placeholder:text-ink-4\",\n c.kind !== \"text\" && \"text-right tabular-nums\",\n )}\n />\n </label>\n ))}\n <IconButton\n label={t(\"list.delete\")}\n onClick={() => onChange(rows.filter((_, j) => j !== i))}\n className=\"order-first col-start-6 row-start-1 size-11 justify-self-end self-end sm:order-none sm:col-start-auto sm:row-start-auto\"\n >\n <Trash2 className=\"size-4\" />\n </IconButton>\n </div>\n ))}\n </div>\n <div className=\"mt-2 flex flex-wrap items-end justify-between gap-3 px-2 pb-1\">\n <button\n type=\"button\"\n onClick={() => onChange([...rows, {}])}\n className=\"inline-flex h-9 items-center gap-1.5 rounded-full px-3 text-[0.8125rem] text-ink-2 hover:bg-accent coarse:h-11\"\n >\n <Plus className=\"size-4\" /> {t(\"run.addRow\")}\n </button>\n <div className=\"text-right text-[0.8125rem] tabular-nums\">\n <div className=\"text-ink-3\">\n {t(\"run.net\")} {formatMoney(totals.net, totals.currency, lang)}\n </div>\n {totals.vatRate ? (\n <div className=\"text-ink-3\">\n {t(\"run.vat\", { r: totals.vatRate })} {formatMoney(totals.vat, totals.currency, lang)}\n </div>\n ) : null}\n <div className=\"font-semibold text-[0.9375rem] text-ink\">\n {t(\"run.total\")} {formatMoney(totals.gross, totals.currency, lang)}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/** Whether a paste belongs to typing somewhere rather than to an upload field. */\nfunction typingTarget(el: Element | null): boolean {\n return Boolean(el?.closest(\"input, textarea, [contenteditable='true']\"));\n}\n\nfunction UploadField({\n field,\n value,\n runId,\n onChange,\n onBusy,\n}: {\n field: Field;\n value: unknown;\n runId: string;\n onChange: (v: unknown) => void;\n onBusy?: (busy: boolean) => void;\n}) {\n const root = useRef<HTMLDivElement>(null);\n const picker = useRef<HTMLInputElement>(null);\n const nativeCamera = useRef<HTMLInputElement>(null);\n const nativeVideo = useRef<HTMLInputElement>(null);\n const [busy, setBusy] = useState(false);\n const [names, setNames] = useState<Record<string, { name: string; mime: string }>>({});\n const [error, setError] = useState<string | null>(null);\n const [camera, setCamera] = useState(false);\n const [over, setOver] = useState(false);\n // The file being dragged to another place in the list. The ref is what the pointer handlers\n // read: a move can arrive before the state has rendered.\n const [dragging, setDragging] = useState<string | null>(null);\n const drag = useRef<string | null>(null);\n const grab = (id: string | null) => {\n drag.current = id;\n setDragging(id);\n };\n const image = field.kind === \"image\";\n const multiple = Boolean(field.multiple);\n const most = multiple ? (field.max ?? MAX_FILES) : 1;\n const withCamera = image || Boolean(field.camera) || Boolean(field.video);\n const clips = !image && Boolean(field.video);\n const ids = Array.isArray(value)\n ? (value as string[])\n : typeof value === \"string\" && value\n ? [value]\n : [];\n // The list as it is now, not as it was when an upload started: several can finish in a row.\n const current = useRef(ids);\n current.current = ids;\n const room = ids.length < most;\n\n const add = async (files: File[]) => {\n // Several picked at once arrive in whatever order the file dialog likes; by name, pictures\n // from a camera are in the order they were taken.\n const wanted = (image ? files.filter((f) => f.type.startsWith(\"image/\")) : files).sort((a, b) =>\n a.name.localeCompare(b.name, undefined, { numeric: true }),\n );\n if (!wanted.length) {\n return;\n }\n const free = most - (multiple ? current.current.length : 0);\n setBusy(true);\n onBusy?.(true);\n setError(wanted.length > free && multiple ? t(\"run.maxFiles\", { n: most }) : null);\n try {\n for (const raw of wanted.slice(0, Math.max(0, free))) {\n const file = await shrinkImage(raw);\n const ref = await api.upload<{ id: string; name: string; mime: string }>(\n `${runBase(runId)}/uploads`,\n file,\n );\n setNames((n) => ({ ...n, [ref.id]: { name: ref.name, mime: ref.mime } }));\n const next = multiple ? [...current.current, ref.id] : ref.id;\n current.current = multiple ? (next as string[]) : [ref.id];\n onChange(next);\n }\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setBusy(false);\n onBusy?.(false);\n }\n };\n const adding = useRef(add);\n adding.current = add;\n const remove = (id: string) => {\n const left = ids.filter((x) => x !== id);\n onChange(multiple ? left : undefined);\n };\n // The order is part of the answer (the rooms of a tour, the pages of a document).\n const move = (id: string, to: number) => {\n const from = current.current.indexOf(id);\n const at = Math.min(current.current.length - 1, Math.max(0, to));\n if (from < 0 || from === at) {\n return;\n }\n const next = current.current.filter((x) => x !== id);\n next.splice(at, 0, id);\n current.current = next;\n onChange(next);\n };\n const sortable = multiple && ids.length > 1;\n\n // A screenshot or a copied picture is pasted straight in: into the field the pointer is on,\n // or the page's only upload field. Typing in a text field keeps its own paste.\n useEffect(() => {\n if (!room) {\n return;\n }\n const onPaste = (e: ClipboardEvent) => {\n const files = Array.from(e.clipboardData?.files ?? []);\n const el = root.current;\n if (!files.length || !el || typingTarget(document.activeElement)) {\n return;\n }\n const fields = document.querySelectorAll(\"[data-upload-field]\");\n if (el.matches(\":hover\") || el.contains(document.activeElement) || fields.length === 1) {\n e.preventDefault();\n void adding.current(files);\n }\n };\n document.addEventListener(\"paste\", onPaste);\n return () => document.removeEventListener(\"paste\", onPaste);\n }, [room]);\n\n const tile = cn(\n \"flex flex-col items-center justify-center gap-2 rounded-xl border border-input border-dashed bg-card px-3 text-[0.875rem] text-ink-3 transition hover:border-ember hover:text-ink\",\n ids.length ? \"py-4\" : \"py-8\",\n );\n return (\n <div\n ref={root}\n data-upload-field=\"\"\n onDragOver={(e) => {\n if (room) {\n e.preventDefault();\n setOver(true);\n }\n }}\n onDragLeave={() => setOver(false)}\n onDrop={(e) => {\n setOver(false);\n if (room) {\n e.preventDefault();\n void add(Array.from(e.dataTransfer.files));\n }\n }}\n >\n {ids.length ? (\n <div className=\"mb-2 flex flex-col gap-2\">\n {ids.map((id, index) => {\n const known = names[id];\n const mime = known?.mime ?? (image ? \"image/\" : \"\");\n return (\n <div\n key={id}\n data-file-id={id}\n className={cn(\n \"flex items-center gap-3 rounded-xl bg-card p-2 ring-1 ring-input transition-shadow\",\n dragging === id && \"relative z-10 shadow-elevated ring-2 ring-ember\",\n )}\n >\n {sortable ? (\n <button\n type=\"button\"\n aria-label={t(\"run.moveFile\", { n: index + 1 })}\n title={t(\"run.moveFileHint\")}\n className={cn(\n \"-mr-1 flex h-14 w-9 shrink-0 touch-none flex-col items-center justify-center gap-0.5 rounded-lg text-ink-3 hover:bg-paper-2 hover:text-ink\",\n dragging === id ? \"cursor-grabbing\" : \"cursor-grab\",\n )}\n onPointerDown={(e) => {\n try {\n e.currentTarget.setPointerCapture(e.pointerId);\n } catch {\n // Without capture the drag still works while the pointer stays on the list.\n }\n grab(id);\n }}\n onPointerMove={(e) => {\n if (drag.current !== id) {\n return;\n }\n // The row under the pointer gives its place to the one being dragged.\n const row = document\n .elementFromPoint(e.clientX, e.clientY)\n ?.closest(\"[data-file-id]\");\n const other = row?.getAttribute(\"data-file-id\");\n if (other && other !== id && root.current?.contains(row ?? null)) {\n move(id, current.current.indexOf(other));\n }\n }}\n onPointerUp={() => grab(null)}\n onPointerCancel={() => grab(null)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowUp\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n move(id, index + (e.key === \"ArrowUp\" ? -1 : 1));\n }\n }}\n >\n <span className=\"font-medium text-[0.75rem] tabular-nums\">{index + 1}</span>\n <GripVertical className=\"size-4\" />\n </button>\n ) : null}\n {mime.startsWith(\"image/\") ? (\n <img\n src={withBase(`${runBase(runId)}/assets/${id}`)}\n alt=\"\"\n className=\"size-14 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"flex size-12 shrink-0 items-center justify-center rounded-lg bg-paper-2\">\n {mime.startsWith(\"video/\") ? (\n <Film className=\"size-5 text-ink-3\" />\n ) : (\n <Paperclip className=\"size-5 text-ink-3\" />\n )}\n </div>\n )}\n <div className=\"min-w-0 flex-1 truncate text-[0.875rem]\">{known?.name ?? \"✓\"}</div>\n <IconButton label={t(\"run.removeFile\")} onClick={() => remove(id)}>\n <X className=\"size-4\" />\n </IconButton>\n </div>\n );\n })}\n </div>\n ) : null}\n {room ? (\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => picker.current?.click()}\n className={cn(tile, \"min-w-[9rem] flex-1 px-4\", over && \"border-ember text-ink\")}\n >\n {image ? <ImagePlus className=\"size-6\" /> : <Paperclip className=\"size-6\" />}\n {busy\n ? t(\"run.uploading\")\n : ids.length\n ? t(\"run.uploadMore\")\n : t(isTouch ? \"run.uploadTouch\" : \"run.upload\")}\n </button>\n {withCamera ? (\n <button\n type=\"button\"\n onClick={() => (canUseMedia ? setCamera(true) : nativeCamera.current?.click())}\n className={cn(tile, \"w-28\")}\n >\n <Camera className=\"size-6\" />\n {t(\"run.camera\")}\n </button>\n ) : null}\n {/* Where the browser cannot record a clip itself, the phone's camera app does. */}\n {clips && !(canUseMedia && canRecordClips) ? (\n <button\n type=\"button\"\n onClick={() => nativeVideo.current?.click()}\n className={cn(tile, \"w-28\")}\n >\n <Video className=\"size-6\" />\n {t(\"camera.video\")}\n </button>\n ) : null}\n </div>\n ) : null}\n <input\n ref={picker}\n type=\"file\"\n hidden\n multiple={multiple}\n accept={image ? \"image/*\" : undefined}\n onChange={(e) => {\n void add(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n <input\n ref={nativeCamera}\n type=\"file\"\n hidden\n accept=\"image/*\"\n capture=\"environment\"\n onChange={(e) => {\n void add(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n {clips ? (\n <input\n ref={nativeVideo}\n type=\"file\"\n hidden\n accept=\"video/*\"\n capture=\"environment\"\n onChange={(e) => {\n void add(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n ) : null}\n <CameraDialog\n open={camera}\n multiple={multiple}\n video={clips}\n onClose={() => setCamera(false)}\n onCapture={(file) => add([file])}\n onNative={() => nativeCamera.current?.click()}\n />\n {multiple && (field.min || field.max) ? (\n <div className=\"mt-2 text-[0.8125rem] text-ink-3 tabular-nums\">\n {field.min && ids.length < field.min\n ? t(\"run.filesMin\", { n: ids.length, min: field.min })\n : field.max\n ? t(\"run.filesOf\", { n: ids.length, max: field.max })\n : null}\n </div>\n ) : null}\n {error ? <div className=\"mt-2 text-[0.8125rem] text-rose\">{error}</div> : null}\n </div>\n );\n}\n\n/**\n * What the keyboard should offer for a short text: a label that asks for a phone number gets the\n * number pad, a name gets the person's own from autofill. Guessed from the field's id and label.\n */\nexport function textHints(field: Field): React.InputHTMLAttributes<HTMLInputElement> {\n const key = `${field.id} ${field.label}`.toLowerCase();\n if (/telefon|phone|handy|mobil(?!it)|\\btel\\b|rückruf/.test(key)) {\n return { type: \"tel\", inputMode: \"tel\", autoComplete: \"tel\" };\n }\n if (/\\bplz\\b|postleitzahl|postal|zip/.test(key)) {\n return { inputMode: \"numeric\", autoComplete: \"postal-code\" };\n }\n if (/iban/.test(key)) {\n return { autoCapitalize: \"characters\", autoCorrect: \"off\", spellCheck: false };\n }\n if (/vorname|first.?name/.test(key)) {\n return { autoComplete: \"given-name\", autoCapitalize: \"words\" };\n }\n if (/nachname|last.?name|surname/.test(key)) {\n return { autoComplete: \"family-name\", autoCapitalize: \"words\" };\n }\n if (/firma|unternehmen|company|organi[sz]ation/.test(key)) {\n return { autoComplete: \"organization\", autoCapitalize: \"words\" };\n }\n if (/straße|strasse|street|anschrift|adresse|address/.test(key)) {\n return { autoComplete: \"street-address\", autoCapitalize: \"words\" };\n }\n if (/\\b(ort|stadt|city|town)\\b/.test(key)) {\n return { autoComplete: \"address-level2\", autoCapitalize: \"words\" };\n }\n if (/\\bname\\b|ansprechp/.test(key)) {\n return { autoComplete: \"name\", autoCapitalize: \"words\" };\n }\n return { autoCapitalize: \"sentences\" };\n}\n\n/** A short text that can also be filled by pointing the camera at a QR code or barcode. */\nfunction ScanInput({\n field,\n value,\n onChange,\n}: {\n field: Field;\n value: string;\n onChange: (v: string) => void;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"flex gap-2\">\n <Input\n value={value}\n placeholder={field.placeholder}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n onChange={(e) => onChange(e.target.value)}\n />\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"inline-flex h-11 shrink-0 items-center gap-2 rounded-lg border border-input bg-card px-3.5 font-medium text-[0.875rem] text-ink-2 transition hover:border-ember hover:text-ink\"\n >\n <ScanLine className=\"size-4\" /> {t(\"scan.button\")}\n </button>\n <ScanDialog open={open} onClose={() => setOpen(false)} onResult={onChange} />\n </div>\n );\n}\n\n/** How many days of offered times show before \"Show later times\". */\nconst SLOT_DAYS = 4;\n\n/** Offered times by calendar day, in their own offset (the business's clock), earliest first. */\nfunction slotDays(options: string[]) {\n const days = new Map<string, { label: string; times: { value: string; time: string }[] }>();\n const sorted = options\n .map((value) => ({ value, slot: slotTime(value) }))\n .filter((o) => o.slot)\n .sort((a, b) => Date.parse(a.value) - Date.parse(b.value));\n for (const { value, slot } of sorted) {\n if (!slot) {\n continue;\n }\n const day = days.get(slot.day) ?? { label: slotDayText(value, lang), times: [] };\n day.times.push({ value, time: slot.time });\n days.set(slot.day, day);\n }\n return [...days.values()];\n}\n\n/**\n * One appointment time from those offered: a small heading per day, the times under it as\n * chips. The chips are one group of radio buttons — the arrow keys move between the times shown.\n */\nfunction SlotField({\n name,\n label,\n options,\n value,\n onChange,\n disabled,\n}: {\n name: string;\n label: string;\n options: string[];\n value: string;\n onChange: (v: string) => void;\n disabled: Set<string>;\n}) {\n const days = slotDays(options);\n const chosenDay = days.findIndex((d) => d.times.some((tm) => tm.value === value));\n const [all, setAll] = useState(chosenDay >= SLOT_DAYS);\n if (!days.length) {\n return <p className=\"text-[0.875rem] text-ink-3\">{t(\"slot.none\")}</p>;\n }\n const shown = all ? days : days.slice(0, SLOT_DAYS);\n return (\n <div className=\"flex flex-col gap-4\">\n <fieldset className=\"flex min-w-0 flex-col gap-4\">\n <legend className=\"sr-only\">{label}</legend>\n {shown.map((day) => (\n <div key={day.label}>\n <div className=\"mb-2 font-medium text-[0.75rem] text-ink-3\">{day.label}</div>\n <div className=\"flex flex-wrap gap-2\">\n {day.times.map((tm) => (\n <label key={tm.value} className=\"relative\">\n <input\n type=\"radio\"\n name={`slot-${name}`}\n value={tm.value}\n checked={tm.value === value}\n disabled={disabled.has(tm.value)}\n aria-label={`${day.label}, ${tm.time}`}\n onChange={() => onChange(tm.value)}\n className=\"peer sr-only\"\n />\n <span\n className={cn(\n \"inline-flex h-10 cursor-pointer items-center rounded-full border px-4 text-sm tabular-nums transition coarse:h-11\",\n \"border-input bg-card text-ink-2 hover:border-ink-4 hover:text-ink\",\n \"peer-checked:border-ember peer-checked:bg-ember-tint peer-checked:text-ink\",\n \"peer-disabled:pointer-events-none peer-disabled:line-through peer-disabled:opacity-60\",\n \"peer-focus-visible:outline-[1.5px] peer-focus-visible:outline-offset-2 peer-focus-visible:outline-(--focus-line) peer-focus-visible:outline-solid\",\n )}\n >\n {tm.time}\n </span>\n </label>\n ))}\n </div>\n </div>\n ))}\n </fieldset>\n {days.length > shown.length ? (\n <button\n type=\"button\"\n onClick={() => setAll(true)}\n className=\"self-start text-[0.8125rem] text-ink-3 underline-offset-4 transition hover:text-ink hover:underline coarse:min-h-11\"\n >\n {t(\"slot.later\")}\n </button>\n ) : null}\n </div>\n );\n}\n\n/**\n * Choices drawn as cards: a picture, the title, a line under it, a price, and a page to open.\n * One or several of them, as the field is a select or a multiselect.\n */\nfunction CardChoice({\n cards,\n value,\n multi,\n runId,\n onChange,\n disabled,\n}: {\n cards: CardOption[];\n value: unknown;\n multi: boolean;\n runId: string;\n onChange: (v: unknown) => void;\n disabled: Set<string>;\n}) {\n const picked = new Set<string>(\n multi\n ? Array.isArray(value)\n ? value.map(String)\n : []\n : value === undefined || value === null || value === \"\"\n ? []\n : [String(value)],\n );\n const toggle = (v: string) => {\n if (multi) {\n onChange(picked.has(v) ? [...picked].filter((x) => x !== v) : [...picked, v]);\n } else {\n onChange(picked.has(v) ? \"\" : v);\n }\n };\n const image = (src: string) =>\n /^(https?:|data:|\\/)/.test(src) ? src : withBase(`/api/runs/${runId}/assets/${src}`);\n return (\n <div\n className=\"grid gap-3\"\n style={{ gridTemplateColumns: \"repeat(auto-fill, minmax(min(100%, 10.5rem), 1fr))\" }}\n >\n {cards.map((c) => {\n const on = picked.has(c.value);\n const shut = disabled.has(c.value);\n return (\n <div\n key={c.value}\n className={cn(\n \"flex flex-col overflow-hidden rounded-xl bg-card ring-1 ring-border-soft transition\",\n on && \"ring-2 ring-ember\",\n shut && \"opacity-50\",\n )}\n >\n {c.image ? (\n <img src={image(c.image)} alt=\"\" className=\"aspect-square w-full object-cover\" />\n ) : null}\n <div className=\"flex flex-1 flex-col gap-1 p-3\">\n <div className=\"font-medium text-[0.9375rem] leading-snug\">{c.label}</div>\n {c.subtitle ? (\n <div className=\"text-[0.8125rem] text-ink-3 leading-snug\">{c.subtitle}</div>\n ) : null}\n {c.meta ? (\n <div className=\"mt-auto pt-1 font-display font-semibold text-[0.9375rem] tabular-nums\">\n {c.meta}\n </div>\n ) : null}\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n <button\n type=\"button\"\n aria-pressed={on}\n disabled={shut}\n onClick={() => toggle(c.value)}\n className={cn(\n \"inline-flex h-9 flex-1 items-center justify-center rounded-full px-3 text-[0.8125rem] transition coarse:h-11\",\n on ? \"bg-ember text-ember-on\" : \"bg-paper-2 text-ink-2 hover:text-ink\",\n )}\n >\n {on ? t(\"cards.picked\") : t(\"cards.pick\")}\n </button>\n {c.link ? (\n <a\n href={c.link}\n target=\"_blank\"\n rel=\"noopener\"\n className=\"inline-flex h-9 items-center rounded-full px-3 text-[0.8125rem] text-ink-2 ring-1 ring-border-soft hover:text-ink coarse:h-11\"\n >\n {t(\"cards.open\")}\n </a>\n ) : null}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport function FieldInput({\n field,\n value,\n values,\n runId,\n view,\n onChange,\n onBusy,\n error,\n closed,\n}: {\n field: Field;\n value: unknown;\n values: Values;\n runId: string;\n /** Answers that lead to a step this app has no model for: shown, not to be picked. */\n closed?: ClosedChoice;\n /** The run as the server sees it: connections, stored lists and card choices come from there. */\n view?: Pick<RunView, \"connections\" | \"lists\" | \"cards\">;\n onChange: (v: unknown) => void;\n /** The field is uploading or recording: the page waits with going on. */\n onBusy?: (busy: boolean) => void;\n error?: string;\n}) {\n const str = value === undefined || value === null ? \"\" : String(value);\n const shut = new Set(closed?.values.map(String));\n let control: React.ReactNode;\n switch (field.kind) {\n case \"textarea\":\n control = (\n <Textarea\n value={str}\n placeholder={field.placeholder}\n autoCapitalize=\"sentences\"\n enterKeyHint=\"enter\"\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"number\":\n control = (\n <Input\n inputMode=\"decimal\"\n autoComplete=\"off\"\n value={str}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"select\": {\n const options = field.options ?? [];\n const cards = view?.cards?.[field.id];\n control = cards?.length ? (\n <CardChoice\n cards={cards}\n value={value}\n multi={false}\n runId={runId}\n onChange={onChange}\n disabled={shut}\n />\n ) : options.length <= 5 && options.every((o) => o.length <= 28) ? (\n <Segmented\n value={str}\n options={options}\n onChange={onChange}\n disabled={[...shut]}\n label={choiceLabel}\n />\n ) : (\n <Select\n value={str}\n placeholder=\"—\"\n onChange={onChange}\n options={options.map((o) => ({ value: o, label: choiceLabel(o), disabled: shut.has(o) }))}\n />\n );\n break;\n }\n case \"slot\":\n control = (\n <SlotField\n name={field.id}\n label={field.label}\n options={field.options ?? []}\n value={str}\n onChange={onChange}\n disabled={shut}\n />\n );\n break;\n case \"multiselect\": {\n const cards = view?.cards?.[field.id];\n control = cards?.length ? (\n <CardChoice\n cards={cards}\n value={value}\n multi\n runId={runId}\n onChange={onChange}\n disabled={shut}\n />\n ) : (\n <Segmented\n multi\n value={Array.isArray(value) ? (value as string[]) : []}\n options={field.options ?? []}\n onChange={onChange}\n label={choiceLabel}\n />\n );\n break;\n }\n case \"date\":\n control = (\n <Input\n type=\"date\"\n value={str}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-full sm:w-56\"\n />\n );\n break;\n case \"email\":\n control = (\n <Input\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={str}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"url\":\n control = (\n <Input\n type=\"url\"\n inputMode=\"url\"\n autoComplete=\"url\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={str}\n placeholder={field.placeholder ?? \"https://\"}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n break;\n case \"toggle\":\n control = (\n <Switch\n checked={value === true}\n onChange={onChange}\n label={field.label}\n disabled={shut.has(String(value !== true))}\n />\n );\n break;\n case \"color\":\n control = (\n <div className=\"flex items-center gap-3\">\n <Swatch value={str || \"#e0531b\"} onChange={(e) => onChange(e.target.value)} />\n <Input\n value={str}\n placeholder=\"#e0531b\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n onChange={(e) => onChange(e.target.value)}\n className=\"w-36\"\n />\n </div>\n );\n break;\n case \"image\":\n case \"file\":\n control = (\n <UploadField\n field={field}\n value={value}\n runId={runId}\n onChange={onChange}\n onBusy={onBusy}\n />\n );\n break;\n case \"items\":\n control = <ItemsField field={field} value={value} values={values} onChange={onChange} />;\n break;\n case \"connection\":\n control = (\n <ConnectionField\n runId={runId}\n connection={view?.connections.find((c) => c.id === field.connection)}\n />\n );\n break;\n case \"list\": {\n const list = view?.lists.find((l) => l.def.id === field.list);\n control = list ? <ListTable runId={runId} list={list} editable /> : null;\n break;\n }\n case \"location\":\n control = (\n <LocationField\n value={value}\n runId={runId}\n placeholder={field.placeholder}\n onChange={onChange}\n onBusy={onBusy}\n />\n );\n break;\n case \"audio\":\n // Nothing here can listen to it: the reason below stands in for the recorder.\n control = closed ? null : (\n <VoiceField value={value} runId={runId} onChange={onChange} onBusy={onBusy} />\n );\n break;\n case \"signature\":\n control = (\n <SignatureField label={field.label} value={value} runId={runId} onChange={onChange} />\n );\n break;\n default:\n control = field.scan ? (\n <ScanInput field={field} value={str} onChange={onChange} />\n ) : (\n <Input\n {...textHints(field)}\n value={str}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n />\n );\n }\n return (\n <div>\n {field.kind === \"toggle\" ? (\n <div className=\"flex items-start justify-between gap-6\">\n <Label hint={field.help}>{field.label}</Label>\n {control}\n </div>\n ) : (\n <>\n <Label hint={field.help} required={field.required}>\n {field.label}\n </Label>\n {control}\n </>\n )}\n {closed ? (\n <div className=\"mt-1.5 text-[0.8125rem] text-ink-3\">\n {t(\"run.closed\", {\n list: closed.classes.map((c) => t(`run.cls.${groupOf(c)}`)).join(\", \"),\n })}\n </div>\n ) : null}\n {error ? <div className=\"mt-1.5 text-[0.8125rem] text-rose\">{error}</div> : null}\n </div>\n );\n}\n\n/**\n * What a model class is called where a person reads that it is missing. A standalone site\n * names its groups directly, \"account\" among them: what only an engenty account would do.\n */\ntype ClassGroup = \"text\" | \"image\" | \"video\" | \"speech\" | \"audio\" | \"account\";\n\nfunction groupOf(cls: string): ClassGroup {\n if (cls in CLASS_GROUP) {\n return CLASS_GROUP[cls as ModelClass];\n }\n return cls === \"account\" ? \"account\" : \"text\";\n}\n\nconst CLASS_GROUP: Record<ModelClass, Exclude<ClassGroup, \"account\">> = {\n classifier: \"text\",\n standard: \"text\",\n high: \"text\",\n highest: \"text\",\n image: \"image\",\n video: \"video\",\n speech: \"speech\",\n audio: \"audio\",\n};\n","import type { RunFontFace } from \"@engenty/wizards-shared/run\";\n\n/** How long a website has to send a brand font before the shipped one is loaded beside it. */\nconst FACE_WAIT_MS = 3000;\n\nconst faces = new Set<string>();\n\n/**\n * Loads a brand font, once, from `url`: our copy of its file, or the space's website (the file,\n * or a stylesheet that holds it). When the website does not answer, does not allow other sites\n * to use the font, or has no font of that name, `fallback` loads the shipped font of its kind:\n * the page's font stack names it right after the brand font.\n */\nexport function loadBrandFace(face: RunFontFace, url: string, fallback: () => void) {\n const key = `${face.family}\\n${face.url}`;\n if (faces.has(key)) {\n return;\n }\n faces.add(key);\n let done = false;\n const wait = setTimeout(() => done || fallback(), FACE_WAIT_MS);\n const loaded = () => {\n done = true;\n clearTimeout(wait);\n };\n const failed = () => {\n loaded();\n fallback();\n };\n if (face.stylesheet) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = url;\n link.onerror = failed;\n link.onload = () => {\n document.fonts\n .load(`1em \"${face.family.replace(/\"/g, \"\")}\"`)\n .then((found) => (found.length ? loaded() : failed()), failed);\n };\n document.head.append(link);\n return;\n }\n const font = new FontFace(face.family, `url(\"${url.replace(/[\"\\\\\\n]/g, encodeURIComponent)}\")`, {\n display: \"swap\",\n weight: \"100 900\",\n });\n font.load().then((f) => {\n document.fonts.add(f);\n loaded();\n }, failed);\n}\n","import { type AgentStep, stepShape } from \"@engenty/wizards-shared/definition\";\nimport {\n type FieldShape,\n type ListShape,\n labelOf,\n type ObjectShape,\n titleKey,\n} from \"@engenty/wizards-shared/shape\";\nimport { lang, t } from \"./i18n.js\";\nimport { cn } from \"./ui.js\";\n\n/**\n * A json result without a view of its own, drawn from the step's shape: things as cards (title,\n * a line about it, its short values), words as chips, ordered text as numbered lines, a yes/no\n * in its own words. A table only where entries are figures to compare across columns.\n */\n\ntype Entry = Record<string, unknown>;\ntype Of = ListShape[\"of\"];\n\nconst text = (v: unknown): string =>\n v === null || v === undefined ? \"\" : typeof v === \"object\" ? JSON.stringify(v) : String(v);\n\nconst sectionLabel = \"mb-1.5 font-medium text-[0.75rem] text-ink-3 uppercase tracking-[0.06em]\";\n\n/** The shape of an entry: declared, or read from the entries themselves (a table without one). */\nfunction entryShape(of: Of | undefined, rows: Entry[]): ObjectShape {\n if (of?.kind === \"object\") {\n return of;\n }\n const keys = [...new Set(rows.flatMap((r) => Object.keys(r ?? {})))];\n return {\n kind: \"object\",\n fields: Object.fromEntries(\n keys.map((k) => {\n const values = rows.map((r) => r?.[k]).filter((v) => v !== null && v !== undefined);\n const kind = values.every((v) => typeof v === \"number\")\n ? (\"number\" as const)\n : values.every((v) => typeof v === \"boolean\")\n ? (\"yesno\" as const)\n : (\"text\" as const);\n const long = kind === \"text\" && values.some((v) => String(v).length > 80);\n return [k, kind === \"text\" ? { kind, long } : { kind }];\n }),\n ),\n };\n}\n\n/** Entries that are figures: at least three numbers and more numbers than words. */\nfunction figures(shape: ObjectShape): boolean {\n const fields = Object.values(shape.fields);\n const numbers = fields.filter((f) => f.kind === \"number\").length;\n return numbers >= 3 && numbers > fields.length / 2;\n}\n\nfunction leafText(f: FieldShape | Of, v: unknown, root: Entry): string {\n if (v === null || v === undefined || v === \"\") {\n return \"\";\n }\n switch (f.kind) {\n case \"number\":\n return `${typeof v === \"number\" ? v.toLocaleString(lang) : text(v)}${f.unit ? ` ${f.unit}` : \"\"}`;\n case \"yesno\":\n return v ? (f.yes ?? t(\"run.yes\")) : (f.no ?? t(\"run.no\"));\n case \"ref\": {\n const list = root[f.to];\n const hit = Array.isArray(list)\n ? (list as Entry[]).find((e) => e && text(e.id) === text(v))\n : undefined;\n return hit ? text(hit.title ?? hit.name ?? hit.label ?? v) : text(v);\n }\n default:\n return text(v);\n }\n}\n\nfunction Chips({ items }: { items: string[] }) {\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {items.map((x, i) => (\n <span\n key={i}\n className=\"rounded-full bg-card px-2.5 py-0.5 text-[0.8125rem] text-ink-2 ring-1 ring-border-soft\"\n >\n {x}\n </span>\n ))}\n </div>\n );\n}\n\n/** A list of values: short ones as chips, sentences as a list. */\nfunction Leaves({ of, values, root }: { of: Of; values: unknown[]; root: Entry }) {\n const items = values.map((v) => leafText(of, v, root)).filter(Boolean);\n return items.every((x) => x.length <= 32) ? (\n <Chips items={items} />\n ) : (\n <ul className=\"flex list-disc flex-col gap-1 pl-5 text-[0.9375rem]\">\n {items.map((x, i) => (\n <li key={i} className=\"break-words\">\n {x}\n </li>\n ))}\n </ul>\n );\n}\n\nfunction FigureTable({ shape, rows, root }: { shape: ObjectShape; rows: Entry[]; root: Entry }) {\n const cols = Object.entries(shape.fields);\n return (\n <div className=\"overflow-x-auto rounded-lg ring-1 ring-border-soft\">\n <table className=\"w-full text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {cols.map(([k, f]) => (\n <th\n key={k}\n className={cn(\n \"whitespace-nowrap px-3 py-2 text-left font-medium\",\n f.kind === \"number\" && \"text-right\",\n )}\n >\n {labelOf(k, f)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((r, i) => (\n <tr key={i} className=\"border-border-soft border-t\">\n {cols.map(([k, f]) => (\n <td\n key={k}\n className={cn(\"px-3 py-2 tabular-nums\", f.kind === \"number\" && \"text-right\")}\n >\n {leafText(f, r?.[k], root)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/** Nested entries inside a card: numbered lines when they are text, else their titles. */\nfunction Nested({ shape, rows, root }: { shape: ObjectShape; rows: Entry[]; root: Entry }) {\n const fields = Object.entries(shape.fields);\n const main = fields.find(([, f]) => f.kind === \"text\" && f.long)?.[0] ?? titleKey(shape);\n const rest = fields.filter(([k, f]) => k !== main && k !== \"id\" && f.kind !== \"list\");\n const ordered = Boolean(fields.find(([, f]) => f.kind === \"text\" && f.long));\n const List = ordered ? \"ol\" : \"ul\";\n return (\n <List className=\"flex flex-col gap-1.5 text-[0.875rem]\">\n {rows.map((r, i) => {\n // The first value reads as the line, the rest beside it, quieter.\n const parts = [\n main ? text(r?.[main]) : \"\",\n ...rest.map(([k, f]) => leafText(f, r?.[k], root)),\n ].filter(Boolean);\n return (\n <li key={i} className={cn(ordered && \"grid grid-cols-[1.25rem_1fr] gap-1.5\")}>\n {ordered ? (\n <span className=\"font-semibold text-ember tabular-nums\">{i + 1}</span>\n ) : null}\n <span>\n {parts[0]}\n {parts.length > 1 ? (\n <span className=\"text-ink-3\"> · {parts.slice(1).join(\" · \")}</span>\n ) : null}\n </span>\n </li>\n );\n })}\n </List>\n );\n}\n\n/**\n * Yes/no values as tags: a yes in its own words or the field's label (\"Bald verbrauchen\"), a no\n * only where it has words of its own (\"einkaufen\") — a plain no is no news.\n */\nfunction Flags({ fields, entry }: { fields: [string, FieldShape][]; entry: Entry }) {\n const tags = fields.flatMap(([k, f]) => {\n if (f.kind !== \"yesno\" || entry[k] === undefined || entry[k] === null) {\n return [];\n }\n const words = entry[k] ? (f.yes ?? labelOf(k, f)) : f.no;\n return words ? [{ k, words, on: Boolean(entry[k]) }] : [];\n });\n return tags.length ? (\n <span className=\"flex shrink-0 flex-wrap justify-end gap-1\">\n {tags.map((tag) => (\n <span\n key={tag.k}\n className={cn(\n \"rounded-full px-2 py-0.5 text-[0.75rem]\",\n tag.on ? \"bg-second-tint text-second\" : \"bg-ember-tint text-ember-strong\",\n )}\n >\n {tag.words}\n </span>\n ))}\n </span>\n ) : null;\n}\n\n/** Small entries (no long text, no lists): one row each, in one card. */\nfunction EntryRows({ shape, rows, root }: { shape: ObjectShape; rows: Entry[]; root: Entry }) {\n const fields = Object.entries(shape.fields).filter(([k]) => k !== \"id\");\n const title = titleKey(shape);\n const flags = fields.filter(([, f]) => f.kind === \"yesno\");\n const metas = fields.filter(([k, f]) => k !== title && f.kind !== \"yesno\");\n return (\n <div className=\"divide-y divide-border-soft overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n {rows.map((r, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-2.5\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-[0.9375rem]\">{title ? text(r?.[title]) : \"\"}</div>\n <div className=\"text-[0.8125rem] text-ink-3\">\n {metas\n .map(([k, f]) => leafText(f, r?.[k], root))\n .filter(Boolean)\n .join(\" · \")}\n </div>\n </div>\n <Flags fields={flags} entry={r ?? {}} />\n </div>\n ))}\n </div>\n );\n}\n\nfunction EntryCard({ shape, entry, root }: { shape: ObjectShape; entry: Entry; root: Entry }) {\n const fields = Object.entries(shape.fields).filter(([k]) => k !== \"id\");\n const title = titleKey(shape);\n const about = fields.find(([, f]) => f.kind === \"text\" && f.long);\n const metas = fields.filter(\n ([k, f]) =>\n k !== title &&\n k !== about?.[0] &&\n (f.kind === \"number\" ||\n f.kind === \"choice\" ||\n f.kind === \"score\" ||\n f.kind === \"ref\" ||\n (f.kind === \"text\" && !f.long)),\n );\n const flags = fields.filter(([, f]) => f.kind === \"yesno\");\n const longs = fields.filter(([k, f]) => f.kind === \"text\" && f.long && k !== about?.[0]);\n const lists = fields.filter(([, f]) => f.kind === \"list\" || f.kind === \"table\");\n return (\n <article className=\"flex flex-col gap-2 rounded-xl bg-card p-4 ring-1 ring-border-soft\">\n <div className=\"flex items-start justify-between gap-3\">\n <h4 className=\"text-balance font-display font-semibold text-[1.0625rem] leading-snug\">\n {title ? text(entry[title]) : \"\"}\n </h4>\n <Flags fields={flags} entry={entry} />\n </div>\n {about ? (\n <p className=\"text-[0.875rem] text-ink-3 leading-relaxed\">{text(entry[about[0]])}</p>\n ) : null}\n {metas.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {metas\n .map(([k, f]) => leafText(f, entry[k], root))\n .filter(Boolean)\n .map((m, i) => (\n <span\n key={i}\n className=\"rounded-full bg-paper-2 px-2 py-0.5 text-[0.75rem] text-ink-2\"\n >\n {m}\n </span>\n ))}\n </div>\n ) : null}\n {longs.map(([k, f]) =>\n entry[k] ? (\n <p key={k} className=\"text-[0.875rem] leading-relaxed\">\n <span className=\"text-ink-3\">{labelOf(k, f)}: </span>\n {text(entry[k])}\n </p>\n ) : null,\n )}\n {lists.map(([k, f]) => {\n const v = entry[k];\n if (!Array.isArray(v) || !v.length) {\n return null;\n }\n return (\n <div key={k} className=\"border-border-soft border-t pt-2\">\n <div className={sectionLabel}>{labelOf(k, f)}</div>\n {f.kind === \"list\" && f.of.kind !== \"object\" ? (\n <Leaves of={f.of} values={v} root={root} />\n ) : (\n <Nested\n shape={entryShape(f.kind === \"list\" ? f.of : undefined, v as Entry[])}\n rows={v as Entry[]}\n root={root}\n />\n )}\n </div>\n );\n })}\n </article>\n );\n}\n\nfunction Entries({ of, rows, root }: { of: Of | undefined; rows: Entry[]; root: Entry }) {\n const shape = entryShape(of, rows);\n if (figures(shape)) {\n return <FigureTable shape={shape} rows={rows} root={root} />;\n }\n const rich = Object.values(shape.fields).some(\n (f) => f.kind === \"list\" || f.kind === \"table\" || (f.kind === \"text\" && f.long),\n );\n if (!rich) {\n return <EntryRows shape={shape} rows={rows} root={root} />;\n }\n return (\n <div className=\"grid grid-cols-[repeat(auto-fill,minmax(min(100%,16rem),1fr))] gap-3\">\n {rows.map((r, i) => (\n <EntryCard key={i} shape={shape} entry={r ?? {}} root={root} />\n ))}\n </div>\n );\n}\n\nexport function JsonView({ step, json }: { step: AgentStep; json: unknown }) {\n if (!json || typeof json !== \"object\" || Array.isArray(json)) {\n return <pre className=\"text-[0.8125rem]\">{JSON.stringify(json, null, 2)}</pre>;\n }\n const root = json as Entry;\n const shape = stepShape(step);\n return (\n <div className=\"flex flex-col gap-5\">\n {Object.entries(root).map(([key, v]) => {\n const f = shape.fields[key];\n const title = f ? labelOf(key, f) : key;\n let body: React.ReactNode;\n if (Array.isArray(v) && v.length && v.every((x) => x && typeof x === \"object\")) {\n body = (\n <Entries of={f?.kind === \"list\" ? f.of : undefined} rows={v as Entry[]} root={root} />\n );\n } else if (Array.isArray(v)) {\n body = (\n <Leaves of={f?.kind === \"list\" ? f.of : { kind: \"text\" }} values={v} root={root} />\n );\n } else if (v && typeof v === \"object\") {\n body = (\n <pre className=\"overflow-auto rounded-lg bg-paper-2 p-3 text-[0.75rem]\">\n {JSON.stringify(v, null, 2)}\n </pre>\n );\n } else {\n const leaf = f && f.kind !== \"list\" && f.kind !== \"table\" ? f : { kind: \"text\" as const };\n body = (\n <div className=\"whitespace-pre-wrap text-[0.9375rem] leading-relaxed\">\n {leafText(leaf, v, root)}\n </div>\n );\n }\n return (\n <section key={key}>\n <div className={sectionLabel}>{title}</div>\n {body}\n </section>\n );\n })}\n </div>\n );\n}\n","import { marked, type Token, type Tokens } from \"marked\";\nimport type { Content, TableCell, TDocumentDefinitions } from \"pdfmake/interfaces\";\nimport { t } from \"./i18n.js\";\n\n/**\n * A written output as a PDF, made in the browser. A host whose server writes no PDF (the\n * WordPress plugin: PHP, no Chromium) still hands the visitor the file the result step\n * promised: pdfmake lays it out from a content tree — a Markdown text through marked's tokens,\n * a structured output as the result page shows it (label, value, list, table) — with Roboto\n * bundled, so German, Czech or Polish read as written. The library and its fonts weigh about\n * 1.5 MB and are loaded on the first click only; the content tree itself is small and pure.\n */\n\nexport interface Written {\n /** The step's title: the document's heading and the file's name. */\n title: string;\n /** A Markdown or plain text. */\n text?: string;\n /** A structured output; its keys are named by `label`. */\n json?: unknown;\n /** What a key of the structured output is called (the step's output fields). */\n label?: (key: string) => string;\n /** The line at the foot of every page: the wizard, the date. */\n foot?: string;\n}\n\n/** A run of text with its look, as pdfmake takes it. */\ninterface Run {\n text: string;\n bold?: boolean;\n italics?: boolean;\n link?: string;\n color?: string;\n decoration?: \"underline\" | \"lineThrough\";\n}\n\nconst INK = \"#282623\";\nconst INK_3 = \"#81807e\";\nconst LINK = \"#1a5fb4\";\nconst LINE = \"#dbd9d6\";\n/** A4 less the margins: what a rule spans. */\nconst TEXT_WIDTH = 595.28 - 2 * 56;\n\nconst ENTITIES: Record<string, string> = {\n amp: \"&\",\n lt: \"<\",\n gt: \">\",\n quot: '\"',\n apos: \"'\",\n \"#39\": \"'\",\n nbsp: \" \",\n};\n\n/** marked keeps some text escaped for HTML; a PDF wants the characters. */\nfunction plain(text: string): string {\n return text.replace(/&(#x[0-9a-f]+|#\\d+|[a-z]+\\d*);/gi, (all, name: string) => {\n if (name[0] === \"#\") {\n const code =\n name[1]?.toLowerCase() === \"x\" ? Number.parseInt(name.slice(2), 16) : Number(name.slice(1));\n return Number.isFinite(code) ? String.fromCodePoint(code) : all;\n }\n return ENTITIES[name.toLowerCase()] ?? all;\n });\n}\n\n/** Tags out of a raw HTML token: its text is what a PDF can hold. */\nfunction untagged(html: string): string {\n return plain(html.replace(/<[^>]+>/g, \"\")).trim();\n}\n\n/** Inline tokens as runs: bold, italics, code, links and line breaks kept; images as their text. */\nfunction runs(tokens: Token[] | undefined, look: Omit<Run, \"text\"> = {}): Run[] {\n const out: Run[] = [];\n for (const token of tokens ?? []) {\n switch (token.type) {\n case \"text\": {\n const inner = (token as Tokens.Text).tokens;\n if (inner?.length) {\n out.push(...runs(inner, look));\n } else {\n out.push({ ...look, text: plain(token.text) });\n }\n break;\n }\n case \"escape\":\n out.push({ ...look, text: plain(token.text) });\n break;\n case \"strong\":\n out.push(...runs((token as Tokens.Strong).tokens, { ...look, bold: true }));\n break;\n case \"em\":\n out.push(...runs((token as Tokens.Em).tokens, { ...look, italics: true }));\n break;\n case \"del\":\n out.push(...runs((token as Tokens.Del).tokens, { ...look, decoration: \"lineThrough\" }));\n break;\n case \"codespan\":\n out.push({ ...look, text: plain(token.text), color: \"#3d3b38\" });\n break;\n case \"link\": {\n const link = token as Tokens.Link;\n out.push(\n ...runs(link.tokens, { ...look, link: link.href, color: LINK, decoration: \"underline\" }),\n );\n break;\n }\n case \"image\":\n out.push({ ...look, text: (token as Tokens.Image).text });\n break;\n case \"br\":\n out.push({ ...look, text: \"\\n\" });\n break;\n case \"html\":\n out.push({ ...look, text: untagged(token.text) });\n break;\n default:\n if (\"tokens\" in token && Array.isArray(token.tokens)) {\n out.push(...runs(token.tokens, look));\n } else if (\"text\" in token && typeof token.text === \"string\") {\n out.push({ ...look, text: plain(token.text) });\n }\n }\n }\n return out;\n}\n\n/** A list item: its own text without a paragraph's space under it, a nested list below. */\nfunction item(tokens: Token[]): Content {\n const parts = blocks(tokens);\n if (parts.length === 1 && typeof parts[0] === \"object\" && \"style\" in parts[0]) {\n const { style: _, ...rest } = parts[0];\n return rest as Content;\n }\n return parts.length === 1 ? parts[0] : { stack: parts };\n}\n\nfunction cell(c: Tokens.TableCell, header: boolean): TableCell {\n return {\n text: runs(c.tokens),\n alignment: c.align ?? \"left\",\n ...(header ? { style: \"th\" } : {}),\n };\n}\n\n/** Thin rules between the rows, nothing between the columns. */\nconst TABLE_LAYOUT = {\n hLineWidth: () => 0.5,\n vLineWidth: () => 0,\n hLineColor: () => LINE,\n paddingTop: () => 4,\n paddingBottom: () => 4,\n};\n\n/** Block tokens as pdfmake content. */\nfunction blocks(tokens: Token[]): Content[] {\n const out: Content[] = [];\n for (const token of tokens) {\n switch (token.type) {\n case \"space\":\n break;\n case \"heading\": {\n const depth = (token as Tokens.Heading).depth;\n out.push({\n text: runs((token as Tokens.Heading).tokens),\n style: depth <= 1 ? \"h1\" : depth === 2 ? \"h2\" : \"h3\",\n });\n break;\n }\n case \"paragraph\":\n out.push({ text: runs((token as Tokens.Paragraph).tokens), style: \"p\" });\n break;\n case \"text\":\n out.push({ text: runs([token]), style: \"p\" });\n break;\n case \"list\": {\n const list = token as Tokens.List;\n const items = list.items.map((i) => item(i.tokens));\n out.push(\n list.ordered\n ? { ol: items, style: \"list\", start: Number(list.start) || 1 }\n : { ul: items, style: \"list\" },\n );\n break;\n }\n case \"table\": {\n const table = token as Tokens.Table;\n if (!table.header.length) {\n break;\n }\n out.push({\n table: {\n headerRows: 1,\n widths: table.header.map(() => \"*\"),\n body: [\n table.header.map((c) => cell(c, true)),\n ...table.rows.map((row) => row.map((c) => cell(c, false))),\n ],\n },\n layout: TABLE_LAYOUT,\n style: \"table\",\n });\n break;\n }\n case \"code\":\n out.push({ text: plain(token.text), style: \"code\", preserveLeadingSpaces: true });\n break;\n case \"blockquote\":\n out.push({ stack: blocks((token as Tokens.Blockquote).tokens), style: \"quote\" });\n break;\n case \"hr\":\n out.push({\n canvas: [\n { type: \"line\", x1: 0, y1: 0, x2: TEXT_WIDTH, y2: 0, lineWidth: 0.5, lineColor: LINE },\n ],\n margin: [0, 6, 0, 12],\n });\n break;\n case \"html\": {\n const text = untagged(token.text);\n if (text) {\n out.push({ text, style: \"p\" });\n }\n break;\n }\n default:\n if (\"tokens\" in token && Array.isArray(token.tokens)) {\n out.push({ text: runs(token.tokens), style: \"p\" });\n } else if (\"text\" in token && typeof token.text === \"string\") {\n out.push({ text: plain(token.text), style: \"p\" });\n }\n }\n }\n return out;\n}\n\n/** A Markdown text as content. */\nexport function markdownContent(text: string): Content[] {\n return blocks(marked.lexer(text));\n}\n\n/** A structured output as the result page shows it: each key with its label, then its value. */\nexport function jsonContent(json: unknown, label: (key: string) => string = (k) => k): Content[] {\n if (!json || typeof json !== \"object\") {\n return [{ text: JSON.stringify(json, null, 2) ?? \"\", style: \"code\" }];\n }\n const out: Content[] = [];\n for (const [key, v] of Object.entries(json as Record<string, unknown>)) {\n out.push({ text: label(key), style: \"label\" });\n if (typeof v === \"boolean\") {\n out.push({ text: t(v ? \"run.yes\" : \"run.no\"), style: \"p\" });\n } else if (typeof v === \"string\" || typeof v === \"number\") {\n out.push({ text: String(v), style: \"p\" });\n } else if (Array.isArray(v) && v.every((x) => typeof x !== \"object\")) {\n out.push({ ul: v.map((x) => String(x)), style: \"list\" });\n } else if (Array.isArray(v) && v.length && typeof v[0] === \"object\") {\n const rows = v as Record<string, unknown>[];\n const cols = [...new Set(rows.flatMap((r) => Object.keys(r)))];\n out.push({\n table: {\n headerRows: 1,\n widths: cols.map(() => \"*\"),\n body: [\n cols.map((c): TableCell => ({ text: c, style: \"th\" })),\n ...rows.map((r) =>\n cols.map(\n (c): TableCell => ({\n text: r[c] === null || r[c] === undefined ? \"\" : String(r[c]),\n }),\n ),\n ),\n ],\n },\n layout: TABLE_LAYOUT,\n style: \"table\",\n });\n } else {\n out.push({ text: JSON.stringify(v, null, 2), style: \"code\" });\n }\n }\n return out;\n}\n\n/** The document: A4, the title first, the body, a foot with the page number. */\nexport function pdfDocument(written: Written): TDocumentDefinitions {\n const body =\n written.json !== undefined && written.json !== null\n ? jsonContent(written.json, written.label)\n : markdownContent(written.text ?? \"\");\n const foot = written.foot ?? \"\";\n return {\n info: { title: written.title },\n pageSize: \"A4\",\n pageMargins: [56, 60, 56, 64],\n defaultStyle: { font: \"Roboto\", fontSize: 10.5, lineHeight: 1.3, color: INK },\n styles: {\n title: { fontSize: 20, bold: true, lineHeight: 1.15, margin: [0, 0, 0, 16] },\n h1: { fontSize: 15, bold: true, margin: [0, 14, 0, 6] },\n h2: { fontSize: 13, bold: true, margin: [0, 12, 0, 5] },\n h3: { fontSize: 11, bold: true, margin: [0, 10, 0, 4] },\n p: { margin: [0, 0, 0, 7] },\n list: { margin: [0, 0, 0, 7] },\n table: { margin: [0, 2, 0, 10] },\n th: { bold: true, fillColor: \"#f3f1ee\" },\n label: { fontSize: 8, bold: true, color: INK_3, characterSpacing: 0.6, margin: [0, 8, 0, 2] },\n code: { fontSize: 9, color: \"#3d3b38\", margin: [0, 0, 0, 8] },\n quote: { italics: true, color: \"#5d5b58\", margin: [14, 0, 0, 8] },\n },\n content: [{ text: written.title, style: \"title\" }, ...body],\n footer: (page, pages) => ({\n columns: [\n { text: foot, color: INK_3, fontSize: 8.5 },\n { text: `${page} / ${pages}`, alignment: \"right\", color: INK_3, fontSize: 8.5 },\n ],\n margin: [56, 26, 56, 0],\n }),\n };\n}\n\n/** pdfmake's browser build as it is loaded: one object with the calls used here. */\ninterface PdfMake {\n addVirtualFileSystem(vfs: Record<string, string>): void;\n addFonts(fonts: Record<string, Record<string, string>>): void;\n createPdf(doc: TDocumentDefinitions): { getBlob(): Promise<Blob> };\n}\n\n/** The fonts in pdfmake's own file: Roboto in four cuts. */\nexport const ROBOTO = {\n Roboto: {\n normal: \"Roboto-Regular.ttf\",\n bold: \"Roboto-Medium.ttf\",\n italics: \"Roboto-Italic.ttf\",\n bolditalics: \"Roboto-MediumItalic.ttf\",\n },\n};\n\nlet loading: Promise<PdfMake> | null = null;\n\n/** The library with Roboto, fetched once. */\nfunction pdfMake(): Promise<PdfMake> {\n loading ??= Promise.all([\n import(\"pdfmake/build/pdfmake\") as Promise<{ default: PdfMake }>,\n import(\"pdfmake/build/vfs_fonts\") as Promise<{ default: Record<string, string> }>,\n ])\n .then(([lib, fonts]) => {\n const pdf = lib.default;\n pdf.addVirtualFileSystem(fonts.default);\n pdf.addFonts(ROBOTO);\n return pdf;\n })\n .catch((err) => {\n loading = null;\n throw err;\n });\n return loading;\n}\n\n/** A title as a file name: what no file system refuses. */\nexport function fileName(title: string): string {\n return (\n title\n .replace(/[\\\\/:*?\"<>|]+|\\p{Cc}+/gu, \"-\")\n .replace(/\\s+/g, \" \")\n .trim() || \"result\"\n );\n}\n\n/** The written output as a PDF file. */\nexport async function writePdf(written: Written): Promise<File> {\n const pdf = await pdfMake();\n const blob = await pdf.createPdf(pdfDocument(written)).getBlob();\n return new File([blob], `${fileName(written.title)}.pdf`, { type: \"application/pdf\" });\n}\n","import type { Surface, SurfaceComponent } from \"@engenty/wizards-shared/surface\";\nimport { bound } from \"@engenty/wizards-shared/surface\";\nimport { Check, ChevronRight, Clock, Lightbulb, Share2 } from \"lucide-react\";\nimport { type ReactNode, useState } from \"react\";\nimport { lang, t } from \"./i18n.js\";\nimport { cn, Dialog, Tabs as Segments } from \"./ui.js\";\n\n/**\n * A surface drawn with the runner's own components: the catalog in shared/surface.ts, nothing\n * else. Unknown components render nothing; a prop that is not there shows empty.\n */\n\nexport type SurfaceAction = { action: \"regenerate\" | \"open\"; target?: unknown };\n\n/** What the person did in a view that is kept with the run: a checklist's ticks, by component id. */\nexport type SurfaceState = Record<string, unknown>;\n\ninterface Ctx {\n byId: Map<string, SurfaceComponent>;\n data: Record<string, unknown>;\n assetUrl: (id: string) => string;\n onAction?: (a: SurfaceAction) => void;\n state: SurfaceState;\n setState: (id: string, value: unknown) => void;\n /** Opens an entry in a sheet, drawn by `view`. */\n open: (view: string, row: unknown) => void;\n}\n\n// A yes/no without words of its own reads as yes or no, never as true or false.\nconst text = (v: unknown): string =>\n v === null || v === undefined\n ? \"\"\n : typeof v === \"boolean\"\n ? t(v ? \"run.yes\" : \"run.no\")\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v);\n\nconst num = (v: unknown): number => {\n const n = typeof v === \"number\" ? v : Number(String(v ?? \"\").replace(\",\", \".\"));\n return Number.isFinite(n) ? n : 0;\n};\n\n/** A picture: an asset of the run by id, or an address. */\nfunction src(v: unknown, assetUrl: (id: string) => string): string | null {\n const s = text(v);\n if (!s) {\n return null;\n }\n return /^(https?:|data:|\\/)/.test(s) ? s : assetUrl(s);\n}\n\nfunction prop(c: SurfaceComponent, key: string, ctx: Ctx, row?: unknown): unknown {\n return bound((c as Record<string, unknown>)[key], ctx.data, row);\n}\n\n/** Chart points from rows: their `label` and `value`, or the columns a chart names instead. */\nfunction points(\n v: unknown,\n labelKey: unknown,\n valueKey: unknown,\n): { label: string; value: number }[] {\n const l = text(labelKey) || \"label\";\n const k = text(valueKey) || \"value\";\n return Array.isArray(v)\n ? v.map((p) => ({ label: text((p as any)?.[l]), value: num((p as any)?.[k]) }))\n : [];\n}\n\nfunction Children({ c, ctx, row }: { c: SurfaceComponent; ctx: Ctx; row?: unknown }) {\n const kids = c.children;\n if (!kids) {\n return null;\n }\n if (Array.isArray(kids)) {\n return (\n <>\n {kids.map((id) => (\n <Node key={id} id={id} ctx={ctx} row={row} />\n ))}\n </>\n );\n }\n const items = bound({ path: kids.path }, ctx.data, row);\n return (\n <>\n {(Array.isArray(items) ? items : []).map((item, i) => (\n <Node key={i} id={kids.componentId} ctx={ctx} row={item} />\n ))}\n </>\n );\n}\n\nconst TONES: Record<string, string> = {\n success: \"bg-second-tint text-second\",\n warning: \"bg-amber-tint text-ink-2\",\n accent: \"bg-ember-tint text-ember-strong\",\n default: \"bg-paper-2 text-ink-2\",\n};\n\nconst rows = (v: unknown): unknown[] => (Array.isArray(v) ? v : []);\n\n/** A cell of an entry by its key; an entry that is itself a value is its own label. */\nfunction cell(item: unknown, key: string): unknown {\n if (item === null || typeof item !== \"object\") {\n return key === \"\" ? item : undefined;\n }\n return (item as Record<string, unknown>)[key];\n}\n\n/** What an entry is called: its `labelKey`, else the usual keys, else the entry itself. */\nfunction labelOf(item: unknown, key: string): string {\n if (item === null || typeof item !== \"object\") {\n return text(item);\n }\n const r = item as Record<string, unknown>;\n return text(key ? r[key] : (r.label ?? r.name ?? r.title ?? r.text));\n}\n\n/** Entries under a heading per value of a key, in `order` first, the rest as they come. */\nfunction grouped(items: unknown[], by: string, order: string[]): [string, unknown[]][] {\n const groups = new Map<string, unknown[]>();\n for (const item of items) {\n const name = text(cell(item, by));\n groups.set(name, [...(groups.get(name) ?? []), item]);\n }\n const rank = (name: string) => {\n const i = order.indexOf(name);\n return i < 0 ? order.length : i;\n };\n return [...groups.entries()].sort((a, b) => rank(a[0]) - rank(b[0]));\n}\n\nconst minutes = (n: unknown) => (n ? `${text(n)} ${lang === \"de\" ? \"Min\" : \"min\"}` : \"\");\n\nfunction Metas({ items }: { items: string[] }) {\n return items.length ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {items.map((m, i) => (\n <span key={i} className=\"rounded-full bg-paper-2 px-2 py-0.5 text-[0.75rem] text-ink-2\">\n {m}\n </span>\n ))}\n </div>\n ) : null;\n}\n\n/** `meta`: one value or a list of them, each a literal or a path. */\nfunction metasOf(c: SurfaceComponent, ctx: Ctx, row?: unknown): string[] {\n const raw = (c as Record<string, unknown>).meta;\n return (Array.isArray(raw) ? raw : [raw])\n .map((m) => text(bound(m, ctx.data, row)))\n .filter(Boolean);\n}\n\nfunction TabsView({ c, ctx, row }: { c: SurfaceComponent; ctx: Ctx; row?: unknown }) {\n const [on, setOn] = useState(\"0\");\n const tabs = rows((c as Record<string, unknown>).tabs) as Record<string, unknown>[];\n const options = tabs.map((tab, i) => {\n const count = bound(tab?.count, ctx.data, row);\n const n = Array.isArray(count) ? count.length : count;\n const label = text(bound(tab?.label, ctx.data, row));\n return {\n id: String(i),\n label: n === undefined || n === null || n === \"\" ? label : `${label} (${text(n)})`,\n };\n });\n const child = tabs[Number(on)]?.child;\n return (\n <div className=\"flex flex-col gap-4\">\n <div className=\"sticky top-2 z-10 max-w-full self-start overflow-x-auto rounded-full\">\n <Segments value={on} onChange={setOn} options={options} />\n </div>\n {typeof child === \"string\" ? <Node id={child} ctx={ctx} row={row} /> : null}\n </div>\n );\n}\n\nfunction ChecklistView({ c, ctx, row }: { c: SurfaceComponent; ctx: Ctx; row?: unknown }) {\n const p = (key: string) => prop(c, key, ctx, row);\n const [copied, setCopied] = useState(false);\n const items = rows(p(\"items\"));\n const labelKey = text(p(\"labelKey\"));\n const detailKey = text(p(\"detailKey\")) || \"amount\";\n const noteKey = text(p(\"noteKey\"));\n const noteFormat = text(p(\"noteFormat\"));\n const groupKey = text(p(\"groupKey\"));\n const order = rows(p(\"groupOrder\")).map(text);\n const ticks = (ctx.state[c.id] ?? {}) as Record<string, boolean>;\n const keyOf = (item: unknown, i: number) => `${i}:${labelOf(item, labelKey)}`;\n const done = items.filter((item, i) => ticks[keyOf(item, i)]).length;\n const indexed = items.map((item, i) => ({ item, i }));\n const groups: [string, { item: unknown; i: number }[]][] = groupKey\n ? grouped(items, groupKey, order).map(([name]) => [\n name,\n indexed.filter(({ item }) => text(cell(item, groupKey)) === name),\n ])\n : [[\"\", indexed]];\n const detailOf = (item: unknown) => text(cell(item, detailKey));\n const noteMap = p(\"noteMap\");\n const noteOf = (item: unknown) => {\n const v = noteKey ? cell(item, noteKey) : undefined;\n // A yes/no says something only in words of its own: \"da\", \"einkaufen\".\n if (typeof v === \"boolean\") {\n const words =\n noteMap && typeof noteMap === \"object\"\n ? (noteMap as Record<string, unknown>)[String(v)]\n : \"\";\n return text(words ?? \"\");\n }\n const words = Array.isArray(v) ? v.map(text).join(\", \") : text(v);\n return words && noteFormat ? noteFormat.replace(\"{}\", words) : words;\n };\n const share = async () => {\n const open = groups\n .map(([name, list]) => {\n const lines = list\n .filter(({ item, i }) => !ticks[keyOf(item, i)])\n .map(\n ({ item }) =>\n `☐ ${labelOf(item, labelKey)}${detailOf(item) ? ` – ${detailOf(item)}` : \"\"}`,\n );\n return lines.length ? [name, ...lines].filter(Boolean).join(\"\\n\") : \"\";\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n try {\n if (navigator.share) {\n await navigator.share({ text: open });\n } else {\n await navigator.clipboard.writeText(open);\n setCopied(true);\n setTimeout(() => setCopied(false), 1600);\n }\n } catch {\n // Closed without sharing, or the clipboard refused: nothing to do.\n }\n };\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-1.5 flex-1 overflow-hidden rounded-full bg-paper-2\">\n <div\n className=\"h-full rounded-full bg-second transition-[width] duration-300\"\n style={{ width: `${items.length ? (done / items.length) * 100 : 0}%` }}\n />\n </div>\n <span className=\"text-[0.8125rem] text-ink-3 tabular-nums\">\n {done === items.length && items.length\n ? t(\"surface.allDone\")\n : t(\"surface.done\", { done, total: items.length })}\n </span>\n {p(\"share\") === false ? null : (\n <button\n type=\"button\"\n onClick={share}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-10\"\n >\n {copied ? <Check className=\"size-3.5\" /> : <Share2 className=\"size-3.5\" />}\n {copied ? t(\"share.copied\") : t(\"run.share\")}\n </button>\n )}\n </div>\n {groups.map(([name, list]) => (\n <section key={name} className=\"rounded-xl bg-card px-4 py-1 ring-1 ring-border-soft\">\n {name ? (\n <h4 className=\"pt-3 pb-1 font-semibold text-[0.6875rem] text-second uppercase tracking-[0.14em]\">\n {name}\n </h4>\n ) : null}\n {list.map(({ item, i }) => {\n const key = keyOf(item, i);\n const on = Boolean(ticks[key]);\n const note = noteOf(item);\n return (\n <label\n key={key}\n className=\"flex cursor-pointer items-start gap-3 border-border-soft border-b border-dashed py-2.5 last:border-0\"\n >\n <input\n type=\"checkbox\"\n checked={on}\n onChange={() => ctx.setState(c.id, { ...ticks, [key]: !on })}\n className=\"mt-0.5 size-[1.125rem] shrink-0 accent-[var(--second)] coarse:size-6\"\n />\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"text-[0.9375rem]\", on && \"text-ink-3 line-through\")}>\n {labelOf(item, labelKey)}\n {detailOf(item) ? (\n <span className=\"text-ink-3\"> · {detailOf(item)}</span>\n ) : null}\n </span>\n {note ? <span className=\"block text-[0.75rem] text-ink-3\">{note}</span> : null}\n </span>\n </label>\n );\n })}\n </section>\n ))}\n </div>\n );\n}\n\nfunction Bars({ data }: { data: { label: string; value: number }[] }) {\n const max = Math.max(1, ...data.map((d) => d.value));\n return (\n <div className=\"flex flex-col gap-1.5\">\n {data.map((d, i) => (\n <div key={i} className=\"grid grid-cols-[minmax(0,8rem)_1fr_auto] items-center gap-2\">\n <span className=\"truncate text-[0.8125rem] text-ink-2\">{d.label}</span>\n <span className=\"h-2.5 rounded-full bg-paper-2\">\n <span\n className=\"block h-full rounded-full bg-ember\"\n style={{ width: `${(d.value / max) * 100}%` }}\n />\n </span>\n <span className=\"text-[0.8125rem] tabular-nums\">{d.value.toLocaleString(lang)}</span>\n </div>\n ))}\n </div>\n );\n}\n\nfunction Line({ data }: { data: { label: string; value: number }[] }) {\n if (data.length < 2) {\n return <Bars data={data} />;\n }\n const w = 320;\n const h = 120;\n const max = Math.max(...data.map((d) => d.value));\n const min = Math.min(...data.map((d) => d.value));\n const span = max - min || 1;\n const xy = data.map((d, i) => [\n (i / (data.length - 1)) * (w - 8) + 4,\n h - 4 - ((d.value - min) / span) * (h - 8),\n ]);\n return (\n <figure>\n <svg viewBox={`0 0 ${w} ${h}`} className=\"w-full text-ember\" role=\"img\">\n <polyline\n points={xy.map(([x, y]) => `${x},${y}`).join(\" \")}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinejoin=\"round\"\n />\n {xy.map(([x, y], i) => (\n <circle key={i} cx={x} cy={y} r=\"3\" fill=\"currentColor\">\n <title>{`${data[i].label}: ${data[i].value}`}</title>\n </circle>\n ))}\n </svg>\n <figcaption className=\"mt-1 flex justify-between text-[0.75rem] text-ink-3\">\n <span>{data[0].label}</span>\n <span>{data.at(-1)?.label}</span>\n </figcaption>\n </figure>\n );\n}\n\nconst DONUT = [\n \"var(--color-ember)\",\n \"var(--color-cobalt)\",\n \"var(--color-moss)\",\n \"var(--color-amber)\",\n \"var(--color-ink-3)\",\n];\n\nfunction Donut({ data }: { data: { label: string; value: number }[] }) {\n const total = data.reduce((a, d) => a + Math.max(0, d.value), 0) || 1;\n let at = 0;\n const r = 40;\n const length = 2 * Math.PI * r;\n return (\n <div className=\"flex items-center gap-4\">\n <svg viewBox=\"0 0 100 100\" className=\"size-28 shrink-0 -rotate-90\" role=\"img\">\n {data.map((d, i) => {\n const part = (Math.max(0, d.value) / total) * length;\n const el = (\n <circle\n key={i}\n cx=\"50\"\n cy=\"50\"\n r={r}\n fill=\"none\"\n stroke={DONUT[i % DONUT.length]}\n strokeWidth=\"16\"\n strokeDasharray={`${part} ${length - part}`}\n strokeDashoffset={-at}\n >\n <title>{`${d.label}: ${d.value}`}</title>\n </circle>\n );\n at += part;\n return el;\n })}\n </svg>\n <ul className=\"flex flex-col gap-1 text-[0.8125rem]\">\n {data.map((d, i) => (\n <li key={i} className=\"flex items-center gap-2\">\n <span\n className=\"size-2.5 rounded-full\"\n style={{ background: DONUT[i % DONUT.length] }}\n />\n <span className=\"text-ink-2\">{d.label}</span>\n <span className=\"tabular-nums\">{d.value.toLocaleString(lang)}</span>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nfunction Titled({ title, children }: { title: string; children: ReactNode }) {\n return (\n <div className=\"rounded-xl bg-card p-4 ring-1 ring-border-soft\">\n {title ? <div className=\"mb-3 font-medium text-[0.875rem]\">{title}</div> : null}\n {children}\n </div>\n );\n}\n\nfunction Node({ id, ctx, row }: { id: string; ctx: Ctx; row?: unknown }) {\n const c = ctx.byId.get(id);\n if (!c) {\n return null;\n }\n const p = (key: string) => prop(c, key, ctx, row);\n switch (c.component) {\n case \"Column\":\n return (\n <div className=\"flex flex-col gap-4\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n case \"Text\": {\n const variant = text(p(\"variant\")) || \"body\";\n return (\n <p\n className={cn(\n variant === \"h3\" && \"font-display font-semibold text-[1.25rem] leading-tight\",\n variant === \"h4\" && \"font-semibold text-[1rem]\",\n variant === \"lead\" && \"font-display text-[1.0625rem] text-ink-2 leading-relaxed\",\n variant === \"body\" && \"text-[0.9375rem] leading-relaxed\",\n variant === \"muted\" && \"text-[0.8125rem] text-ink-3\",\n )}\n >\n {text(p(\"text\"))}\n </p>\n );\n }\n case \"List\":\n return (\n <div className=\"flex flex-col divide-y divide-border-soft overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n case \"Row\": {\n const image = src(p(\"image\"), ctx.assetUrl);\n const badge = text(p(\"badge\"));\n return (\n <div className=\"flex items-center gap-3 px-4 py-3\">\n {image ? (\n <img src={image} alt=\"\" className=\"size-10 shrink-0 rounded-lg object-cover\" />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[0.9375rem]\">{text(p(\"title\"))}</div>\n {p(\"subtitle\") ? (\n <div className=\"truncate text-[0.8125rem] text-ink-3\">{text(p(\"subtitle\"))}</div>\n ) : null}\n </div>\n {p(\"meta\") ? (\n <span className=\"shrink-0 text-[0.8125rem] text-ink-3 tabular-nums\">\n {text(p(\"meta\"))}\n </span>\n ) : null}\n {badge ? (\n <span\n className={cn(\n \"shrink-0 rounded-full px-2 py-0.5 text-[0.75rem]\",\n TONES[text(p(\"badgeTone\"))] ?? TONES.default,\n )}\n >\n {badge}\n </span>\n ) : null}\n </div>\n );\n }\n case \"DetailGrid\": {\n const rows = p(\"rows\");\n return (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 rounded-xl bg-card p-4 text-[0.875rem] ring-1 ring-border-soft\">\n {(Array.isArray(rows) ? rows : []).map((r, i) => (\n <div key={i} className=\"contents\">\n <dt className=\"text-ink-3\">{text(bound((r as any)?.label, ctx.data, row))}</dt>\n <dd className=\"break-words\">{text(bound((r as any)?.value, ctx.data, row))}</dd>\n </div>\n ))}\n </dl>\n );\n }\n case \"Badge\":\n return (\n <span\n className={cn(\n \"inline-flex w-fit rounded-full px-2.5 py-0.5 text-[0.75rem]\",\n TONES[text(p(\"tone\"))] ?? TONES.default,\n )}\n >\n {text(p(\"label\"))}\n </span>\n );\n case \"Grid\": {\n const columns = Math.min(4, Math.max(1, num(p(\"columns\")) || 2));\n // The narrowest a tile gets: small tiles (figures) sit two to a phone, cards one.\n const min = Math.min(24, Math.max(6, num(p(\"min\")) || (columns > 2 ? 9 : 12)));\n return (\n <div\n className=\"grid gap-3\"\n style={{\n gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${min}rem), 1fr))`,\n }}\n >\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n }\n case \"Metric\":\n return (\n <div className=\"rounded-xl bg-card p-4 ring-1 ring-border-soft\">\n <div className=\"text-[0.75rem] text-ink-3 uppercase tracking-[0.06em]\">\n {text(p(\"label\"))}\n </div>\n <div className=\"mt-1 font-display font-semibold text-[1.5rem] tabular-nums\">\n {text(p(\"value\"))}\n </div>\n {p(\"caption\") ? (\n <div className=\"text-[0.8125rem] text-ink-3\">{text(p(\"caption\"))}</div>\n ) : null}\n </div>\n );\n case \"Table\": {\n const rows = p(\"rows\");\n const list = (Array.isArray(rows) ? rows : []) as Record<string, unknown>[];\n const declared = p(\"columns\");\n const cols: { key: string; label: string }[] = Array.isArray(declared)\n ? declared.map((d: any) => ({ key: text(d?.key), label: text(d?.label ?? d?.key) }))\n : [...new Set(list.flatMap((r) => Object.keys(r ?? {})))].map((k) => ({\n key: k,\n label: k,\n }));\n return (\n <div className=\"overflow-x-auto rounded-xl ring-1 ring-border-soft\">\n <table className=\"w-full text-[0.8125rem]\">\n <thead className=\"bg-paper-2 text-ink-2\">\n <tr>\n {cols.map((col) => (\n <th key={col.key} className=\"px-3 py-2 text-left font-medium\">\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {list.map((r, i) => (\n <tr key={i} className=\"border-border-soft border-t\">\n {cols.map((col) => (\n <td key={col.key} className=\"px-3 py-2 tabular-nums\">\n {text(r?.[col.key])}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n }\n case \"Image\": {\n const url = src(p(\"src\"), ctx.assetUrl);\n return url ? <img src={url} alt={text(p(\"alt\"))} className=\"w-full rounded-xl\" /> : null;\n }\n case \"BarChart\":\n return (\n <Titled title={text(p(\"title\"))}>\n <Bars data={points(p(\"points\"), p(\"labelKey\"), p(\"valueKey\"))} />\n </Titled>\n );\n case \"LineChart\":\n return (\n <Titled title={text(p(\"title\"))}>\n <Line data={points(p(\"points\"), p(\"labelKey\"), p(\"valueKey\"))} />\n </Titled>\n );\n case \"DonutChart\":\n return (\n <Titled title={text(p(\"title\"))}>\n <Donut data={points(p(\"slices\"), p(\"labelKey\"), p(\"valueKey\"))} />\n </Titled>\n );\n case \"Actions\":\n return (\n <div className=\"flex flex-wrap gap-2\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n );\n case \"Button\": {\n const action = text(p(\"action\")) as SurfaceAction[\"action\"];\n if (!ctx.onAction && action !== \"open\") {\n return null;\n }\n return (\n <button\n type=\"button\"\n onClick={() => {\n const target = p(\"target\");\n if (action === \"open\") {\n const url = src(target, ctx.assetUrl);\n if (url) {\n window.open(url, \"_blank\", \"noopener\");\n }\n return;\n }\n ctx.onAction?.({ action, target });\n }}\n className=\"inline-flex h-9 items-center rounded-full bg-paper-2 px-4 text-[0.875rem] text-ink-2 hover:text-ink coarse:h-11\"\n >\n {text(p(\"label\"))}\n </button>\n );\n }\n case \"Tabs\":\n return <TabsView c={c} ctx={ctx} row={row} />;\n case \"Card\": {\n const image = src(p(\"image\"), ctx.assetUrl);\n const eyebrow = text(p(\"eyebrow\"));\n const subtitle = text(p(\"subtitle\"));\n return (\n <article className=\"overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n {image ? <img src={image} alt=\"\" className=\"aspect-[16/9] w-full object-cover\" /> : null}\n <div className={cn(\"flex flex-col gap-1.5 px-4 py-3.5\", c.children && \"bg-paper-2/60\")}>\n {eyebrow ? (\n <div className=\"font-medium text-[0.6875rem] text-ink-3 uppercase tracking-[0.14em]\">\n {eyebrow}\n </div>\n ) : null}\n <h3 className=\"text-balance font-display font-semibold text-[1.1875rem] leading-snug\">\n {text(p(\"title\"))}\n </h3>\n {subtitle ? (\n <p className=\"text-[0.875rem] text-ink-3 leading-relaxed\">{subtitle}</p>\n ) : null}\n <Metas items={metasOf(c, ctx, row)} />\n </div>\n {c.children ? (\n <div className=\"flex flex-col gap-3 border-border-soft border-t px-4 py-3.5 empty:hidden\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n ) : null}\n </article>\n );\n }\n case \"Fold\":\n return (\n <details\n open={Boolean(p(\"open\"))}\n className=\"group border-border-soft border-t pt-3 first:border-0 first:pt-0\"\n >\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 font-display font-semibold text-[1rem] [&::-webkit-details-marker]:hidden\">\n {text(p(\"title\"))}\n <ChevronRight className=\"size-4 text-ink-3 transition-transform group-open:rotate-90 motion-reduce:transition-none\" />\n </summary>\n <div className=\"flex flex-col gap-3 pt-3\">\n <Children c={c} ctx={ctx} row={row} />\n </div>\n </details>\n );\n case \"Group\": {\n const kids = c.children;\n if (!kids || Array.isArray(kids)) {\n return null;\n }\n const items = rows(bound({ path: kids.path }, ctx.data, row));\n return (\n <div className=\"flex flex-col gap-5\">\n {grouped(items, text(p(\"by\")), rows(p(\"order\")).map(text)).map(([name, list]) => (\n <section key={name} className=\"flex flex-col gap-2\">\n {name ? (\n <h4 className=\"font-semibold text-[0.6875rem] text-second uppercase tracking-[0.14em]\">\n {name}\n </h4>\n ) : null}\n {list.map((item, i) => (\n <Node key={i} id={kids.componentId} ctx={ctx} row={item} />\n ))}\n </section>\n ))}\n </div>\n );\n }\n case \"Chips\": {\n const labelKey = text(p(\"labelKey\"));\n const flagKey = text(p(\"flagKey\"));\n const flag = text(p(\"flag\"));\n const title = text(p(\"title\"));\n return (\n <div className=\"flex flex-col gap-2\">\n {title ? <div className=\"text-[0.8125rem] text-ink-3\">{title}</div> : null}\n <div className=\"flex flex-wrap gap-1.5\">\n {rows(p(\"items\")).map((item, i) => {\n const flagged = Boolean(flagKey && cell(item, flagKey));\n return (\n <span\n key={i}\n className={cn(\n \"rounded-full px-2.5 py-1 text-[0.8125rem]\",\n flagged\n ? \"bg-amber-tint font-medium text-ink ring-1 ring-amber/60\"\n : \"bg-card text-ink-2 ring-1 ring-border-soft\",\n )}\n >\n {labelOf(item, labelKey)}\n {flagged && flag ? ` · ${flag}` : \"\"}\n </span>\n );\n })}\n </div>\n </div>\n );\n }\n case \"Checklist\":\n return <ChecklistView c={c} ctx={ctx} row={row} />;\n case \"Steps\": {\n const textKey = text(p(\"textKey\")) || \"text\";\n const minutesKey = text(p(\"minutesKey\")) || \"minutes\";\n return (\n <ol className=\"flex flex-col gap-3\">\n {rows(p(\"items\")).map((item, i) => {\n const words = typeof item === \"object\" ? text(cell(item, textKey)) : text(item);\n const time = minutes(cell(item, minutesKey));\n return (\n <li key={i} className=\"grid grid-cols-[1.5rem_1fr] gap-2\">\n <span className=\"font-display font-semibold text-[1.125rem] text-ember leading-snug\">\n {i + 1}\n </span>\n <span className=\"text-[0.9375rem] leading-relaxed\">\n {words}\n {time ? (\n <span className=\"ml-1.5 inline-flex items-center gap-1 whitespace-nowrap rounded-full bg-paper-2 px-2 py-0.5 align-[1px] text-[0.75rem] text-ink-2\">\n <Clock className=\"size-3\" />\n {time}\n </span>\n ) : null}\n </span>\n </li>\n );\n })}\n </ol>\n );\n }\n case \"Link\": {\n // The entry it opens: title, subtitle and meta read it; the eyebrow reads the row it sits in.\n const key = text(p(\"key\")) || \"id\";\n const value = text(p(\"value\"));\n const entry = rows(p(\"items\")).find((item) => text(cell(item, key)) === value);\n const view = (c as Record<string, unknown>).view;\n if (entry === undefined) {\n return null;\n }\n const at = (k: string) => bound((c as Record<string, unknown>)[k], ctx.data, entry);\n const eyebrow = text(p(\"eyebrow\"));\n const meta = metasOf(c, ctx, entry);\n return (\n <button\n type=\"button\"\n onClick={() => typeof view === \"string\" && ctx.open(view, entry)}\n className={cn(\n \"group flex w-full items-center gap-3 text-left\",\n text(p(\"look\")) === \"card\"\n ? \"rounded-xl bg-card p-4 ring-1 ring-border-soft hover:ring-ink-4\"\n : \"-mx-2 w-[calc(100%+1rem)] rounded-lg px-2 py-2 hover:bg-paper-2/70 coarse:py-3\",\n )}\n >\n <span className=\"min-w-0 flex-1\">\n {eyebrow ? (\n <span className=\"block font-semibold text-[0.6875rem] text-second uppercase tracking-[0.14em]\">\n {eyebrow}\n </span>\n ) : null}\n <span className=\"block font-display font-semibold text-[1rem] leading-snug group-hover:text-ember\">\n {text(at(\"title\"))}\n </span>\n {at(\"subtitle\") ? (\n <span className=\"block text-[0.8125rem] text-ink-3\">{text(at(\"subtitle\"))}</span>\n ) : null}\n {meta.length ? (\n <span className=\"mt-0.5 flex items-center gap-1 text-[0.75rem] text-ink-3\">\n <Clock className=\"size-3\" />\n {meta.join(\" · \")}\n </span>\n ) : null}\n </span>\n <ChevronRight className=\"size-4 shrink-0 text-ink-3\" />\n </button>\n );\n }\n case \"Callout\": {\n const tone = text(p(\"tone\")) || \"tip\";\n const title = text(p(\"title\"));\n return (\n <div\n className={cn(\n \"flex gap-2.5 rounded-xl px-4 py-3 text-[0.875rem] leading-relaxed\",\n tone === \"tip\" && \"bg-second-tint\",\n tone === \"note\" && \"bg-paper-2\",\n tone === \"warning\" && \"bg-amber-tint\",\n )}\n >\n <Lightbulb\n className={cn(\"mt-0.5 size-4 shrink-0\", tone === \"tip\" ? \"text-second\" : \"text-ink-3\")}\n />\n <p>\n {title ? <b className=\"font-semibold\">{title} </b> : null}\n {text(p(\"text\"))}\n </p>\n </div>\n );\n }\n }\n return null;\n}\n\nexport function SurfaceView({\n surface,\n assetUrl,\n onAction,\n initial,\n onState,\n}: {\n surface: Surface;\n assetUrl: (id: string) => string;\n onAction?: (a: SurfaceAction) => void;\n /** What the person did in the view last time (kept with the run). */\n initial?: SurfaceState;\n /** Keeps what the person did; without it, it lasts as long as the page. */\n onState?: (next: SurfaceState) => void;\n}) {\n const [state, setState] = useState<SurfaceState>(initial ?? {});\n const [sheet, setSheet] = useState<{ view: string; row: unknown } | null>(null);\n const ctx: Ctx = {\n byId: new Map(surface.components.map((c) => [c.id, c])),\n data: surface.data,\n assetUrl,\n onAction,\n state,\n setState: (id, value) => {\n const next = { ...state, [id]: value };\n setState(next);\n onState?.(next);\n },\n open: (view, row) => setSheet({ view, row }),\n };\n return (\n <>\n <Node id=\"root\" ctx={ctx} />\n <Dialog open={sheet !== null} onClose={() => setSheet(null)} height=\"tall\">\n {sheet ? (\n <div className=\"flex flex-col gap-4\">\n <Node id={sheet.view} ctx={ctx} row={sheet.row} />\n <button\n type=\"button\"\n onClick={() => setSheet(null)}\n className=\"h-10 self-center rounded-full bg-paper-2 px-5 text-[0.875rem] text-ink-2 hover:text-ink\"\n >\n {t(\"surface.close\")}\n </button>\n </div>\n ) : null}\n </Dialog>\n </>\n );\n}\n","import type { Format, Step } from \"@engenty/wizards-shared/definition\";\nimport { stepShape } from \"@engenty/wizards-shared/definition\";\nimport type { StepOutput } from \"@engenty/wizards-shared/run\";\nimport { labelOf } from \"@engenty/wizards-shared/shape\";\nimport DOMPurify from \"dompurify\";\nimport { Check, Copy, Download, FileText, Maximize2, Printer, Share } from \"lucide-react\";\nimport { marked } from \"marked\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { canShareFiles } from \"./device\";\nimport { appCall, appCan, appDownload, asset, standalone, withBase } from \"./env.js\";\nimport { t } from \"./i18n.js\";\nimport { JsonView } from \"./json-view.js\";\nimport { type Written, writePdf } from \"./pdf.js\";\nimport { type SurfaceAction, SurfaceView } from \"./surface\";\nimport { cn, Spinner, Textarea } from \"./ui.js\";\n\nexport function Markdown({ text, className }: { text: string; className?: string }) {\n const html = useMemo(\n () => DOMPurify.sanitize(marked.parse(text, { async: false }) as string),\n [text],\n );\n return (\n // biome-ignore lint/security/noDangerouslySetInnerHtml: model output, sanitised by DOMPurify above\n <div className={cn(\"prose-zen\", className)} dangerouslySetInnerHTML={{ __html: html }} />\n );\n}\n\n/**\n * Generated HTML in a sandboxed frame: scripts run (scrubbers, tabs, animations) but in an opaque\n * origin with no network. The frame is mounted only once its HTML is there — Chrome paints a\n * sandboxed frame whose content changes after mount blank. `page` is the layout width; the frame\n * is scaled to fit.\n */\nexport function HtmlFrame({\n src,\n page,\n height,\n fit,\n flow,\n state,\n onState,\n}: {\n src: string;\n /** Layout width in CSS px; null = the frame's own width. */\n page: number | null;\n height: number;\n /** Scale up as well as down, so a fixed-size widget fills the width. */\n fit?: boolean;\n /**\n * A widget laid out as part of the page: as wide as the page, as tall as its content says\n * (`height` until it does), never scaled. It may keep a state and share text.\n */\n flow?: boolean;\n /** What the widget kept last time (`wizard.state`). */\n state?: Record<string, unknown>;\n onState?: (state: Record<string, unknown>) => void;\n}) {\n const frame = useRef<HTMLIFrameElement>(null);\n const [tall, setTall] = useState(height);\n // The state the frame started with: later saves must not reload it.\n const [initial] = useState(() => state ?? {});\n const keep = useRef(onState);\n keep.current = onState;\n useEffect(() => {\n const listen = (e: MessageEvent) => {\n if (!frame.current || e.source !== frame.current.contentWindow) {\n return;\n }\n const msg = e.data as { wizard?: string; height?: unknown; state?: unknown; text?: unknown };\n if (msg?.wizard === \"height\" && typeof msg.height === \"number\") {\n setTall(Math.min(20_000, Math.max(120, Math.ceil(msg.height))));\n } else if (msg?.wizard === \"state\" && msg.state && typeof msg.state === \"object\") {\n keep.current?.(msg.state as Record<string, unknown>);\n } else if (msg?.wizard === \"share\" && typeof msg.text === \"string\") {\n const text = msg.text.slice(0, 10_000);\n if (navigator.share) {\n navigator.share({ text }).catch(() => undefined);\n } else {\n navigator.clipboard?.writeText(text).catch(() => undefined);\n }\n }\n };\n window.addEventListener(\"message\", listen);\n return () => window.removeEventListener(\"message\", listen);\n }, []);\n const wrap = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(0);\n useEffect(() => {\n const el = wrap.current;\n if (!el) {\n return;\n }\n const ro = new ResizeObserver(() => setWidth(el.clientWidth));\n ro.observe(el);\n setWidth(el.clientWidth);\n return () => ro.disconnect();\n }, []);\n const [html, setHtml] = useState<{ src: string; text: string } | null>(null);\n useEffect(() => {\n let alive = true;\n fetch(src, { credentials: \"include\" })\n .then((r) => (r.ok ? r.text() : \"\"))\n .then((text) => alive && setHtml({ src, text }));\n return () => {\n alive = false;\n };\n }, [src]);\n const layout = flow ? width || 360 : (page ?? Math.max(width, 900));\n const scale = flow ? 1 : width ? (fit ? width / layout : Math.min(1, width / layout)) : 1;\n const shown = flow ? tall : height;\n // The kept state goes in ahead of the widget's own scripts, so `wizard.state` is there at once.\n const doc =\n flow && html\n ? `<script>window.__WIZARD_STATE=${JSON.stringify(initial).replace(/</g, \"\\\\u003c\")}</script>${html.text}`\n : html?.text;\n return (\n <div\n ref={wrap}\n className={cn(\n \"relative overflow-hidden\",\n !flow && \"rounded-lg bg-white ring-1 ring-border-soft\",\n )}\n style={{ height: shown * scale }}\n >\n {html?.src === src ? (\n <iframe\n ref={frame}\n key={src}\n title={t(\"output.preview\")}\n srcDoc={doc}\n sandbox=\"allow-scripts allow-popups allow-popups-to-escape-sandbox\"\n className=\"absolute top-0 left-0 origin-top-left border-0\"\n style={{ width: layout, height: shown, transform: `scale(${scale})` }}\n />\n ) : (\n <div className=\"absolute inset-0 animate-pulse bg-paper-2\" />\n )}\n {flow ? null : (\n <a\n href={src}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"absolute top-3 right-3 inline-flex size-9 items-center justify-center rounded-full bg-card/90 text-ink-2 shadow-soft ring-1 ring-border-soft backdrop-blur hover:text-ink coarse:size-11\"\n aria-label={t(\"run.openFull\")}\n >\n <Maximize2 className=\"size-4\" />\n </a>\n )}\n </div>\n );\n}\n\n/**\n * Where the artwork sits inside the Commission's icon files (the half-transparent variants):\n * each leaves clear space around its shape, and the label is laid out by the shape.\n */\nconst AI_ICONS = {\n disc: { file: \"ai\", box: 566.93, x: 89.28, y: 100.72, w: 365.49, h: 365.49 },\n generated: { file: \"ai-generated\", box: 1789.84, x: 207.3, y: 144.36, w: 1384.24, h: 266.41 },\n edited: { file: \"ai-modified\", box: 1700.79, x: 231.11, y: 144.36, w: 1230.56, h: 266.41 },\n} as const;\n\n/** One of the icons, scaled so that its shape is `size` px high, with the shape at the box's corner. */\nfunction AiIcon({\n icon,\n tone,\n size,\n className,\n}: {\n icon: keyof typeof AI_ICONS;\n tone: \"white\" | \"black\";\n size: number;\n className?: string;\n}) {\n const art = AI_ICONS[icon];\n const scale = size / art.h;\n return (\n <img\n src={asset(`ai-labels/${art.file}-${tone}.svg`)}\n alt=\"\"\n draggable={false}\n className={cn(\"pointer-events-none absolute max-w-none select-none\", className)}\n style={{\n width: art.box * scale,\n height: 566.93 * scale,\n left: -art.x * scale,\n top: -art.y * scale,\n }}\n />\n );\n}\n\n/**\n * The EU's label on media a model made or changed: the round \"AI\" alone, and on hover, on focus\n * and on a tap the long form — \"AI GENERATED\" or \"AI MODIFIED\". It lies over the picture in the\n * interface and is not part of the file; the file says the same in its metadata.\n */\nexport function AiBadge({\n ai,\n className,\n}: {\n ai: \"generated\" | \"edited\" | undefined;\n /** Where on the media it sits; default: bottom left. \"static\" sets it into the text flow. */\n className?: string;\n}) {\n // A phone has no hover: a tap opens the label and the next one closes it.\n const [open, setOpen] = useState(false);\n if (!ai) {\n return null;\n }\n // Small, and of glass: the icon's ground is half transparent, the picture behind it blurred.\n const size = 18;\n const long = AI_ICONS[ai];\n const inline = className === \"static\";\n const shown = \"opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100\";\n const hidden = \"opacity-100 group-hover:opacity-0 group-focus-visible:opacity-0\";\n // Over a picture the white label reads on anything; in the text it follows the theme.\n const tones = inline\n ? ([\n [\"black\", \"dark:hidden\"],\n [\"white\", \"hidden dark:block\"],\n ] as const)\n : ([[\"white\", \"\"]] as const);\n return (\n <button\n type=\"button\"\n aria-label={t(ai === \"edited\" ? \"ai.modified\" : \"ai.generated\")}\n aria-expanded={open}\n data-open={open}\n onClick={() => setOpen((v) => !v)}\n className={cn(\n \"group block cursor-default overflow-hidden rounded-full backdrop-blur-md transition-[width] duration-200\",\n \"w-[var(--ai-disc)] hover:w-[var(--ai-long)] focus-visible:w-[var(--ai-long)] data-[open=true]:w-[var(--ai-long)]\",\n inline\n ? \"relative\"\n : cn(\"absolute shadow-[0_1px_3px_rgba(0,0,0,0.25)]\", className ?? \"bottom-2 left-2\"),\n )}\n style={\n {\n height: size,\n \"--ai-disc\": `${size}px`,\n \"--ai-long\": `${(long.w / long.h) * size}px`,\n } as React.CSSProperties\n }\n >\n {tones.map(([tone, theme]) => (\n <span key={tone} className={theme}>\n <AiIcon\n icon=\"disc\"\n tone={tone}\n size={size}\n className={cn(\"transition-opacity duration-200\", open ? \"opacity-0\" : hidden)}\n />\n <AiIcon\n icon={ai}\n tone={tone}\n size={size}\n className={cn(\"transition-opacity duration-200\", open ? \"opacity-100\" : shown)}\n />\n </span>\n ))}\n </button>\n );\n}\n\n/** What people read for a key of a step's output: its label in the step's shape. */\nfunction labelFor(step: Step, key: string): string {\n const f = step.type === \"agent\" ? stepShape(step).fields[key] : undefined;\n return f ? labelOf(key, f) : key;\n}\n\nfunction CopyButton({ text }: { text: string }) {\n const [done, setDone] = useState(false);\n return (\n <button\n type=\"button\"\n onClick={() => {\n void navigator.clipboard.writeText(text);\n setDone(true);\n setTimeout(() => setDone(false), 1500);\n }}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full bg-paper-2 px-3 text-[0.8125rem] text-ink-2 hover:text-ink coarse:h-11 coarse:px-4\"\n >\n {done ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {done ? t(\"share.copied\") : t(\"run.copy\")}\n </button>\n );\n}\n\n/** One step's result: the right preview for what it produced. */\nexport function OutputView({\n base,\n step,\n output,\n editable,\n draft,\n onDraft,\n picked,\n onPick,\n onSurfaceAction,\n onView,\n}: {\n /** `/api/runs/<id>` or `/api/shares/<token>` — where the output's files are served. */\n base: string;\n step: Step;\n output: StepOutput | null;\n editable?: boolean;\n draft?: string;\n onDraft?: (text: string) => void;\n /** Several results: the ones picked to be made again (from 0), and the tap that picks one. */\n picked?: number[];\n onPick?: (index: number) => void;\n /** A surface's buttons: \"regenerate\" where the review allows it. */\n onSurfaceAction?: (a: SurfaceAction) => void;\n /** Keeps what the person did in the view (ticks, a widget's state) with the run. */\n onView?: (state: Record<string, unknown>) => void;\n}) {\n if (!output) {\n return null;\n }\n const assetUrl = (id: string) => withBase(`${base}/assets/${id}`);\n // A view from the catalog stands for the step's data.\n if (output.surface) {\n return (\n <SurfaceView\n surface={output.surface}\n assetUrl={assetUrl}\n onAction={onSurfaceAction}\n initial={output.view}\n onState={onView}\n />\n );\n }\n if (step.type === \"widget\" || step.type === \"film\") {\n const film = output.assets?.find((a) => a.kind === \"video\");\n if (film) {\n const poster = output.assets?.find((a) => a.kind === \"poster\");\n const tall =\n step.type === \"film\"\n ? step.format === \"9:16\"\n : (step.size?.height ?? 0) > (step.size?.width ?? 1);\n const video = (\n <div className={cn(\"relative mx-auto\", tall ? \"w-fit\" : \"w-full\")}>\n {/* biome-ignore lint/a11y/useMediaCaption: the film's captions are part of the picture */}\n <video\n src={assetUrl(film.id)}\n poster={poster ? assetUrl(poster.id) : undefined}\n controls\n playsInline\n className={cn(\n \"rounded-lg bg-black ring-1 ring-border-soft\",\n tall ? \"max-h-[76vh]\" : \"w-full\",\n )}\n />\n <AiBadge ai={film.ai} className=\"top-2 right-2\" />\n </div>\n );\n // A film step's text is the client's own word on what it made or changed — or why not.\n return step.type === \"film\" && output.text ? (\n <div className=\"flex flex-col gap-4\">\n {video}\n <Markdown text={output.text} className=\"text-[0.875rem] text-ink-2\" />\n </div>\n ) : (\n video\n );\n }\n if (step.type === \"film\") {\n return null;\n }\n const html = output.assets?.find((a) => a.mime === \"text/html\");\n const size = step.size ?? { width: 1280, height: 720 };\n return html ? (\n <HtmlFrame\n src={assetUrl(html.id)}\n page={size.width}\n height={size.height}\n fit\n flow={step.layout === \"page\"}\n state={output.view}\n onState={onView}\n />\n ) : null;\n }\n if (step.type === \"generate\") {\n const asset = output.assets?.[0];\n if (!asset) {\n return null;\n }\n if (step.asset === \"voice\") {\n return (\n <div className=\"flex flex-col gap-3\">\n {/* biome-ignore lint/a11y/useMediaCaption: what is said stands right below */}\n <audio src={assetUrl(asset.id)} controls className=\"w-full\" />\n <AiBadge ai={asset.ai} className=\"static\" />\n {output.text ? (\n <p className=\"text-[0.875rem] text-ink-2 leading-relaxed\">{output.text}</p>\n ) : null}\n </div>\n );\n }\n const several = (output.assets?.length ?? 0) > 1;\n if (several && (step.asset === \"image\" || step.asset === \"video\")) {\n const tall = step.options?.aspectRatio === \"9:16\" || step.options?.aspectRatio === \"2:3\";\n return (\n <div className={cn(\"grid gap-3\", tall ? \"grid-cols-2 sm:grid-cols-3\" : \"sm:grid-cols-2\")}>\n {output.assets?.map((a, i) => {\n const on = picked?.includes(i);\n return (\n <figure\n key={a.id}\n className={cn(\n \"relative overflow-hidden rounded-lg bg-paper-2 ring-1 ring-border-soft\",\n on && \"ring-2 ring-ember\",\n )}\n >\n {step.asset === \"image\" ? (\n <img src={assetUrl(a.id)} alt={`${step.title} ${i + 1}`} className=\"w-full\" />\n ) : (\n // biome-ignore lint/a11y/useMediaCaption: generated clips have no caption track to offer\n <video src={assetUrl(a.id)} controls playsInline loop className=\"w-full\" />\n )}\n {onPick ? (\n <button\n type=\"button\"\n aria-pressed={on}\n onClick={() => onPick(i)}\n className={cn(\n \"absolute top-2 left-2 inline-flex h-8 items-center gap-1.5 rounded-full px-3 font-medium text-[0.75rem] shadow-soft backdrop-blur coarse:h-11\",\n on ? \"bg-ember text-ember-on\" : \"bg-card/90 text-ink-2 hover:text-ink\",\n )}\n >\n {on ? <Check className=\"size-3.5\" /> : null}\n {t(on ? \"run.pickedItem\" : \"run.pickItem\", { n: i + 1 })}\n </button>\n ) : (\n <span className=\"absolute top-2 left-2 rounded-full bg-card/90 px-2.5 py-1 font-medium text-[0.75rem] text-ink-2\">\n {i + 1}\n </span>\n )}\n <AiBadge\n ai={a.ai}\n className={step.asset === \"image\" ? \"bottom-2 left-2\" : \"top-2 right-2\"}\n />\n </figure>\n );\n })}\n </div>\n );\n }\n if (step.asset === \"image\") {\n return (\n <div className=\"relative\">\n <img\n src={assetUrl(asset.id)}\n alt={step.title}\n className=\"w-full rounded-lg bg-paper-2 ring-1 ring-border-soft\"\n />\n <AiBadge ai={asset.ai} />\n </div>\n );\n }\n if (step.asset === \"video\") {\n const tall = step.options?.aspectRatio === \"9:16\";\n return (\n <div className={cn(\"relative mx-auto\", tall ? \"w-fit\" : \"w-full\")}>\n {/* biome-ignore lint/a11y/useMediaCaption: generated clips have no caption track to offer */}\n <video\n src={assetUrl(asset.id)}\n controls\n playsInline\n loop\n className={cn(\n \"rounded-lg bg-black ring-1 ring-border-soft\",\n tall ? \"max-h-[70vh]\" : \"w-full\",\n )}\n />\n <AiBadge ai={asset.ai} className=\"top-2 left-2\" />\n </div>\n );\n }\n return step.asset === \"document\" ? (\n <HtmlFrame src={assetUrl(asset.id)} page={820} height={1100} />\n ) : (\n <HtmlFrame src={assetUrl(asset.id)} page={null} height={760} />\n );\n }\n if (step.type === \"agent\") {\n const images =\n output.assets?.filter((a) => a.kind !== \"file\" && a.mime.startsWith(\"image/\")) ?? [];\n const files = output.assets?.filter((a) => a.kind === \"file\") ?? [];\n return (\n <div className=\"flex flex-col gap-4\">\n {step.output.format === \"json\" && output.json !== undefined ? (\n <JsonView step={step} json={output.json} />\n ) : editable ? (\n <Textarea\n value={draft ?? output.text ?? \"\"}\n onChange={(e) => onDraft?.(e.target.value)}\n minRows={4}\n maxRows={24}\n />\n ) : step.output.format === \"markdown\" ? (\n <Markdown text={output.text ?? \"\"} />\n ) : (\n <div className=\"whitespace-pre-wrap text-[1rem] leading-relaxed\">{output.text}</div>\n )}\n {images.map((img) => (\n <div key={img.id} className=\"relative\">\n <img\n src={assetUrl(img.id)}\n alt=\"\"\n className=\"w-full rounded-lg ring-1 ring-border-soft\"\n />\n <AiBadge ai={img.ai} />\n </div>\n ))}\n {files.length ? (\n <ul className=\"overflow-hidden rounded-lg ring-1 ring-border-soft\">\n {files.map((f) => (\n <li key={f.id} className=\"border-border-soft border-b last:border-0\">\n <a\n href={assetUrl(f.id)}\n download={f.name}\n onClick={(e) => appDownload(e, assetUrl(f.id), f.name)}\n className=\"flex items-center gap-2 px-3 py-2 text-[0.8125rem] hover:bg-paper-2 coarse:min-h-11\"\n >\n <FileText className=\"size-3.5 shrink-0 text-ink-3\" />\n <span className=\"min-w-0 flex-1 truncate\">{f.name}</span>\n </a>\n </li>\n ))}\n </ul>\n ) : null}\n {step.output.format !== \"json\" && !editable && output.text ? (\n <div>\n <CopyButton text={output.text} />\n </div>\n ) : null}\n </div>\n );\n }\n return null;\n}\n\n/** A download format as a person reads it. */\nexport const FORMAT_LABEL: Record<Format, string> = {\n png: \"PNG\",\n mp4: \"MP4\",\n mp3: \"MP3\",\n pdf: \"PDF\",\n docx: \"Word\",\n html: \"HTML\",\n md: \"Markdown\",\n txt: \"Text\",\n csv: \"CSV\",\n xlsx: \"Excel\",\n json: \"JSON\",\n zip: \"ZIP\",\n};\n\n/** The file's name as the server sends it, for the share sheet and \"Save to Files\". */\nfunction downloadName(res: Response, fallback: string): string {\n const header = res.headers.get(\"content-disposition\") ?? \"\";\n return header.match(/filename=\"([^\"]+)\"/)?.[1] ?? fallback;\n}\n\n/** A file made in the browser, saved as a download would be. */\nfunction saveFile(file: File) {\n const url = URL.createObjectURL(file);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = file.name;\n a.rel = \"noopener\";\n document.body.append(a);\n a.click();\n a.remove();\n setTimeout(() => URL.revokeObjectURL(url), 60_000);\n}\n\n/**\n * Hands a result to the phone's share sheet as a file — Mail, WhatsApp, \"Save to Files\", \"Open\n * in …\". The file is fetched first (or made here); when that took longer than the browser lets\n * a tap wait, a second tap sends it.\n */\nfunction ShareFileButton({\n url,\n format,\n title,\n make,\n}: {\n url: string;\n format: Format;\n title?: string;\n /** The file made in the browser instead of fetched: a written output's PDF on a site. */\n make?: () => Promise<File>;\n}) {\n const [state, setState] = useState<\"idle\" | \"busy\" | \"ready\">(\"idle\");\n const file = useRef<File | null>(null);\n const share = async () => {\n if (appCan(\"share\") && !make) {\n // The app fetches the file itself and opens the native share sheet with it.\n setState(\"busy\");\n await appCall(\"share\", { url: new URL(url, location.href).href, title }).catch(\n () => undefined,\n );\n setState(\"idle\");\n return;\n }\n try {\n if (!file.current) {\n setState(\"busy\");\n if (make) {\n file.current = await make();\n } else {\n const res = await fetch(url, { credentials: \"include\" });\n if (!res.ok) {\n throw new Error(String(res.status));\n }\n const blob = await res.blob();\n file.current = new File([blob], downloadName(res, `download.${format}`), {\n type: blob.type.split(\";\")[0],\n });\n }\n }\n const data = { files: [file.current], title };\n if (!navigator.canShare(data)) {\n // A type the share sheet does not take: it is downloaded instead.\n if (make) {\n saveFile(file.current);\n } else {\n location.href = url;\n }\n setState(\"idle\");\n return;\n }\n await navigator.share(data);\n setState(\"idle\");\n } catch (err) {\n // Fetched, but the tap is too long ago for the browser: the next tap shares at once.\n setState(file.current && (err as DOMException).name === \"NotAllowedError\" ? \"ready\" : \"idle\");\n }\n };\n return (\n <button\n type=\"button\"\n onClick={() => void share()}\n disabled={state === \"busy\"}\n aria-label={t(\"run.shareFile\")}\n title={t(\"run.shareFile\")}\n className={cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-full px-3 font-medium text-[0.8125rem] transition coarse:h-11 coarse:px-4\",\n state === \"ready\"\n ? \"bg-ember-tint text-ink ring-1 ring-ember\"\n : \"bg-paper-2 text-ink-2 hover:bg-paper-3 hover:text-ink\",\n )}\n >\n {state === \"busy\" ? <Spinner className=\"size-3.5\" /> : <Share className=\"size-3.5\" />}\n {state === \"ready\" ? t(\"run.shareNow\") : t(\"run.share\")}\n </button>\n );\n}\n\nconst SHARES_FILES = appCan(\"share\") || canShareFiles();\n\nexport function DownloadButtons({\n base,\n stepId,\n formats,\n title,\n step,\n output,\n foot,\n}: {\n base: string;\n stepId: string;\n formats: Format[];\n /** Named in the share sheet. */\n title?: string;\n /** The step and its output: on a standalone host a written output's PDF is made here. */\n step?: Step;\n output?: StepOutput;\n /** The foot of a PDF made here: the wizard, the date. */\n foot?: string;\n}) {\n const href = (f: Format) => withBase(`${base}/steps/${stepId}/download?format=${f}`);\n const [busy, setBusy] = useState(false);\n const made = useRef<File | null>(null);\n // The server of a standalone host writes no PDF: a written output's PDF is made in the browser.\n const written: Written | null =\n standalone() && step?.type === \"agent\" && output && (output.text || output.json !== undefined)\n ? {\n title: title ?? step.title,\n text: output.text,\n json: step.output.format === \"json\" ? output.json : undefined,\n label: (key) => labelFor(step, key),\n foot,\n }\n : null;\n const makePdf = async () => {\n if (!written) {\n throw new Error(\"nothing written\");\n }\n made.current ??= await writePdf(written);\n return made.current;\n };\n const savePdf = async () => {\n setBusy(true);\n try {\n saveFile(await makePdf());\n } catch (err) {\n console.warn(`pdf: ${(err as Error).message}`);\n // Without the library (offline, a blocked script): the page to print stands in.\n if (formats.includes(\"html\")) {\n window.open(href(\"html\"), \"_blank\", \"noopener\");\n }\n } finally {\n setBusy(false);\n }\n };\n const look = (i: number) =>\n cn(\n \"inline-flex h-9 items-center gap-1.5 rounded-full px-3.5 font-medium text-[0.8125rem] transition coarse:h-11 coarse:px-4\",\n i === 0\n ? \"bg-primary text-primary-foreground hover:brightness-105\"\n : \"bg-paper-2 text-ink-2 hover:bg-paper-3 hover:text-ink\",\n );\n const inBrowser = (f: Format) => f === \"pdf\" && written !== null;\n return (\n <div className=\"flex flex-wrap gap-2\">\n {formats.map((f, i) =>\n inBrowser(f) ? (\n <button\n key={f}\n type=\"button\"\n onClick={() => void savePdf()}\n disabled={busy}\n className={look(i)}\n >\n {busy ? (\n <Spinner className=\"size-3.5\" />\n ) : i === 0 ? (\n <Download className=\"size-3.5\" />\n ) : null}\n {FORMAT_LABEL[f]}\n </button>\n ) : f === \"html\" && standalone() ? (\n // On a site the HTML of a result is a page to print, opened beside the run.\n <a key={f} href={href(f)} target=\"_blank\" rel=\"noopener\" className={look(i)}>\n {i === 0 ? <Printer className=\"size-3.5\" /> : null}\n {t(\"run.print\")}\n </a>\n ) : (\n <a key={f} href={href(f)} onClick={(e) => appDownload(e, href(f))} className={look(i)}>\n {i === 0 ? <Download className=\"size-3.5\" /> : null}\n {FORMAT_LABEL[f]}\n </a>\n ),\n )}\n {SHARES_FILES && formats.length ? (\n <ShareFileButton\n key={href(formats[0])}\n url={href(formats[0])}\n format={formats[0]}\n title={title}\n make={inBrowser(formats[0]) ? makePdf : undefined}\n />\n ) : null}\n </div>\n );\n}\n","import {\n isDecidedField,\n type PageStep,\n type ResultStep,\n type ReviewStep,\n type Step,\n shownFields,\n stepShape,\n} from \"@engenty/wizards-shared/definition\";\nimport type { RunView, StepOutput } from \"@engenty/wizards-shared/run\";\nimport {\n ArrowLeft,\n ArrowRight,\n Bell,\n BellRing,\n Languages,\n Pencil,\n RefreshCw,\n RotateCcw,\n Sparkles,\n} from \"lucide-react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { AskPanel } from \"./AskPanel.js\";\nimport { DataEditor, editableData, StudioData } from \"./data.js\";\nimport {\n disableNotify,\n enableNotify,\n notificationsBlocked,\n signalPerson,\n useKeyboardInset,\n useNotifyState,\n useWakeLock,\n} from \"./device\";\nimport { api, runBase, runnerEnv, withBase } from \"./env.js\";\nimport { FieldInput, type Values } from \"./fields\";\nimport { eventText, setChoiceLabels, t } from \"./i18n.js\";\nimport { DownloadButtons, OutputView } from \"./outputs\";\nimport { ListCheck, ListDownloads, ListTable, StoreButton } from \"./store\";\nimport { Button, Card, cn, LinkedText, Spinner, Textarea } from \"./ui.js\";\n\n/**\n * A run as the runner drives it: the view, and the commands a person can give. `useRun` in the\n * studio (a server-sent stream), `useLocalRun` in the WordPress plugin (one request per step).\n */\nexport interface RunSource {\n view: RunView | null;\n notFound: boolean;\n error: string | null;\n busy: boolean;\n fieldErrors: Record<string, string>;\n submitPage(stepId: string, values: Record<string, unknown>): Promise<boolean>;\n accept(\n stepId: string,\n edits?: Record<string, string | Record<string, unknown>>,\n ): Promise<boolean>;\n regenerate(stepId: string, target: string, note: string, items?: number[]): Promise<boolean>;\n back(): Promise<boolean>;\n retry(): Promise<boolean>;\n /** A finished result's text in the language the run is read in (a translated wizard). */\n translateResult?(stepId: string): Promise<boolean>;\n}\n\ntype Run = RunSource;\n\nfunction Progress({ view }: { view: RunView }) {\n const pct = Math.round(\n (Math.min(view.progress.done, view.progress.total) / Math.max(1, view.progress.total)) * 100,\n );\n return (\n <div className=\"h-[3px] w-full bg-paper-2\">\n <div\n className=\"h-full bg-ember transition-[width] duration-700 ease-out\"\n style={{ width: `${pct}%` }}\n />\n </div>\n );\n}\n\n/** Keeps what the person did in a step's view (ticks, a widget's state) with the run. */\nconst keepView = (runId: string, stepId: string) => (state: Record<string, unknown>) => {\n api.put(`${runBase(runId)}/views/${stepId}`, { state }).catch(() => undefined);\n};\n\nfunction StepHeading({\n title,\n description,\n kicker,\n}: {\n title: string;\n description?: string;\n kicker?: string | null;\n}) {\n return (\n <div className=\"kb-title mb-8\">\n {kicker ? (\n <p className=\"kb-hide mb-4 text-[0.9375rem] text-ink-2 leading-relaxed\">{kicker}</p>\n ) : null}\n <h1 className=\"wizard-title font-display font-semibold text-[1.75rem] leading-[1.15] tracking-tight sm:text-[2rem]\">\n {title}\n </h1>\n {description ? (\n <p className=\"kb-hide mt-2 text-[0.9375rem] text-ink-3 leading-relaxed\">{description}</p>\n ) : null}\n </div>\n );\n}\n\nexport function initialValues(step: PageStep, view: RunView): Values {\n const out: Values = {};\n for (const f of step.fields) {\n out[f.id] =\n view.values[f.id] ??\n view.prefill?.[f.id] ??\n f.default ??\n (f.kind === \"multiselect\" ? [] : undefined);\n }\n return out;\n}\n\n/** Text inputs of a page, in order — what Enter and the keyboard's action key walk through. */\nfunction typedInputs(form: HTMLElement): HTMLElement[] {\n return Array.from(\n form.querySelectorAll<HTMLElement>(\n 'input:not([type=\"hidden\"], [type=\"file\"], [type=\"checkbox\"], [type=\"color\"], [type=\"range\"], [disabled]), textarea:not([disabled])',\n ),\n ).filter((el) => !el.closest(\"dialog\") && el.offsetParent !== null);\n}\n\nfunction PageForm({ view, run, step }: { view: RunView; run: Run; step: PageStep }) {\n // Keyed by the page at the call site, so a page (or a page revisited) starts from the run's values.\n const [values, setValues] = useState<Values>(() => initialValues(step, view));\n // Fields still uploading or recording; going on now would leave their answer behind.\n const [pending, setPending] = useState<ReadonlySet<string>>(new Set());\n const form = useRef<HTMLFormElement>(null);\n const first = view.progress.done === 0;\n // Choices from earlier data stand in for the fixed ones; a field whose condition does not\n // hold is not shown, decided again as the person types.\n const fields = useMemo(\n () =>\n step.fields\n .filter((f) => !isDecidedField(f) || view.decidedFields?.includes(f.id))\n .map((f) => (view.options?.[f.id]?.length ? { ...f, options: view.options[f.id] } : f)),\n [step.fields, view.options, view.decidedFields],\n );\n const shown = shownFields(fields, view.known ?? {}, values);\n const submit = () => void run.submitPage(step.id, values);\n\n // The keyboard's action key says what it does: \"next\" between fields, \"go\" on the last one.\n useEffect(() => {\n if (!form.current) {\n return;\n }\n const inputs = typedInputs(form.current).filter((el) => el instanceof HTMLInputElement);\n for (const [i, el] of inputs.entries()) {\n if (el.dataset.hint || !el.hasAttribute(\"enterkeyhint\")) {\n el.dataset.hint = \"1\";\n el.setAttribute(\"enterkeyhint\", i === inputs.length - 1 ? \"go\" : \"next\");\n }\n }\n });\n\n return (\n <form\n ref={form}\n className=\"animate-rise\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!pending.size) {\n submit();\n }\n }}\n onKeyDown={(e) => {\n const el = e.target;\n if (\n e.key !== \"Enter\" ||\n e.defaultPrevented ||\n e.nativeEvent.isComposing ||\n !(el instanceof HTMLInputElement) ||\n el.closest(\"dialog\")\n ) {\n return;\n }\n // Enter walks to the next field; only on the last one it sends the page.\n const inputs = typedInputs(e.currentTarget);\n const next = inputs[inputs.indexOf(el) + 1];\n if (next) {\n e.preventDefault();\n next.focus();\n }\n }}\n >\n <StepHeading\n title={step.title}\n description={step.description}\n kicker={first ? view.wizard.intro : null}\n />\n <div className=\"flex flex-col gap-7\">\n {shown.map((f) => (\n <FieldInput\n key={f.id}\n field={f}\n value={values[f.id]}\n values={values}\n runId={view.id}\n view={view}\n error={run.fieldErrors[f.id]}\n closed={view.closed?.[f.id]}\n onChange={(v) => setValues((prev) => ({ ...prev, [f.id]: v }))}\n onBusy={(busy) =>\n setPending((prev) => {\n if (prev.has(f.id) === busy) {\n return prev;\n }\n const next = new Set(prev);\n if (busy) {\n next.add(f.id);\n } else {\n next.delete(f.id);\n }\n return next;\n })\n }\n />\n ))}\n </div>\n <Footer view={view} run={run} sticky>\n <Button type=\"submit\" size=\"lg\" busy={run.busy} disabled={pending.size > 0}>\n {step.cta || t(\"run.next\")} <ArrowRight className=\"size-4\" />\n </Button>\n </Footer>\n </form>\n );\n}\n\nfunction Footer({\n view,\n run,\n sticky,\n children,\n}: {\n view: RunView;\n run: Run;\n /** The page's primary action: on a phone it stays in reach at the bottom of the screen. */\n sticky?: boolean;\n children: React.ReactNode;\n}) {\n return (\n <div className={cn(\"mt-10 flex items-center justify-between gap-3\", sticky && \"action-bar\")}>\n {view.canBack ? (\n <Button variant=\"ghost\" onClick={() => void run.back()} disabled={run.busy}>\n <ArrowLeft className=\"size-4\" /> {t(\"run.back\")}\n </Button>\n ) : (\n <span />\n )}\n {children}\n </div>\n );\n}\n\n/** \"Tell me when it's done\": asked for with a tap, never on page load. */\nfunction NotifyToggle() {\n const state = useNotifyState();\n const [busy, setBusy] = useState(false);\n const on = state !== \"off\";\n return (\n <div className=\"mt-6 flex flex-col items-center gap-2\">\n <button\n type=\"button\"\n aria-pressed={on}\n disabled={busy}\n onClick={async () => {\n if (on) {\n disableNotify();\n return;\n }\n setBusy(true);\n await enableNotify();\n setBusy(false);\n }}\n className={cn(\n \"inline-flex h-11 items-center gap-2 rounded-full px-4 font-medium text-[0.875rem] ring-1 transition\",\n on\n ? \"bg-ember-tint text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink hover:ring-ink-4\",\n )}\n >\n {on ? <BellRing className=\"size-4 text-ember-strong\" /> : <Bell className=\"size-4\" />}\n {t(on ? \"notify.on\" : \"notify.ask\")}\n </button>\n <p className=\"max-w-xs text-[0.75rem] text-ink-4 leading-relaxed\">\n {state === \"off\"\n ? t(\"notify.why\")\n : state === \"on\"\n ? t(\"notify.onHint\")\n : t(notificationsBlocked() ? \"notify.blocked\" : \"notify.quiet\")}\n </p>\n </div>\n );\n}\n\nfunction Working({\n view,\n compact,\n awake,\n}: {\n view: RunView;\n compact?: boolean;\n /** The screen is kept on while the step works. */\n awake: boolean;\n}) {\n const started = useMemo(() => {\n const e = [...view.events]\n .reverse()\n .find((ev) => ev.type === \"step_started\" && ev.stepId === view.step?.id);\n return e ? new Date(e.at).getTime() : Date.now();\n }, [view.events, view.step?.id]);\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, []);\n const label =\n [...view.events]\n .reverse()\n .find((ev) => ev.type === \"step_started\" && ev.stepId === view.step?.id)?.message ??\n view.step?.title ??\n t(\"run.working\");\n const recent = view.events.filter(\n (ev) =>\n (ev.type === \"tool\" || ev.type === \"info\") && new Date(ev.at).getTime() >= started - 500,\n );\n const trail = recent.slice(-4);\n const { Mascot } = runnerEnv();\n // The pictures the step is about — photos it looks at, images it has just made — newest last.\n const pictures = [...new Set(recent.map((ev) => ev.asset).filter((id): id is string => !!id))];\n const latest = [...recent].reverse().find((ev) => ev.asset)?.asset;\n return (\n <div className=\"flex animate-rise flex-col items-center pt-6 text-center\">\n <Mascot\n kind={view.wizard.avatar}\n costume={view.wizard.costume}\n size={compact ? 130 : 170}\n fluffy\n />\n <h2 className=\"wizard-heading mt-4 font-display font-semibold text-[1.375rem] tracking-tight\">\n {label}\n </h2>\n <div className=\"mt-1 text-[0.8125rem] text-ink-4 tabular-nums\">\n {t(\"run.elapsed\", { s: Math.max(0, Math.round((now - started) / 1000)) })}\n </div>\n {pictures.length ? (\n <div className=\"mt-5 flex max-w-full flex-wrap justify-center gap-2\">\n {pictures.slice(-8).map((id) => (\n <img\n key={id}\n src={withBase(`${runBase(view.id)}/assets/${id}`)}\n alt=\"\"\n className={cn(\n \"size-16 animate-rise rounded-lg bg-paper-2 object-cover ring-1 ring-border-soft transition sm:size-20\",\n id === latest ? \"ring-2 ring-ember\" : \"opacity-70\",\n )}\n />\n ))}\n </div>\n ) : null}\n <div className=\"mt-6 flex min-h-[7rem] w-full max-w-sm flex-col gap-1.5\">\n {trail.map((ev, i) => (\n <div\n key={ev.id}\n className={cn(\n \"flex items-center justify-center gap-2 text-[0.8125rem] transition-opacity\",\n i === trail.length - 1 ? \"text-ink-2\" : \"text-ink-4\",\n )}\n >\n {i === trail.length - 1 ? (\n <Sparkles className=\"size-3.5 animate-breathe text-ember\" />\n ) : null}\n <span className=\"truncate\">{eventText(ev)}</span>\n </div>\n ))}\n </div>\n {compact ? null : <NotifyToggle />}\n {awake ? <p className=\"mt-3 text-[0.75rem] text-ink-4\">{t(\"run.awake\")}</p> : null}\n </div>\n );\n}\n\n/**\n * Tells the person when a step that took a while is done, or when it needs them (a sign-in, a\n * confirmation) — if they asked for it. A page in the background also marks its title.\n */\nexport function useDoneSignal(view: RunView | null) {\n const last = useRef({ running: false, since: 0, ask: null as string | null });\n useEffect(() => {\n if (!view) {\n return;\n }\n const prev = last.current;\n const running = view.status === \"running\";\n const since = running ? (prev.running ? prev.since : Date.now()) : 0;\n const tell = (body: string) => {\n if (document.visibilityState !== \"visible\" && !document.title.startsWith(\"● \")) {\n document.title = `● ${document.title}`;\n }\n void signalPerson({ title: view.wizard.title, body, tag: view.id });\n };\n if (running && view.ask && view.ask.id !== prev.ask) {\n tell(t(\"notify.needsYou\"));\n } else if (!running && prev.running && Date.now() - prev.since > 8000) {\n tell(\n view.status === \"failed\"\n ? t(\"run.failed\")\n : view.status === \"done\"\n ? t(\"notify.done\")\n : t(\"notify.next\"),\n );\n }\n last.current = { running, since, ask: view.ask?.id ?? null };\n }, [view]);\n useEffect(() => {\n const seen = () => {\n if (document.visibilityState === \"visible\" && document.title.startsWith(\"● \")) {\n document.title = document.title.slice(2);\n }\n };\n document.addEventListener(\"visibilitychange\", seen);\n return () => document.removeEventListener(\"visibilitychange\", seen);\n }, []);\n}\n\nfunction Review({\n view,\n run,\n step,\n studio,\n}: {\n view: RunView;\n run: Run;\n step: ReviewStep;\n studio?: boolean;\n}) {\n const [drafts, setDrafts] = useState<Record<string, string | Record<string, unknown>>>({});\n const [editing, setEditing] = useState<Record<string, boolean>>({});\n // What the person wants changed, and which of the shown results it is about.\n const [note, setNote] = useState(\"\");\n const made = view.shown.filter((x) => x.output);\n const [target, setTarget] = useState<string | null>(made.length === 1 ? made[0].step.id : null);\n // Steps with several results: the ones picked to be made again.\n const [picked, setPicked] = useState<Record<string, number[]>>({});\n const prompt = useRef<HTMLTextAreaElement>(null);\n const aim = made.find((x) => x.step.id === target);\n const several = aim?.step.type === \"generate\" && (aim.output?.assets?.length ?? 0) > 1;\n const send = () => {\n if (aim && note.trim()) {\n void run.regenerate(step.id, aim.step.id, note.trim(), picked[aim.step.id]);\n }\n };\n return (\n <div className=\"animate-rise\">\n <StepHeading title={step.title} description={step.description} />\n <div className=\"flex flex-col gap-6\">\n {/* A step the run skipped (a branch) has nothing to review. */}\n {view.shown\n .filter((x) => x.output)\n .map(({ step: s, output }) => {\n // A json step's data is edited by its schema, a written one as its text.\n const data = editableData(s) ? s : null;\n const editable =\n Boolean(step.edit) && s.type === \"agent\" && (s.output.format !== \"json\" || !!data);\n const draft = drafts[s.id];\n const heading = (menu: React.ReactNode) => (\n <div className=\"mb-2 flex items-center justify-between gap-3\">\n <h3 className=\"font-medium text-[0.8125rem] text-ink-3 uppercase tracking-[0.06em]\">\n {s.title}\n </h3>\n <div className=\"flex items-center\">\n {editable && !editing[s.id] ? (\n <button\n type=\"button\"\n onClick={() => setEditing((e) => ({ ...e, [s.id]: true }))}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-full px-3 text-[0.8125rem] text-ink-2 hover:bg-accent hover:text-ink coarse:h-11\"\n >\n <Pencil className=\"size-3.5\" /> {t(\"run.edit\")}\n </button>\n ) : null}\n {menu}\n </div>\n </div>\n );\n const shown =\n data && output && editable && editing[s.id] ? (\n <div className=\"overflow-hidden rounded-xl bg-card ring-1 ring-border-soft\">\n <DataEditor\n shape={stepShape(data)}\n value={\n draft && typeof draft === \"object\"\n ? draft\n : ((output.json ?? {}) as Record<string, unknown>)\n }\n onChange={(next) => setDrafts((d) => ({ ...d, [s.id]: next }))}\n start=\"edit\"\n />\n </div>\n ) : (\n <OutputView\n base={`${runBase(view.id)}`}\n step={s}\n output={output}\n onView={keepView(view.id, s.id)}\n editable={editable && editing[s.id] && !data}\n draft={typeof draft === \"string\" ? draft : undefined}\n onDraft={(text) => setDrafts((d) => ({ ...d, [s.id]: text }))}\n picked={picked[s.id]}\n onPick={\n step.regenerate\n ? (i) => {\n // Picking a result says what the change is about.\n setTarget(s.id);\n setPicked((p) => {\n const now = p[s.id] ?? [];\n return {\n ...p,\n [s.id]: now.includes(i) ? now.filter((x) => x !== i) : [...now, i],\n };\n });\n prompt.current?.focus();\n }\n : undefined\n }\n onSurfaceAction={\n step.regenerate\n ? () => {\n setTarget(s.id);\n prompt.current?.focus();\n }\n : undefined\n }\n />\n );\n return (\n <section key={s.id}>\n {studio && data && output ? (\n <StudioData runId={view.id} step={data} output={output} header={heading}>\n {shown}\n </StudioData>\n ) : (\n <>\n {heading(null)}\n {shown}\n </>\n )}\n </section>\n );\n })}\n {view.lists.map((list) => (\n <section key={list.def.id}>\n <h3 className=\"mb-2 font-medium text-[0.8125rem] text-ink-3 uppercase tracking-[0.06em]\">\n {list.def.title}\n </h3>\n {list.def.check ? (\n <ListCheck runId={view.id} list={list} />\n ) : (\n <ListTable runId={view.id} list={list} editable />\n )}\n </section>\n ))}\n {step.regenerate && made.length ? (\n // The way to say what should be different: always there, below what it is about.\n <Card className=\"p-3\">\n {made.length > 1 ? (\n <div className=\"flex flex-wrap items-center gap-1.5 px-1 pb-2\">\n <span className=\"mr-1 text-[0.8125rem] text-ink-3\">{t(\"run.feedbackTarget\")}</span>\n {made.map(({ step: s }) => (\n <button\n key={s.id}\n type=\"button\"\n aria-pressed={target === s.id}\n onClick={() => {\n setTarget(s.id);\n prompt.current?.focus();\n }}\n className={cn(\n \"inline-flex h-8 items-center rounded-full px-3 text-[0.8125rem] ring-1 transition coarse:h-11\",\n target === s.id\n ? \"bg-ember-tint text-ink ring-ember\"\n : \"bg-card text-ink-2 ring-input hover:text-ink\",\n )}\n >\n {s.title}\n </button>\n ))}\n </div>\n ) : null}\n <Textarea\n ref={prompt}\n minRows={2}\n maxRows={8}\n value={note}\n placeholder={t(\"run.feedbackPlaceholder\")}\n onChange={(e) => setNote(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n send();\n }\n }}\n className=\"border-0 bg-transparent shadow-none focus:ring-0\"\n />\n <div className=\"flex items-center justify-between gap-3 px-1 pt-1\">\n <span className=\"min-w-0 text-[0.75rem] text-ink-3\">\n {several\n ? picked[aim.step.id]?.length\n ? t(\"run.regeneratePicked\", {\n n: [...picked[aim.step.id]]\n .sort((x, y) => x - y)\n .map((i) => i + 1)\n .join(\", \"),\n })\n : t(\"run.regenerateAll\")\n : !aim && note.trim()\n ? t(\"run.feedbackPick\")\n : null}\n </span>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n busy={run.busy}\n disabled={!note.trim() || !aim}\n onClick={send}\n >\n <RefreshCw className=\"size-3.5\" /> {t(\"run.regenerateGo\")}\n </Button>\n </div>\n </Card>\n ) : null}\n </div>\n <Footer view={view} run={run} sticky>\n <Button\n size=\"lg\"\n busy={run.busy}\n onClick={() => void run.accept(step.id, Object.keys(drafts).length ? drafts : undefined)}\n >\n {t(\"run.accept\")} <ArrowRight className=\"size-4\" />\n </Button>\n </Footer>\n </div>\n );\n}\n\nfunction Result({\n view,\n run,\n step,\n onRestart,\n studio,\n}: {\n view: RunView;\n run: Run;\n step: ResultStep;\n onRestart?: () => void;\n studio?: boolean;\n}) {\n const made = view.shown.filter((x) => x.output);\n const { Mascot, ShareResultButton } = runnerEnv();\n return (\n <div className=\"animate-rise\">\n <div className=\"mb-8 flex flex-wrap items-center gap-x-4 gap-y-5\">\n <Mascot kind={view.wizard.avatar} costume={view.wizard.costume} size={64} />\n {/* On a phone the title keeps the row; the share button goes below it. */}\n <div className=\"min-w-0 flex-1 basis-[12rem]\">\n <h1 className=\"wizard-title text-balance font-display font-semibold text-[1.75rem] leading-tight tracking-tight sm:text-[2rem]\">\n {step.title}\n </h1>\n {step.message ? <p className=\"mt-1 text-[0.9375rem] text-ink-3\">{step.message}</p> : null}\n </div>\n {ShareResultButton && view.shown.some((x) => x.output) ? (\n <div className=\"max-sm:basis-full\">\n <ShareResultButton view={view} title={`${step.title} · ${view.wizard.title}`} />\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-col gap-6\">\n {/* A step the run skipped (a branch) has made nothing to hand over. */}\n {made.map(({ step: s, output, formats, label }) => {\n const heading = (menu: React.ReactNode) => (\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-3\">\n <h3 className=\"font-display font-semibold text-[1.0625rem]\">{label ?? s.title}</h3>\n <div className=\"flex items-center gap-1\">\n <DownloadButtons\n base={`${runBase(view.id)}`}\n stepId={s.id}\n formats={formats}\n title={label ?? s.title}\n step={s}\n output={output ?? undefined}\n foot={`${view.wizard.title} · ${new Date().toLocaleDateString(runnerEnv().lang)}`}\n />\n {menu}\n </div>\n </div>\n );\n const shown = (\n <TranslatedOutput\n view={view}\n run={run}\n step={s}\n output={output}\n onView={keepView(view.id, s.id)}\n />\n );\n return (\n <Card key={s.id} className=\"p-4 sm:p-5\">\n {studio && editableData(s) && output ? (\n <StudioData runId={view.id} step={s} output={output} header={heading}>\n {shown}\n </StudioData>\n ) : (\n <>\n {heading(null)}\n {shown}\n </>\n )}\n {output?.assets?.some((a) => a.ai) ? (\n // Whoever publishes it has to say so too; the file already does, in its metadata.\n <p className=\"mt-3 text-[0.75rem] text-ink-3 leading-relaxed\">{t(\"ai.publish\")}</p>\n ) : null}\n </Card>\n );\n })}\n {view.lists.map((list) => (\n <Card key={list.def.id} className=\"p-4 sm:p-5\">\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-3\">\n <h3 className=\"font-display font-semibold text-[1.0625rem]\">\n {list.label ?? list.def.title}\n </h3>\n <ListDownloads runId={view.id} list={list} />\n </div>\n <ListTable runId={view.id} list={list} editable />\n </Card>\n ))}\n </div>\n <Footer view={view} run={run}>\n {onRestart ? (\n <Button variant=\"secondary\" onClick={onRestart}>\n <RotateCcw className=\"size-4\" /> {t(\"run.again\")}\n </Button>\n ) : (\n <span />\n )}\n </Footer>\n </div>\n );\n}\n\nfunction Failed({ view, run }: { view: RunView; run: Run }) {\n const { Mascot } = runnerEnv();\n return (\n <div className=\"flex animate-rise flex-col items-center pt-8 text-center\">\n <Mascot kind={view.wizard.avatar} costume={view.wizard.costume} size={90} />\n <h2 className=\"wizard-heading mt-4 font-display font-semibold text-[1.375rem]\">\n {t(\"run.failed\")}\n </h2>\n <p className=\"mt-2 max-w-md text-[0.9375rem] text-ink-3\">\n <LinkedText text={view.error ?? \"\"} />\n </p>\n <div className=\"mt-8 flex gap-3\">\n {view.canBack ? (\n <Button variant=\"ghost\" onClick={() => void run.back()}>\n <ArrowLeft className=\"size-4\" /> {t(\"run.back\")}\n </Button>\n ) : null}\n <Button onClick={() => void run.retry()} busy={run.busy}>\n <RotateCcw className=\"size-4\" /> {t(\"run.retry\")}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * A result in a translated run: as it was made, with the offer to read its text in the run's\n * language; once translated, the translation with the way back to the original.\n */\nfunction TranslatedOutput({\n view,\n run,\n step,\n output,\n onView,\n}: {\n view: RunView;\n run: Run;\n step: Step;\n output: StepOutput | null;\n onView?: (state: Record<string, unknown>) => void;\n}) {\n const [original, setOriginal] = useState(false);\n const [busy, setBusy] = useState(false);\n const base = runBase(view.id);\n const translated = view.translation?.results[step.id];\n if (!(view.translation && output?.text && run.translateResult)) {\n return <OutputView base={base} step={step} output={output} onView={onView} />;\n }\n const shown = translated && !original ? { ...output, text: translated } : output;\n return (\n <>\n <OutputView base={base} step={step} output={shown} onView={onView} />\n <div className=\"mt-3 flex items-center gap-3 text-[0.8125rem] text-ink-3\">\n {translated ? (\n <>\n {original ? null : <span>{t(\"translation.machine\")}</span>}\n <button\n type=\"button\"\n className=\"underline-offset-4 hover:text-ink hover:underline coarse:min-h-11\"\n onClick={() => setOriginal((o) => !o)}\n >\n {t(original ? \"translation.showTranslated\" : \"translation.showOriginal\")}\n </button>\n </>\n ) : (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n busy={busy}\n onClick={async () => {\n setBusy(true);\n await run.translateResult?.(step.id);\n setBusy(false);\n }}\n >\n <Languages className=\"size-4\" />{\" \"}\n {busy ? t(\"translation.working\") : t(\"result.translate\")}\n </Button>\n )}\n </div>\n </>\n );\n}\nexport function RunnerBody({\n run,\n compact,\n onRestart,\n onView,\n stickyProgress,\n studio,\n}: {\n run: RunSource;\n compact?: boolean;\n /** In the studio: a json step's data can be viewed, edited and its JSON Schema read. */\n studio?: boolean;\n onRestart?: () => void;\n onView?: (view: RunView | null) => void;\n /** In a box of its own (an AI app's widget): the progress stays on top while the page scrolls. */\n stickyProgress?: boolean;\n}) {\n const { view } = run;\n setChoiceLabels(view?.translation?.labels);\n useEffect(() => {\n onView?.(view);\n }, [view, onView]);\n useKeyboardInset();\n const awake = useWakeLock(view?.status === \"running\" && !view.ask);\n useDoneSignal(view);\n if (run.notFound) {\n return <div className=\"py-24 text-center text-ink-3\">{t(\"run.notFound\")}</div>;\n }\n if (!view) {\n return (\n <div className=\"flex justify-center py-24 text-ink-4\">\n <Spinner />\n </div>\n );\n }\n const step = view.step;\n let body: React.ReactNode = null;\n if (view.status === \"running\" && view.ask) {\n body = <AskPanel key={view.ask.id} runId={view.id} ask={view.ask} />;\n } else if (view.status === \"running\") {\n body = <Working view={view} compact={compact} awake={awake} />;\n } else if (view.status === \"failed\") {\n body = <Failed view={view} run={run} />;\n } else if (view.status === \"cancelled\") {\n body = <div className=\"py-24 text-center text-ink-3\">{t(\"run.cancelled\")}</div>;\n } else if (step?.type === \"page\") {\n body = <PageForm key={step.id} view={view} run={run} step={step} />;\n } else if (step?.type === \"review\") {\n // A regenerated output is a fresh review: drafts and notes start over.\n const version = view.shown.map((x) => x.output?.at ?? \"\").join(\"|\");\n body = (\n <Review key={`${step.id}:${version}`} view={view} run={run} step={step} studio={studio} />\n );\n } else if (step?.type === \"result\") {\n body = <Result view={view} run={run} step={step} onRestart={onRestart} studio={studio} />;\n }\n // Rows beside their files need the width of the screen.\n const wide =\n step?.type === \"review\" &&\n view.status === \"waiting_input\" &&\n view.lists.some((l) => l.def.check);\n return (\n <div className=\"flex min-h-full flex-col\">\n {stickyProgress ? (\n <div className=\"sticky top-0 z-10\">\n <Progress view={view} />\n </div>\n ) : (\n <Progress view={view} />\n )}\n <div\n className={cn(\n \"safe-x kb-tight mx-auto w-full flex-1\",\n wide\n ? \"max-w-[1240px] py-8\"\n : compact\n ? \"max-w-[620px] py-8\"\n : \"max-w-[640px] py-8 sm:py-16\",\n )}\n >\n {body}\n {run.error && view.status !== \"failed\" ? (\n <div className=\"mt-4 rounded-lg bg-rose-tint px-4 py-3 text-[0.875rem] text-rose\">\n {run.error}\n </div>\n ) : null}\n {view.keeps && view.status !== \"running\" ? (\n <div className=\"mt-10 flex justify-center\">\n <StoreButton runId={view.id} />\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n","import { z } from \"zod\";\nimport { ENGENTY_COSTUMES, THEME_ID } from \"./definition.js\";\nimport { luminance } from \"./projects.js\";\nimport type { RunFontFace, RunTheme } from \"./run.js\";\n\n// --- themes ------------------------------------------------------------------------\n// How a wizard's pages look, as a document of its own: values only (colours for light and dark,\n// fonts, shape, effects from the runner's library), kept in the space and shipped in a wizard\n// file. No CSS, no files, no addresses: a theme is data a schema checks completely, and every\n// place a wizard runs draws as much of it as it can. docs/plans/themes.md\n\n/** The themes every space has. Nobody defines or publishes them. */\nexport const BUILT_IN_THEMES = [\"brand\", \"host\", \"default\"] as const;\nexport type BuiltInTheme = (typeof BUILT_IN_THEMES)[number];\n\n/** Ids no theme of a space may take, and scopes only engenty wizards publishes under. */\nexport const RESERVED_THEME_IDS: readonly string[] = [\n ...BUILT_IN_THEMES,\n \"engenty\",\n \"wizard\",\n \"wizards\",\n];\nexport const RESERVED_THEME_SCOPES: readonly string[] = [\"@wizards\", \"@engenty\", \"@wizard\"];\n\nexport { THEME_ID };\n\n/** A wizard names at most this many themes; a space keeps at most this many. */\nexport const MAX_WIZARD_THEMES = 8;\nexport const MAX_SPACE_THEMES = 40;\n\n/**\n * The fonts the runner ships (OFL): a run page loads them from its own address. A theme names\n * one of them by family, or the space's brand by role (`\"brand\"`).\n */\nexport const SHIPPED_FONTS = [\n \"Inter\",\n \"Figtree\",\n \"DM Sans\",\n \"Nunito\",\n \"Fredoka\",\n \"Bricolage Grotesque\",\n \"Fraunces\",\n \"Playfair Display\",\n \"Lora\",\n \"Young Serif\",\n \"Caveat\",\n \"Creepster\",\n \"Nosifer\",\n] as const;\nexport type ShippedFont = (typeof SHIPPED_FONTS)[number];\n\n/**\n * The runner's effects and their options. Names stay open in the schema: a theme that names an\n * effect this runner does not know is drawn without it.\n */\nexport const THEME_EFFECTS = {\n glow: {},\n corners: { kind: [\"webs\", \"frost\"] },\n particles: { kind: [\"embers\", \"snow\", \"confetti\", \"stars\"] },\n figures: { costume: ENGENTY_COSTUMES, motion: [\"fly\", \"peek\"] },\n fog: {},\n pattern: { kind: [\"dots\", \"grid\"] },\n} as const satisfies Record<string, Record<string, readonly string[]>>;\nexport type ThemeEffectId = keyof typeof THEME_EFFECTS;\n\nconst hex = z.string().regex(/^#[0-9a-fA-F]{6}$/, \"a colour as #rrggbb\");\n\nexport const themeColoursSchema = z.object({\n /** Buttons and marks. */\n accent: hex.optional(),\n /** The ground the pages stand on. */\n background: hex.optional(),\n /** Text. Left out: taken from the ground. */\n text: hex.optional(),\n});\nexport type ThemeColours = z.infer<typeof themeColoursSchema>;\n\nexport const COLOR_SCHEMES = [\"light\", \"dark\"] as const;\nexport type ColorScheme = (typeof COLOR_SCHEMES)[number];\n\n/** The colours of light or of dark pages (`scheme`, as CSS's `color-scheme` names them). */\nexport const themeColorsSchema = themeColoursSchema.extend({ scheme: z.enum(COLOR_SCHEMES) });\nexport type ThemeColors = z.infer<typeof themeColorsSchema>;\n\nexport const themeShapeSchema = z.object({\n radius: z.enum([\"sharp\", \"soft\", \"round\"]).optional(),\n cards: z.enum([\"solid\", \"outline\", \"glass\"]).optional(),\n headings: z.enum([\"normal\", \"uppercase\"]).optional(),\n});\nexport type ThemeShape = z.infer<typeof themeShapeSchema>;\n\nexport const themeEffectSchema = z\n .object({ id: z.string().min(1).max(40) })\n .catchall(z.union([z.string().max(40), z.number(), z.boolean()]));\nexport type ThemeEffect = z.infer<typeof themeEffectSchema>;\n\n/** A shipped family by name, or `brand`: never an address. */\nconst fontName = z\n .string()\n .min(1)\n .max(60)\n .regex(/^[A-Za-z0-9 -]+$/, \"a font by its family name, or brand\");\n\nexport const themeSchema = z.object({\n id: z.string().regex(THEME_ID, \"a theme id: lowercase letters, digits and dashes\"),\n name: z.string().min(1).max(80),\n version: z\n .string()\n .regex(/^\\d+\\.\\d+\\.\\d+$/)\n .default(\"1.0.0\"),\n /** What the theme builds on: what it leaves out comes from there. */\n base: z.enum(BUILT_IN_THEMES).default(\"brand\"),\n /**\n * The colours of light and of dark pages, in order: the first shows until the person picks.\n * One entry: the pages are always that.\n */\n colors: z\n .array(themeColorsSchema)\n .min(1)\n .max(2)\n .refine((list) => new Set(list.map((c) => c.scheme)).size === list.length, {\n message: \"Each scheme once: light, dark.\",\n })\n .optional(),\n fonts: z\n .object({\n heading: fontName.optional(),\n text: fontName.optional(),\n })\n .optional(),\n shape: themeShapeSchema.optional(),\n effects: z.array(themeEffectSchema).max(8).optional(),\n});\nexport type Theme = z.infer<typeof themeSchema>;\n\n/** Why an id cannot be a theme of a space; null when it can. */\nexport function themeIdProblem(id: string): string | null {\n if (!THEME_ID.test(id)) {\n return `\"${id}\" is no theme id: lowercase letters, digits and dashes, optionally after @owner/.`;\n }\n const scope = id.startsWith(\"@\") ? id.slice(0, id.indexOf(\"/\")) : null;\n if (scope && RESERVED_THEME_SCOPES.includes(scope) && scope !== \"@wizards\") {\n return `The scope ${scope} is reserved.`;\n }\n if (!scope && RESERVED_THEME_IDS.includes(id)) {\n return `\"${id}\" is reserved for engenty wizards.`;\n }\n return null;\n}\n\n/** A theme's content as one string: the same content gives the same key, whatever the order of keys. */\nexport function themeContentKey(theme: Theme): string {\n const sorted = (v: unknown): unknown =>\n Array.isArray(v)\n ? v.map(sorted)\n : v && typeof v === \"object\"\n ? Object.fromEntries(\n Object.entries(v)\n .filter(([, x]) => x !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, x]) => [k, sorted(x)]),\n )\n : v;\n const { id: _, ...content } = theme;\n return JSON.stringify(sorted(content));\n}\n\n/** An id like `id` that `taken` does not hold yet: `halloween`, `halloween-2`, … */\nexport function freeThemeId(id: string, taken: ReadonlySet<string>): string {\n if (!taken.has(id)) {\n return id;\n }\n for (let n = 2; ; n++) {\n const next = `${id.slice(0, 44)}-${n}`;\n if (!taken.has(next)) {\n return next;\n }\n }\n}\n\n/** A theme id from a wizard's title: \"Spukhaus-Exposé\" → `spukhaus-expose`. */\nexport function themeIdFrom(title: string): string {\n const slug = title\n .normalize(\"NFKD\")\n .replace(/[̀-ͯ]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 48);\n return slug && !RESERVED_THEME_IDS.includes(slug) ? slug : \"look\";\n}\n\n/**\n * Whether the place that shows a wizard may pick `asked`: a built-in name, or a theme of the\n * wizard's own chain. The host always wins, but only among what the wizard offers.\n */\nexport function themeOffered(asked: string, chain: readonly string[] | undefined): boolean {\n return (BUILT_IN_THEMES as readonly string[]).includes(asked) || Boolean(chain?.includes(asked));\n}\n\n/**\n * The theme a wizard's pages show: what the place showing it asks for (`asked`, an embed's\n * `data-theme`), where the wizard offers it and the space has it; else the first of its chain\n * the space has (a built-in name counts). Undefined: none of them, so the brand.\n */\nexport function chosenTheme(\n chain: readonly string[] | undefined,\n themes: readonly Theme[],\n asked?: string | null,\n): Theme | BuiltInTheme | undefined {\n const ask = asked && themeOffered(asked, chain) ? [asked] : [];\n for (const id of [...ask, ...(chain ?? [])]) {\n if ((BUILT_IN_THEMES as readonly string[]).includes(id)) {\n return id as BuiltInTheme;\n }\n const found = themes.find((t) => t.id === id);\n if (found) {\n return found;\n }\n }\n return undefined;\n}\n\n/** The engenty wizards look without a brand: what `default` shows and builds on. */\nconst NEUTRAL: RunTheme = {\n accent: null,\n second: null,\n background: null,\n display: null,\n body: null,\n faces: [],\n dark: false,\n pinned: false,\n modes: null,\n prefer: null,\n shape: null,\n effects: [],\n};\n\n/**\n * The look of a wizard's pages: the space's brand (`runTheme`), or the theme the wizard chose\n * built on its base. `host` is drawn as the brand on pages of our own; a host that passes a\n * look of its own puts it over this. The base's colours stay in `accent` and `background`; the\n * theme's colours for light and dark pages go into `modes`, and the page takes those of what it\n * shows.\n */\nexport function themedLook(brand: RunTheme, theme: Theme | BuiltInTheme | undefined): RunTheme {\n if (theme === undefined || theme === \"brand\" || theme === \"host\") {\n return brand;\n }\n if (theme === \"default\") {\n return NEUTRAL;\n }\n const base = theme.base === \"default\" ? NEUTRAL : brand;\n // `brand` is the brand's font for the role, whatever the theme builds on.\n const font = (name: string | undefined, role: \"display\" | \"body\") =>\n name === \"brand\" ? brand[role] : (name ?? base[role]);\n const display = font(theme.fonts?.heading, \"display\");\n const body = font(theme.fonts?.text, \"body\");\n const schemes = (theme.colors ?? []).map((c) => c.scheme);\n const only = schemes.length === 1 ? schemes[0] : null;\n const shown = schemes[0] ?? (base.dark ? \"dark\" : \"light\");\n const background = themeColors(theme, shown)?.background;\n return {\n ...base,\n display,\n body,\n faces: brand.faces.filter((f) => f.family === display || f.family === body),\n dark: background ? luminance(background) < 0.18 : shown === \"dark\",\n pinned: only !== null,\n modes: schemes.length\n ? { light: themeColors(theme, \"light\") ?? null, dark: themeColors(theme, \"dark\") ?? null }\n : null,\n prefer: schemes.length === 2 ? shown : null,\n shape: theme.shape ?? null,\n effects: theme.effects ?? [],\n };\n}\n\nconst SANS = \"ui-sans-serif, system-ui, sans-serif\";\nconst SERIF = \"ui-serif, Georgia, serif\";\nconst SERIFS =\n /serif|fraunces|playfair|lora|garamond|antiqua|baskerville|caslon|bodoni|didot|times|georgia|merriweather|tiempos/i;\n\n/** A family looks like a serif by its name: what takes its place is a serif too. */\nexport const serifFamily = (family: string) => SERIFS.test(family) && !/sans/i.test(family);\n\n/** The shipped font that shows where a brand font does not load: one of its kind. */\nexport const shippedLike = (family: string): ShippedFont =>\n serifFamily(family) ? \"Lora\" : \"Inter\";\n\n/** A shipped font's name in its package and its files: \"Bricolage Grotesque\" → bricolage-grotesque. */\nexport const shippedFontSlug = (family: ShippedFont) => family.toLowerCase().replace(/ /g, \"-\");\n\n/**\n * Where the runtime serves a shipped font's stylesheet, for pages that are not its own (a host's\n * OpenUI chat); null for a family that is not one of ours. Its files sit next to it.\n */\nexport function shippedFontStylesheet(family: string): string | null {\n return (SHIPPED_FONTS as readonly string[]).includes(family)\n ? `/api/public/fonts/shipped/${shippedFontSlug(family as ShippedFont)}.css`\n : null;\n}\n\n/**\n * A family as CSS takes it, with a fallback of its kind while it loads or where it is missing. A\n * brand font with a source (`faces`) names the shipped font of its kind next: it shows if the\n * brand font does not load.\n */\nexport function fontStack(family: string, faces: readonly RunFontFace[] = []): string {\n const next = faces.some((f) => f.family === family) ? `\"${shippedLike(family)}\", ` : \"\";\n return `\"${family.replace(/\"/g, \"\")}\", ${next}${serifFamily(family) ? SERIF : SANS}`;\n}\n\n/** A theme's colours for light or dark pages, without the scheme's name; undefined: it has none. */\nexport function themeColors(\n theme: Pick<Theme, \"colors\"> | undefined,\n scheme: ColorScheme,\n): ThemeColours | undefined {\n const found = theme?.colors?.find((c) => c.scheme === scheme);\n if (!found) {\n return undefined;\n }\n const { scheme: _, ...colours } = found;\n return colours;\n}\n\n/** The colours a page shows in light or dark: the theme's for that mode, else the base's. */\nexport function lookColours(\n look: Pick<RunTheme, \"accent\" | \"background\" | \"modes\">,\n mode: \"light\" | \"dark\",\n): { accent: string | null; background: string | null; text: string | null } {\n const own = look.modes?.[mode];\n return {\n accent: own?.accent ?? look.accent,\n background: own?.background ?? look.background,\n text: own?.text ?? null,\n };\n}\n","import { loadBrandFace } from \"@engenty/wizards-runner\";\nimport type { RunTheme } from \"@engenty/wizards-shared/run\";\nimport { shippedFontStylesheet, shippedLike } from \"@engenty/wizards-shared/theme\";\n\nconst sheets = new Set<string>();\n\n/** A font the runner ships, once, from the runtime; a family that is not one of ours is left. */\nfunction loadShippedFont(family: string | null, runtime: string) {\n const sheet = family ? shippedFontStylesheet(family) : null;\n if (!sheet || sheets.has(sheet)) {\n return;\n }\n sheets.add(sheet);\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = `${runtime}${sheet}`;\n document.head.append(link);\n}\n\n/**\n * Loads the fonts a theme names, as the wizard's own page does: the brand's from their source,\n * the shipped ones from the runtime at `runtime`, and the shipped font of its kind where a brand\n * font fails.\n */\nexport function loadLookFonts(look: RunTheme, runtime: string) {\n for (const face of look.faces) {\n loadBrandFace(face, face.url.startsWith(\"/\") ? `${runtime}${face.url}` : face.url, () =>\n loadShippedFont(shippedLike(face.family), runtime),\n );\n }\n loadShippedFont(look.display, runtime);\n loadShippedFont(look.body, runtime);\n}\n","import type { RunTheme } from \"@engenty/wizards-shared/run\";\nimport { fontStack, lookColours } from \"@engenty/wizards-shared/theme\";\n\n/**\n * A wizard's theme in a host's own page (OpenUI, an own UI): values on the element with\n * `.engenty-runner`, never CSS in the page around it. runner.css derives every token from them.\n */\n\n/** The effects the wizard's card draws itself, when the host turns them on: CSS inside the card. */\nexport const CARD_EFFECTS = [\"glow\", \"pattern\"] as const;\n\nexport interface WizardLookOptions {\n /** Light or dark, as the host shows; else what the theme prefers. A theme with only one keeps it. */\n mode?: \"light\" | \"dark\";\n /** The effects the host turns on (`CARD_EFFECTS`); none unless given. */\n effects?: readonly string[];\n}\n\n/** What goes on the element with `.engenty-runner`: CSS variables and data attributes. */\nexport interface WizardLookProps {\n style: Record<string, string>;\n \"data-cards\"?: string;\n \"data-headings\"?: string;\n \"data-effects\"?: string;\n}\n\nconst RADIUS = { sharp: \"0.25rem\", soft: \"0.5rem\", round: \"0.8rem\" } as const;\n\n/**\n * A theme's values as props for the runner's element: colours, fonts by family and the corner\n * radius as `--wizard-*` variables, how cards and headings look as data attributes, and of the\n * effects only those the host turns on and the card can draw. A brand font with a source names\n * the shipped font of its kind next, which shows where it does not load (`loadLookFonts`).\n */\nexport function wizardLook(look: RunTheme, options: WizardLookOptions = {}): WizardLookProps {\n const own = look.dark ? \"dark\" : \"light\";\n const mode = look.pinned ? own : (options.mode ?? look.prefer ?? own);\n const colours = lookColours(look, mode);\n const style: Record<string, string> = {};\n const set = (name: string, value: string | null | undefined) => {\n if (value) {\n style[name] = value;\n }\n };\n set(\"--wizard-accent\", colours.accent);\n set(\"--wizard-background\", colours.background);\n set(\"--wizard-text\", colours.text);\n set(\"--wizard-font-heading\", look.display ? fontStack(look.display, look.faces) : null);\n set(\"--wizard-font-text\", look.body ? fontStack(look.body, look.faces) : null);\n set(\"--wizard-radius\", look.shape?.radius ? RADIUS[look.shape.radius] : null);\n // runner.css styles what is inside the element; the ground of the element itself is set here.\n set(\"backgroundColor\", colours.background ? \"var(--paper)\" : null);\n\n const on = new Set(options.effects ?? []);\n const effects = look.effects.flatMap((e) =>\n !on.has(e.id)\n ? []\n : e.id === \"glow\"\n ? [\"glow\"]\n : e.id === \"pattern\"\n ? [`pattern-${e.kind === \"grid\" ? \"grid\" : \"dots\"}`]\n : [],\n );\n return {\n style,\n ...(look.shape?.cards ? { \"data-cards\": look.shape.cards } : {}),\n ...(look.shape?.headings ? { \"data-headings\": look.shape.headings } : {}),\n ...(effects.length ? { \"data-effects\": effects.join(\" \") } : {}),\n };\n}\n","import { ApiError, api, type RunSource, runnerEnv, setChoiceLabels } from \"@engenty/wizards-runner\";\nimport type { RunView } from \"@engenty/wizards-shared/run\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\n/** Two missed pings: the stream is taken for dead. */\nconst STALE_MS = 45_000;\n\n/**\n * One run, live: the runtime's stream of the whole view, plus the commands a person gives. The\n * same as the studio's `useRun` (apps/web/src/runner/useRun.ts), on the runner's own client, so\n * it talks to whichever runtime `configureWizards` named. `prefill` starts a page's fields with\n * answers the chat already knows; the person still sees and sends the page.\n */\nexport function useWizardRun(\n runId: string | null,\n prefill: Record<string, unknown> | undefined,\n): RunSource {\n const [view, setView] = useState<RunView | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [notFound, setNotFound] = useState(false);\n const [busy, setBusy] = useState(false);\n const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});\n\n useEffect(() => {\n setView(null);\n setNotFound(false);\n if (!runId) {\n return;\n }\n const { runBase, withBase } = runnerEnv();\n let stopped = false;\n let retry = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let es: EventSource | null = null;\n let lastHeard = Date.now();\n const refresh = async () => {\n try {\n const fresh = await api.get<RunView>(runBase(runId));\n if (!stopped) {\n setView(fresh);\n }\n } catch (err) {\n if (err instanceof ApiError && err.status === 404) {\n stopped = true;\n es?.close();\n setNotFound(true);\n }\n }\n };\n const open = () => {\n clearTimeout(timer);\n es?.close();\n if (stopped) {\n return;\n }\n const stream = new EventSource(withBase(`${runBase(runId)}/stream`), {\n withCredentials: true,\n });\n es = stream;\n lastHeard = Date.now();\n stream.addEventListener(\"view\", (e) => {\n retry = 0;\n lastHeard = Date.now();\n setView(JSON.parse((e as MessageEvent).data));\n });\n stream.addEventListener(\"ping\", () => {\n lastHeard = Date.now();\n });\n stream.onerror = () => {\n stream.close();\n if (stopped || es !== stream) {\n return;\n }\n es = null;\n void refresh();\n retry = Math.min(retry + 1, 6);\n timer = setTimeout(open, 500 * 2 ** retry);\n };\n };\n const watchdog = setInterval(() => {\n if (!stopped && es && Date.now() - lastHeard > STALE_MS) {\n retry = 0;\n open();\n }\n }, 15_000);\n open();\n return () => {\n stopped = true;\n clearTimeout(timer);\n clearInterval(watchdog);\n es?.close();\n };\n }, [runId]);\n\n const command = useCallback(\n async (path: string, body?: unknown) => {\n if (!runId) {\n return false;\n }\n setBusy(true);\n setError(null);\n setFieldErrors({});\n try {\n await api.post(`${runnerEnv().runBase(runId)}/${path}`, body);\n return true;\n } catch (err) {\n if (err instanceof ApiError && err.status === 422 && Array.isArray(err.body?.fields)) {\n setFieldErrors(\n Object.fromEntries(\n err.body.fields.map((f: { field: string; message: string }) => [f.field, f.message]),\n ),\n );\n }\n setError((err as Error).message);\n return false;\n } finally {\n setBusy(false);\n }\n },\n [runId],\n );\n\n // The chat's answers start the page's fields, under what the run already holds.\n const shown = useMemo(() => {\n if (!view || !prefill || view.step?.type !== \"page\") {\n return view;\n }\n const known = Object.fromEntries(\n view.step.fields.filter((f) => f.id in prefill).map((f) => [f.id, prefill[f.id]]),\n );\n return Object.keys(known).length ? { ...view, prefill: { ...known, ...view.prefill } } : view;\n }, [view, prefill]);\n\n setChoiceLabels(view?.translation?.labels);\n return {\n view: shown,\n notFound,\n error,\n busy,\n fieldErrors,\n submitPage: (stepId, values) => command(`pages/${stepId}`, { values }),\n accept: (stepId, edits) => command(`reviews/${stepId}`, { type: \"accept\", edits }),\n regenerate: (stepId, target, note, items) =>\n command(`reviews/${stepId}`, {\n type: \"regenerate\",\n target,\n note,\n items: items?.length ? items : undefined,\n }),\n back: () => command(\"back\"),\n retry: () => command(\"retry\"),\n translateResult: (stepId) => command(\"translate-result\", { stepId }),\n };\n}\n","import {\n useGetFieldValue,\n useIsStreaming,\n useSetFieldValue,\n useTriggerAction,\n} from \"@openuidev/react-lang\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { WIZARD_COMPONENT } from \"./server.js\";\n\n/**\n * What the Wizard component keeps with its message, in OpenUI's state of the message.\n *\n * OpenUI keeps that state as the fields of forms, saves it with the message and restores it when\n * the message is shown again. An action hands the chat the fields of the form it names, or every\n * field where it names none; the chat shows them as “Form data” and gives them to the model. So\n * the run id is a field of its own, which no action names, and the action that reports the\n * result names a form that holds nothing.\n */\n\nconst runField = (token: string) => `wizard:${token}`;\nconst EMPTY_FORM = \"wizard:empty\";\n\n/**\n * The run this message shows: the one it kept, else a new one from `start`. A run starts once\n * the reply has finished streaming, as the token can be half written until then, and once per\n * message, however often React runs the effect (twice in Strict Mode).\n */\nexport function useMessageRun(\n token: string | undefined,\n start: (token: string) => Promise<string>,\n): { runId: string | null; failed: string | null } {\n const streaming = useIsStreaming();\n const getField = useGetFieldValue();\n const setField = useSetFieldValue();\n const [runId, setRunId] = useState<string | null>(null);\n const [failed, setFailed] = useState<string | null>(null);\n const started = useRef<Promise<string> | null>(null);\n\n useEffect(() => {\n if (streaming || runId || failed || !token) {\n return;\n }\n let cancelled = false;\n const take = async () => {\n // OpenUI restores the message's state in an effect of its own, which runs after this one.\n await Promise.resolve();\n if (cancelled) {\n return;\n }\n const kept = getField(undefined, runField(token));\n if (typeof kept === \"string\") {\n setRunId(kept);\n return;\n }\n started.current ??= start(token);\n const id = await started.current;\n if (!cancelled) {\n setRunId(id);\n setField(undefined, WIZARD_COMPONENT, runField(token), id, true);\n }\n };\n take().catch((err: unknown) => {\n if (!cancelled) {\n setFailed(err instanceof Error ? err.message : String(err));\n }\n });\n return () => {\n cancelled = true;\n };\n }, [streaming, runId, failed, token, getField, setField, start]);\n\n return { runId, failed };\n}\n\n/** Tells the chat something as a turn of the person, with `context` for the model. */\nexport function useReport(): (message: string, context: unknown) => void {\n const setField = useSetFieldValue();\n const trigger = useTriggerAction();\n return useCallback(\n (message, context) => {\n setField(EMPTY_FORM, undefined, \"empty\", undefined, false);\n void trigger(message, EMPTY_FORM, { type: \"continue_conversation\", params: { context } });\n },\n [setField, trigger],\n );\n}\n","import {\n api,\n configureRunner,\n type Lang,\n type MascotProps,\n RunnerBody,\n} from \"@engenty/wizards-runner\";\nimport type { PublicWizard, RunTheme, RunView } from \"@engenty/wizards-shared/run\";\nimport { defineComponent } from \"@openuidev/react-lang\";\nimport { type CSSProperties, useEffect, useRef, useState } from \"react\";\nimport { loadLookFonts } from \"./fonts.js\";\nimport { type WizardLookProps, wizardLook } from \"./look.js\";\nimport { useMessageRun, useReport } from \"./message.js\";\nimport { useWizardRun } from \"./run.js\";\nimport { WIZARD_COMPONENT, WIZARD_DESCRIPTION, type WizardProps, wizardProps } from \"./server.js\";\n\nexport interface WizardsConfig {\n /**\n * Where the runtime answers, as the browser reaches it: a path the host proxies to it\n * (`/wizards-runtime`, so the runner's cookie stays first-party) or the runtime's address.\n */\n runtime: string;\n /** The language of the runner's own words: `en` unless given. */\n lang?: Lang;\n /** The wizard's mascot above its pages; a plain dot in the wizard's colour unless given. */\n Mascot?: (props: MascotProps) => React.ReactNode;\n /**\n * The wizard's look here: `host` (your page's own `--wizard-*` variables, nothing of the\n * wizard's), `brand`, `default` or the id of a theme the wizard offers. Unless given, or one the\n * wizard does not offer: its first theme.\n */\n theme?: string;\n /** Light or dark, as your page shows; else what the theme prefers. */\n mode?: \"light\" | \"dark\";\n /** The effects of the wizard's theme the card may draw (`CARD_EFFECTS`); none unless given. */\n effects?: readonly string[];\n}\n\nlet shown: Pick<WizardsConfig, \"theme\" | \"mode\" | \"effects\"> = {};\n/** The runtime as the browser reaches it, without a trailing slash. */\nlet runtime = \"\";\n\n/** A plain stand-in for the studio's engenty. */\nfunction Dot({ size = 64 }: MascotProps) {\n const d = Math.min(size, 72);\n return (\n <span\n aria-hidden=\"true\"\n className=\"inline-block rounded-full bg-ember\"\n style={{ width: d * 0.6, height: d * 0.6 }}\n />\n );\n}\n\n/** Names the runtime the Wizard component talks to. Once, before the first render. */\nexport function configureWizards(config: WizardsConfig) {\n const base = config.runtime.replace(/\\/+$/, \"\");\n runtime = base;\n configureRunner({\n lang: config.lang ?? \"en\",\n runBase: (runId) => `/api/runs/${runId}`,\n withBase: (path) => `${base}${path}`,\n asset: (path) => `${base}/${path.replace(/^\\/+/, \"\")}`,\n Mascot: config.Mascot ?? Dot,\n });\n shown = { theme: config.theme, mode: config.mode, effects: config.effects };\n looks.clear();\n}\n\n/** Each wizard's look, asked once a page; its fonts load when it comes. */\nconst looks = new Map<string, Promise<RunTheme | null>>();\n\nfunction lookOf(token: string): Promise<RunTheme | null> {\n let found = looks.get(token);\n if (!found) {\n const query = shown.theme ? `?theme=${encodeURIComponent(shown.theme)}` : \"\";\n found = api.get<PublicWizard>(`/api/public/wizards/${encodeURIComponent(token)}${query}`).then(\n (w) => {\n loadLookFonts(w.brand.theme, runtime);\n return w.brand.theme;\n },\n () => null,\n );\n looks.set(token, found);\n }\n return found;\n}\n\n/** The look of the wizard behind `token` on its card; none for `host`, or while it loads. */\nfunction useLook(token: string): WizardLookProps | null {\n const [look, setLook] = useState<RunTheme | null>(null);\n useEffect(() => {\n if (shown.theme === \"host\") {\n return;\n }\n let live = true;\n void lookOf(token).then((found) => live && setLook(found));\n return () => {\n live = false;\n };\n }, [token]);\n return look ? wizardLook(look, { mode: shown.mode, effects: shown.effects }) : null;\n}\n\n/** Starts a run of the published wizard behind `token`, as a visitor of the runtime. */\nconst startRun = (token: string) =>\n api\n .post<{ runId: string }>(`/api/public/wizards/${encodeURIComponent(token)}/runs`, {})\n .then((started) => started.runId);\n\n/** What the chat hears when a run is done: the result's texts, each cut short. */\nfunction resultContext(view: RunView) {\n const results = Object.entries(view.outputs)\n .filter(([, out]) => typeof out.text === \"string\" && out.text.trim())\n .map(([step, out]) => ({ step, text: (out.text ?? \"\").slice(0, 4000) }));\n return { wizard: view.wizard.title, runId: view.id, results };\n}\n\nfunction WizardRun({ props }: { props: WizardProps }) {\n const { runId, failed } = useMessageRun(props.wizard, startRun);\n const run = useWizardRun(runId, props.prefill);\n const report = useReport();\n const look = useLook(props.wizard);\n\n // The chat hears of a run it saw finish. A message shown again with a done run tells nothing.\n const view = run.view;\n const seenRunning = useRef(false);\n useEffect(() => {\n if (!view) {\n return;\n }\n if (view.status !== \"done\") {\n seenRunning.current = true;\n } else if (seenRunning.current) {\n seenRunning.current = false;\n report(`The wizard “${view.wizard.title}” finished.`, resultContext(view));\n }\n }, [view, report]);\n\n return (\n <div\n {...look}\n style={look?.style as CSSProperties | undefined}\n className=\"engenty-runner overflow-hidden rounded-2xl border border-paper-3 bg-paper\"\n >\n {props.note ? <p className=\"px-5 pt-4 text-[0.9375rem] text-ink-2\">{props.note}</p> : null}\n <div className=\"px-5 pb-6\">\n {failed ? (\n <p className=\"py-10 text-center text-ink-3\">{failed}</p>\n ) : (\n <RunnerBody run={run} compact />\n )}\n </div>\n </div>\n );\n}\n\n/** The component an OpenUI library gets: `Wizard(\"<token>\", \"<note>\", {prefill})`. */\nexport const Wizard = defineComponent({\n name: WIZARD_COMPONENT,\n description: WIZARD_DESCRIPTION,\n props: wizardProps,\n component: ({ props }) => <WizardRun props={props} />,\n});\n"],"mappings":"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X,cACE;CACF,cAAc;CACd,eAAe;CACf,aAAa;CACb,aAAa;CACb,eACE;CACF,mBAAmB;CACnB,6BAA6B;CAC7B,mBAAmB;CACnB,cAAc;CACd,oBACE;CACF,yBACE;CACF,mBAAmB;CACnB,4BACE;CACF,0BAA0B;CAC1B,uBAAuB;CACvB,2BAA2B;CAC3B,qBACE;CACF,mBAAmB;CACnB,oBACE;CACF,gBAAgB;CAChB,wBACE;CACF,4BACE;CACF,2BACE;CACF,2BACE;CACF,wBAAwB;CACxB,sBAAsB;CACtB,iBAAiB;CACjB,oBAAoB;CACpB,uBACE;CACF,iBACE;CACF,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,gBAAgB;CAChB,0BAA0B;CAC1B,mBAAmB;CACnB,sBACE;CACF,0BACE;CACF,eAAe;CACf,eAAe;CACf,cAAc;CACd,aAAa;CACb,eAAe;CACf,gBAAgB;CAChB,sBAAsB;CACtB,aAAa;CACb,qBAAqB;CACrB,mBACE;CACF,oBAAoB;CACpB,iBAAiB;CACjB,qBAAqB;CACrB,iBAAiB;CACjB,cAAc;CACd,cAAc;CACd,mBAAmB;CACnB,qBAAqB;CACrB,oBAAoB;CACpB,0BAA0B;CAC1B,iBAAiB;CACjB,mBAAmB;CACnB,oBAAoB;CACpB,eAAe;CACf,YAAY;CACZ,gBAAgB;CAChB,cAAc;CACd,oBAAoB;CACpB,iBAAiB;CACjB,2BAA2B;CAC3B,gBAAgB;CAChB,qBAAqB;CACrB,YAAY;EACV,KAAK;EACL,OAAO;CACT;CACA,mBAAmB;CACnB,iBAAiB;CACjB,eAAe;CACf,WAAW;CACX,oBAAoB;CACpB,UAAU;CACV,mBAAmB;CACnB,qBAAqB;CACrB,qBAAqB;EACnB,KAAK;EACL,OAAO;CACT;CACA,uBAAuB;CACvB,4BAA4B;CAC5B,uBAAuB;CACvB,2BACE;CACF,cAAc;CACd,eAAe;CACf,oBAAoB;CACpB,sBAAsB;CACtB,oBAAoB;CACpB,qBAAqB;CACrB,sBAAsB;EACpB,KAAK;EACL,OAAO;CACT;CACA,0BAA0B;EACxB,KAAK;EACL,OAAO;CACT;CACA,sBACE;CACF,wBAAwB;CACxB,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,iBAAiB;EACf,KAAK;EACL,OAAO;CACT;CACA,uBACE;CACF,oBAAoB;CACpB,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,gBAAgB;EACd,KAAK;EACL,OAAO;CACT;CACA,iBAAiB;CACjB,mBAAmB;CACnB,gBAAgB;CAChB,cAAc;CACd,cAAc;CACd,gBACE;CACF,oBAAoB;CACpB,yBACE;CACF,iBAAiB;CACjB,oBAAoB;CACpB,aACE;CACF,mBAAmB;CACnB,kBAAkB;CAClB,qBAAqB;CACrB,qBAAqB;CACrB,oBAAoB;CACpB,uBAAuB;CACvB,oBAAoB;EAClB,KAAK;EACL,OAAO;CACT;CACA,kBAAkB;CAClB,sBAAsB;CACtB,oBAAoB;CACpB,sBAAsB;CACtB,sBACE;CACF,aAAa;CACb,oBACE;CACF,qBACE;CACF,mBAAmB;CACnB,kBAAkB;CAClB,2BAA2B;CAC3B,iBAAiB;CACjB,uBAAuB;CACvB,eAAe;CACf,wBAAwB;CACxB,sBACE;CACF,eACE;CACF,YAAY;CACZ,kBAAkB;CAClB,oBAAoB;CACpB,mBACE;CACF,eAAe;CACf,kBAAkB;CAClB,mBAAmB;CACnB,oBAAoB;CACpB,YAAY;CACZ,aAAa;CACb,UACE;CACF,WAAW;CACX,QAAQ;CACR,YAAY;CACZ,cAAc;CACd,QAAQ;CACR,YAAY;CACZ,gBAAgB;CAChB,YAAY;CACZ,sBAAsB;EACpB,KAAK;EACL,OAAO;CACT;CACA,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,gBAAgB;CAChB,kBAAkB;CAClB,eAAe;EACb,KAAK;EACL,OAAO;CACT;CACA,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CACb,iBAAiB;AACnB,GAuVaC,KAAgC;CAAE,IAAID;CAAU,IAAI;EAnV/D,OAAO;EACP,UAAU;EACV,gBAAgB;EAChB,WAAW;EACX,SAAS;EACT,SAAS;EACT,gBAAgB;GACd,KAAK;GACL,OAAO;EACT;EACA,gBAAgB;EAChB,OAAO;EACP,OAAO;EACP,QAAQ;EACR,cAAc;EACd,aAAa;EACb,cAAc;EACd,WAAW;EACX,aAAa;EACb,cAAc;EACd,gBAAgB;EAChB,OAAO;EACP,WAAW;GAAE,KAAK;GAA0B,OAAO;EAA0B;EAC7E,OAAO;EACP,QAAQ;EACR,UAAU;EACV,OAAO;EACP,WAAW;EACX,SAAS;EACT,SAAS;EACT,SAAS;EACT,UAAU;EACV,cAAc;EACd,UAAU;EACV,cAAc;EACd,aAAa;EACb,aAAa;EACb,gBAAgB;EAChB,WAAW;EACX,UAAU;EACV,MAAM;EACN,aAAa;EACb,QAAQ;EACR,SAAS;EACT,YAAY;EACZ,mBAAmB;EACnB,mBAAmB;EACnB,gBAAgB;EAChB,cAAc;EACd,eAAe;GACb,KAAK;GACL,OAAO;EACT;EACA,WAAW;EACX,OAAO;GAAE,KAAK;GAAyB,OAAO;EAA0B;EACxE,WAAW;EACX,YAAY;EACZ,UAAU;EACV,WAAW;EACX,SAAS;EACT,YAAY;EACZ,mBAAmB;EACnB,mBACE;EACF,gBAAgB;EAChB,wBACE;EACF,aAAa;EACb,aAAa;EACb,cAAc;EACd,aAAa;EACb,eAAe;EACf,aAAa;EACb,SAAS;EACT,SAAS;EACT,cAAc;EACd,cAAc;EACd,aAAa;EACb,SAAS;EACT,gBAAgB;EAChB,YAAY;EACZ,cAAc;EACd,UAAU;EACV,mBAAmB;EACnB,cAAc;EACd,kBAAkB;EAClB,uBAAuB;EACvB,kBACE;EACF,oBAAoB;EACpB,WAAW;EACX,WAAW;EACX,YAAY;EACZ,eAAe;EACf,UAAU;EACV,WAAW;EACX,eAAe;EACf,kBAAkB;EAClB,UACE;EACF,cACE;EACF,cAAc;EACd,SAAS;EACT,aAAa;EACb,WACE;EACF,cACE;EACF,cACE;EACF,eAAe;EACf,aAAa;EACb,aAAa;EACb,eACE;EACF,mBAAmB;EACnB,6BAA6B;EAC7B,mBAAmB;EACnB,cAAc;EACd,oBACE;EACF,yBAAyB;EACzB,mBAAmB;EACnB,4BACE;EACF,0BACE;EACF,uBAAuB;EACvB,2BAA2B;EAC3B,qBACE;EACF,mBACE;EACF,oBACE;EACF,gBACE;EACF,wBACE;EACF,4BACE;EACF,2BACE;EACF,2BACE;EACF,wBAAwB;EACxB,sBAAsB;EACtB,iBAAiB;EACjB,oBAAoB;EACpB,uBACE;EACF,iBACE;EACF,kBAAkB;EAClB,kBAAkB;EAClB,kBAAkB;EAClB,gBACE;EACF,0BAA0B;EAC1B,mBAAmB;EACnB,sBACE;EACF,0BACE;EACF,eAAe;EACf,eAAe;EACf,cAAc;EACd,aAAa;EACb,eAAe;EACf,gBAAgB;EAChB,sBAAsB;EACtB,aAAa;EACb,qBACE;EACF,mBACE;EACF,oBAAoB;EACpB,iBAAiB;EACjB,qBAAqB;EACrB,iBAAiB;EACjB,cAAc;EACd,cAAc;EACd,mBAAmB;EACnB,qBAAqB;EACrB,oBAAoB;EACpB,0BAA0B;EAC1B,iBAAiB;EACjB,mBAAmB;EACnB,oBAAoB;EACpB,eAAe;EACf,YAAY;EACZ,gBAAgB;EAChB,cAAc;EACd,oBAAoB;EACpB,iBAAiB;EACjB,2BAA2B;EAC3B,gBAAgB;EAChB,qBAAqB;EACrB,YAAY;GACV,KAAK;GACL,OAAO;EACT;EACA,mBAAmB;EACnB,iBAAiB;EACjB,eAAe;EACf,WAAW;EACX,oBAAoB;EACpB,UAAU;EACV,mBAAmB;EACnB,qBAAqB;EACrB,qBAAqB;GACnB,KAAK;GACL,OAAO;EACT;EACA,uBAAuB;EACvB,4BAA4B;EAC5B,uBAAuB;EACvB,2BACE;EACF,cAAc;EACd,eAAe;EACf,oBAAoB;EACpB,sBAAsB;EACtB,oBAAoB;EACpB,qBAAqB;EACrB,sBAAsB;GACpB,KAAK;GACL,OAAO;EACT;EACA,0BAA0B;GACxB,KAAK;GACL,OAAO;EACT;EACA,sBACE;EACF,wBAAwB;EACxB,cAAc;EACd,gBAAgB;EAChB,gBAAgB;EAChB,iBAAiB;GACf,KAAK;GACL,OAAO;EACT;EACA,uBACE;EACF,oBAAoB;EACpB,eAAe;GACb,KAAK;GACL,OAAO;EACT;EACA,gBAAgB;GACd,KAAK;GACL,OAAO;EACT;EACA,iBAAiB;EACjB,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"}