@innspel/react-native 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/index.cjs +102 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +156 -91
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/InnspelProvider.tsx","../src/skjermbilde.ts","../src/tema.ts","../src/generated/tokens.ts","../src/widget/Widget.tsx","../src/Ikon.tsx","../../../node_modules/ionicons/dist/svg/arrow-back-outline.svg","../../../node_modules/ionicons/dist/svg/brush-outline.svg","../../../node_modules/ionicons/dist/svg/bug.svg","../../../node_modules/ionicons/dist/svg/bug-outline.svg","../../../node_modules/ionicons/dist/svg/bulb.svg","../../../node_modules/ionicons/dist/svg/calendar-outline.svg","../../../node_modules/ionicons/dist/svg/camera-outline.svg","../../../node_modules/ionicons/dist/svg/checkmark-circle-outline.svg","../../../node_modules/ionicons/dist/svg/chevron-down-outline.svg","../../../node_modules/ionicons/dist/svg/chevron-up-outline.svg","../../../node_modules/ionicons/dist/svg/close-circle-outline.svg","../../../node_modules/ionicons/dist/svg/close-outline.svg","../../../node_modules/ionicons/dist/svg/cloud-offline-outline.svg","../../../node_modules/ionicons/dist/svg/construct-outline.svg","../../../node_modules/ionicons/dist/svg/contrast-outline.svg","../../../node_modules/ionicons/dist/svg/ellipse-outline.svg","../../../node_modules/ionicons/dist/svg/exit-outline.svg","../../../node_modules/ionicons/dist/svg/flask-outline.svg","../../../node_modules/ionicons/dist/svg/grid-outline.svg","../../../node_modules/ionicons/dist/svg/hourglass-outline.svg","../../../node_modules/ionicons/dist/svg/image-outline.svg","../../../node_modules/ionicons/dist/svg/images-outline.svg","../../../node_modules/ionicons/dist/svg/list-outline.svg","../../../node_modules/ionicons/dist/svg/lock-closed-outline.svg","../../../node_modules/ionicons/dist/svg/git-merge-outline.svg","../../../node_modules/ionicons/dist/svg/open-outline.svg","../../../node_modules/ionicons/dist/svg/scan-outline.svg","../../../node_modules/ionicons/dist/svg/swap-vertical-outline.svg","../../../node_modules/ionicons/dist/svg/trash-outline.svg","../../../node_modules/ionicons/dist/svg/warning-outline.svg","../src/widget/Felt.tsx","../src/widget/primitiver.tsx","../src/widget/tekster.ts","../src/widget/Valg.tsx","../src/widget/KjenteFeil.tsx","../src/widget/Kvittering.tsx","../src/widget/status.ts","../src/widget/MineInnspill.tsx","../src/widget/Skjermbilde.tsx","../src/InnspelPrivate.tsx","../src/program/InnspelProgram.tsx","../src/program/Aksept.tsx","../src/program/periode.ts","../src/program/HvordanGikkDet.tsx","../src/program/Oppfolging.tsx","../src/program/Oppgaver.tsx","../src/lagring.ts"],"sourcesContent":["/**\n * `@innspel/react-native` — innsendingswidgeten.\n *\n * Widgeten lever inne i vertsappen og arver dens flate (DD-21). Den er en\n * dialog med fokusfelle, tilbake-knapp og live-region (DD-47), viser kjente\n * feil før feltet i feilsporet (DD-03, DD-29), krever bare et minimum antall\n * tegn (DD-44), varsler om PII uten å fjerne noe (DD-46) og gjør offline-køen\n * synlig (DD-41).\n *\n * Se README.md for quickstart, og `docs/sdk/README.md` for det verten må levere.\n */\n\nexport { InnspelProvider, useInnspel } from './InnspelProvider.js';\nexport { InnspelPrivate } from './InnspelPrivate.js';\nexport { InnspelProgram } from './program/InnspelProgram.js';\nexport {\n createScreenshotAdapter,\n type CaptureOptions,\n type CaptureRefFn,\n type ImageStepNote,\n type PickImageFn,\n type ScreenshotAdapter,\n type ScreenshotAdapterOptions,\n type ScreenshotCapture,\n} from './skjermbilde.js';\nexport { createMemoryStorage, createStorage, type AsyncStorageLike } from './lagring.js';\nexport { byggTema, useTema, type PartialTheme, type Tema } from './tema.js';\nexport { light, screenRules, t as darkTokens, type InnspelColors, type InnspelTheme } from './generated/tokens.js';\nexport { statusVisning, venterVisning, type StatusVisning } from './widget/status.js';\nexport { lofte, tekst } from './widget/tekster.js';\n\n// Videresendt fra kjernen, så verten slipper å installere begge for typene.\nexport type {\n AttachmentInput,\n AttachmentOutcome,\n CaptureInput,\n ContextInput,\n InnspelClient,\n InnspelOptions,\n InnspelStorage,\n InvitationView,\n MyPrograms,\n MySubmission,\n OpenFeedbackOptions,\n ParticipationView,\n ProgramTask,\n ProgramView,\n SubmissionStatusView,\n} from '@innspel/core';\n","import type { InnspelClient, OpenFeedbackOptions } from '@innspel/core';\nimport React, { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';\nimport { View } from 'react-native';\nimport { createPrivateRegistry, SkjermbildeContext, type ImageStepNote, type ScreenshotAdapter, type SkjermbildeKontekst, type ViewRef } from './skjermbilde.js';\nimport { byggTema, TemaProvider, type PartialTheme } from './tema.js';\nimport { Widget } from './widget/Widget.js';\n\ninterface InnspelKontekst {\n client: InnspelClient;\n /** Åpner widgeten. Samme som `client.openFeedback()`. */\n open: (options?: OpenFeedbackOptions) => Promise<void>;\n close: () => void;\n}\n\nconst Kontekst = createContext<InnspelKontekst | null>(null);\n\n/**\n * Pakk appen i denne, og widgeten finnes.\n *\n * Provideren gjør fire ting: den registrerer visningen hos kjernen (så\n * `client.openFeedback()` virker hvor som helst i appen, også utenfor React),\n * den holder temaet, den rendrer selve arket — og den pakker vertsappen i én\n * `View` med referanse, som er det skjermbildet tas av (K4). Modalen ligger\n * utenfor den viewen og kommer aldri med på bildet.\n *\n * @example\n * ```tsx\n * const innspel = init({ … });\n *\n * export default function App() {\n * return (\n * <InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef)}>\n * <MinApp />\n * </InnspelProvider>\n * );\n * }\n * ```\n */\nexport function InnspelProvider({\n client,\n children,\n theme,\n colorScheme = 'dark',\n tenantName,\n screenshot,\n imageStepNote,\n}: {\n client: InnspelClient;\n children?: React.ReactNode;\n /** Vertens egne tokens. Alt som utelates faller tilbake på Innspels tema. */\n theme?: PartialTheme;\n colorScheme?: 'dark' | 'light';\n /** Navnet som står på svaret i «Mine innspill» — leietakerens, ikke Innspels. */\n tenantName?: string;\n /**\n * Fangst av skjermbilde, typisk `createScreenshotAdapter(captureRef)` fra\n * react-native-view-shot. Uten den finnes ikke skjermbilde-steget (DD-26) —\n * og det finnes uansett ikke når `screenshotsEnabled` er av (K18).\n */\n screenshot?: ScreenshotAdapter;\n /**\n * Leietakerens egen setning ved bildesteget, f.eks. «Legg ved et skjermbilde av feilen.\n * Ikke send bilder av andre personer.» Står ved knappene og i forhåndsvisningen. Én\n * streng gjelder begge spor; `{ feil, onske }` gir hvert spor sin. Leietakeren kjenner\n * brukerne sine; plattformen eier ikke den setningen.\n */\n imageStepNote?: ImageStepNote;\n}) {\n const [synlig, setSynlig] = useState(false);\n const [apneOpsjoner, setApneOpsjoner] = useState<OpenFeedbackOptions | undefined>();\n const registrert = useRef(false);\n const rootRef = useRef<ViewRef | null>(null);\n const privat = useMemo(createPrivateRegistry, []);\n\n const open = useCallback(\n async (options?: OpenFeedbackOptions) => {\n setApneOpsjoner(options);\n setSynlig(true);\n },\n [],\n );\n\n const close = useCallback(() => setSynlig(false), []);\n\n // Registreres én gang. Kjernen kaller `presenter.open()` fra\n // `client.openFeedback()`, som er veien inn for kode som ikke er en\n // React-komponent — en navigasjonshandler, en krasjlytter hos verten.\n if (!registrert.current) {\n client.registerPresenter({ open });\n registrert.current = true;\n }\n\n const tema = useMemo(() => byggTema(theme, colorScheme), [theme, colorScheme]);\n const verdi = useMemo<InnspelKontekst>(() => ({ client, open, close }), [client, open, close]);\n const skjermbilde = useMemo<SkjermbildeKontekst>(\n () => ({ adapter: screenshot ?? null, rootRef, privat }),\n [screenshot, privat],\n );\n\n return (\n <Kontekst.Provider value={verdi}>\n <SkjermbildeContext.Provider value={skjermbilde}>\n <TemaProvider value={tema}>\n <View ref={rootRef} collapsable={false} style={{ flex: 1 }} testID=\"innspel-rot\">\n {children}\n </View>\n <Widget\n client={client}\n synlig={synlig}\n {...(apneOpsjoner ? { apneOpsjoner } : {})}\n {...(tenantName ? { tenantName } : {})}\n {...(imageStepNote ? { imageStepNote } : {})}\n onLukk={close}\n />\n </TemaProvider>\n </SkjermbildeContext.Provider>\n </Kontekst.Provider>\n );\n}\n\n/**\n * Klienten og `open` fra nærmeste {@link InnspelProvider}.\n *\n * Kaster utenfor provideren i stedet for å gi `null`: en knapp som stille ikke\n * gjør noe er verre enn en feil under utvikling (tech-decisions.md, «Feil bruk\n * feiler høyt og tidlig»).\n */\nexport function useInnspel(): InnspelKontekst {\n const k = useContext(Kontekst);\n if (!k) {\n throw new Error(\n '[innspel] useInnspel() ble kalt utenfor <InnspelProvider>. Pakk appen din i den — se README.md.',\n );\n }\n return k;\n}\n","import type { MaskRect } from '@innspel/core';\nimport { createContext, useContext, type ComponentRef, type RefObject } from 'react';\nimport { Image, type View } from 'react-native';\n\n/** Host-elementet bak en `View` — det som kan måles og fanges. RN 0.87: `View` er en funksjonskomponent, så typen hentes herfra. */\nexport type ViewRef = ComponentRef<typeof View>;\n\n/**\n * Fangst av skjermbilde er det ene stedet widgeten trenger noe React Native\n * ikke har innebygd. Pakken tar INGEN avhengighet på det (K19, samme mønster som\n * `createStorage`): verten sender inn `captureRef` fra `react-native-view-shot`,\n * og uten adapter finnes ikke skjermbilde-steget (DD-26) — ikke som en grå\n * knapp, det finnes ikke.\n *\n * Alt som rører plattformen går gjennom adapteren, også måling og fillesing, så\n * widgeten kan testes med en fake og maskeringen bevises uten native kode.\n */\n\nexport interface ScreenshotCapture {\n /** Fil-URI fra fangsten. Forlater aldri enheten før den er maskert og rekomponert. */\n uri: string;\n /** Bitmapens størrelse i piksler. */\n width: number;\n height: number;\n}\n\nexport interface CaptureOptions {\n format: 'jpg' | 'png';\n /** 0–1, kun JPEG. */\n quality: number;\n}\n\nexport interface ScreenshotAdapter {\n /** Fanger viewen bak referansen til en fil. Kalles ved «Legg ved skjermbilde» (K4), og igjen på forhåndsvisningen for å rekomponere. */\n capture(ref: RefObject<ViewRef | null>, options: CaptureOptions): Promise<ScreenshotCapture>;\n /**\n * Velger et bilde fra enhetens bildebibliotek — «Velg bilde». `null` når innsenderen\n * avbryter. Uten metoden finnes ikke valget. Bildet går gjennom samme forhåndsvisning\n * og maskering, og det som lastes opp er komposittet fra `capture`, aldri fila.\n */\n pick?(): Promise<ScreenshotCapture | null>;\n /**\n * `false` fjerner «Legg ved skjermbilde» og lar bare «Velg bilde» stå — når skjermen\n * widgeten åpnes fra sjelden er der feilen er. `capture` trengs likevel til å\n * rekomponere forhåndsvisningen. Standard er `true`.\n */\n captureScreen?: boolean;\n /** Viewens rektangel i vinduskoordinater, i punkter. Null når den ikke er montert. */\n measure(ref: RefObject<ViewRef | null>): Promise<MaskRect | null>;\n /** Leser en fangst som Blob for opplasting. */\n read(uri: string): Promise<Blob>;\n}\n\n/** Signaturen til `captureRef` i react-native-view-shot — det eneste verten trenger å sende inn. */\nexport type CaptureRefFn = (\n ref: RefObject<ViewRef | null> | ViewRef,\n options: { format: 'jpg' | 'png'; quality: number; result: 'tmpfile' },\n) => Promise<string>;\n\n/**\n * Vertens bildevelger. Resultatet trenger bare `uri`; mangler størrelsen, måles den.\n * Returner `null` når innsenderen avbryter.\n *\n * @example\n * ```ts\n * import * as ImagePicker from 'expo-image-picker';\n * const pickImage: PickImageFn = async () => {\n * const r = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], exif: false });\n * return r.canceled ? null : { uri: r.assets[0]!.uri, width: r.assets[0]!.width, height: r.assets[0]!.height };\n * };\n * ```\n */\nexport type PickImageFn = () => Promise<{ uri: string; width?: number; height?: number } | null>;\n\n/**\n * Leietakerens setning ved bildesteget: én for begge spor, eller én per spor.\n * Et spor uten setning viser ingen.\n */\nexport type ImageStepNote = string | { feil?: string; onske?: string };\n\nexport interface ScreenshotAdapterOptions {\n /** Gir «Velg bilde». Pakken tar ingen avhengighet på en velger (K19). */\n pickImage?: PickImageFn;\n /** `false` fjerner «Legg ved skjermbilde». Standard er `true`. */\n captureScreen?: boolean;\n}\n\nfunction storrelse(uri: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => Image.getSize(uri, (w, h) => resolve({ width: w, height: h }), reject));\n}\n\n/**\n * Lager adapteren av vertens `captureRef`. Dimensjonene hentes med `Image.getSize`,\n * målingen med `measureInWindow`, og fila leses med `fetch(uri).blob()` — alt fra\n * React Native selv.\n *\n * @example\n * ```tsx\n * import { captureRef } from 'react-native-view-shot';\n * <InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef)}>\n * // Med bildevelger, og uten fangst av skjermen widgeten åpnes fra:\n * <InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef, { pickImage, captureScreen: false })}>\n * ```\n */\nexport function createScreenshotAdapter(captureRef: CaptureRefFn, options: ScreenshotAdapterOptions = {}): ScreenshotAdapter {\n const { pickImage, captureScreen } = options;\n return {\n async capture(ref, opts) {\n const uri = await captureRef(ref, { format: opts.format, quality: opts.quality, result: 'tmpfile' });\n return { uri, ...(await storrelse(uri)) };\n },\n ...(pickImage\n ? {\n async pick() {\n const valgt = await pickImage();\n if (!valgt) return null;\n const { width, height } = valgt.width && valgt.height ? { width: valgt.width, height: valgt.height } : await storrelse(valgt.uri);\n return { uri: valgt.uri, width, height };\n },\n }\n : {}),\n ...(captureScreen === false ? { captureScreen: false } : {}),\n measure(ref) {\n return new Promise((resolve) => {\n const view = ref.current;\n if (!view) return resolve(null);\n view.measureInWindow((x, y, width, height) => resolve({ x, y, width, height }));\n });\n },\n async read(uri) {\n const res = await fetch(uri);\n return res.blob();\n },\n };\n}\n\n/**\n * Private views (DD-39): det verten har merket med `<InnspelPrivate>`. Registeret\n * lever i provideren; widgeten måler hver av dem i fangstøyeblikket og legger en\n * maske brukeren ikke kan fjerne.\n */\nexport interface PrivateRegistry {\n register(ref: RefObject<ViewRef | null>): () => void;\n refs(): ReadonlyArray<RefObject<ViewRef | null>>;\n}\n\nexport function createPrivateRegistry(): PrivateRegistry {\n const alle = new Set<RefObject<ViewRef | null>>();\n return {\n register(ref) {\n alle.add(ref);\n return () => {\n alle.delete(ref);\n };\n },\n refs: () => [...alle],\n };\n}\n\nexport interface SkjermbildeKontekst {\n adapter: ScreenshotAdapter | null;\n /** Vertsappen — det som fanges. Modalen ligger utenfor og kommer aldri med. */\n rootRef: RefObject<ViewRef | null>;\n privat: PrivateRegistry;\n}\n\nexport const SkjermbildeContext = createContext<SkjermbildeKontekst | null>(null);\n\nexport function useSkjermbilde(): SkjermbildeKontekst | null {\n return useContext(SkjermbildeContext);\n}\n","import { createContext, useContext } from 'react';\nimport { light, t, type InnspelColors, type InnspelTheme } from './generated/tokens.js';\n\n/**\n * Widgeten lever INNE i vertsappen (DD-21) og skal arve dens flate. Verten\n * sender et delvis tema; alt den ikke sender faller tilbake på Innspels eget\n * (M0.4), som er generert fra `theme/theme.ts` og målt mot WCAG AA.\n *\n * Ingen hex-verdi, px-verdi eller fontstørrelse skrives i en komponent — alt\n * hentes herfra (CLAUDE.md, «Styling»). `fontFamily` finnes ikke: systemfonten\n * er standard i React Native, og å sette den ville brutt med vertsappen.\n */\n\n/**\n * De genererte tokenene er `as const`, så `t.touch` har typen `48` og ikke\n * `number`. Det er riktig for KILDEN — den skal ikke kunne endres ved et uhell\n * — men gjør temaet umulig å overstyre: verten ville måttet sende nøyaktig 48.\n * Denne typen åpner verdiene uten å åpne nøkkelsettet: en vert kan bytte en\n * farge, men ikke finne på en ny.\n */\nexport type Tema = Omit<\n InnspelTheme,\n 'color' | 'space' | 'radius' | 'font' | 'lineHeight' | 'motion' | 'touch' | 'screenPadding' | 'hairline'\n> & {\n color: Record<keyof InnspelColors, string>;\n space: Record<keyof InnspelTheme['space'], number>;\n radius: Record<keyof InnspelTheme['radius'], number>;\n font: Record<keyof InnspelTheme['font'], number>;\n lineHeight: Record<keyof InnspelTheme['lineHeight'], number>;\n motion: Record<keyof InnspelTheme['motion'], number>;\n touch: number;\n screenPadding: number;\n hairline: number;\n};\n\nexport type PartialTheme = {\n color?: Partial<Tema['color']>;\n} & Partial<Omit<Tema, 'color'>>;\n\n/**\n * Fletter vertens tokens over Innspels egne.\n *\n * @param vertens Delvis tema fra `<InnspelProvider theme={…}>`.\n * @param palett `dark` er standard: widgeten åpnes oftest over en app i mørk\n * modus, og et lyst ark over en mørk app blender.\n */\nexport function byggTema(vertens?: PartialTheme, palett: 'dark' | 'light' = 'dark'): Tema {\n const bunn = (palett === 'light' ? light : t) as unknown as Tema;\n if (!vertens) return bunn;\n\n return {\n ...bunn,\n ...vertens,\n color: { ...bunn.color, ...vertens.color },\n };\n}\n\nconst TemaContext = createContext<Tema>(t as unknown as Tema);\n\nexport const TemaProvider = TemaContext.Provider;\n\n/** Tokenene som gjelder her. Bruk ALDRI en literal farge eller avstand i stedet. */\nexport function useTema(): Tema {\n return useContext(TemaContext);\n}\n","/**\n * tokens.ts — GENERERT fra theme/theme.ts (avtrykk 6a743a62a4fd).\n * Rediger aldri denne filen. Endre temaet i kilden og kjør\n * `node scripts/generate-tokens.ts`, som CI verifiserer med `--check`.\n *\n * Tokenene @innspel/react-native faller tilbake på når verten ikke sender egne.\n * Widgeten lever inne i vertsappen og skal arve dens flate (DD-21); dette er\n * bunnen, ikke fasiten.\n *\n * 73 kontrastpar er målt mot WCAG AA i begge paletter, og generatoren\n * nekter å skrive hvis ett faller under kravet. Farge bærer aldri mening alene\n * — hver status har ikon og tekstetikett (DD-08).\n *\n * fontFamily finnes ikke her med vilje: systemfonten er standard i React\n * Native, og å sette den ville brutt med vertsappen.\n */\n\n/** Mørk palett — fallback når verten ikke sender egne tokens. */\nexport const t = {\n color: {\n bg: \"#111417\",\n surface: \"#1A1E22\",\n surfaceRaised: \"#232830\",\n border: \"#2E343B\",\n borderStrong: \"#3D444D\",\n borderInteractive: \"#7C8894\",\n textPrimary: \"#F2F4F6\",\n textSecondary: \"#B4BCC5\",\n textMuted: \"#8D96A1\",\n textDisabled: \"#5A626B\",\n actionPrimary: \"#5AD3E2\",\n onActionPrimary: \"#04252A\",\n actionSecondaryBorder: \"#7C8894\",\n actionSecondaryText: \"#F2F4F6\",\n brand: \"#5AD3E2\",\n onBrand: \"#04252A\",\n brandFill: \"#0E7C8C\",\n onBrandFill: \"#FFFFFF\",\n brandBg: \"#0C2A30\",\n danger: \"#FF7A8C\",\n dangerFill: \"#C4001F\",\n onDangerFill: \"#FFFFFF\",\n dangerBg: \"#2C1116\",\n success: \"#3ED88A\",\n onSuccess: \"#062015\",\n successBg: \"#0E2A1E\",\n warning: \"#FFC24D\",\n onWarning: \"#2A1C02\",\n warningBg: \"#2C2107\",\n info: \"#5CC0FF\",\n onInfo: \"#04222F\",\n infoBg: \"#0E2531\",\n neutral: \"#A3ACB6\",\n onNeutral: \"#111417\",\n neutralBg: \"#242A31\",\n scrim: \"rgba(0, 0, 0, 0.72)\",\n },\n space: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n xxl: 48,\n },\n radius: {\n sm: 6,\n md: 8,\n lg: 12,\n pill: 999,\n },\n font: {\n display: 40,\n h1: 24,\n h2: 21,\n h3: 18,\n body: 16,\n small: 13,\n tiny: 11,\n },\n lineHeight: {\n display: 48,\n h1: 30,\n h2: 27,\n h3: 24,\n body: 24,\n small: 18,\n tiny: 16,\n },\n weight: {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n },\n motion: {\n fast: 120,\n base: 200,\n slow: 320,\n },\n icon: { inline: 20, minste: 16 },\n touch: 48,\n screenPadding: 24,\n hairline: 1,\n} as const;\n\n/** Lys palett. */\nexport const light = {\n color: {\n bg: \"#F6F7F9\",\n surface: \"#FFFFFF\",\n surfaceRaised: \"#EDEFF3\",\n border: \"#D2D7DE\",\n borderStrong: \"#B9C0C9\",\n borderInteractive: \"#6F7883\",\n textPrimary: \"#14181D\",\n textSecondary: \"#454D57\",\n textMuted: \"#5C6470\",\n textDisabled: \"#9AA2AD\",\n actionPrimary: \"#0A6673\",\n onActionPrimary: \"#FFFFFF\",\n actionSecondaryBorder: \"#6F7883\",\n actionSecondaryText: \"#14181D\",\n brand: \"#0A6673\",\n onBrand: \"#FFFFFF\",\n brandFill: \"#0A6673\",\n onBrandFill: \"#FFFFFF\",\n brandBg: \"#E0F0F2\",\n danger: \"#B3001B\",\n dangerFill: \"#B3001B\",\n onDangerFill: \"#FFFFFF\",\n dangerBg: \"#FCE8EA\",\n success: \"#04693C\",\n onSuccess: \"#FFFFFF\",\n successBg: \"#E4F4EC\",\n warning: \"#7A5200\",\n onWarning: \"#FFFFFF\",\n warningBg: \"#FBF1DE\",\n info: \"#00588F\",\n onInfo: \"#FFFFFF\",\n infoBg: \"#E4F0F8\",\n neutral: \"#5C6470\",\n onNeutral: \"#FFFFFF\",\n neutralBg: \"#EEF0F3\",\n scrim: \"rgba(10, 14, 18, 0.45)\",\n },\n space: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n xxl: 48,\n },\n radius: {\n sm: 6,\n md: 8,\n lg: 12,\n pill: 999,\n },\n font: {\n display: 40,\n h1: 24,\n h2: 21,\n h3: 18,\n body: 16,\n small: 13,\n tiny: 11,\n },\n lineHeight: {\n display: 48,\n h1: 30,\n h2: 27,\n h3: 24,\n body: 24,\n small: 18,\n tiny: 16,\n },\n weight: {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n },\n motion: {\n fast: 120,\n base: 200,\n slow: 320,\n },\n icon: { inline: 20, minste: 16 },\n touch: 48,\n screenPadding: 24,\n hairline: 1,\n} as const;\n\n/** Innspillets statuser. `fg`/`bg` er TOKENNAVN og slås opp i den aktive paletten. Nøklene er Submissions.SubmissionStatus i contracts/. */\nexport const submissionStatus = {\n ny: {\n statusType: \"reviewing\",\n ikon: \"ellipse-outline\",\n etikett: { feil: \"Mottatt\", onske: \"Mottatt\" },\n lofte: { feil: \"Vi har fått den. Du hører fra oss.\", onske: \"Vi har fått den. Du hører fra oss.\" },\n fg: \"textSecondary\",\n bg: \"neutralBg\",\n variant: \"outline\",\n },\n vurderes: {\n statusType: \"reviewing\",\n ikon: \"hourglass-outline\",\n etikett: { feil: \"Vurderes\", onske: \"Vurderes\" },\n lofte: { feil: \"Svar innen {frist} — også hvis det er nei.\", onske: \"Svar innen {frist} — også hvis det er nei.\" },\n fg: \"info\",\n bg: \"infoBg\",\n variant: \"outline\",\n },\n planlagt: {\n statusType: \"active\",\n ikon: \"calendar-outline\",\n etikett: { feil: \"Planlagt\", onske: \"Planlagt\" },\n lofte: { feil: \"Du får beskjed når den er rettet.\", onske: \"Du får beskjed når det er levert.\" },\n fg: \"brand\",\n bg: \"brandBg\",\n variant: \"outline\",\n },\n bygges: {\n statusType: \"active\",\n ikon: \"construct-outline\",\n etikett: { feil: \"Retter nå\", onske: \"Bygger\" },\n lofte: { feil: \"Du får beskjed når den er rettet.\", onske: \"Du får beskjed når det er levert.\" },\n fg: \"brand\",\n bg: \"brandBg\",\n variant: \"filled\",\n },\n kjent_feil: {\n statusType: \"active\",\n ikon: \"warning-outline\",\n etikett: { feil: \"Kjent feil\", onske: \"Kjent feil\" },\n lofte: { feil: \"Kjent feil. Du får beskjed når den er rettet.\", onske: \"Kjent feil. Du får beskjed når den er rettet.\" },\n fg: \"warning\",\n bg: \"warningBg\",\n variant: \"outline\",\n },\n levert: {\n statusType: \"complete\",\n ikon: \"checkmark-circle-outline\",\n etikett: { feil: \"Rettet\", onske: \"Levert\" },\n lofte: { feil: \"Ferdig. Ser du feilen igjen, send et nytt innspill.\", onske: \"Ferdig. Takk for ønsket.\" },\n fg: \"success\",\n bg: \"successBg\",\n variant: \"outline\",\n },\n avvist: {\n statusType: \"closed\",\n ikon: \"close-circle-outline\",\n etikett: { feil: \"Avvist\", onske: \"Avvist\" },\n lofte: { feil: \"Vi har svart på denne.\", onske: \"Vi har svart på denne.\" },\n fg: \"danger\",\n bg: \"dangerBg\",\n variant: \"outline\",\n },\n duplikat: {\n statusType: \"closed\",\n ikon: \"git-merge-outline\",\n etikett: { feil: \"Slått sammen\", onske: \"Slått sammen\" },\n lofte: { feil: \"Slått sammen med et innspill som ligner.\", onske: \"Slått sammen med et innspill som ligner.\" },\n fg: \"neutral\",\n bg: \"neutralBg\",\n variant: \"outline\",\n },\n} as const;\n\n/** Programmets statuser. Nøklene er Programs.ProgramStatus i contracts/. */\nexport const programStatus = {\n utkast: {\n ikon: \"create-outline\",\n etikett: \"Utkast\",\n fg: \"textSecondary\",\n bg: \"neutralBg\",\n variant: \"dashed\",\n },\n aapen: {\n ikon: \"ellipse-outline\",\n etikett: \"Åpen — invitasjoner kan sendes\",\n fg: \"info\",\n bg: \"infoBg\",\n variant: \"outline\",\n },\n aktiv: {\n ikon: \"checkmark-circle-outline\",\n etikett: \"Aktiv\",\n fg: \"success\",\n bg: \"successBg\",\n variant: \"outline\",\n },\n avsluttes: {\n ikon: \"time-outline\",\n etikett: \"Avsluttes — oppfølginger går ut\",\n fg: \"warning\",\n bg: \"warningBg\",\n variant: \"outline\",\n },\n avsluttet: {\n ikon: \"checkmark-circle-outline\",\n etikett: \"Avsluttet — rapport fryst\",\n fg: \"neutral\",\n bg: \"neutralBg\",\n variant: \"outline\",\n },\n avbrutt: {\n ikon: \"close-circle\",\n etikett: \"Avbrutt\",\n fg: \"dangerFill\",\n bg: \"onDangerFill\",\n variant: \"filled\",\n },\n} as const;\n\n/** Kjent feil-statusene (M2.4). Nøklene er KnownIssues.KnownIssueStatus i contracts/; «fikset» heter «Rettet» (DD-22). */\nexport const knownIssueStatus = {\n aktiv: {\n ikon: \"warning-outline\",\n etikett: \"Aktiv\",\n fg: \"warning\",\n bg: \"warningBg\",\n variant: \"outline\",\n },\n fikset: {\n ikon: \"checkmark-circle-outline\",\n etikett: \"Rettet\",\n fg: \"success\",\n bg: \"successBg\",\n variant: \"dashed\",\n },\n} as const;\n\n/** Løftet for `vurderes` uten frist: svaret loves, tidspunktet ikke (DD-07, DD-28). */\nexport const lofteUtenFrist = \"Du får svar — også hvis det er nei.\";\n\n/** Skjermbilde-maskering. Faste signalfarger, uavhengig av palett (DD-39, DD-40). Vedlegg er M1.3. */\nexport const screenRules = {\n brushFill: \"#E5007D\",\n autoMaskFill: \"#101114\",\n autoMaskStroke: \"#E5007D\",\n autoMaskText: \"#FFFFFF\",\n previewBackdrop: \"#000000\",\n qrBackdrop: \"#FFFFFF\",\n brushWidth: 28,\n textBlurRadius: 24,\n} as const;\n\n/** Formen widgeten tar imot. Verten sender et delvis tema; resten faller tilbake hit. */\nexport type InnspelTheme = typeof t;\nexport type InnspelColors = InnspelTheme['color'];\n","import {\n InnspelApiError,\n InnspelQueueFullError,\n type AttachmentInput,\n type InnspelClient,\n type KnownIssueCard,\n type MaskRect,\n type MySubmission,\n type OpenFeedbackOptions,\n type PatternFinding,\n} from '@innspel/core';\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { KeyboardAvoidingView, Modal, Pressable, View } from 'react-native';\nimport { initialWindowMetrics, SafeAreaInsetsContext } from 'react-native-safe-area-context';\nimport { Ikon } from '../Ikon.js';\nimport { useSkjermbilde, type ImageStepNote, type ScreenshotCapture, type ViewRef } from '../skjermbilde.js';\nimport { useTema } from '../tema.js';\nimport { Felt } from './Felt.js';\nimport { Valg } from './Valg.js';\nimport { KjenteFeil } from './KjenteFeil.js';\nimport { Kvittering, type KvitteringArt } from './Kvittering.js';\nimport { MineInnspill } from './MineInnspill.js';\nimport { Skjermbilde } from './Skjermbilde.js';\nimport { Banner, Btn } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\nexport type Steg = 'valg' | 'kjenteFeil' | 'felt' | 'skjermbilde' | 'kvittering' | 'mine';\n\n/** JPEG med denne kvaliteten holder et 3×-skjermbilde godt under 5 MB (K9) og gjør uskarphet irreversibel i praksis. */\nconst FANGST = { format: 'jpg', quality: 0.85 } as const;\n\n/**\n * Widgeten. Ett ark over vertsappen — aldri en flytende knapp over innhold\n * (DD-21).\n *\n * **DD-47, og hvorfor det står her og ikke i en TODO:** arket er en dialog og\n * oppfører seg som en. `<Modal>` gir fokusfellen; `onRequestClose` er\n * Android-tilbake og ESC på tastatur; `accessibilityViewIsModal` skjuler\n * vertsappen for skjermlesere på iOS; kvitteringen er en live-region. Sentrys\n * crash-modal mangler alle fire (issue #23288, #9291) — den er leverandøren som\n * dokumenterer både løsningen og mangelen.\n *\n * **Flyten er ikke symmetrisk.** Feilsporet møter kjente feil FØR feltet: den\n * som står i en feil skal slippe å skrive noe hvis svaret allerede finnes.\n * Ønskesporet møter dem ETTER: et ønske må formuleres før det kan sammenlignes.\n *\n * **Skjermbildet (2f, K4):** tas først når innsenderen trykker, aldri ved åpning.\n * Steget finnes bare når leietakeren har skjermbilde på OG verten har gitt en\n * adapter (DD-26). Private views måles i fangstøyeblikket (DD-39). Det som\n * lastes opp er komposittet av forhåndsvisningen med maskene — rå-URI-en går\n * aldri videre. Teksten sendes først; bildet kan feile alene (DD-42).\n */\nexport function Widget({\n client,\n synlig,\n apneOpsjoner,\n onLukk,\n tenantName,\n imageStepNote,\n}: {\n client: InnspelClient;\n synlig: boolean;\n apneOpsjoner?: OpenFeedbackOptions;\n onLukk: () => void;\n tenantName?: string;\n imageStepNote?: ImageStepNote;\n}) {\n const tema = useTema();\n // Edge-to-edge (Android 15+, Expo SDK 53+): Modal tegner under status- og\n // navigasjonslinja uansett props. Insets fra vertens SafeAreaProvider, ellers\n // vinduets fra oppstart; useSafeAreaInsets ville kastet uten provider.\n const insets = useContext(SafeAreaInsetsContext) ?? initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };\n const skjermbilde = useSkjermbilde();\n const previewRef = useRef<ViewRef | null>(null);\n\n const [steg, setSteg] = useState<Steg>('valg');\n const [spor, setSpor] = useState<'feil' | 'onske'>('feil');\n const [verdi, setVerdi] = useState('');\n const [kort, setKort] = useState<KnownIssueCard[]>([]);\n const [lasterKort, setLasterKort] = useState(false);\n const [lenketTil, setLenketTil] = useState<KnownIssueCard | undefined>();\n const [funn, setFunn] = useState<PatternFinding[]>([]);\n const [fjernede, setFjernede] = useState<string[]>([]);\n const [sender, setSender] = useState(false);\n const online = useNettstatus(client);\n const [feil, setFeil] = useState<string | undefined>();\n const [kvittering, setKvittering] = useState<{ art: KvitteringArt; nr?: string; vedlegg?: 'feilet' | 'forkastet'; frist?: string }>();\n const [mine, setMine] = useState<MySubmission[]>([]);\n const [lasterMine, setLasterMine] = useState(false);\n\n // Skjermbildet: rå fangst til forhåndsvisning, private views i rotens punkter,\n // og det ferdige, maskerte vedlegget som sendes med teksten.\n const [bilde, setBilde] = useState<ScreenshotCapture | undefined>();\n const [automasker, setAutomasker] = useState<MaskRect[]>([]);\n const [rotStorrelse, setRotStorrelse] = useState({ width: 1, height: 1 });\n const [komponerer, setKomponerer] = useState(false);\n const [kilde, setKilde] = useState<'skjerm' | 'galleri'>('skjerm');\n const [vedlegg, setVedlegg] = useState<AttachmentInput | undefined>();\n\n // Leietakerens grenser: startverdiene fra init(), oppdatert fra plattformen ved åpning (M2.5).\n const [innstillinger, setInnstillinger] = useState({ ...client.settings });\n\n // DD-26: steget finnes ikke uten begge. Aldri en deaktivert knapp.\n const skjermbildeMulig = innstillinger.screenshotsEnabled && skjermbilde?.adapter != null;\n const fangstMulig = skjermbildeMulig && skjermbilde?.adapter?.captureScreen !== false;\n const galleriMulig = skjermbildeMulig && typeof skjermbilde?.adapter?.pick === 'function';\n // Vertens setning for sporet innsenderen står i.\n const bildeNotat = typeof imageStepNote === 'string' ? imageStepNote : imageStepNote?.[spor];\n\n const nullstill = useCallback(() => {\n setSteg('valg');\n setSpor('feil');\n setVerdi('');\n setKort([]);\n setLenketTil(undefined);\n setFunn([]);\n setFjernede([]);\n setFeil(undefined);\n setKvittering(undefined);\n setBilde(undefined);\n setAutomasker([]);\n setVedlegg(undefined);\n setKomponerer(false);\n }, []);\n\n // «Mine innspill» åpnet av verten (`view: 'mine'`) er en visning OVER det innsenderen\n // holdt på, ikke et steg i skjemaet (F3). `stegForMine` er steget under — det lukking\n // og «Tilbake» fører tilbake til, så et utkast i feltet står der ved neste åpning.\n const [mineDirekte, setMineDirekte] = useState(false);\n const [stegForMine, setStegForMine] = useState<Steg>('valg');\n const stegRef = useRef(steg);\n stegRef.current = steg;\n\n /** Noe innsenderen har laget og ikke sendt. Det vinner over vertens `track` (F1). */\n const harUtkast = verdi.trim().length > 0 || vedlegg !== undefined;\n\n /**\n * Lukking beholder spor, steg og tekst (F1, samme modell som `@innspel/web`). Fram til\n * 2026-09-15 nullstilte den, og Android-tilbake kastet teksten på ett trykk.\n */\n const lukk = useCallback(() => {\n onLukk();\n if (stegRef.current === 'mine' && mineDirekte) {\n setSteg(stegForMine);\n setMineDirekte(false);\n }\n }, [onLukk, mineDirekte, stegForMine]);\n\n /** Kvitteringen er det ene stedet som nullstiller — der er innspillet sendt. */\n const lukkOgNullstill = useCallback(() => {\n onLukk();\n nullstill();\n setMineDirekte(false);\n setStegForMine('valg');\n }, [onLukk, nullstill]);\n\n // Køen tømmes når widgeten ÅPNES — aldri ved oppstart (DD-41). Resultatet\n // vises ikke: en flush som lykkes er ikke en hendelse innsenderen ba om.\n useEffect(() => {\n if (!synlig) return;\n client.track({ name: 'widget_opened' });\n void client.queue.flush().catch(() => undefined);\n // Konfigurasjonen er et tilbud: svarer den, oppdateres grensene; ellers står de.\n void client.loadSettings().then((s) => setInnstillinger({ ...s })).catch(() => undefined);\n\n // «Mine innspill» (DD-62): tellingen på knappen hentes ved åpning, stille — feiler\n // kallet, står knappen uten tall. Anonym modus har ingen liste og kalles aldri.\n if (!client.isAnonymous) {\n void client.subjects\n .submissions()\n .then(setMine)\n .catch(() => undefined);\n }\n\n // Et utkast vinner over vertens `track`: å bytte spor under en skrevet tekst ville\n // sendt en feil som ønske. «Mine innspill» legges over utkastet og tar det ikke bort.\n if (apneOpsjoner?.view === 'mine' && !client.isAnonymous) void visMine(true);\n else if (apneOpsjoner?.track && !harUtkast) void velgSpor(apneOpsjoner.track);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [synlig]);\n\n const hentKort = useCallback(async () => {\n setLasterKort(true);\n try {\n const q = apneOpsjoner?.screen ? { screen: apneOpsjoner.screen } : {};\n setKort(await client.knownIssues.for(q));\n } finally {\n setLasterKort(false);\n }\n }, [client, apneOpsjoner?.screen]);\n\n const velgSpor = useCallback(\n async (valgt: 'feil' | 'onske') => {\n setSpor(valgt);\n client.track({ name: 'track_selected', type: valgt });\n\n if (valgt === 'onske') {\n // Ønskesporet skriver først; sammenligningen kommer etterpå.\n setSteg('felt');\n return;\n }\n\n setSteg('kjenteFeil');\n await hentKort();\n },\n [client, hentKort],\n );\n\n // Treffene er et tilbud, aldri en sperre (wireframe 2c): er lista tom når\n // oppslaget er ferdig, hoppes skjermen over — rett til feltet, ingen melding.\n useEffect(() => {\n if (steg === 'kjenteFeil' && !lasterKort && kort.length === 0) setSteg('felt');\n }, [steg, lasterKort, kort.length]);\n\n const endreTekst = useCallback(\n (v: string) => {\n setVerdi(v);\n setFunn(client.scanText(v));\n },\n [client],\n );\n\n /**\n * «Legg ved skjermbilde» (K4): fangsten skjer HER, ved trykket, av vertsappen\n * bak arket. Private views måles i samme øyeblikk (DD-39) og regnes om til\n * rotens punkter. Feiler fangsten, kan innsenderen sende uten.\n */\n const taSkjermbilde = useCallback(async () => {\n if (!skjermbilde?.adapter) return;\n const { adapter, rootRef, privat } = skjermbilde;\n setFeil(undefined);\n try {\n const fangst = await adapter.capture(rootRef, FANGST);\n const rot = await adapter.measure(rootRef);\n const private_ = await Promise.all(privat.refs().map((r) => adapter.measure(r)));\n if (rot) {\n setRotStorrelse({ width: rot.width, height: rot.height });\n setAutomasker(\n private_\n .filter((r): r is MaskRect => r !== null)\n .map((r) => ({ x: r.x - rot.x, y: r.y - rot.y, width: r.width, height: r.height })),\n );\n } else {\n setRotStorrelse({ width: fangst.width, height: fangst.height });\n setAutomasker([]);\n }\n setBilde(fangst);\n setKilde('skjerm');\n setSteg('skjermbilde');\n } catch {\n setFeil(tekst.skjermbildeFeilet);\n }\n }, [skjermbilde]);\n\n /**\n * «Velg bilde»: vertens velger, ved trykket. Ingen private views — de hører til\n * skjermen bak arket, ikke til et bilde fra et annet sted — og rot-viewen fanges\n * aldri. Avbryter innsenderen, skjer ingenting.\n */\n const velgBilde = useCallback(async () => {\n const pick = skjermbilde?.adapter?.pick;\n if (!pick) return;\n setFeil(undefined);\n try {\n const valgt = await pick.call(skjermbilde.adapter);\n if (!valgt) return;\n setRotStorrelse({ width: valgt.width, height: valgt.height });\n setAutomasker([]);\n setBilde(valgt);\n setKilde('galleri');\n setSteg('skjermbilde');\n } catch {\n setFeil(tekst.bildeFeilet);\n }\n }, [skjermbilde]);\n\n /**\n * «Legg ved og fortsett»: forhåndsvisningen MED maskene fanges på nytt, og det\n * er komposittet som blir vedlegget. Rå-URI-en brukes aldri etter dette.\n */\n const leggVedBilde = useCallback(async () => {\n if (!skjermbilde?.adapter) return;\n setKomponerer(true);\n try {\n const komposit = await skjermbilde.adapter.capture(previewRef, FANGST);\n const body = await skjermbilde.adapter.read(komposit.uri);\n setVedlegg({ mime: 'image/jpeg', body, width: komposit.width, height: komposit.height });\n setBilde(undefined);\n setSteg('felt');\n } catch {\n setFeil(tekst.skjermbildeFeilet);\n setSteg('felt');\n } finally {\n setKomponerer(false);\n }\n }, [skjermbilde]);\n\n const fjernBilde = useCallback(() => {\n setBilde(undefined);\n setAutomasker([]);\n setVedlegg(undefined);\n setSteg('felt');\n }, []);\n\n /**\n * Ett steg tilbake, ALDRI en nullstilling (UX-gjennomgangen C1). Fra feltet er\n * forrige steg kjente feil i feilsporet når det fantes treff — ellers valget.\n * Fram til 2026-09-14 kalte «Tilbake» `nullstill`, og 120 tegn forsvant på ett\n * trykk.\n */\n const gaaTilbake = useCallback(() => {\n setFeil(undefined);\n // F3: åpnet verten lista direkte, finnes det ikke noe forrige steg i widgeten.\n if (steg === 'mine') {\n if (mineDirekte) lukk();\n else setSteg('valg');\n return;\n }\n if (steg === 'skjermbilde') {\n setBilde(undefined);\n setAutomasker([]);\n setSteg('felt');\n return;\n }\n if (steg === 'felt' && spor === 'feil' && kort.length > 0) {\n setSteg('kjenteFeil');\n return;\n }\n setSteg('valg');\n }, [steg, spor, kort.length, mineDirekte, lukk]);\n\n /**\n * Android-tilbake og ESC (`onRequestClose`). Er det et forrige steg, er det «Tilbake»;\n * på første steg lukker den; på kvitteringen er innspillet sendt, og den nullstiller.\n */\n const androidTilbake = useCallback(() => {\n if (steg === 'valg') lukk();\n else if (steg === 'kvittering') lukkOgNullstill();\n else gaaTilbake();\n }, [steg, lukk, lukkOgNullstill, gaaTilbake]);\n\n const send = useCallback(async () => {\n // Ønskesporet sendes rett fra feltet: kontrakten har ingen ønskekort, og steget\n // «Har noen ønsket dette?» kommer tilbake når den har det (DD-03, presisert\n // 2026-09-14 — fram til da gikk Send i ring uten treff).\n setSender(true);\n setFeil(undefined);\n try {\n const res = await client.capture({\n type: spor,\n text: verdi,\n ...(vedlegg ? { attachment: vedlegg } : {}),\n ...(spor === 'feil' && lenketTil ? { relatedKnownIssueId: lenketTil.id } : {}),\n ...(fjernede.length ? { context: fjernetKontekst(client, fjernede) } : {}),\n } as never);\n\n if (res.status === 'queued') {\n setKvittering({ art: 'kø', ...(res.attachment ? { vedlegg: 'forkastet' as const } : {}) });\n } else {\n setKvittering({\n art: spor,\n nr: res.submission.id,\n // Tidsløftet i kvitteringen er DATOEN fra svaret, aldri «innen 90 dager» (DD-07, DD-28).\n ...(res.submission.deadlineAt ? { frist: res.submission.deadlineAt } : {}),\n ...(res.attachment?.status === 'failed' ? { vedlegg: 'feilet' as const } : {}),\n });\n }\n setSteg('kvittering');\n } catch (e) {\n // Teksten mistes ALDRI: den står i feltet, og årsaken er i klartekst.\n if (e instanceof InnspelQueueFullError) setFeil(e.userMessage);\n else if (e instanceof InnspelApiError) setFeil(e.message);\n else setFeil('tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n }, [client, spor, verdi, vedlegg, lenketTil, fjernede]);\n\n const jaOgsa = useCallback(\n async (k: KnownIssueCard) => {\n setSender(true);\n try {\n const res = await client.knownIssues.confirm(k.id);\n setKvittering({ art: 'jaOgsa', nr: res.id });\n setSteg('kvittering');\n } catch (e) {\n setFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n },\n [client],\n );\n\n /** `direkte`: verten åpnet lista (`view: 'mine'`). Ellers kom innsenderen via knappen på valget. */\n const visMine = useCallback(async (direkte = false) => {\n if (direkte) {\n if (stegRef.current !== 'mine') setStegForMine(stegRef.current);\n } else {\n setStegForMine('valg');\n }\n setMineDirekte(direkte);\n setSteg('mine');\n setLasterMine(true);\n try {\n setMine(await client.subjects.submissions());\n } catch {\n setMine([]);\n } finally {\n setLasterMine(false);\n }\n }, [client]);\n\n /** «Send nytt innspill» i lista: til utkastet om det finnes, ellers et nytt skjema. */\n const nyttFraMine = useCallback(() => {\n setMineDirekte(false);\n if (harUtkast) setSteg(stegForMine);\n else nullstill();\n }, [harUtkast, stegForMine, nullstill]);\n\n return (\n <Modal\n visible={synlig}\n transparent\n animationType=\"slide\"\n // Android-tilbake og ESC. Uten den er dialogen en felle (DD-47); med `lukk` direkte\n // kastet den teksten (F1). Den er «Tilbake» så lenge det finnes et forrige steg.\n onRequestClose={androidTilbake}\n accessibilityViewIsModal\n >\n {/* Vinduet krymper ikke lenger for tastaturet på edge-to-edge, så arket løftes\n her. Offseten trekker fra navigasjonslinja: arket har den alt som padding,\n og tastaturet dekker den. */}\n <KeyboardAvoidingView\n behavior=\"padding\"\n keyboardVerticalOffset={-insets.bottom}\n style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end', paddingTop: insets.top }}\n >\n <View\n testID=\"innspel-widget\"\n accessibilityViewIsModal\n accessibilityRole=\"none\"\n style={{\n backgroundColor: tema.color.bg,\n borderTopLeftRadius: tema.radius.lg * 2,\n borderTopRightRadius: tema.radius.lg * 2,\n padding: tema.screenPadding,\n paddingBottom: tema.screenPadding + insets.bottom,\n paddingLeft: tema.screenPadding + insets.left,\n paddingRight: tema.screenPadding + insets.right,\n gap: tema.space.md,\n maxHeight: '92%',\n minHeight: '60%',\n // Bildesteget får fast høyde: forhåndsvisningen tilpasses plassen som er igjen, og\n // uten en kjent høyde har den ingen øvre grense (se Skjermbilde.tsx).\n ...(steg === 'skjermbilde' ? { height: '92%' as const } : {}),\n }}\n >\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>\n {steg !== 'valg' && steg !== 'kvittering' ? (\n <Btn variant=\"ghost\" testID=\"tilbake\" ikon=\"arrow-back-outline\" label={tekst.tilbake} onPress={gaaTilbake} />\n ) : (\n <View />\n )}\n <Pressable\n testID=\"lukk\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.lukk}\n onPress={steg === 'kvittering' ? lukkOgNullstill : lukk}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n\n {feil ? <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.sendefeilBanner(feil)} /> : null}\n {/* `cloud-offline-outline` er samme ikon portalens offline-banner bruker. */}\n {!online && steg !== 'kvittering' && steg !== 'mine' ? (\n <Banner ikon=\"cloud-offline-outline\" tone=\"info\" testID=\"offline-banner\" children={tekst.offlineBanner} />\n ) : null}\n\n {steg === 'valg' ? (\n <>\n <Valg onVelg={velgSpor} />\n {/* DD-62: med innspill fra før er dette en inngang på linje med sporene — flate og telling; uten står den dempet. Anonym: ingen liste, ingen knapp (DD-02). */}\n {!client.isAnonymous ? (\n <Btn\n variant={mine.length > 0 ? 'secondary' : 'ghost'}\n testID=\"mine-innspill\"\n ikon=\"list-outline\"\n label={mine.length > 0 ? tekst.mineMedAntall(mine.length) : tekst.mineTittel}\n accessibilityLabel={mine.length > 0 ? tekst.mineEtikett(mine.length) : tekst.mineTittel}\n onPress={() => void visMine()}\n />\n ) : null}\n </>\n ) : null}\n\n {steg === 'kjenteFeil' ? (\n <KjenteFeil\n kort={kort}\n spor={spor}\n laster={lasterKort}\n sender={sender}\n onJaOgsa={jaOgsa}\n onLigner={(k) => {\n setLenketTil(k);\n setSteg('felt');\n }}\n onNei={() => setSteg('felt')}\n />\n ) : null}\n\n {steg === 'felt' ? (\n <Felt\n spor={spor}\n verdi={verdi}\n onEndre={endreTekst}\n minTextLength={innstillinger.minTextLength}\n textMaxLength={innstillinger.textMaxLength}\n kontekst={client.context}\n fjernedeFelter={fjernede}\n onFjernKontekst={(f) => setFjernede((x) => [...x, f])}\n {...(lenketTil ? { lenketTil, onFjernLenke: () => setLenketTil(undefined) } : {})}\n funn={funn}\n onSend={send}\n sender={sender}\n harFeil={feil !== undefined}\n offline={!online}\n {...(fangstMulig ? { onSkjermbilde: taSkjermbilde } : {})}\n {...(galleriMulig ? { onVelgBilde: velgBilde } : {})}\n {...(bildeNotat ? { bildeNotat } : {})}\n harVedlegg={vedlegg !== undefined}\n onFjernVedlegg={fjernBilde}\n />\n ) : null}\n\n {steg === 'skjermbilde' && bilde ? (\n <Skjermbilde\n bilde={bilde}\n automaskerRot={automasker}\n rotStorrelse={rotStorrelse}\n previewRef={previewRef}\n komponerer={komponerer}\n kilde={kilde}\n {...(bildeNotat ? { notat: bildeNotat } : {})}\n onFjern={fjernBilde}\n onLeggVed={leggVedBilde}\n />\n ) : null}\n\n {steg === 'kvittering' && kvittering ? (\n <Kvittering\n art={kvittering.art}\n {...(kvittering.nr ? { saksnummer: kvittering.nr } : {})}\n {...(kvittering.vedlegg ? { vedlegg: kvittering.vedlegg } : {})}\n {...(kvittering.frist ? { frist: kvittering.frist } : {})}\n onLukk={lukkOgNullstill}\n />\n ) : null}\n\n {steg === 'mine' ? (\n <MineInnspill\n rader={mine}\n laster={lasterMine}\n {...(tenantName ? { tenantName } : {})}\n onNytt={nyttFraMine}\n />\n ) : null}\n </View>\n </KeyboardAvoidingView>\n </Modal>\n );\n}\n\n/**\n * Konteksten uten linjene innsenderen har fjernet (DD-05). Et fjernet felt\n * settes til `undefined` — det er slik kjernen (0.2.1) skiller «fjern» fra\n * «behold fra init»; å bare utelate nøkkelen ville fylt feltet igjen. Feltene\n * er en lukket hviteliste, så det som ikke står i `client.context` finnes ikke\n * å fjerne.\n */\n/**\n * Nettstatus fra verten (`init({ connectivity })`). Uten den er svaret alltid «på nett»:\n * widgeten vet da om nettet først når et kall feiler, og køen tar over (DD-41).\n */\nfunction useNettstatus(client: InnspelClient): boolean {\n const c = client.connectivity;\n const [online, setOnline] = useState(() => c?.isOnline() ?? true);\n useEffect(() => {\n if (!c) return undefined;\n setOnline(c.isOnline());\n return c.subscribe?.((v) => setOnline(v));\n }, [c]);\n return online;\n}\n\nfunction fjernetKontekst(client: InnspelClient, fjernede: string[]) {\n const ut: Record<string, unknown> = {};\n for (const k of Object.keys(client.context)) {\n if (k !== 'sdkVersion' && fjernede.includes(k)) ut[k] = undefined;\n }\n return ut;\n}\n","import React from 'react';\nimport { SvgXml } from 'react-native-svg';\nimport { useTema } from './tema.js';\n\nimport arrowBackOutline from '../../../node_modules/ionicons/dist/svg/arrow-back-outline.svg';\nimport brushOutline from '../../../node_modules/ionicons/dist/svg/brush-outline.svg';\nimport bug from '../../../node_modules/ionicons/dist/svg/bug.svg';\nimport bugOutline from '../../../node_modules/ionicons/dist/svg/bug-outline.svg';\nimport bulb from '../../../node_modules/ionicons/dist/svg/bulb.svg';\nimport calendarOutline from '../../../node_modules/ionicons/dist/svg/calendar-outline.svg';\nimport cameraOutline from '../../../node_modules/ionicons/dist/svg/camera-outline.svg';\nimport checkmarkCircleOutline from '../../../node_modules/ionicons/dist/svg/checkmark-circle-outline.svg';\nimport chevronDownOutline from '../../../node_modules/ionicons/dist/svg/chevron-down-outline.svg';\nimport chevronUpOutline from '../../../node_modules/ionicons/dist/svg/chevron-up-outline.svg';\nimport closeCircleOutline from '../../../node_modules/ionicons/dist/svg/close-circle-outline.svg';\nimport closeOutline from '../../../node_modules/ionicons/dist/svg/close-outline.svg';\nimport cloudOfflineOutline from '../../../node_modules/ionicons/dist/svg/cloud-offline-outline.svg';\nimport constructOutline from '../../../node_modules/ionicons/dist/svg/construct-outline.svg';\nimport contrastOutline from '../../../node_modules/ionicons/dist/svg/contrast-outline.svg';\nimport ellipseOutline from '../../../node_modules/ionicons/dist/svg/ellipse-outline.svg';\nimport exitOutline from '../../../node_modules/ionicons/dist/svg/exit-outline.svg';\nimport flaskOutline from '../../../node_modules/ionicons/dist/svg/flask-outline.svg';\nimport gridOutline from '../../../node_modules/ionicons/dist/svg/grid-outline.svg';\nimport hourglassOutline from '../../../node_modules/ionicons/dist/svg/hourglass-outline.svg';\nimport imageOutline from '../../../node_modules/ionicons/dist/svg/image-outline.svg';\nimport imagesOutline from '../../../node_modules/ionicons/dist/svg/images-outline.svg';\nimport listOutline from '../../../node_modules/ionicons/dist/svg/list-outline.svg';\nimport lockClosedOutline from '../../../node_modules/ionicons/dist/svg/lock-closed-outline.svg';\nimport mergeOutline from '../../../node_modules/ionicons/dist/svg/git-merge-outline.svg';\nimport openOutline from '../../../node_modules/ionicons/dist/svg/open-outline.svg';\nimport scanOutline from '../../../node_modules/ionicons/dist/svg/scan-outline.svg';\nimport swapVerticalOutline from '../../../node_modules/ionicons/dist/svg/swap-vertical-outline.svg';\nimport trashOutline from '../../../node_modules/ionicons/dist/svg/trash-outline.svg';\nimport warningOutline from '../../../node_modules/ionicons/dist/svg/warning-outline.svg';\n\n/**\n * Ionicons som inline SVG i React Native. «Emoji brukes aldri i\n * implementasjonen» (brand-ui-guidelines): en emoji tegnes av operativsystemet\n * i sine egne faste farger — den følger verken vertens palett eller temaets\n * ikonmål, den ser ulik ut på iOS og Android, og 🐞 leses opp som «marihøne».\n *\n * Navnene er de SAMME som i `submissionStatus`/`knownIssueStatus` i\n * `theme/theme.ts` (gjennom `src/generated/tokens.ts`), i ikonkartene i\n * `design/wireframes/innsending-widget.jsx` og `betaprogram-tester.jsx`, og i\n * `portal/src/lib/Ikon.tsx` og `panel/src/status/Ikon.tsx` — ett ikonkart for\n * hele produktet, tre rendrere.\n *\n * Stiene går via `node_modules` fordi ioniconss `exports` ikke eksponerer\n * SVG-filene. Strengene INLINES ved bygg av esbuild-lasteren `.svg: text` i\n * `tsup.config.ts`, så pakken får ingen runtime-avhengighet av `ionicons` —\n * bare av `react-native-svg`, som er en peer.\n *\n * **Importen er statisk og uten `try`.** Mangler verten `react-native-svg`,\n * feiler Metro ved bygg med navnet på pakken. Det er riktig sted: et manglende\n * peer skal stoppe bygget, ikke bli til et usynlig ikon i en widget som er i\n * drift. Se «`react-native-svg` som peer i @innspel/react-native» i\n * `docs/tech-decisions.md`.\n */\n\n/**\n * En `<title>` i en SVG leses opp — «Bug» foran teksten — og ikonet er\n * dekorativt: teksten ved siden av bærer meningen (DD-08). Samme stripping som\n * `portal/src/lib/Ikon.tsx` og `panel/src/status/Ikon.tsx`.\n *\n * Ionicons 8.1.0 leverer ingen titler (målt: 0 av 1357 filer), så steget er\n * forebyggende — det finnes fordi en oppgradering som legger dem tilbake ellers\n * ville endret opplesningsrekkefølgen i widgeten uten at noe ble rødt.\n * Eksportert for at testen skal kunne bevise at det faktisk fjerner noe.\n */\nexport const utenTittel = (svg: string) => svg.replace(/<title>[\\s\\S]*?<\\/title>/g, '');\n\nconst IKONER: Record<string, string> = Object.fromEntries(\n Object.entries({\n 'arrow-back-outline': arrowBackOutline,\n 'brush-outline': brushOutline,\n // Fylte varianter: bare på sporvalgets to kort (DD-63), der ikonet bærer stemningen.\n bug,\n bulb,\n 'bug-outline': bugOutline,\n 'calendar-outline': calendarOutline,\n 'camera-outline': cameraOutline,\n 'checkmark-circle-outline': checkmarkCircleOutline,\n 'chevron-down-outline': chevronDownOutline,\n 'chevron-up-outline': chevronUpOutline,\n 'close-circle-outline': closeCircleOutline,\n 'close-outline': closeOutline,\n 'cloud-offline-outline': cloudOfflineOutline,\n 'construct-outline': constructOutline,\n 'contrast-outline': contrastOutline,\n 'ellipse-outline': ellipseOutline,\n 'exit-outline': exitOutline,\n 'flask-outline': flaskOutline,\n 'git-merge-outline': mergeOutline,\n 'grid-outline': gridOutline,\n 'hourglass-outline': hourglassOutline,\n 'image-outline': imageOutline,\n 'images-outline': imagesOutline,\n 'list-outline': listOutline,\n 'lock-closed-outline': lockClosedOutline,\n 'open-outline': openOutline,\n 'scan-outline': scanOutline,\n 'swap-vertical-outline': swapVerticalOutline,\n 'trash-outline': trashOutline,\n 'warning-outline': warningOutline,\n }).map(([navn, svg]) => [navn, utenTittel(svg)]),\n);\n\n/** Navnene `Ikon` kjenner. Et navn som ikke står her kaster ved rendring, aldri stille. */\nexport const IKONNAVN: readonly string[] = Object.keys(IKONER);\n\n/**\n * Dekorativt ikon — alltid ved siden av tekst, aldri alene. Farge og form\n * bærer ikke mening alene (DD-08), så ikonet er skjult for skjermlesere og\n * teksten sier alt.\n *\n * Målet kommer fra `icon` i temaet, aldri fra et tall her: Ionicons tegner med\n * 6,25 % av boksen, så strektykkelsen følger målet, og `minste` (16) er gulvet\n * der streken treffer 1,00 px. Fargen settes som `color`, som er det\n * `currentColor` i SVG-en løses mot.\n */\nexport function Ikon({\n navn,\n storrelse = 'inline',\n farge,\n}: {\n navn: string;\n /**\n * `minste` i piller, hint og chips · `inline` ved siden av brødtekst · `stor`\n * de to stedene ikonet står ALENE og bærer stemningen: sporvalgets flater og\n * kvitteringen. `stor` er et MULTIPLUM av tokenet, ikke et nytt tall — samme\n * regel som `.innspel-flate-ikon` og `.innspel-kvittering-ikon` på web.\n */\n storrelse?: 'stor' | 'inline' | 'minste';\n /** En farge fra temaet. Uten: `textPrimary`. Aldri en literal. */\n farge?: string;\n}) {\n const tema = useTema();\n const svg = IKONER[navn];\n if (!svg) throw new Error(`[innspel] Ikonet «${navn}» er ikke tatt med i Ikon.tsx.`);\n\n const maal =\n storrelse === 'minste' ? tema.icon.minste : storrelse === 'stor' ? 2 * tema.icon.inline : tema.icon.inline;\n return (\n <SvgXml\n // `testID` er navnet: en test kan da slå fast HVILKET ikon en flate tegner,\n // ikke bare at den tegner ett. @testing-library/react-native v14 har ingen\n // spørring på komponenttype lenger, så uten den ville ikonet vært usynlig i test.\n testID={`ikon-${navn}`}\n xml={svg}\n width={maal}\n height={maal}\n color={farge ?? tema.color.textPrimary}\n // Konturikonene har `fill=\"none\"` og `stroke=\"currentColor\"` selv. De fylte (DD-63)\n // har ingen fill på stiene, og react-native-svg tegner dem da svarte — fargen arves\n // fra rota her, og rører ikke en sti som alt sier «none».\n fill={farge ?? tema.color.textPrimary}\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n />\n );\n}\n","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M244 400 100 256l144-144M120 256h292\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M452.37 59.63a40.49 40.49 0 0 0-57.26 0L184 294.74c23.08 4.7 46.12 27.29 49.26 49.26l219.11-227.11a40.49 40.49 0 0 0 0-57.26M138 336c-29.88 0-54 24.5-54 54.86 0 23.95-20.88 36.57-36 36.57C64.56 449.74 92.82 464 120 464c39.78 0 72-32.73 72-73.14 0-30.36-24.12-54.86-54-54.86\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M463.55 272.13H400v-48.2q0-4.32-.27-8.47c29.57-27.88 32.25-64.63 32.27-103 0-8.61-6.64-16-15.25-16.41A16 16 0 0 0 400 112c0 28-1.86 48.15-9.9 63.84-19.22-41.15-65.78-63.91-134.1-63.91-39.8 0-74.19 9.13-99.43 26.39-14.9 10.19-26.2 22.91-33.7 37.72C114 160.65 112 141 112 112.46c0-8.61-6.6-16-15.2-16.44A16 16 0 0 0 80 112c0 37.63 2.61 73.73 32.44 101.63q-.43 5.06-.44 10.3v48.2H48.45c-8.61 0-16 6.62-16.43 15.23a16 16 0 0 0 16 16.77h64V320a143.3 143.3 0 0 0 10.39 53.69C96.74 396.64 80.18 422 80 463.34c0 8.74 6.62 16.3 15.36 16.65A16 16 0 0 0 112 464c0-27.66 9.1-44.71 26.17-61.32A144.37 144.37 0 0 0 220 459.42a16 16 0 0 0 20-15.49V192.45c0-8.61 6.62-16 15.23-16.43A16 16 0 0 1 272 192v251.93a16 16 0 0 0 20 15.49 144.4 144.4 0 0 0 81.82-56.74c17 16.54 26.09 33.52 26.17 60.95a16.27 16.27 0 0 0 15.1 16.37A16 16 0 0 0 432 464c0-41.68-16.6-67.23-42.39-90.31A143.3 143.3 0 0 0 400 320v-15.87h64a16 16 0 0 0 16-16.77c-.42-8.61-7.84-15.23-16.45-15.23\"/><path d=\"m321.39 104 .32.09c13.57 3.8 25.07-10.55 18.2-22.85A95.86 95.86 0 0 0 256.21 32h-.42a95.87 95.87 0 0 0-84.19 50.13c-6.84 12.58 5.14 27 18.84 22.86 19.71-6 41.79-9.06 65.56-9.06 24.09 0 46.09 2.72 65.39 8.07\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M370 378c28.89 23.52 46 46.07 46 86M142 378c-28.89 23.52-46 46.06-46 86M384 208c28.89-23.52 32-56.07 32-96M128 206c-28.89-23.52-32-54.06-32-94M464 288.13h-80M128 288.13H48M256 192v256\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M256 448c-70.4 0-128-57.6-128-128v-96.07c0-65.07 57.6-96 128-96h0c70.4 0 128 25.6 128 96V320c0 70.4-57.6 128-128 128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M179.43 143.52a49.1 49.1 0 0 1-3.43-15.73A80 80 0 0 1 255.79 48h.42A80 80 0 0 1 336 127.79a41.9 41.9 0 0 1-3.12 14.3\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M288 464h-64a16 16 0 0 0 0 32h64a16 16 0 0 0 0-32M304 416h-96a16 16 0 0 0 0 32h96a16 16 0 0 0 0-32M369.42 62.69C339.35 32.58 299.07 16 256 16A159.62 159.62 0 0 0 96 176c0 46.62 17.87 90.23 49 119.64l4.36 4.09C167.37 316.57 192 339.64 192 360v24a16 16 0 0 0 16 16h24a8 8 0 0 0 8-8V274.82a8 8 0 0 0-5.13-7.47A130.7 130.7 0 0 1 208.71 253a16 16 0 1 1 18.58-26c7.4 5.24 21.65 13 28.71 13s21.31-7.78 28.73-13a16 16 0 0 1 18.56 26 130.7 130.7 0 0 1-26.16 14.32 8 8 0 0 0-5.13 7.47V392a8 8 0 0 0 8 8h24a16 16 0 0 0 16-16v-24c0-19.88 24.36-42.93 42.15-59.77l4.91-4.66C399.08 265 416 223.61 416 176a159.16 159.16 0 0 0-46.58-113.31\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><rect width=\"416\" height=\"384\" x=\"48\" y=\"80\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32\" rx=\"48\"/><circle cx=\"296\" cy=\"232\" r=\"24\"/><circle cx=\"376\" cy=\"232\" r=\"24\"/><circle cx=\"296\" cy=\"312\" r=\"24\"/><circle cx=\"376\" cy=\"312\" r=\"24\"/><circle cx=\"136\" cy=\"312\" r=\"24\"/><circle cx=\"216\" cy=\"312\" r=\"24\"/><circle cx=\"136\" cy=\"392\" r=\"24\"/><circle cx=\"216\" cy=\"392\" r=\"24\"/><circle cx=\"296\" cy=\"392\" r=\"24\"/><path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\" d=\"M128 48v32M384 48v32\"/><path fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32\" d=\"M464 160H48\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m350.54 148.68-26.62-42.06C318.31 100.08 310.62 96 302 96h-92c-8.62 0-16.31 4.08-21.92 10.62l-26.62 42.06C155.85 155.23 148.62 160 140 160H80a32 32 0 0 0-32 32v192a32 32 0 0 0 32 32h352a32 32 0 0 0 32-32V192a32 32 0 0 0-32-32h-59c-8.65 0-16.85-4.77-22.46-11.32\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"256\" cy=\"272\" r=\"80\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M124 158v-22h-24v22\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192Z\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M352 176 217.6 336 160 272\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m112 184 144 144 144-144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m112 328 144-144 144 144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192Z\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M320 320 192 192M192 320l128-128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M368 368 144 144M368 144 144 368\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M93.72 183.25C49.49 198.05 16 233.1 16 288c0 66 54 112 120 112h184.37M467.82 377.74C485.24 363.3 496 341.61 496 312c0-59.82-53-85.76-96-88-8.89-89.54-71-144-144-144-26.16 0-48.79 6.93-67.6 18.14\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M448 448 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M436.67 184.11a27.17 27.17 0 0 1-38.3 0l-22.48-22.49a27.15 27.15 0 0 1 0-38.29l50.89-50.89a.85.85 0 0 0-.26-1.38C393.68 57 351.09 64.15 324.05 91c-25.88 25.69-27.35 64.27-17.87 98a27 27 0 0 1-7.67 27.14l-173 160.76a40.76 40.76 0 1 0 57.57 57.54l162.15-173.3a27 27 0 0 1 26.77-7.7c33.46 8.94 71.49 7.26 97.07-17.94 27.49-27.08 33.42-74.94 20.1-102.33a.85.85 0 0 0-1.36-.22Z\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M224 284c-17.48-17-25.49-24.91-31-30.29a18.24 18.24 0 0 1-3.33-21.35 20.8 20.8 0 0 1 3.5-4.62l15.68-15.29a18.7 18.7 0 0 1 5.63-3.87 18.11 18.11 0 0 1 20 3.62c5.45 5.29 15.43 15 33.41 32.52M317.07 291.3c40.95 38.1 90.62 83.27 110 99.41a13.46 13.46 0 0 1 .94 19.92L394.63 444a14 14 0 0 1-20.29-.76c-16.53-19.18-61.09-67.11-99.27-107\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"m17.34 193.5 29.41-28.74a4.7 4.7 0 0 1 3.41-1.35 4.85 4.85 0 0 1 3.41 1.35h0a9.86 9.86 0 0 0 8.19 2.77c3.83-.42 7.92-1.6 10.57-4.12 6-5.8-.94-17.23 4.34-24.54a207 207 0 0 1 19.78-22.6c6-5.88 29.84-28.32 69.9-44.45A107.3 107.3 0 0 1 206.67 64c22.59 0 40 10 46.26 15.67a89.5 89.5 0 0 1 10.28 11.64 79 79 0 0 0-9.21-2.77 68.8 68.8 0 0 0-20-1.26c-13.33 1.09-29.41 7.26-38 14-13.9 11-19.87 25.72-20.81 44.71-.68 14.12 2.72 22.1 36.1 55.49a6.6 6.6 0 0 1-.34 9.16l-18.22 18a6.88 6.88 0 0 1-9.54.09c-21.94-21.94-36.65-33.09-45-38.16s-15.07-6.5-18.3-6.85a30.85 30.85 0 0 0-18.27 3.87 11.4 11.4 0 0 0-2.64 2 14.14 14.14 0 0 0 .42 20.08l1.71 1.6a4.63 4.63 0 0 1 0 6.64L71.73 246.6a4.7 4.7 0 0 1-3.41 1.4 4.86 4.86 0 0 1-3.41-1.35l-47.57-46.43a4.88 4.88 0 0 1 0-6.72\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><circle cx=\"256\" cy=\"256\" r=\"208\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M256 464c-114.88 0-208-93.12-208-208S141.12 48 256 48Z\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><circle cx=\"256\" cy=\"256\" r=\"192\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M320 176v-40a40 40 0 0 0-40-40H88a40 40 0 0 0-40 40v240a40 40 0 0 0 40 40h192a40 40 0 0 0 40-40v-40M384 176l80 80-80 80M191 256h273\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M176 48h160M118 304h276M208 48v93.48a64.1 64.1 0 0 1-9.88 34.18L73.21 373.49C48.4 412.78 76.63 464 123.08 464h265.84c46.45 0 74.68-51.22 49.87-90.51L313.87 175.66a64.1 64.1 0 0 1-9.87-34.18V48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><rect width=\"176\" height=\"176\" x=\"48\" y=\"48\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"176\" height=\"176\" x=\"288\" y=\"48\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"176\" height=\"176\" x=\"48\" y=\"288\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"176\" height=\"176\" x=\"288\" y=\"288\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M145.61 464h220.78c19.8 0 35.55-16.29 33.42-35.06C386.06 308 304 310 304 256s83.11-51 95.8-172.94c2-18.78-13.61-35.06-33.41-35.06H145.61c-19.8 0-35.37 16.28-33.41 35.06C124.89 205 208 201 208 256s-82.06 52-95.8 172.94c-2.14 18.77 13.61 35.06 33.41 35.06\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M343.3 432H169.13c-15.6 0-20-18-9.06-29.16C186.55 376 240 356.78 240 326V224c0-19.85-38-35-61.51-67.2-3.88-5.31-3.49-12.8 6.37-12.8h142.73c8.41 0 10.23 7.43 6.4 12.75C310.82 189 272 204.05 272 224v102c0 30.53 55.71 47 80.4 76.87 9.95 12.04 6.47 29.13-9.1 29.13\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><rect width=\"416\" height=\"352\" x=\"48\" y=\"80\" rx=\"48\" ry=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"336\" cy=\"176\" r=\"32\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"m304 335.79-90.66-90.49a32 32 0 0 0-43.87-1.3L48 352M224 432l123.34-123.34a32 32 0 0 1 43.11-2L464 368\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M432 112V96a48.14 48.14 0 0 0-48-48H64a48.14 48.14 0 0 0-48 48v256a48.14 48.14 0 0 0 48 48h16\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"400\" height=\"336\" x=\"96\" y=\"128\" rx=\"45.99\" ry=\"45.99\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><ellipse cx=\"372.92\" cy=\"219.64\" rx=\"30.77\" ry=\"30.55\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M342.15 372.17 255 285.78a30.93 30.93 0 0 0-42.18-1.21L96 387.64M265.23 464l118.59-117.73a31 31 0 0 1 41.46-1.87L496 402.91\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M160 144h288M160 256h288M160 368h288\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"80\" cy=\"144\" r=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"80\" cy=\"256\" r=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"80\" cy=\"368\" r=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M336 208v-95a80 80 0 0 0-160 0v95\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"320\" height=\"272\" x=\"96\" y=\"208\" rx=\"48\" ry=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><circle cx=\"129\" cy=\"96\" r=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"129\" cy=\"416\" r=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M129 144v224\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"385\" cy=\"288\" r=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M129 144c0 96 112 144 208 144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M384 224v184a40 40 0 0 1-40 40H104a40 40 0 0 1-40-40V168a40 40 0 0 1 40-40h167.48M336 64h112v112M224 288 440 72\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M336 448h56a56 56 0 0 0 56-56v-56M448 176v-56a56 56 0 0 0-56-56h-56M176 448h-56a56 56 0 0 1-56-56v-56M64 176v-56a56 56 0 0 1 56-56h56\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M464 208 352 96 240 208M352 113.13V416M48 304l112 112 112-112M160 398V96\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m112 112 20 320c.95 18.49 14.4 32 32 32h184c17.67 0 30.87-13.51 32-32l20-320\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M80 112h352\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M192 112V72h0a23.93 23.93 0 0 1 24-24h80a23.93 23.93 0 0 1 24 24h0v40M256 176v224M184 176l8 224M328 176l-8 224\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M85.57 446.25h340.86a32 32 0 0 0 28.17-47.17L284.18 82.58c-12.09-22.44-44.27-22.44-56.36 0L57.4 399.08a32 32 0 0 0 28.17 47.17\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"m250.26 195.39 5.74 122 5.73-121.95a5.74 5.74 0 0 0-5.79-6h0a5.74 5.74 0 0 0-5.68 5.95\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path fill=\"currentColor\" d=\"M256 397.25a20 20 0 1 1 20-20 20 20 0 0 1-20 20\"/></svg>","import type { ContextInput, KnownIssueCard, PatternFinding } from '@innspel/core';\nimport React, { useMemo, useState } from 'react';\nimport { Pressable, ScrollView, Text, TextInput, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, H, Hint } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\n/**\n * 2d + 2e — feltet og kontekstlinja. Ett felt, ingenting annet.\n *\n * DD-44: send er inaktiv under `minTextLength` (standard 10), og det er det\n * ENESTE kravet. Ingen kategori, ingen alvorlighet, ingen reproduksjonsfelt.\n * 2h i wireframen er ikke en skjerm — den er fraværet av felter her.\n *\n * DD-45: placeholderen stiller to spørsmål i feilsporet.\n *\n * DD-46: mønstervarselet vises FØR sending og fjerner aldri noe selv.\n * «Fjern» og «Behold» er innsenderens valg; teksten endres bare ved «Fjern».\n *\n * DD-05: konteksten er synlig og kan fjernes linje for linje. Den er en lukket\n * hviteliste (K5) — det som ikke står der, finnes ikke å fjerne.\n */\nexport function Felt({\n spor,\n verdi,\n onEndre,\n minTextLength,\n textMaxLength,\n kontekst,\n fjernedeFelter,\n onFjernKontekst,\n lenketTil,\n onFjernLenke,\n funn,\n onSend,\n sender,\n harFeil,\n offline,\n onSkjermbilde,\n onVelgBilde,\n bildeNotat,\n harVedlegg,\n onFjernVedlegg,\n}: {\n spor: 'feil' | 'onske';\n verdi: string;\n onEndre: (v: string) => void;\n minTextLength: number;\n textMaxLength: number;\n kontekst: ContextInput & { sdkVersion: string };\n fjernedeFelter: string[];\n onFjernKontekst: (felt: string) => void;\n lenketTil?: KnownIssueCard;\n onFjernLenke?: () => void;\n funn: PatternFinding[];\n onSend: () => void;\n sender?: boolean;\n /** Forrige sending feilet: knappen heter «Prøv igjen» til neste forsøk (C7). */\n harFeil?: boolean;\n /** Verten har meldt at nettet er nede (`init({ connectivity })`): knappen heter «Lagre — sendes når du er på nett». */\n offline?: boolean;\n /**\n * «Legg ved skjermbilde» (2f, K4). Utelatt = steget finnes ikke (DD-26): leietakeren\n * har skjermbilde av, eller verten ga ingen adapter. Aldri en deaktivert knapp.\n */\n onSkjermbilde?: () => void;\n /** «Velg bilde» fra galleriet. Utelatt = valget finnes ikke; samme regel som over. */\n onVelgBilde?: () => void;\n /** Vertens setning ved bildesteget (`imageStepNote`). Leietakeren eier den, ikke plattformen. */\n bildeNotat?: string;\n /** Et maskert skjermbilde ligger klart og sendes etter teksten (DD-42). */\n harVedlegg?: boolean;\n onFjernVedlegg?: () => void;\n}) {\n const tema = useTema();\n const [apen, setApen] = useState(false);\n const [beholdt, setBeholdt] = useState<string[]>([]);\n\n const brukt = verdi.length;\n const forKort = brukt < minTextLength;\n const full = brukt >= textMaxLength;\n // Telleren dukker opp ved 80 % — ikke før. En teller fra første tegn gjør\n // lengden til oppgaven i stedet for innholdet.\n const visTeller = brukt >= textMaxLength * 0.8;\n\n const uavklart = funn.find((f) => !beholdt.includes(f.match));\n\n const linjer = useMemo(() => {\n const etiketter: Record<string, string> = {\n screen: 'Skjerm',\n appVersion: 'Appversjon',\n platform: 'Plattform',\n os: 'OS',\n build: 'Bygg',\n locale: 'Språk',\n };\n return Object.entries(etiketter)\n .map(([felt, etikett]) => {\n const verdi = (kontekst as unknown as Record<string, string | undefined>)[felt];\n return verdi && !fjernedeFelter.includes(felt) ? { felt, etikett, verdi } : null;\n })\n .filter((x): x is { felt: string; etikett: string; verdi: string } => x !== null);\n }, [kontekst, fjernedeFelter]);\n\n // Kroppen scroller og Send står fast under den. Arket har bare maxHeight, så\n // uten scrollflate tegnet et høyt skjema (utvidet kontekst) forbi bunnpaddingen\n // og Send havnet under navigasjonslinja. Roten er flexGrow/flexShrink, ikke\n // flex: 1 — den gir flexBasis 0, og arket ville aldri vokst forbi minHeight.\n return (\n <View testID=\"skjema\" style={{ flexGrow: 1, flexShrink: 1, gap: tema.space.md }}>\n <ScrollView\n testID=\"skjema-kropp\"\n style={{ flexGrow: 0, flexShrink: 1 }}\n contentContainerStyle={{ gap: tema.space.md }}\n keyboardShouldPersistTaps=\"handled\"\n >\n {lenketTil ? (\n <View\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n minHeight: tema.touch,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderInteractive,\n borderRadius: tema.radius.pill,\n paddingLeft: tema.space.md,\n paddingRight: tema.space.xs,\n }}\n >\n <Text style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }}>\n {tekst.lenketTil(lenketTil.title)}\n </Text>\n <Pressable\n testID=\"fjern-lenke\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.fjernLenke}\n onPress={onFjernLenke}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n ) : null}\n\n {uavklart ? (\n <View\n style={{\n gap: tema.space.sm,\n backgroundColor: tema.color.warningBg,\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n }}\n >\n <Text\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n style={{\n color: tema.color.warning,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n fontWeight: tema.weight.medium,\n }}\n >\n {tekst.monsterSpm[uavklart.kind]}\n </Text>\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n <Btn\n grow\n variant=\"secondary\"\n testID=\"monster-fjern\"\n label={tekst.monsterFjern}\n onPress={() => onEndre(verdi.slice(0, uavklart.start) + verdi.slice(uavklart.end))}\n />\n <Btn\n grow\n variant=\"ghost\"\n testID=\"monster-behold\"\n label={tekst.monsterBehold}\n onPress={() => setBeholdt((b) => [...b, uavklart.match])}\n />\n </View>\n <Hint>{tekst.monsterForklaring}</Hint>\n </View>\n ) : null}\n\n <H>{spor === 'onske' ? tekst.feltLabelOnske : tekst.feltLabelFeil}</H>\n\n <TextInput\n testID=\"innspill-tekst\"\n accessibilityLabel={spor === 'onske' ? tekst.feltLabelOnske : tekst.feltLabelFeil}\n value={verdi}\n onChangeText={onEndre}\n maxLength={textMaxLength}\n multiline\n numberOfLines={4}\n placeholder={spor === 'onske' ? tekst.placeholderOnske : tekst.placeholderFeil}\n placeholderTextColor={tema.color.textMuted}\n style={{\n backgroundColor: tema.color.surfaceRaised,\n borderWidth: tema.hairline,\n borderColor: full ? tema.color.warning : tema.color.borderStrong,\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n minHeight: tema.touch * 2,\n textAlignVertical: 'top',\n }}\n />\n\n {visTeller ? (\n <Text\n testID=\"teller\"\n accessibilityLiveRegion={full ? 'assertive' : 'polite'}\n style={{\n alignSelf: 'flex-end',\n color: full ? tema.color.warning : tema.color.textMuted,\n fontSize: tema.font.small,\n }}\n >\n {brukt} / {textMaxLength}\n {full ? tekst.tellerFull : ''}\n </Text>\n ) : null}\n\n {/* 2f — opt-in per innsending. Bildet tas først ved trykk (K4). */}\n {harVedlegg ? (\n <View\n testID=\"vedlegg-chip\"\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n minHeight: tema.touch,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderInteractive,\n borderRadius: tema.radius.pill,\n paddingLeft: tema.space.md,\n paddingRight: tema.space.xs,\n }}\n >\n <Ikon navn=\"image-outline\" storrelse=\"minste\" farge={tema.color.textPrimary} />\n <Text style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }}>{tekst.bildeLagtVed}</Text>\n <Pressable\n testID=\"fjern-vedlegg\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.fjernSkjermbilde}\n onPress={onFjernVedlegg}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n ) : onSkjermbilde || onVelgBilde ? (\n <View style={{ gap: tema.space.sm }}>\n {onSkjermbilde ? (\n <Btn\n variant=\"secondary\"\n testID=\"legg-ved-skjermbilde\"\n ikon=\"camera-outline\"\n label={tekst.leggVedSkjermbilde}\n hint={tekst.leggVedHint}\n onPress={onSkjermbilde}\n />\n ) : null}\n {onVelgBilde ? (\n <Btn\n variant=\"secondary\"\n testID=\"velg-bilde\"\n ikon=\"images-outline\"\n label={tekst.velgBilde}\n hint={tekst.velgBildeHint}\n onPress={onVelgBilde}\n />\n ) : null}\n {bildeNotat ? (\n <View testID=\"bilde-notat\">\n <Hint>{bildeNotat}</Hint>\n </View>\n ) : null}\n </View>\n ) : null}\n\n {/* 2e — synlig, ikke skjult (DD-05) */}\n <View style={{ borderTopWidth: tema.hairline, borderTopColor: tema.color.border, paddingTop: tema.space.sm }}>\n <Pressable\n testID=\"kontekst-bryter\"\n accessibilityRole=\"button\"\n accessibilityState={{ expanded: apen }}\n accessibilityLabel={`${tekst.kontekstLinje}${apen ? '' : tekst.kontekstVis}`}\n onPress={() => setApen((a) => !a)}\n style={{ minHeight: tema.touch, justifyContent: 'center' }}\n >\n {/* Ikonet er et eget element, ikke et tegn i teksten: en SVG kan ikke\n ligge inne i en `Text` i React Native. */}\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon\n navn={apen ? 'chevron-up-outline' : 'chevron-down-outline'}\n storrelse=\"minste\"\n farge={tema.color.textSecondary}\n />\n <Text style={{ flex: 1, color: tema.color.textSecondary, fontSize: tema.font.small }}>\n {tekst.kontekstLinje}\n {apen ? '' : tekst.kontekstVis}\n </Text>\n </View>\n </Pressable>\n\n {apen ? (\n <View>\n {linjer.map((l) => (\n <View\n key={l.felt}\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n minHeight: tema.touch,\n borderBottomWidth: tema.hairline,\n borderBottomColor: tema.color.border,\n }}\n >\n <Text style={{ color: tema.color.textMuted, fontSize: tema.font.small, minWidth: tema.touch * 2 }}>\n {l.etikett}\n </Text>\n <Text style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }}>{l.verdi}</Text>\n <Pressable\n testID={`fjern-${l.felt}`}\n accessibilityRole=\"button\"\n accessibilityLabel={`${tekst.kontekstFjern} ${l.etikett.toLowerCase()} fra innsendingen`}\n onPress={() => onFjernKontekst(l.felt)}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"close-outline\" storrelse=\"minste\" farge={tema.color.textSecondary} />\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>\n {tekst.kontekstFjern}\n </Text>\n </View>\n </Pressable>\n </View>\n ))}\n <View style={{ paddingTop: tema.space.sm }}>\n <Hint>{tekst.kontekstAldri}</Hint>\n </View>\n </View>\n ) : null}\n </View>\n\n </ScrollView>\n\n <View testID=\"skjema-fot\" style={{ flexGrow: 1, flexShrink: 0, justifyContent: 'flex-end' }}>\n <Btn\n testID=\"send\"\n label={sender ? tekst.sender : harFeil ? tekst.provIgjen : offline ? tekst.offlineLagre : tekst.send}\n disabled={forKort || sender}\n busy={sender}\n hint={forKort ? tekst.forKort(minTextLength) : harVedlegg ? tekst.sendHintMedBilde : undefined}\n onPress={onSend}\n // F10: tastaturet er oppe når Send trykkes. En ScrollView i vertens tre over\n // provideren kan ta første trykk — det skal likevel sende.\n trykkForbiForelder\n />\n </View>\n </View>\n );\n}\n","import React, { useMemo, useRef } from 'react';\nimport { Pressable, Text, View, type GestureResponderEvent, type StyleProp, type ViewStyle } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\n\n/**\n * Primitivene widgeten er bygget av. Alt visuelt kommer fra tema-tokens —\n * ingen hex, ingen px, ingen fontstørrelse skrives her (CLAUDE.md, «Styling»).\n *\n * Minste trykkflate er `skala.touch` (48). Den er ikke en anbefaling: den er\n * grønt-kriterium for widgeten, og en knapp under målet er en feil.\n *\n * `ikon` er alltid et IONICONS-NAVN, aldri en emoji (brand-ui-guidelines,\n * UX-gjennomgangen C3). Navnene står i `src/Ikon.tsx`, og et ukjent navn kaster.\n */\n\ntype Variant = 'primary' | 'secondary' | 'ghost' | 'danger';\n\nexport function Btn({\n label,\n onPress,\n variant = 'primary',\n ikon,\n hint,\n disabled,\n accessibilityLabel,\n grow,\n testID,\n busy,\n trykkForbiForelder,\n}: {\n label: string;\n onPress?: () => void;\n variant?: Variant;\n ikon?: string;\n hint?: string;\n disabled?: boolean;\n accessibilityLabel?: string;\n grow?: boolean;\n testID?: string;\n /** Handlingen pågår: `busy` i tilstanden, så skjermleseren hører at knappen jobber, ikke bare at den er låst. */\n busy?: boolean;\n /**\n * Trykket teller selv om en FORELDER i vertens tre tok responderen (F10). Se\n * {@link useTrykkForbiForelder}. Brukes på Send, der et tapt trykk er et innspill som\n * ikke ble sendt.\n */\n trykkForbiForelder?: boolean;\n}) {\n const tema = useTema();\n const c = tema.color;\n const forbi = useTrykkForbiForelder(onPress, !!disabled, tema.touch / 2);\n\n const bakgrunn =\n variant === 'primary' ? c.actionPrimary : variant === 'secondary' ? c.surfaceRaised : 'transparent';\n const tekstfarge =\n variant === 'primary' ? c.onActionPrimary : variant === 'danger' ? c.danger : c.actionSecondaryText;\n const kant = variant === 'ghost' ? 'transparent' : variant === 'primary' ? c.actionPrimary : c.actionSecondaryBorder;\n\n return (\n <View style={grow ? { flex: 1 } : undefined}>\n <Pressable\n testID={testID}\n accessibilityRole=\"button\"\n // Hintet er synlig tekst OG del av etiketten: en skjermleserbruker skal\n // få vite hvorfor knappen er inaktiv uten å lete etter teksten under.\n accessibilityLabel={accessibilityLabel ?? (hint ? `${label}. ${hint}` : label)}\n accessibilityState={{ disabled: !!disabled, busy: !!busy }}\n disabled={disabled}\n onPress={onPress}\n {...(trykkForbiForelder ? forbi : {})}\n style={{\n minHeight: tema.touch,\n borderRadius: tema.radius.md,\n borderWidth: tema.hairline,\n borderColor: kant,\n backgroundColor: disabled ? c.surface : bakgrunn,\n paddingHorizontal: tema.space.md,\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'row',\n gap: tema.space.sm,\n opacity: disabled ? 0.6 : 1,\n }}\n >\n {ikon ? <Ikon navn={ikon} farge={disabled ? c.textDisabled : tekstfarge} /> : null}\n <Text\n style={{\n color: disabled ? c.textDisabled : tekstfarge,\n fontSize: tema.font.body,\n fontWeight: tema.weight.semibold,\n }}\n >\n {label}\n </Text>\n </Pressable>\n {hint ? <Hint>{hint}</Hint> : null}\n </View>\n );\n}\n\n/**\n * Et trykk som ender på knappen, teller — også når knappen aldri fikk responderen (F10).\n *\n * React Natives responder-system spør forfedrene i REACT-treet, ytterst først, i\n * capture-fasen (`traverseTwoPhase` over `fiber.return` i renderen). Modalen er et eget\n * vindu på Android, men i React-treet står den der verten plasserte provideren. Står den i\n * en `ScrollView` med `keyboardShouldPersistTaps` på `'never'` (standard), tar den\n * ScrollView-en trykket mens tastaturet er oppe og slipper det med `blurTextInput`\n * (`_handleStartShouldSetResponderCapture` i ScrollView.js). Pressable-en får aldri\n * `onResponderGrant`, og `onPress` kalles aldri: første trykk lukker bare tastaturet.\n *\n * Widgeten kan ikke vinne capture-fasen over en forelder. Men `onTouchStart`/`onTouchEnd`\n * sendes av `ReactNativeBridgeEventPlugin` til målet uavhengig av hvem som er responder.\n * Et trykk som endte innenfor `slingring` av der det startet, uten at `onPressIn` kom,\n * kalles derfor som `onPress` — etter at responder-hendelsene for samme trykk er\n * ferdige, så et vanlig trykk aldri teller to ganger. En låst knapp trykkes aldri.\n */\nfunction useTrykkForbiForelder(onPress: (() => void) | undefined, laast: boolean, slingring: number) {\n const start = useRef<{ x: number; y: number } | null>(null);\n const fikkResponder = useRef(false);\n // Siste verdier leses i timeouten, ikke verdiene fra renderen trykket startet i.\n const siste = useRef({ onPress, laast });\n siste.current = { onPress, laast };\n\n return useMemo(\n () => ({\n onPressIn: () => {\n fikkResponder.current = true;\n },\n onTouchStart: (e: GestureResponderEvent) => {\n start.current = { x: e.nativeEvent.pageX, y: e.nativeEvent.pageY };\n },\n onTouchEnd: (e: GestureResponderEvent) => {\n const s = start.current;\n start.current = null;\n const innenfor =\n s !== null &&\n Math.abs(e.nativeEvent.pageX - s.x) <= slingring &&\n Math.abs(e.nativeEvent.pageY - s.y) <= slingring;\n setTimeout(() => {\n const tatt = fikkResponder.current;\n fikkResponder.current = false;\n if (!tatt && innenfor && !siste.current.laast) siste.current.onPress?.();\n }, 0);\n },\n onTouchCancel: () => {\n start.current = null;\n fikkResponder.current = false;\n },\n }),\n [slingring],\n );\n}\n\nexport function H({ children, sub }: { children: string; sub?: string }) {\n const tema = useTema();\n return (\n <View style={{ gap: tema.space.xs }}>\n <Text\n accessibilityRole=\"header\"\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.h2,\n lineHeight: tema.lineHeight.h2,\n fontWeight: tema.weight.semibold,\n }}\n >\n {children}\n </Text>\n {sub ? (\n <Text\n style={{\n color: tema.color.textSecondary,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {sub}\n </Text>\n ) : null}\n </View>\n );\n}\n\nexport function Hint({ children }: { children: React.ReactNode }) {\n const tema = useTema();\n return (\n <Text\n style={{\n color: tema.color.textMuted,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {children}\n </Text>\n );\n}\n\nexport function Card({\n children,\n dashed,\n style,\n}: {\n children: React.ReactNode;\n dashed?: boolean;\n style?: StyleProp<ViewStyle>;\n}) {\n const tema = useTema();\n return (\n <View\n style={[\n {\n backgroundColor: tema.color.surface,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.border,\n borderStyle: dashed ? 'dashed' : 'solid',\n padding: tema.space.md,\n gap: tema.space.sm,\n },\n style,\n ]}\n >\n {children}\n </View>\n );\n}\n\n/**\n * Status som ikon + etikett. Fargen er et TILLEGG, aldri bæreren: to av\n * palettens statusfarger er målt til under 1,5 i innbyrdes kontrast, så\n * etiketten er det som faktisk skiller dem (DD-08).\n */\nexport function StatusPill({ ikon, etikett, fg, bg }: { ikon: string; etikett: string; fg: string; bg: string }) {\n const tema = useTema();\n // `fg`/`bg` er TOKENNAVN fra theme.ts, ikke farger: samme mappe virker i begge\n // paletter og i vertens eget tema (DD-21).\n const farge = (navn: string, reserve: string) => (tema.color as Record<string, string>)[navn] ?? reserve;\n return (\n <View\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.xs,\n alignSelf: 'flex-start',\n paddingHorizontal: tema.space.sm,\n paddingVertical: tema.space.xs,\n borderRadius: tema.radius.pill,\n backgroundColor: farge(bg, tema.color.neutralBg),\n }}\n >\n <Ikon navn={ikon} storrelse=\"minste\" farge={farge(fg, tema.color.textSecondary)} />\n <Text style={{ color: farge(fg, tema.color.textSecondary), fontSize: tema.font.small, fontWeight: tema.weight.medium }}>\n {etikett}\n </Text>\n </View>\n );\n}\n\n/**\n * Varsel. Rollen ligger på `Text`, ikke på containeren: `accessible` på en\n * container sluker barna som egne fokusstopp (`tdd-contract-validation`).\n */\nexport function Banner({\n ikon,\n tone,\n children,\n live,\n testID,\n}: {\n ikon: string;\n tone: 'info' | 'warning' | 'danger' | 'success';\n children: string;\n live?: boolean;\n testID?: string;\n}) {\n const tema = useTema();\n return (\n <View\n testID={testID}\n style={{\n flexDirection: 'row',\n gap: tema.space.sm,\n backgroundColor: tema.color[`${tone}Bg` as keyof typeof tema.color],\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n }}\n >\n <Ikon navn={ikon} farge={tema.color[tone]} />\n <Text\n accessibilityRole=\"alert\"\n accessibilityLiveRegion={live ? 'polite' : 'none'}\n style={{\n flex: 1,\n color: tema.color[tone],\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {children}\n </Text>\n </View>\n );\n}\n","/**\n * Hver streng innsenderen ser, ett sted.\n *\n * Ordlyden er ikke fri: den er tegnet i `design/wireframes/innsending-widget.jsx`\n * og bundet av beslutninger.\n *\n * SETNINGEN innsenderen får for en status (DD-08) står IKKE her lenger — den bor\n * i `submissionStatus` i `theme/theme.ts` og leses fra den genererte mappa\n * (`status.ts`), så appen, portalen og panelet ikke kan love tre ulike ting.\n *\n * Språket er innsenderens, ikke repoets (DD-50, presisert 2026-09-14): aldri\n * «spor», «reproduksjon», «privat view» eller et kontraktfeltnavn.\n *\n * Norsk bokmål. Ingen leietakernavn: strengen som nevner avsenderen tar navnet\n * som parameter, siden pakken skal kunne brukes av hvem som helst.\n */\n\n/**\n * Saksnummeret uten kontraktens id-prefiks. `sub_2041` er databasens nøkkel;\n * innsenderen skal lese «sak 2041» (DD-50). Et id uten prefiks står som det er.\n */\n/**\n * «Sak f8dc» — de fire siste tegnene av id-en, som panelet viser (`#f8dc`, DD-63): innsender\n * og saksbehandler skal peke på samme nummer. Ekte id-er er UUIDv7 (36 tegn); før sto hele\n * strengen i lista. Et kort prefiks-format («sub_2041») beholder resten etter understreken.\n */\nexport function saksnr(id: string): string {\n const i = id.indexOf('_');\n const rest = i >= 0 ? id.slice(i + 1) : id;\n return rest.length > 8 ? rest.slice(-4) : rest;\n}\n\nconst stor = (s: string): string => (s ? s.charAt(0).toUpperCase() + s.slice(1) : s);\n\nexport const tekst = {\n // 2b — første valg\n valgTittel: 'Hva gjelder det?',\n sporFeil: 'Noe virker ikke',\n sporFeilUnder: 'Noe er galt eller virker rart',\n sporOnske: 'Jeg ønsker meg noe',\n sporOnskeUnder: 'Noe du savner eller vil ha annerledes',\n\n // 2c — kjente feil (DD-29, DD-30)\n kjenteFeilTittelFeil: 'Er det dette du ser?',\n kjenteFeilUnderFeil: 'Kjenner du igjen en av disse?',\n kjenteFeilTittelOnske: 'Har noen ønsket dette?',\n kjenteFeilUnderOnske: 'Ett trykk legger deg til på ønsket — ingen ny sak.',\n svarJa: 'Ja, jeg også',\n svarLigner: 'Ligner, men ikke helt',\n svarNei: 'Nei, det er noe annet',\n omvei: 'Omvei:',\n rettesI: (versjon: string) => `Rettes i ${versjon}`,\n rettetI: (versjon: string) => `Rettet i ${versjon}`,\n\n // 2d + 2e — feltet og kontekstlinja\n /**\n * «Ditt innspill», ikke «Din feil» (DD-54). «Din» festet saken til personen, og\n * «feil» karakteriserte den før noen hadde lest den — innsenderen leste det som\n * skyld. Ønskesporet beholder «Ditt ønske»: et ønske er ingen feil, og der finnes\n * ikke problemet. De to står aldri ved siden av hverandre; sporet velges før dette.\n */\n feltLabelFeil: 'Ditt innspill',\n feltLabelOnske: 'Ditt ønske',\n /** DD-45: to spørsmål i feilsporet. Kilde: Sentry «What's the bug? What did you expect?» */\n placeholderFeil: 'Hva skjedde? Hva forventet du?',\n placeholderOnske: 'Hva ønsker du deg?',\n send: 'Send',\n sender: 'Sender …',\n /** DD-44: minimum tegn er det ENESTE kravet. */\n forKort: (min: number) => `Minst ${min} tegn. Ingenting annet er obligatorisk.`,\n tellerFull: ' — kort og konkret holder',\n kontekstLinje: 'Legges ved: skjerm, appversjon, plattform, OS',\n kontekstVis: ' — Vis',\n kontekstFjern: 'Fjern',\n kontekstAldri:\n 'Aldri: navn, e-post, telefon, posisjon eller det som står på skjermen.',\n lenketTil: (tittel: string) => `Lenket til: «${tittel}»`,\n fjernLenke: 'Fjern lenken til den kjente feilen',\n\n // 2f — skjermbilde (K4, DD-39, DD-40, DD-42)\n leggVedSkjermbilde: 'Legg ved skjermbilde',\n leggVedHint: 'Bildet tas først når du trykker — du ser det før det sendes.',\n velgBilde: 'Velg bilde',\n velgBildeHint: 'Fra bildene dine. Du ser det og kan maskere det før det sendes.',\n skjermbildeUnderGalleri: 'Bildet er fra galleriet. Appen maskerer ingenting i det for deg — mal over det som ikke skal med.',\n bildeFeilet: 'kunne ikke hente bildet. Du kan sende uten.',\n skjermbildeTittel: 'Se over bildet',\n skjermbildeUnder: 'Bildet ble tatt da du trykket. Det du maskerer, ser vi aldri.',\n maskering: 'Maskering',\n maskerFelt: 'Masker felt',\n tegnOver: 'Tegn over',\n maskerAllTekst: 'Masker all tekst',\n maskertAvAppen: 'Maskert av appen',\n maskertAvAppenHint: 'Dette feltet er alltid dekket og kan ikke avdekkes.',\n dittStrok: 'Trykk på et dekket felt for å angre.',\n angreSiste: 'Angre siste',\n angreSisteA11y: 'Angre det siste feltet du dekket',\n allTekstHint: 'Hele bildet er gjort uskarpt så tekst ikke kan leses. Layouten er synlig.',\n fjernBildet: 'Fjern bildet',\n leggVed: 'Legg ved',\n bildeLagtVed: 'Bilde lagt ved',\n fjernSkjermbilde: 'Fjern bildet',\n sendHintMedBilde: 'Teksten sendes først; bildet lastes opp for seg.',\n skjermbildeFeilet: 'kunne ikke ta skjermbilde. Du kan sende uten.',\n skjermbildeA11y: (auto: number, egne: number, uskarpt: boolean) =>\n `Forhåndsvisning av skjermbildet. ${auto ? `${auto} felt maskert av appen og kan ikke avmaskeres. ` : ''}${egne ? `${egne} felt maskert av deg. ` : ''}${uskarpt ? 'All tekst er gjort uskarp. ' : ''}Trykk for å maskere et felt, dra for å tegne over.`,\n\n // DD-46 — mønstervarsel. Aldri stille redaksjon.\n monsterSpm: {\n email: 'Dette ser ut som en e-postadresse. Vil du fjerne den?',\n phone: 'Dette ser ut som et telefonnummer. Vil du fjerne det?',\n card: 'Dette ser ut som et kortnummer. Vil du fjerne det?',\n ip: 'Dette ser ut som en IP-adresse. Vil du fjerne den?',\n token: 'Dette ser ut som en tilgangsnøkkel. Vil du fjerne den?',\n },\n monsterFjern: 'Fjern',\n monsterBehold: 'Behold',\n monsterForklaring: 'Teksten endres bare hvis du trykker Fjern. Vi fjerner aldri noe stille.',\n\n // 2g — kvittering\n kvitteringSendt: 'Sendt',\n kvitteringRegistrert: 'Registrert',\n kvitteringFeil: 'Du får beskjed når den er rettet, eller hvis vi trenger mer.',\n kvitteringJaOgsa: 'Du får beskjed når den er rettet.',\n saksnummer: (nr: string) => `Sak ${saksnr(nr)}`,\n tilbakeTilAppen: 'Tilbake til appen',\n /** DD-42: saken er sendt, bildet kom ikke med — aldri en blokkert innsending. */\n kvitteringVedleggFeilet: 'Sendt — skjermbildet kunne ikke legges ved',\n tekstenErLagret: 'Teksten din er lagret.',\n vedleggFeiletBanner: 'Bildet ble ikke lastet opp. Saken er sendt uten det — vil du, kan du sende et nytt innspill med bilde.',\n saksnummerUtenVedlegg: (nr: string) => `Sak ${saksnr(nr)} · uten vedlegg`,\n\n // 2i — tilstander\n koKvitteringTittel: 'Lagret — sendes når du er på nett',\n offlineBanner:\n 'Ingen nett. Lagres og sendes automatisk — du ser det under «Mine innspill» til det er sendt.',\n offlineLagre: 'Lagre — sendes når du er på nett',\n /** DD-41: et skjermbilde køes aldri. */\n offlineUtenBilde: 'Skjermbilde kan ikke legges ved uten nett. Teksten sendes; bildet ble ikke lagret.',\n sendefeilBanner: (arsak: string) => `Kunne ikke sende: ${arsak} Teksten din er beholdt.`,\n provIgjen: 'Prøv igjen',\n\n // 2j — mine innspill\n mineTittel: 'Mine innspill',\n /** Knappen på første steg med innspill fra før (DD-62): tallet er det som gjør den til en inngang. */\n mineMedAntall: (n: number) => `Mine innspill · ${n}`,\n mineEtikett: (n: number) => `Mine innspill, ${n} innspill`,\n mineUnder: 'Status og hva du kan vente deg.',\n mineTom: 'Du har ikke sendt noe ennå.',\n mineIkkeSendt: 'Ikke sendt ennå',\n mineSak: (nr: string) => `Sak ${saksnr(nr)}`,\n /** «Feil · sak 2041» — sporet først, aldri rå id og aldri kontraktens type (DD-50). */\n sakHode: (spor: string, nr: string) => `${stor(spor)} · sak ${saksnr(nr)}`,\n // Leietakeren fjernet vedlegget. Bare AT — aldri hvorfor, av hvem eller når.\n bildeFjernet: 'Bildet er fjernet.',\n svarFra: (leietaker: string) => `Svar fra ${leietaker}`,\n svarFraGenerisk: 'Svar',\n sendNytt: 'Send nytt innspill',\n /** Tom tilstand: det finnes ikke noe «nytt» å sende når ingenting er sendt. */\n sendForste: 'Send innspill',\n\n // 3a — invitasjonsbanneret (DD-12)\n invitasjonRegion: 'Invitasjon til betaprogram',\n invitasjonHva: (navn: string) => `Vil du teste «${navn}»?`,\n invitasjonKontakter: (maks: number) =>\n `Vi tar kontakt maks ${maks} ganger. Du kan gå ut når som helst.`,\n lesMer: 'Les mer og bli med',\n avvisInvitasjon: 'Avvis invitasjonen',\n\n // 3b — aksepten (DD-13, DD-32, DD-37)\n akseptHva: 'Hva testes',\n /** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */\n akseptTall: (oppgaver: number, minutter: number, periode: string, kontakter: number) =>\n `${oppgaver} oppgaver · ca. ${minutter} min hver · ${periode} · maks ${kontakter} kontakter`,\n akseptOppgaver: 'Hva vi ber om',\n akseptOppgaveTid: (minutter: number) => `ca. ${minutter} min`,\n akseptKjenteFeil: (antall: number) => `Kjente feil (${antall})`,\n akseptKjenteFeilUnder: 'Disse trenger du ikke melde — vi vet om dem.',\n akseptInnsamling: 'Hva som samles inn',\n akseptInnsamlingTekst:\n 'Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.',\n akseptVilkar: 'Les vilkårene (åpnes i nettleser)',\n akseptVilkarHint: 'Bare en lenke. Ingen avkryssing, ingen signatur — «Bli med» binder deg ikke til noe.',\n akseptIngenVilkar:\n 'Ingen vilkår, ingen avtale — plattformen kjenner ikke navnet ditt og kan ikke inngå én.',\n akseptUtgang: 'Du kan gå ut når som helst — herfra.',\n bliMed: 'Bli med',\n bliMedHint: 'Samtykket gjelder bare dette programmet.',\n /** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */\n bliMedUtenToken: 'Åpne lenken vi sendte deg for å bli med.',\n akseptFeil: (arsak: string) => `Kunne ikke bli med: ${arsak}`,\n\n // 3c (M3.1-delen) — deltakelsen og «Gå ut» (DD-36)\n deltakelseRegion: 'Ditt betaprogram',\n deltakelsePeriode: (periode: string, brukt: number, maks: number) =>\n `${periode} · Vi tar kontakt maks ${maks} ganger — ${brukt} brukt`,\n deltakelseOppgaverKommer: 'Oppgavene kan gjøres når det passer deg.',\n gaaUt: 'Gå ut av programmet',\n gaaUtTittel: 'Gå ut av programmet?',\n gaaUtTekst: (navn: string) =>\n `Du tas ut av testgruppen med en gang. «${navn}» slås av for deg, og vi tar ikke kontakt igjen. Det du allerede har svart, beholdes.`,\n bliVaerende: 'Bli værende',\n gaaUtBekreft: 'Gå ut',\n\n // 3c (M3.2) — oppgavene og «Hvordan gikk det?»: tre lukkede valg, aldri en skala\n oppgaverTittel: 'Oppgavene',\n oppgaveIkkeBegynt: 'Ikke begynt',\n oppgaveGjort: 'Gjort',\n oppgaveGjortLabel: (tittel: string) => `Gjort: ${tittel}`,\n oppgaveGjortMed: (utfall: string) => `Prøvd · ${utfall}`,\n hvordanGikkDet: 'Hvordan gikk det?',\n utfallFungerte: 'Fungerte',\n utfallDelvis: 'Fungerte delvis',\n utfallIkke: 'Fungerte ikke',\n setningLabel: 'Vil du si én setning om det? (valgfritt)',\n setningPlaceholder: 'Kopien kom, men rullesjefen manglet på torsdag.',\n lagre: 'Lagre',\n lagreHint: 'Ferdig — ingen flere spørsmål nå.',\n /** Etter «Ikke»: feilsporet er vertens — plattformen navigerer aldri selv. */\n meldFeil: 'Meld det som feil',\n meldFeilHint: 'Gikk det ikke? Et innspill hjelper oss å finne ut hvorfor.',\n svarFeil: (arsak: string) => `Kunne ikke lagre svaret: ${arsak}`,\n\n // 3d (M3.2) — oppfølgingskortene (DD-34): arten avgjør knappene\n oppfolgingRegion: 'Oppfølging fra betaprogrammet',\n oppfolgingKontakt: (nr: number, maks: number) => `Kontakt ${nr} av ${maks} · tar under ett minutt`,\n oppfolgingPaaminnelseHint: (nr: number, maks: number) => `Kontakt ${nr} av ${maks} · planlagt påminnelse`,\n oppfolgingUtgangHint: (nr: number, maks: number) => `Kontakt ${nr} av ${maks} · den siste vi sender`,\n senere: 'Senere',\n svarNaa: 'Svar nå',\n aapneOppgavene: 'Åpne oppgavene',\n\n // Felles\n tilbake: 'Tilbake',\n lukk: 'Lukk',\n venterPaaNett: 'Venter på nett — sendes automatisk',\n feil: 'feil',\n onske: 'ønske',\n} as const;\n\n/**\n * Løftene som IKKE hører til en innsendingsstatus. Statusenes løfter står i\n * `submissionStatus` i `theme/theme.ts` og leses gjennom `status.ts` — det var\n * tre kopier av dem før 2026-09-14 (UX-gjennomgangen C5).\n */\nexport const lofte = {\n venterNett: 'Sendes automatisk når du er på nett — kvitteringen kommer da.',\n} as const;\n","import React from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { H } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\n/**\n * 2b — første valg. To flater, hele nedre halvdel, ikon og tekst.\n *\n * DD-02: ALDRI et tredje valg, og aldri spørsmål om kategori eller\n * alvorlighet. Valget her styrer alt etterpå: feilsporet får kjente feil FØR\n * feltet og kan bære koblingsnøkler, ønskesporet får dem etter og kan ikke.\n */\nexport function Valg({ onVelg }: { onVelg: (spor: 'feil' | 'onske') => void }) {\n const tema = useTema();\n\n const flate = (spor: 'feil' | 'onske', ikon: string, label: string, under: string) => (\n <Pressable\n testID={`spor-${spor}`}\n accessibilityRole=\"button\"\n accessibilityLabel={`${label}. ${under}`}\n onPress={() => onVelg(spor)}\n style={{\n flex: 1,\n minHeight: tema.touch * 3,\n backgroundColor: tema.color.surface,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n borderRadius: tema.radius.lg,\n alignItems: 'center',\n justifyContent: 'center',\n gap: tema.space.sm,\n padding: tema.space.md,\n }}\n >\n {/* Ikonet er det som skiller de to flatene på avstand — derfor `stor`, fylt, i merkefargen\n på en rund tonet flate (DD-63). Valget er et produktelement, ikke en status; brand er\n riktig her og målt mot brandBg i temaet. */}\n <View\n testID={`spor-${spor}-ikonflate`}\n style={{\n width: 2 * tema.icon.inline + 2 * tema.space.md,\n height: 2 * tema.icon.inline + 2 * tema.space.md,\n borderRadius: tema.radius.pill,\n backgroundColor: tema.color.brandBg,\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Ikon navn={ikon} storrelse=\"stor\" farge={tema.color.brand} />\n </View>\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.h3,\n fontWeight: tema.weight.semibold,\n textAlign: 'center',\n }}\n >\n {label}\n </Text>\n <Text style={{ color: tema.color.textMuted, fontSize: tema.font.small, textAlign: 'center' }}>\n {under}\n </Text>\n </Pressable>\n );\n\n return (\n <View style={{ flex: 1, gap: tema.space.lg }}>\n <H>{tekst.valgTittel}</H>\n <View style={{ flex: 1, justifyContent: 'flex-end' }}>\n <View style={{ flexDirection: 'row', gap: tema.space.md }}>\n {flate('feil', 'bug', tekst.sporFeil, tekst.sporFeilUnder)}\n {flate('onske', 'bulb', tekst.sporOnske, tekst.sporOnskeUnder)}\n </View>\n </View>\n </View>\n );\n}\n","import type { KnownIssueCard } from '@innspel/core';\nimport React from 'react';\nimport { ActivityIndicator, ScrollView, Text, View } from 'react-native';\nimport { knownIssueStatus } from '../generated/tokens.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Card, H, StatusPill } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\n/** DD-03: maks tre kort. Grensen er klientens — registeret kan ha flere. */\nconst MAKS_KORT = 3;\n\n/**\n * 2c — kjente feil. Differensiatoren: vises FØR feltet i feilsporet, ETTER i\n * ønskesporet.\n *\n * DD-29 gir kortet TRE svar, ikke to: «Ja, jeg også» (Reach +1, ingen ny sak) ·\n * «Ligner, men ikke helt» (eget innspill med lenke, uten tvunget match) · «Nei,\n * det er noe annet» (vanlig innsending). Det midterste er hele poenget — uten\n * det tvinger man et valg mellom å bli talt feil og å ikke bli talt.\n *\n * Tilgjengelighet: kortet er IKKE én knapp. Tre svar må være tre fokusstopp,\n * og `accessible` på kortcontaineren ville slukt dem. I stedet bærer hver\n * knapp kortets tittel i etiketten, så en skjermleserbruker som lander på «Ja,\n * jeg også» vet hvilken feil svaret gjelder. Se `docs/sdk`-notatet i PR-en:\n * `tdd-contract-validation` sa «ett kort = én knapp», skrevet før DD-29.\n *\n * Treffene er et tilbud, aldri en sperre: feiler oppslaget eller er lista tom,\n * hoppes skjermen over uten melding. Det håndteres i Widget, ikke her.\n */\nexport function KjenteFeil({\n kort,\n spor,\n laster,\n sender,\n onJaOgsa,\n onLigner,\n onNei,\n}: {\n kort: KnownIssueCard[];\n spor: 'feil' | 'onske';\n laster?: boolean;\n /** «Ja, jeg også» er underveis: alle svar låses, så ett trykk gir én bekreftelse (C7). */\n sender?: boolean;\n onJaOgsa: (k: KnownIssueCard) => void;\n onLigner: (k: KnownIssueCard) => void;\n onNei: () => void;\n}) {\n const tema = useTema();\n\n if (laster) {\n return (\n <View style={{ flex: 1, gap: tema.space.md }}>\n <H sub={spor === 'onske' ? tekst.kjenteFeilUnderOnske : tekst.kjenteFeilUnderFeil}>\n {spor === 'onske' ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil}\n </H>\n <ActivityIndicator accessibilityLabel=\"Sjekker kjente feil\" color={tema.color.textSecondary} />\n </View>\n );\n }\n\n // Samme form som skjemaet: kortene scroller, «Nei, det er noe annet» står fast.\n // Lista har ingen tak, og med tre kort havnet svaret under navigasjonslinja.\n return (\n <View testID=\"kjente-feil\" style={{ flexGrow: 1, flexShrink: 1, gap: tema.space.md }}>\n <H sub={spor === 'onske' ? tekst.kjenteFeilUnderOnske : tekst.kjenteFeilUnderFeil}>\n {spor === 'onske' ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil}\n </H>\n\n <ScrollView\n testID=\"kjente-feil-liste\"\n style={{ flexGrow: 0, flexShrink: 1 }}\n contentContainerStyle={{ gap: tema.space.md }}\n keyboardShouldPersistTaps=\"handled\"\n >\n {kort.slice(0, MAKS_KORT).map((k) => {\n // Kortet har ALLTID en status (C5/C6): «Aktiv» eller «Rettet», fra\n // knownIssueStatus i temaet. Versjonen er et TILLEGG når den finnes\n // (DD-30: «Rettes i X» når aktiv, «Rettet i X» når fikset) — før\n // 2026-09-14 var pillen borte på et kort uten versjon.\n const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv;\n const versjon = k.fixedIn\n ? k.status === 'fikset'\n ? tekst.rettetI(k.fixedIn)\n : tekst.rettesI(k.fixedIn)\n : undefined;\n const kontekst = versjon ? `${k.title}. ${o.etikett}. ${versjon}` : `${k.title}. ${o.etikett}`;\n\n return (\n <Card key={k.id}>\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n fontWeight: tema.weight.medium,\n }}\n >\n {k.title}\n </Text>\n\n {k.workaround ? (\n <Text\n style={{\n color: tema.color.textSecondary,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {tekst.omvei} {k.workaround}\n </Text>\n ) : null}\n\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.sm, flexWrap: 'wrap' }}>\n <StatusPill ikon={o.ikon} etikett={o.etikett} fg={o.fg} bg={o.bg} />\n {versjon ? (\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>{versjon}</Text>\n ) : null}\n </View>\n\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n <Btn\n grow\n testID={`ja-ogsa-${k.id}`}\n label={tekst.svarJa}\n accessibilityLabel={`${tekst.svarJa}. ${kontekst}`}\n disabled={sender}\n busy={sender}\n onPress={() => onJaOgsa(k)}\n />\n <Btn\n grow\n variant=\"secondary\"\n testID={`ligner-${k.id}`}\n label={tekst.svarLigner}\n accessibilityLabel={`${tekst.svarLigner}. ${kontekst}`}\n disabled={sender}\n onPress={() => onLigner(k)}\n />\n </View>\n </Card>\n );\n })}\n </ScrollView>\n\n <View testID=\"kjente-feil-fot\" style={{ flexShrink: 0 }}>\n <Btn variant=\"secondary\" testID=\"nei-noe-annet\" label={tekst.svarNei} disabled={sender} onPress={onNei} />\n </View>\n </View>\n );\n}\n","import React from 'react';\nimport { Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, H, Hint } from './primitiver.js';\nimport { statusVisning } from './status.js';\nimport { tekst } from './tekster.js';\n\nexport type KvitteringArt = 'feil' | 'onske' | 'jaOgsa' | 'kø';\n\n/**\n * 2g — kvitteringen. Den LOVER noe, per spor (DD-07), og saksnummeret er der\n * så innsenderen kan vise til det hos support.\n *\n * Ingen «vurder appen». Ingen oppfordring til å dele. Innsenderen har nettopp\n * gjort oss en tjeneste — å be om en til er å ta betalt for den.\n *\n * DD-42: feilet vedlegget, er saken likevel sendt. Overskriften sier det rett\n * ut, løftet står, og saksnummeret merkes «uten vedlegg». Køet offline med et\n * skjermbilde: teksten sendes senere, bildet ble aldri køet (DD-41).\n *\n * DD-47: `accessibilityLiveRegion` og rolle `alert` på TEKSTEN, slik at en\n * skjermleser leser kvitteringen når den kommer, uten at brukeren må lete.\n */\nexport function Kvittering({\n art,\n saksnummer,\n vedlegg,\n frist,\n onLukk,\n}: {\n art: KvitteringArt;\n saksnummer?: string;\n /** `feilet`: teksten er lagret, bildet kom ikke med. `forkastet`: køet offline uten bilde. */\n vedlegg?: 'feilet' | 'forkastet';\n /** Svarfristen fra svaret (`deadlineAt`). Tidsløftet er DATOEN, aldri «innen 90 dager» (DD-07, DD-28). */\n frist?: string;\n onLukk: () => void;\n}) {\n const tema = useTema();\n\n const innhold = {\n feil: { h: tekst.kvitteringSendt, p: tekst.kvitteringFeil },\n // Løftet er NØYAKTIG det «Mine innspill» og panelet viser for «Vurderes»:\n // det leses fra temaet, så kvitteringen og statusen ikke kan si to ting.\n onske: { h: tekst.kvitteringSendt, p: statusVisning('vurderes', 'onske', frist).lofte },\n jaOgsa: { h: tekst.kvitteringRegistrert, p: tekst.kvitteringJaOgsa },\n // Køet offline: kvitteringen kan IKKE love svar på noe som ikke er sendt\n // (DD-41 presiserer DD-07). Den lover bare at det sendes.\n kø: { h: tekst.koKvitteringTittel, p: tekst.offlineBanner },\n }[art];\n\n const overskrift = vedlegg === 'feilet' ? tekst.kvitteringVedleggFeilet : innhold.h;\n const brodtekst = vedlegg === 'feilet' ? `${tekst.tekstenErLagret} ${innhold.p}` : innhold.p;\n\n return (\n <View style={{ flex: 1, justifyContent: 'center', gap: tema.space.lg }}>\n <View style={{ alignItems: 'center', gap: tema.space.md }}>\n {/* Det ene stedet ikonet står ALENE og bærer stemningen — derfor `stor`. */}\n <Ikon\n navn={art === 'kø' ? 'swap-vertical-outline' : 'checkmark-circle-outline'}\n storrelse=\"stor\"\n farge={art === 'kø' ? tema.color.neutral : tema.color.success}\n />\n\n <H>{overskrift}</H>\n\n {vedlegg === 'feilet' ? (\n <Banner ikon=\"warning-outline\" tone=\"warning\" children={tekst.vedleggFeiletBanner} />\n ) : null}\n {vedlegg === 'forkastet' ? <Banner ikon=\"image-outline\" tone=\"info\" children={tekst.offlineUtenBilde} /> : null}\n\n <Text\n testID=\"kvittering-tekst\"\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n textAlign: 'center',\n }}\n >\n {brodtekst}\n </Text>\n\n {saksnummer ? (\n <Hint>{vedlegg === 'feilet' ? tekst.saksnummerUtenVedlegg(saksnummer) : tekst.saksnummer(saksnummer)}</Hint>\n ) : null}\n </View>\n\n <Btn testID=\"tilbake-til-appen\" label={tekst.tilbakeTilAppen} onPress={onLukk} />\n </View>\n );\n}\n","import type { SubmissionStatus, SubmissionStatusView, SubmissionType } from '@innspel/core';\nimport { lofteUtenFrist, submissionStatus } from '../generated/tokens.js';\nimport { lofte, tekst } from './tekster.js';\n\n/**\n * Statusen slik innsenderen ser den. ALT kommer fra `submissionStatus` i\n * `theme/theme.ts`, gjennom den genererte mappa: navnet per spor (DD-22),\n * setningen innsenderen får (DD-08), IKONNAVNET og tokennavnene for farge.\n *\n * Navn, farge og løfte sto hardkodet her OG i `@innspel/web` OG i panelet før\n * 2026-09-14 og spriket (UX-gjennomgangen C5). Ikonet sto igjen som emoji til\n * 2026-09-15, fordi Ionicons i React Native krever en peer-avhengighet — se\n * «`react-native-svg` som peer i @innspel/react-native» i `tech-decisions.md`.\n *\n * DD-08 / «Styling» i CLAUDE.md: **farge bærer aldri mening alene.** `brand` og\n * `info`, og `brand` og `danger`, er målt til under 1,5 i innbyrdes kontrast av\n * tema-generatoren, så etiketten er det som faktisk bærer meningen.\n */\nexport interface StatusVisning {\n /** Ionicons-navn fra temaet — aldri en emoji (brand-ui-guidelines). */\n ikon: string;\n etikett: string;\n /** Tokennavn i den aktive paletten, ikke en farge. */\n fg: string;\n bg: string;\n lofte: string;\n}\n\n/** Norsk dato uten klokkeslett — fristen er en dato, ikke et tidspunkt (DD-28). */\nexport function formaterFrist(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return new Intl.DateTimeFormat('nb-NO', { day: 'numeric', month: 'long' }).format(d);\n}\n\n/**\n * Oversetter en innsending til det innsenderen skal se.\n *\n * @param status Maskinens status fra kontrakten.\n * @param type Sporet — avgjør «Rettet» mot «Levert» (DD-22).\n * @param deadlineAt Svarfristen, satt kun i `vurderes`.\n */\nexport function statusVisning(status: SubmissionStatus, type: SubmissionType, deadlineAt?: string): StatusVisning {\n const o = submissionStatus[status];\n const spor: 'feil' | 'onske' = type === 'onske' ? 'onske' : 'feil';\n return {\n ikon: o.ikon,\n etikett: o.etikett[spor],\n fg: o.fg,\n bg: o.bg,\n lofte: settInnFrist(o.lofte[spor], deadlineAt),\n };\n}\n\n/**\n * `{frist}` byttes med datoen (DD-28). Uten frist finnes ikke tidsløftet, og da\n * står den fristløse setningen i stedet — aldri en tom plassholder på skjermen.\n */\nfunction settInnFrist(mal: string, deadlineAt: string | undefined): string {\n if (!mal.includes('{frist}')) return mal;\n return deadlineAt ? mal.replace('{frist}', formaterFrist(deadlineAt)) : lofteUtenFrist;\n}\n\n/** Raden som venter på nett (DD-41). Den har ingen saksnummer og intet løfte om svar. */\nexport const venterVisning: StatusVisning = {\n ikon: 'cloud-offline-outline',\n etikett: 'Venter på nett',\n fg: 'textSecondary',\n bg: 'neutralBg',\n lofte: lofte.venterNett,\n};\n\n/**\n * Etikett for en hel rad, brukt som skjermleserens sammendrag. Ikonet er\n * `aria-hidden` i UI-et, så etiketten må bære alt.\n */\nexport function radEtikett(rad: SubmissionStatusView): string {\n const v = statusVisning(rad.status, rad.type, rad.deadlineAt);\n const spor = rad.type === 'onske' ? tekst.onske : tekst.feil;\n return `${tekst.sakHode(spor, rad.id)}: ${rad.text}. Status ${v.etikett.toLowerCase()}. ${v.lofte}`;\n}\n","import type { MySubmission } from '@innspel/core';\nimport React from 'react';\nimport { ActivityIndicator, ScrollView, Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Card, H, Hint, StatusPill } from './primitiver.js';\nimport { statusVisning, venterVisning } from './status.js';\nimport { tekst } from './tekster.js';\n\n/**\n * 2j — «Mine innspill» (DD-27).\n *\n * To ting skjer her som ikke skjer noe annet sted:\n *\n * - **Offline-køen er synlig** (DD-41). Raden som venter på nett står øverst,\n * uten saksnummer, med «Venter på nett — sendes automatisk». Shake er den\n * eneste leverandøren som viser dette til brukeren; alle andre skjuler køen,\n * og en usynlig kø er ikke til å skille fra tapt tekst.\n * - **Svaret står under saken**, ordrett som i panelet. Innsenderen skal ikke\n * måtte lete etter svaret i en e-post som aldri kom — plattformen sender\n * ingen e-post (K14).\n */\nexport function MineInnspill({\n rader,\n laster,\n tenantName,\n onNytt,\n}: {\n rader: MySubmission[];\n laster?: boolean;\n tenantName?: string;\n onNytt: () => void;\n}) {\n const tema = useTema();\n\n return (\n <View style={{ flex: 1, gap: tema.space.md }}>\n <H sub={tekst.mineUnder}>{tekst.mineTittel}</H>\n\n {laster ? (\n <ActivityIndicator accessibilityLabel=\"Henter innspillene dine\" color={tema.color.textSecondary} />\n ) : rader.length === 0 ? (\n <Hint>{tekst.mineTom}</Hint>\n ) : (\n <ScrollView style={{ flex: 1 }} contentContainerStyle={{ gap: tema.space.sm }}>\n {rader.map((rad) => {\n const venter = rad.pending === true;\n const v = venter ? venterVisning : statusVisning(rad.status, rad.type, rad.deadlineAt);\n const nokkel = venter ? rad.clientRef : rad.id;\n const svar = venter ? undefined : rad.reply;\n\n return (\n <Card key={nokkel} dashed={venter}>\n <Hint>\n {venter\n ? `${tekst.mineIkkeSendt} · ${rad.type === 'onske' ? tekst.onske : tekst.feil}`\n : tekst.sakHode(rad.type === 'onske' ? tekst.onske : tekst.feil, rad.id)}\n </Hint>\n\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n }}\n >\n {rad.text}\n </Text>\n\n <View style={{ gap: tema.space.xs }}>\n <StatusPill ikon={v.ikon} etikett={v.etikett} fg={v.fg} bg={v.bg} />\n <Hint>{v.lofte}</Hint>\n </View>\n\n {!venter && rad.attachmentRemoved ? (\n <View testID={`bilde-fjernet-${rad.id}`} style={{ flexDirection: 'row', gap: tema.space.xs, alignItems: 'center' }}>\n <Ikon navn=\"trash-outline\" storrelse=\"minste\" farge={tema.color.textMuted} />\n <Hint>{tekst.bildeFjernet}</Hint>\n </View>\n ) : null}\n\n {svar ? (\n <View\n style={{\n borderLeftWidth: tema.hairline * 2,\n borderLeftColor: tema.color.brand,\n paddingLeft: tema.space.sm,\n gap: tema.space.xs,\n }}\n >\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>\n {tenantName ? tekst.svarFra(tenantName) : tekst.svarFraGenerisk}\n </Text>\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {svar.text}\n </Text>\n </View>\n ) : null}\n </Card>\n );\n })}\n </ScrollView>\n )}\n\n <Btn testID=\"send-nytt\" label={rader.length === 0 ? tekst.sendForste : tekst.sendNytt} onPress={onNytt} />\n </View>\n );\n}\n","import { skaler, strokTilRekter, treffer, trykkTilRekt, type MaskPoint, type MaskRect } from '@innspel/core';\nimport React, { useCallback, useMemo, useRef, useState, type RefObject } from 'react';\nimport { Image, Pressable, StyleSheet, Text, View, type GestureResponderEvent, type LayoutChangeEvent } from 'react-native';\nimport { screenRules } from '../generated/tokens.js';\nimport { Ikon } from '../Ikon.js';\nimport type { ScreenshotCapture, ViewRef } from '../skjermbilde.js';\nimport { useTema } from '../tema.js';\nimport { Btn, H, Hint } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\nexport type MaskVerktoy = 'felt' | 'pensel';\n\n/**\n * 2f — skjermbildet, tatt ved trykk og forhåndsvist (K4). Tre likestilte\n * maskeringsveier (DD-40): «Masker felt» (ett trykk legger en boks), «Tegn over»\n * (fingerstrøk) og «Masker all tekst» (heldekkende uskarphet — se DD-40,\n * presisert for RN). Private views (DD-39) ligger der FØR innsenderen ser bildet,\n * merket «Maskert av appen», og kan ikke fjernes. Egne masker fjernes med ett\n * trykk på dem.\n *\n * Maskeringen skjer i bitmapen ved komposisjon: bildet vises med maskeringslagene\n * over, og «Legg ved og fortsett» fanger denne viewen på nytt. Det er komposittet\n * som lastes opp — rå-URI-en forlater aldri widgeten.\n *\n * Fargene her er `screenRules`: det ene stedet temaet ikke gjelder, fordi\n * maskene må være synlige uansett hva skjermbildet selv inneholder.\n */\nexport function Skjermbilde({\n bilde,\n automaskerRot,\n rotStorrelse,\n previewRef,\n komponerer,\n kilde = 'skjerm',\n notat,\n onFjern,\n onLeggVed,\n}: {\n bilde: ScreenshotCapture;\n /** Private views i vertsappens punkter (relativt til rot-viewen). */\n automaskerRot: MaskRect[];\n rotStorrelse: { width: number; height: number };\n previewRef: RefObject<ViewRef | null>;\n komponerer: boolean;\n /** Fra galleriet: private views kan ikke gjelde, og forhåndsvisningen sier det. */\n kilde?: 'skjerm' | 'galleri';\n /** Vertens setning ved bildesteget. */\n notat?: string;\n onFjern: () => void;\n onLeggVed: () => void;\n}) {\n const tema = useTema();\n const [verktoy, setVerktoy] = useState<MaskVerktoy>('pensel');\n const [allTekst, setAllTekst] = useState(false);\n const [egne, setEgne] = useState<MaskRect[]>([]);\n const [ramme, setRamme] = useState<{ width: number; height: number } | null>(null);\n const strok = useRef<MaskPoint[]>([]);\n\n // Bildet tilpasses rammen med bevart sideforhold; alt annet regnes i visningens punkter.\n const visning = useMemo(() => {\n if (!ramme) return null;\n const s = Math.min(ramme.width / bilde.width, ramme.height / bilde.height);\n return { width: Math.floor(bilde.width * s), height: Math.floor(bilde.height * s) };\n }, [ramme, bilde.width, bilde.height]);\n\n const automasker = useMemo(\n () => (visning ? automaskerRot.map((r) => skaler(r, rotStorrelse, visning)) : []),\n [automaskerRot, rotStorrelse, visning],\n );\n\n const onLayout = useCallback((e: LayoutChangeEvent) => {\n const { width, height } = e.nativeEvent.layout;\n setRamme({ width, height });\n }, []);\n\n const punkt = (e: GestureResponderEvent): MaskPoint => ({ x: e.nativeEvent.locationX, y: e.nativeEvent.locationY });\n\n const onGrant = (e: GestureResponderEvent) => {\n if (!visning) return;\n const p = punkt(e);\n // Ett trykk på en egen maske angrer den (wireframe 2f). Private views rører den aldri.\n const treff = egne.findIndex((r) => treffer(p, r));\n if (treff >= 0) {\n setEgne((x) => x.filter((_, i) => i !== treff));\n return;\n }\n if (verktoy === 'felt') {\n const r = trykkTilRekt(p, { width: tema.touch * 4, height: tema.touch }, visning);\n if (r) setEgne((x) => [...x, r]);\n return;\n }\n strok.current = [p];\n };\n\n const onMove = (e: GestureResponderEvent) => {\n if (verktoy !== 'pensel' || strok.current.length === 0) return;\n strok.current.push(punkt(e));\n };\n\n const onRelease = () => {\n if (verktoy !== 'pensel' || !visning || strok.current.length === 0) return;\n const rekter = strokTilRekter(strok.current, screenRules.brushWidth, visning);\n strok.current = [];\n if (rekter.length) setEgne((x) => [...x, ...rekter]);\n };\n\n const knapp = (id: MaskVerktoy | 'allTekst', ikon: string, label: string) => {\n const valgt = id === 'allTekst' ? allTekst : verktoy === id && !allTekst;\n return (\n <Pressable\n key={id}\n testID={`verktoy-${id}`}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n accessibilityState={{ selected: valgt }}\n onPress={() => (id === 'allTekst' ? setAllTekst((a) => !a) : setVerktoy(id))}\n style={{\n flex: 1,\n minHeight: tema.touch,\n alignItems: 'center',\n justifyContent: 'center',\n gap: tema.space.xs,\n padding: tema.space.xs,\n borderRadius: tema.radius.md,\n borderWidth: tema.hairline,\n borderColor: tema.color.actionSecondaryBorder,\n borderBottomWidth: valgt ? tema.hairline * 2 : tema.hairline,\n borderBottomColor: valgt ? tema.color.textPrimary : tema.color.actionSecondaryBorder,\n backgroundColor: valgt ? tema.color.surfaceRaised : 'transparent',\n }}\n >\n <Ikon navn={ikon} farge={tema.color.textPrimary} />\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.small,\n fontWeight: valgt ? tema.weight.semibold : tema.weight.regular,\n }}\n >\n {label}\n </Text>\n </Pressable>\n );\n };\n\n const a11y = tekst.skjermbildeA11y(automasker.length, egne.length, allTekst);\n\n // Høyden kommer ovenfra: arket har fast høyde i dette steget (Widget.tsx), rammen får det\n // som er igjen etter overskrift, verktøylinje og fot, og forhåndsvisningen ligger OVER rammen\n // i stedet for i flyten. Før vokste rammen med visningen, onLayout ga ny ramme, og et 9:20-\n // bilde endte begrenset av bredden alene — knappene havnet under navigasjonslinja. Ingen\n // scroll: berøring på forhåndsvisningen er maskering.\n return (\n <View testID=\"skjermbilde-steg\" style={{ flexGrow: 1, flexShrink: 1, gap: tema.space.md }}>\n <H sub={kilde === 'galleri' ? tekst.skjermbildeUnderGalleri : tekst.skjermbildeUnder}>{tekst.skjermbildeTittel}</H>\n {notat ? (\n <View testID=\"bilde-notat\">\n <Hint>{notat}</Hint>\n </View>\n ) : null}\n\n <View accessibilityRole=\"toolbar\" accessibilityLabel={tekst.maskering} style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {knapp('felt', 'scan-outline', tekst.maskerFelt)}\n {knapp('pensel', 'brush-outline', tekst.tegnOver)}\n {knapp('allTekst', 'grid-outline', tekst.maskerAllTekst)}\n </View>\n\n <View\n testID=\"skjermbilde-ramme\"\n onLayout={onLayout}\n style={{\n flexGrow: 1,\n flexShrink: 1,\n flexBasis: 0,\n minHeight: tema.touch * 5,\n backgroundColor: screenRules.previewBackdrop,\n borderRadius: tema.radius.md,\n overflow: 'hidden',\n }}\n >\n <View testID=\"skjermbilde-flate\" pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, { alignItems: 'center', justifyContent: 'center' }]}>\n {visning ? (\n <View\n ref={previewRef}\n collapsable={false}\n testID=\"forhandsvisning\"\n accessibilityRole=\"image\"\n accessibilityLabel={a11y}\n onStartShouldSetResponder={() => !komponerer}\n onMoveShouldSetResponder={() => !komponerer}\n onResponderGrant={onGrant}\n onResponderMove={onMove}\n onResponderRelease={onRelease}\n onResponderTerminate={onRelease}\n style={{ width: visning.width, height: visning.height, backgroundColor: screenRules.previewBackdrop }}\n >\n <Image\n testID=\"skjermbilde-bilde\"\n source={{ uri: bilde.uri }}\n blurRadius={allTekst ? screenRules.textBlurRadius : 0}\n style={{ width: visning.width, height: visning.height }}\n accessibilityIgnoresInvertColors\n />\n\n {automasker.map((r, i) => (\n <View\n key={`auto-${i}`}\n testID={`automask-${i}`}\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: r.x,\n top: r.y,\n width: r.width,\n height: r.height,\n backgroundColor: screenRules.autoMaskFill,\n borderWidth: tema.hairline * 2,\n borderColor: screenRules.autoMaskStroke,\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {!komponerer ? (\n // Etiketten står PÅ den maskerte flaten og måles mot NETTOPP den\n // (skjermKontrastpar i theme.ts). textSecondary var 2,2:1 (C11a).\n // Ikonet arver samme farge: det er unntaket i «Styling» — maskeringen\n // tegnes i faste signalfarger, ikke i palettens.\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"lock-closed-outline\" storrelse=\"minste\" farge={screenRules.autoMaskText} />\n <Text style={{ color: screenRules.autoMaskText, fontSize: tema.font.small }} numberOfLines={1}>\n {tekst.maskertAvAppen}\n </Text>\n </View>\n ) : null}\n </View>\n ))}\n\n {egne.map((r, i) => (\n <View\n key={`egen-${i}`}\n testID={`maske-${i}`}\n pointerEvents=\"none\"\n style={{ position: 'absolute', left: r.x, top: r.y, width: r.width, height: r.height, backgroundColor: screenRules.brushFill }}\n />\n ))}\n </View>\n ) : null}\n </View>\n </View>\n\n {automasker.length ? (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"lock-closed-outline\" storrelse=\"minste\" farge={tema.color.textMuted} />\n <Hint>{tekst.maskertAvAppenHint}</Hint>\n </View>\n ) : null}\n {egne.length ? <Hint>{tekst.dittStrok}</Hint> : null}\n {allTekst ? <Hint>{tekst.allTekstHint}</Hint> : null}\n\n <View testID=\"skjermbilde-fot\" style={{ flexShrink: 0, gap: tema.space.sm }}>\n {/* «Angre siste» som KNAPP: å treffe en maske med fingeren er en motorisk\n oppgave, og angrefunksjonen kan ikke være den eneste veien tilbake — samme\n grunn som DD-40 gir både pensel og knapp (C11d). */}\n <Btn\n variant=\"secondary\"\n testID=\"angre-siste\"\n label={tekst.angreSiste}\n accessibilityLabel={tekst.angreSisteA11y}\n disabled={komponerer || egne.length === 0}\n onPress={() => setEgne((x) => x.slice(0, -1))}\n />\n <Btn\n variant=\"danger\"\n testID=\"fjern-bildet\"\n ikon=\"trash-outline\"\n label={tekst.fjernBildet}\n onPress={onFjern}\n disabled={komponerer}\n />\n <Btn testID=\"legg-ved\" label={tekst.leggVed} onPress={onLeggVed} disabled={komponerer || !visning} />\n </View>\n </View>\n );\n}\n","import React, { useEffect, useRef } from 'react';\nimport { View, type StyleProp, type ViewStyle } from 'react-native';\nimport { useSkjermbilde, type ViewRef } from './skjermbilde.js';\n\n/**\n * Merk det som aldri skal være med på et skjermbilde (DD-39): navn i en liste,\n * et kontonummer, en samtale. Pakk det inn, og widgeten maskerer det FØR\n * innsenderen ser forhåndsvisningen — som «Maskert av appen», og penselen kan\n * ikke oppheve det. Din kode er sannheten, ikke brukerens presisjon.\n *\n * Uten skjermbilde-adapter gjør komponenten ingenting utover å rendre barna.\n *\n * @example\n * ```tsx\n * <InnspelPrivate><Text>{bruker.navn}</Text></InnspelPrivate>\n * ```\n */\nexport function InnspelPrivate({ children, style }: { children?: React.ReactNode; style?: StyleProp<ViewStyle> }) {\n const ref = useRef<ViewRef | null>(null);\n const kontekst = useSkjermbilde();\n const registrer = kontekst?.privat.register;\n\n useEffect(() => {\n if (!registrer) return;\n return registrer(ref);\n }, [registrer]);\n\n // collapsable={false}: Android slår ellers sammen en View uten stil med\n // forelderen, og da finnes det ingenting å måle.\n return (\n <View ref={ref} collapsable={false} style={style} testID=\"innspel-privat\">\n {children}\n </View>\n );\n}\n","import {\n InnspelApiError,\n type FollowUpView,\n type MyPrograms,\n type ParticipationView,\n type ProgramTask,\n type ProgramView,\n type TaskOutcome,\n} from '@innspel/core';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { Modal, Pressable, Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useInnspel } from '../InnspelProvider.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, Card, H, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\nimport { Aksept } from './Aksept.js';\nimport { HvordanGikkDet } from './HvordanGikkDet.js';\nimport { Oppfolging } from './Oppfolging.js';\nimport { Oppgaver } from './Oppgaver.js';\nimport { periode } from './periode.js';\n\ntype Dialog = { type: 'oppgave'; task: ProgramTask } | { type: 'oppfolging'; oppfolging: FollowUpView };\n\n/**\n * Betaprogrammet i vertsappen: 3a banneret, 3b aksepten og deltakelsen med\n * «Gå ut» (DD-36). Sett den der vertsappen vil ha invitasjonen — typisk øverst\n * på hjemskjermen. Uten invitasjon og uten deltakelse rendrer den INGENTING;\n * det er wireframens «tom → fanen skjules helt», ikke en tom tilstand.\n *\n * **Tokenet kommer fra verten** (DD-12). Plattformen sender aldri invitasjonen:\n * leietakeren får `program.invitation_created` med tokenet, løser pseudonymet til\n * sin egen bruker og sender lenken i sin egen kanal. Verten fanger tokenet fra\n * dyplenken og gir det hit. Uten det viser banneret fortsatt invitasjonen — men\n * «Bli med» er inaktiv, med lenken forklart, i stedet for å feile ved trykk.\n *\n * Deltakelsen (3c) viser oppgavene med «Gjort» → «Hvordan gikk det?» (tre lukkede\n * valg og en setning, aldri en skala) og oppfølgingskortene (3d, DD-34), der arten\n * avgjør knappene. «Ikke» tilbyr å melde feilen — til verten via `onMeldFeil`, fordi\n * feilsporet og navigasjonen er vertens.\n *\n * @example\n * ```tsx\n * <InnspelProgram invitationToken={tokenFraDyplenke} />\n * ```\n */\nexport function InnspelProgram({\n invitationToken,\n onEndring,\n onMeldFeil,\n}: {\n /** Engangs-tokenet fra leietakerens egen kanal, typisk fanget fra en dyplenke. */\n invitationToken?: string;\n /** Kalles når testeren blir med eller går ut — for vertens egen navigasjon. */\n onEndring?: (deltakelse: ParticipationView | null) => void;\n /** Kalles når testeren vil melde at en oppgave ikke gikk — verten åpner feilsporet med oppgaven som kontekst. Utelatt = tilbudet vises ikke. */\n onMeldFeil?: (task: ProgramTask) => void;\n}) {\n const { client } = useInnspel();\n const tema = useTema();\n\n const [mine, setMine] = useState<MyPrograms | undefined>();\n const [deltakelse, setDeltakelse] = useState<ParticipationView | undefined>();\n const [viserAksept, setViserAksept] = useState(false);\n const [viserGaaUt, setViserGaaUt] = useState(false);\n const [avvist, setAvvist] = useState(false);\n const [sender, setSender] = useState(false);\n const [feil, setFeil] = useState<string | undefined>();\n const [dialog, setDialog] = useState<Dialog | undefined>();\n const [svarFeil, setSvarFeil] = useState<string | undefined>();\n const [lagtBort, setLagtBort] = useState<ReadonlySet<string>>(new Set());\n const [meldFeilFor, setMeldFeilFor] = useState<ProgramTask | undefined>();\n\n const leggBort = useCallback((id: string) => setLagtBort((s) => new Set([...s, id])), []);\n\n // «Lagre» i «Hvordan gikk det?»: én dialog, to mål. Fullføringen legges på deltakelsen\n // så raden viser svaret straks; et svar på oppfølging tar kortet ut av lista.\n const lagreSvar = useCallback(\n async (outcome: TaskOutcome, text: string | undefined) => {\n if (!dialog || !deltakelse) return;\n setSender(true);\n setSvarFeil(undefined);\n try {\n if (dialog.type === 'oppgave') {\n const ny = await client.programs.completeTask(dialog.task.id, { outcome, ...(text ? { text } : {}) });\n setDeltakelse({ ...deltakelse, completions: [...deltakelse.completions, ny] });\n if (outcome === 'ikke' && onMeldFeil) setMeldFeilFor(dialog.task);\n } else {\n await client.programs.respond(dialog.oppfolging.id, { outcome, ...(text ? { text } : {}) });\n setMine((m) => (m ? { ...m, pendingFollowUps: m.pendingFollowUps.filter((f) => f.id !== dialog.oppfolging.id) } : m));\n }\n setDialog(undefined);\n } catch (e) {\n setSvarFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n },\n [client, deltakelse, dialog, onMeldFeil],\n );\n\n // Anonym modus har ingen programmer, og skal ikke spørre: kallet ville blitt\n // 401 uansett, og et kall som alltid feiler er ikke en tilstand — det er støy.\n useEffect(() => {\n if (client.isAnonymous) return;\n let levende = true;\n void client.programs\n .list()\n .then((svar) => {\n if (!levende) return;\n setMine(svar);\n // Aktiv deltakelse er det som vises; trukket kommer aldri tilbake fra listen.\n setDeltakelse(svar.participations.find((p) => p.status !== 'trukket'));\n })\n // Programmet er et tilbud, aldri en sperre: svarer ikke kallet, finnes\n // banneret ikke — vertsappen står uendret.\n .catch(() => undefined);\n return () => {\n levende = false;\n };\n }, [client]);\n\n const bliMed = useCallback(async () => {\n if (!invitationToken) return;\n setSender(true);\n setFeil(undefined);\n try {\n const ny = await client.programs.accept(invitationToken);\n setDeltakelse(ny);\n setViserAksept(false);\n onEndring?.(ny);\n } catch (e) {\n setFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n }, [client, invitationToken, onEndring]);\n\n const gaaUt = useCallback(async () => {\n if (!deltakelse) return;\n setSender(true);\n try {\n await client.programs.withdraw(deltakelse.id);\n setDeltakelse(undefined);\n setViserGaaUt(false);\n onEndring?.(null);\n } catch (e) {\n setFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n }, [client, deltakelse, onEndring]);\n\n // Deltakelsen vinner over invitasjonen: har man sagt ja, er banneret ferdig.\n const invitasjon = deltakelse ? undefined : mine?.invitations[0];\n const program: ProgramView | undefined = deltakelse?.program ?? invitasjon?.program;\n\n if (!program) return null;\n\n if (deltakelse) {\n // 3d: kortene for DETTE programmet, i den rekkefølgen kontaktene kom. Et kort testeren\n // har lagt bort i denne økten vises ikke igjen før neste oppstart.\n const kort = (mine?.pendingFollowUps ?? [])\n .filter((f) => f.programId === program.id && !lagtBort.has(f.id))\n .sort((a, b) => a.emittedAt.localeCompare(b.emittedAt));\n const forsteKontaktNr = Math.max(1, deltakelse.contactsSent - kort.length + 1);\n\n return (\n <View testID=\"program-deltakelse\" accessibilityLabel={tekst.deltakelseRegion} style={{ gap: tema.space.sm }}>\n {kort.map((f, i) => (\n <Oppfolging\n key={f.id}\n oppfolging={f}\n kontaktNr={forsteKontaktNr + i}\n maksKontakter={program.maxContacts}\n onSenere={() => leggBort(f.id)}\n onSvar={() => {\n setSvarFeil(undefined);\n setDialog({ type: 'oppfolging', oppfolging: f });\n }}\n onAapneOppgavene={() => leggBort(f.id)}\n onGaaUt={() => setViserGaaUt(true)}\n />\n ))}\n\n <Card>\n <H sub={tekst.deltakelsePeriode(periode(program.opensAt, program.closesAt), deltakelse.contactsSent, program.maxContacts)}>\n {program.name}\n </H>\n <Oppgaver\n tasks={program.tasks}\n completions={deltakelse.completions}\n onGjort={(task) => {\n setSvarFeil(undefined);\n setDialog({ type: 'oppgave', task });\n }}\n />\n {meldFeilFor && onMeldFeil ? (\n <View style={{ gap: tema.space.xs }}>\n <Hint>{tekst.meldFeilHint}</Hint>\n <Btn\n variant=\"secondary\"\n testID=\"meld-feil\"\n ikon=\"bug-outline\"\n label={tekst.meldFeil}\n onPress={() => {\n const task = meldFeilFor;\n setMeldFeilFor(undefined);\n onMeldFeil(task);\n }}\n />\n </View>\n ) : null}\n {/* DD-36: «Gå ut» er ALLTID synlig — aldri gjemt bak en meny eller under rullefeltet. */}\n <Btn variant=\"ghost\" testID=\"gaa-ut\" ikon=\"exit-outline\" label={tekst.gaaUt} onPress={() => setViserGaaUt(true)} />\n </Card>\n\n {dialog ? (\n <HvordanGikkDet\n under={dialog.type === 'oppgave' ? dialog.task.title : dialog.oppfolging.question}\n sender={sender}\n {...(svarFeil ? { feil: svarFeil } : {})}\n onLagre={(outcome, text) => void lagreSvar(outcome, text)}\n onLukk={() => setDialog(undefined)}\n />\n ) : null}\n\n {viserGaaUt ? (\n <Modal visible transparent animationType=\"fade\" onRequestClose={() => setViserGaaUt(false)} accessibilityViewIsModal>\n <View style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end', padding: tema.space.md }}>\n <View\n testID=\"gaa-ut-dialog\"\n accessibilityViewIsModal\n style={{\n backgroundColor: tema.color.surface,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n padding: tema.space.md,\n gap: tema.space.md,\n }}\n >\n <H>{tekst.gaaUtTittel}</H>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {tekst.gaaUtTekst(program.name)}\n </Text>\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {/* «Bli værende» står først: utgangen er et valg, ikke en felle med en angreknapp. */}\n <Btn grow variant=\"secondary\" testID=\"bli-vaerende\" label={tekst.bliVaerende} onPress={() => setViserGaaUt(false)} />\n <Btn\n grow\n variant=\"danger\"\n testID=\"bekreft-gaa-ut\"\n ikon=\"exit-outline\"\n label={tekst.gaaUtBekreft}\n disabled={sender}\n onPress={() => void gaaUt()}\n />\n </View>\n </View>\n </View>\n </Modal>\n ) : null}\n </View>\n );\n }\n\n if (!invitasjon || avvist) return null;\n\n return (\n <>\n <View\n testID=\"program-banner\"\n accessibilityLabel={tekst.invitasjonRegion}\n style={{\n backgroundColor: tema.color.brandBg,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.brand,\n padding: tema.space.md,\n gap: tema.space.sm,\n }}\n >\n <View style={{ flexDirection: 'row', gap: tema.space.sm, alignItems: 'flex-start' }}>\n <Ikon navn=\"flask-outline\" farge={tema.color.textPrimary} />\n <View style={{ flex: 1, gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {tekst.invitasjonHva(program.name)}\n </Text>\n <Hint>{tekst.invitasjonKontakter(program.maxContacts)}</Hint>\n </View>\n {/* Avvisbart: invitasjonen er et tilbud. Den kommer tilbake ved neste oppstart, aldri som mas i samme økt. */}\n <Pressable\n testID=\"avvis-invitasjon\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.avvisInvitasjon}\n onPress={() => setAvvist(true)}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n {feil && !viserAksept ? (\n <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.akseptFeil(feil)} />\n ) : null}\n <Btn variant=\"secondary\" testID=\"les-mer\" label={tekst.lesMer} onPress={() => setViserAksept(true)} />\n </View>\n\n {viserAksept ? (\n <Aksept\n program={program}\n harToken={!!invitationToken}\n sender={sender}\n {...(feil ? { feil } : {})}\n onBliMed={() => void bliMed()}\n onLukk={() => setViserAksept(false)}\n />\n ) : null}\n </>\n );\n}\n","import type { ProgramView } from '@innspel/core';\nimport React from 'react';\nimport { Linking, Modal, Pressable, ScrollView, Text, View } from 'react-native';\nimport { knownIssueStatus } from '../generated/tokens.js';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, Card, H, Hint, StatusPill } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\nimport { minutterPerOppgave, periode } from './periode.js';\n\n/**\n * 3b — aksepten. Én skjerm i fast rekkefølge (DD-13) med TALLENE øverst (DD-32):\n * N oppgaver × M minutter, dato til dato, maks K kontakter. Oppgavene står HER,\n * ikke i en e-post etterpå, og kjente feil er hele lista — testeren skal slippe\n * å melde det vi vet om.\n *\n * Vilkår er en LENKE, aldri en avkryssing (DD-37); ved forpliktelsesfri form\n * (tvunget når leietakeren har mindreårige brukere, K37) finnes ingen vilkår ut\n * over at man kan gå ut når som helst.\n *\n * «Bli med» krever tokenet leietakeren sendte i sin egen kanal (DD-12).\n * Plattformen sender aldri, og tokenet finnes ikke i `programs.list()` — uten\n * det verten har fanget fra dyplenken er knappen inaktiv, med lenken forklart.\n */\nexport function Aksept({\n program,\n harToken,\n sender,\n feil,\n onBliMed,\n onLukk,\n}: {\n program: ProgramView;\n harToken: boolean;\n sender: boolean;\n feil?: string;\n onBliMed: () => void;\n onLukk: () => void;\n}) {\n const tema = useTema();\n const tall = tekst.akseptTall(\n program.tasks.length,\n minutterPerOppgave(program.tasks),\n periode(program.opensAt, program.closesAt),\n program.maxContacts,\n );\n\n return (\n <Modal visible transparent animationType=\"slide\" onRequestClose={onLukk} accessibilityViewIsModal>\n <View style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end' }}>\n <View\n testID=\"program-aksept\"\n accessibilityViewIsModal\n style={{\n backgroundColor: tema.color.bg,\n borderTopLeftRadius: tema.radius.lg * 2,\n borderTopRightRadius: tema.radius.lg * 2,\n padding: tema.screenPadding,\n gap: tema.space.md,\n maxHeight: '92%',\n minHeight: '60%',\n }}\n >\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>\n <Btn variant=\"ghost\" testID=\"aksept-tilbake\" ikon=\"arrow-back-outline\" label={tekst.tilbake} onPress={onLukk} />\n <View />\n </View>\n\n {feil ? <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.akseptFeil(feil)} /> : null}\n\n <ScrollView contentContainerStyle={{ gap: tema.space.md }}>\n <H sub={tekst.akseptHva}>{program.name}</H>\n\n {/* DD-32: tallene på én linje, før forklaringen. */}\n <Text\n accessibilityRole=\"text\"\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n fontWeight: tema.weight.semibold,\n }}\n >\n {tall}\n </Text>\n\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {program.hypothesis}\n </Text>\n\n <Card>\n <H>{tekst.akseptOppgaver}</H>\n {program.tasks.map((o) => (\n <View key={o.id} style={{ gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {o.title}\n </Text>\n <Hint>\n {tekst.akseptOppgaveTid(o.estimatedMinutes)}\n {o.screenHint ? ` · ${o.screenHint}` : ''}\n </Hint>\n </View>\n ))}\n </Card>\n\n {program.knownIssues.length > 0 ? (\n <Card>\n <H sub={tekst.akseptKjenteFeilUnder}>{tekst.akseptKjenteFeil(program.knownIssues.length)}</H>\n {program.knownIssues.map((k) => {\n const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv!;\n return (\n <View key={k.id} style={{ gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }}>\n {k.title}\n </Text>\n {k.workaround ? (\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }}>\n {tekst.omvei} {k.workaround}\n </Text>\n ) : null}\n {/* Ikon og farge kommer fra `knownIssueStatus` i temaet — samme kilde\n som widgetens kort (C5). Etiketten bærer versjonen her. */}\n {k.fixedIn ? (\n <StatusPill\n ikon={o.ikon}\n etikett={k.status === 'fikset' ? tekst.rettetI(k.fixedIn) : tekst.rettesI(k.fixedIn)}\n fg={o.fg}\n bg={o.bg}\n />\n ) : null}\n </View>\n );\n })}\n </Card>\n ) : null}\n\n <Card>\n <H sub={tekst.akseptInnsamlingTekst}>{tekst.akseptInnsamling}</H>\n <Hint>{tekst.kontekstAldri}</Hint>\n </Card>\n\n {/* DD-37: lenke, aldri avkryssing — og ingen vilkår i forpliktelsesfri form. */}\n {program.termsUrl && !program.commitmentFree ? (\n <View style={{ gap: tema.space.xs }}>\n <Pressable\n testID=\"vilkar-lenke\"\n accessibilityRole=\"link\"\n accessibilityLabel={tekst.akseptVilkar}\n onPress={() => void Linking.openURL(String(program.termsUrl))}\n style={{ minHeight: tema.touch, justifyContent: 'center' }}\n >\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"open-outline\" farge={tema.color.textPrimary} />\n <Text\n style={{ color: tema.color.textPrimary, fontSize: tema.font.body, textDecorationLine: 'underline' }}\n >\n {tekst.akseptVilkar}\n </Text>\n </View>\n </Pressable>\n <Hint>{tekst.akseptVilkarHint}</Hint>\n </View>\n ) : (\n <Hint>{tekst.akseptIngenVilkar}</Hint>\n )}\n\n <View style={{ flexDirection: 'row', alignItems: 'flex-start', gap: tema.space.sm }}>\n <Ikon navn=\"exit-outline\" farge={tema.color.textPrimary} />\n <Text\n style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}\n >\n {tekst.akseptUtgang}\n </Text>\n </View>\n </ScrollView>\n\n <Btn\n testID=\"bli-med\"\n label={tekst.bliMed}\n disabled={!harToken || sender}\n hint={harToken ? tekst.bliMedHint : tekst.bliMedUtenToken}\n onPress={onBliMed}\n />\n </View>\n </View>\n </Modal>\n );\n}\n","/**\n * Datoene testeren ser i aksepten (DD-32): «10.–24. oktober», eller med begge\n * måneder når perioden krysser et månedsskifte. Norsk bokmål, ingen klokkeslett —\n * et program varer i dager, og et tidspunkt ville lovet en presisjon som ikke finnes.\n */\nconst MANEDER = [\n 'januar',\n 'februar',\n 'mars',\n 'april',\n 'mai',\n 'juni',\n 'juli',\n 'august',\n 'september',\n 'oktober',\n 'november',\n 'desember',\n] as const;\n\nexport function periode(opensAt: string, closesAt: string): string {\n const fra = new Date(opensAt);\n const til = new Date(closesAt);\n if (Number.isNaN(fra.getTime()) || Number.isNaN(til.getTime())) return '';\n\n const sammeManed = fra.getMonth() === til.getMonth() && fra.getFullYear() === til.getFullYear();\n return sammeManed\n ? `${fra.getDate()}.–${til.getDate()}. ${MANEDER[til.getMonth()]}`\n : `${fra.getDate()}. ${MANEDER[fra.getMonth()]} – ${til.getDate()}. ${MANEDER[til.getMonth()]}`;\n}\n\n/** Anslått tid per oppgave, avrundet. Obligatorisk ved opprettelse (DD-32), så lista er aldri tom her. */\nexport function minutterPerOppgave(tasks: ReadonlyArray<{ estimatedMinutes: number }>): number {\n if (tasks.length === 0) return 0;\n return Math.round(tasks.reduce((sum, t) => sum + t.estimatedMinutes, 0) / tasks.length);\n}\n","import type { TaskOutcome } from '@innspel/core';\nimport React, { useState } from 'react';\nimport { Modal, Pressable, Text, TextInput, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, H, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\n\n/** Ionicons-navn fra ikonkartet i `design/wireframes/betaprogram-tester.jsx`, aldri en emoji. */\nexport const UTFALL: ReadonlyArray<{ verdi: TaskOutcome; ikon: string; etikett: string }> = [\n { verdi: 'fungerte', ikon: 'checkmark-circle-outline', etikett: tekst.utfallFungerte },\n { verdi: 'delvis', ikon: 'contrast-outline', etikett: tekst.utfallDelvis },\n { verdi: 'ikke', ikon: 'close-circle-outline', etikett: tekst.utfallIkke },\n];\n\nexport const SETNING_MAKS = 140;\n\nexport function utfallEtikett(verdi: TaskOutcome): string {\n return UTFALL.find((u) => u.verdi === verdi)?.etikett ?? verdi;\n}\n\n/**\n * 3c — «Hvordan gikk det?». ETT spørsmål med tre lukkede valg og en valgfri\n * setning ≤ 140 — aldri en skala (tech-decisions «M3.2 (forts.)»). Samme dialog\n * for «Gjort» på en oppgave og for «Svar nå» på en oppfølging (3d): det er det\n * samme spørsmålet, og testeren skal kjenne det igjen.\n *\n * NN/G «task, then ask»: rett etter handlingen, under ett minutt, og «Lagre» er\n * slutten — ingen flere spørsmål etterpå. Push-spørsmålet fra wireframen (7c) er\n * vertens: plattformen holder aldri push-tokens.\n */\nexport function HvordanGikkDet({\n under,\n sender,\n feil,\n onLagre,\n onLukk,\n}: {\n /** Hva spørsmålet gjelder — oppgavens tittel eller oppfølgingens spørsmål. */\n under: string;\n sender: boolean;\n feil?: string;\n onLagre: (outcome: TaskOutcome, text: string | undefined) => void;\n onLukk: () => void;\n}) {\n const tema = useTema();\n const [valgt, setValgt] = useState<TaskOutcome | undefined>();\n const [setning, setSetning] = useState('');\n\n return (\n <Modal visible transparent animationType=\"fade\" onRequestClose={onLukk} accessibilityViewIsModal>\n <View style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end', padding: tema.space.md }}>\n <View\n testID=\"hvordan-gikk-det\"\n accessibilityViewIsModal\n style={{\n backgroundColor: tema.color.surface,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n padding: tema.space.md,\n gap: tema.space.md,\n }}\n >\n <Btn variant=\"ghost\" testID=\"hvordan-tilbake\" ikon=\"arrow-back-outline\" label={tekst.tilbake} onPress={onLukk} />\n <Hint>{under}</Hint>\n <H>{tekst.hvordanGikkDet}</H>\n\n <View testID=\"utfall-gruppe\" accessibilityRole=\"radiogroup\" accessibilityLabel={tekst.hvordanGikkDet} style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {UTFALL.map((u) => {\n const aktiv = valgt === u.verdi;\n return (\n <Pressable\n key={u.verdi}\n testID={`utfall-${u.verdi}`}\n accessibilityRole=\"radio\"\n accessibilityLabel={u.etikett}\n accessibilityState={{ checked: aktiv }}\n onPress={() => setValgt(u.verdi)}\n style={{\n flex: 1,\n minHeight: tema.touch,\n alignItems: 'center',\n justifyContent: 'center',\n gap: tema.space.xs,\n padding: tema.space.sm,\n borderRadius: tema.radius.md,\n borderWidth: tema.hairline,\n borderColor: aktiv ? tema.color.brand : tema.color.borderStrong,\n backgroundColor: aktiv ? tema.color.brandBg : tema.color.surfaceRaised,\n }}\n >\n <Ikon navn={u.ikon} farge={tema.color.textPrimary} />\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.small, fontWeight: aktiv ? tema.weight.semibold : tema.weight.regular }}>\n {u.etikett}\n </Text>\n </Pressable>\n );\n })}\n </View>\n\n <View style={{ gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>{tekst.setningLabel}</Text>\n <TextInput\n testID=\"hvordan-setning\"\n accessibilityLabel={tekst.setningLabel}\n value={setning}\n onChangeText={setSetning}\n maxLength={SETNING_MAKS}\n multiline\n numberOfLines={3}\n placeholder={tekst.setningPlaceholder}\n placeholderTextColor={tema.color.textMuted}\n style={{\n backgroundColor: tema.color.surfaceRaised,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n minHeight: tema.touch * 2,\n textAlignVertical: 'top',\n }}\n />\n </View>\n\n {feil ? <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.svarFeil(feil)} /> : null}\n\n <Btn\n testID=\"hvordan-lagre\"\n label={tekst.lagre}\n hint={tekst.lagreHint}\n disabled={valgt === undefined || sender}\n onPress={() => {\n if (valgt === undefined) return;\n const trimmet = setning.trim();\n onLagre(valgt, trimmet.length > 0 ? trimmet : undefined);\n }}\n />\n </View>\n </View>\n </Modal>\n );\n}\n","import type { FollowUpView } from '@innspel/core';\nimport React from 'react';\nimport { Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\n\n/** Kontakter med spørsmål tar svar; de andre er handlinger (tech-decisions «M3.2 (forts.)»). */\nexport function tarSvar(kind: FollowUpView['kind']): boolean {\n return kind === 'hvordan_gikk_det' || kind === 'sjekkpunkt';\n}\n\n/**\n * 3d — oppfølgingskortene i appen (DD-34). Hvert kort er én av de maks tre\n * kontaktene, og arten avgjør knappene: et spørsmål får «Svar nå», en påminnelse\n * «Åpne oppgavene» (fristen står i teksten fra produkteier), og tilbudet om utgang\n * «Gå ut» — invertert fra press: utgangen er svaret som tilbys. «Senere» legger\n * kortet bort i denne økten; det kommer tilbake ved neste oppstart, aldri som\n * push — plattformen holder ingen push-tokens.\n */\nexport function Oppfolging({\n oppfolging,\n kontaktNr,\n maksKontakter,\n onSenere,\n onSvar,\n onAapneOppgavene,\n onGaaUt,\n}: {\n oppfolging: FollowUpView;\n kontaktNr: number;\n maksKontakter: number;\n onSenere: () => void;\n onSvar: () => void;\n onAapneOppgavene: () => void;\n onGaaUt: () => void;\n}) {\n const tema = useTema();\n const art = tarSvar(oppfolging.kind) ? 'spoersmaal' : oppfolging.kind === 'tilbud_om_utgang' ? 'utgang' : 'paaminnelse';\n const ikon = art === 'spoersmaal' ? 'flask-outline' : art === 'utgang' ? 'exit-outline' : 'calendar-outline';\n const hint =\n art === 'spoersmaal'\n ? tekst.oppfolgingKontakt(kontaktNr, maksKontakter)\n : art === 'utgang'\n ? tekst.oppfolgingUtgangHint(kontaktNr, maksKontakter)\n : tekst.oppfolgingPaaminnelseHint(kontaktNr, maksKontakter);\n\n return (\n <View\n testID={`oppfolging-${oppfolging.id}`}\n accessibilityLabel={tekst.oppfolgingRegion}\n style={{\n backgroundColor: tema.color.brandBg,\n borderWidth: tema.hairline,\n borderColor: tema.color.brand,\n borderRadius: tema.radius.lg,\n padding: tema.space.md,\n gap: tema.space.sm,\n }}\n >\n <View style={{ flexDirection: 'row', gap: tema.space.sm, alignItems: 'flex-start' }}>\n <Ikon navn={ikon} farge={tema.color.textPrimary} />\n <View style={{ flex: 1, gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>{oppfolging.question}</Text>\n <Hint>{hint}</Hint>\n </View>\n </View>\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {art === 'utgang' ? (\n <>\n {/* «Bli værende» står først: utgangen er et valg, ikke en felle. */}\n <Btn grow variant=\"secondary\" testID={`bli-vaerende-${oppfolging.id}`} label={tekst.bliVaerende} onPress={onSenere} />\n <Btn\n grow\n variant=\"danger\"\n testID={`gaa-ut-${oppfolging.id}`}\n ikon=\"exit-outline\"\n label={tekst.gaaUtBekreft}\n onPress={onGaaUt}\n />\n </>\n ) : (\n <>\n <Btn grow variant=\"secondary\" testID={`senere-${oppfolging.id}`} label={tekst.senere} onPress={onSenere} />\n {art === 'spoersmaal' ? (\n <Btn grow testID={`svar-naa-${oppfolging.id}`} label={tekst.svarNaa} onPress={onSvar} />\n ) : (\n <Btn grow testID={`aapne-oppgavene-${oppfolging.id}`} label={tekst.aapneOppgavene} onPress={onAapneOppgavene} />\n )}\n </>\n )}\n </View>\n </View>\n );\n}\n","import type { ParticipationView, ProgramTask, TaskCompletionView } from '@innspel/core';\nimport React from 'react';\nimport { Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\nimport { utfallEtikett } from './HvordanGikkDet.js';\n\n/**\n * 3c — oppgavelista i deltakelseskortet. Hver oppgave er én rad: tittel, anslag og\n * status «Ikke begynt» eller «Gjort · utfall». «Gjort» åpner «Hvordan gikk det?»\n * (én gang per oppgave — fullføringen er engangs, og raden viser svaret etterpå).\n * Fritt innspill er alltid mulig utenom oppgavene; det er widgetens sak, ikke denne.\n */\nexport function Oppgaver({\n tasks,\n completions,\n onGjort,\n}: {\n tasks: ProgramTask[];\n completions: ParticipationView['completions'];\n onGjort: (task: ProgramTask) => void;\n}) {\n const tema = useTema();\n const ferdig = new Map<string, TaskCompletionView>(completions.map((c) => [c.taskId, c]));\n\n return (\n <View testID=\"oppgaver\" accessibilityLabel={tekst.oppgaverTittel} style={{ gap: tema.space.sm }}>\n {[...tasks]\n .sort((a, b) => a.order - b.order)\n .map((o) => {\n const c = ferdig.get(o.id);\n return (\n <View\n key={o.id}\n testID={`oppgave-${o.id}`}\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n paddingVertical: tema.space.xs,\n borderBottomWidth: tema.hairline,\n borderBottomColor: tema.color.border,\n }}\n >\n <View style={{ flex: 1, gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>{o.title}</Text>\n <Hint>\n {c ? tekst.oppgaveGjortMed(utfallEtikett(c.outcome)) : `${tekst.oppgaveIkkeBegynt} · ${tekst.akseptOppgaveTid(o.estimatedMinutes)}`}\n {c?.text ? ` · «${c.text}»` : ''}\n </Hint>\n </View>\n {c ? (\n // Merket er den eneste flaten der ikonet står alene, så etiketten\n // ligger på containeren: skjermleseren hører utfallet, ikke «hake».\n <View accessibilityLabel={tekst.oppgaveGjortMed(utfallEtikett(c.outcome))} accessible>\n <Ikon navn=\"checkmark-circle-outline\" farge={tema.color.success} />\n </View>\n ) : (\n <Btn\n variant=\"secondary\"\n testID={`gjort-${o.id}`}\n ikon=\"checkmark-circle-outline\"\n label={tekst.oppgaveGjort}\n accessibilityLabel={tekst.oppgaveGjortLabel(o.title)}\n onPress={() => onGjort(o)}\n />\n )}\n </View>\n );\n })}\n </View>\n );\n}\n","import type { InnspelStorage } from '@innspel/core';\n\n/**\n * Formen på lagringspakkene i React Native-økosystemet: AsyncStorage, MMKV med\n * async-fasade, expo-secure-store. Alle tre har disse tre metodene.\n */\nexport interface AsyncStorageLike {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n}\n\n/**\n * Lager en {@link InnspelStorage} av vertens egen lagringspakke.\n *\n * Pakken tar ingen avhengighet på AsyncStorage eller MMKV med vilje: verten har\n * som regel én av dem allerede, og to kopier av samme lagring i én app er verre\n * enn litt oppsett. Send inn den du bruker:\n *\n * @example\n * ```ts\n * import AsyncStorage from '@react-native-async-storage/async-storage';\n * const storage = createStorage(AsyncStorage);\n * ```\n *\n * Det eneste som lagres er offline-køen (DD-41) — aldri feedback-tokenet, aldri\n * en install- eller enhets-ID (K20). Lagringen trenger derfor ikke være kryptert.\n */\nexport function createStorage(pakke: AsyncStorageLike): InnspelStorage {\n return {\n get: (key) => pakke.getItem(key),\n set: (key, value) => pakke.setItem(key, value),\n remove: (key) => pakke.removeItem(key),\n };\n}\n\n/**\n * Lagring i minne. Køen overlever da ikke at appen lukkes, så den er til\n * utvikling og test — ikke til produksjon. `InnspelProvider` sier fra i\n * konsollen hvis den brukes uten at det er sagt eksplisitt.\n */\nexport function createMemoryStorage(): InnspelStorage {\n const rader = new Map<string, string>();\n return {\n get: async (key) => rader.get(key) ?? null,\n set: async (key, value) => {\n rader.set(key, value);\n },\n remove: async (key) => {\n rader.delete(key);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,IAAAA,iBAAyF;AACzF,IAAAC,wBAAqB;;;ACDrB,mBAA6E;AAC7E,0BAAiC;AAqFjC,SAAS,UAAU,KAAyD;AAC1E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW,0BAAM,QAAQ,KAAK,CAAC,GAAG,MAAM,QAAQ,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC;AAChH;AAeO,SAAS,wBAAwB,YAA0B,UAAoC,CAAC,GAAsB;AAC3H,QAAM,EAAE,WAAW,cAAc,IAAI;AACrC,SAAO;AAAA,IACL,MAAM,QAAQ,KAAK,MAAM;AACvB,YAAM,MAAM,MAAM,WAAW,KAAK,EAAE,QAAQ,KAAK,QAAQ,SAAS,KAAK,SAAS,QAAQ,UAAU,CAAC;AACnG,aAAO,EAAE,KAAK,GAAI,MAAM,UAAU,GAAG,EAAG;AAAA,IAC1C;AAAA,IACA,GAAI,YACA;AAAA,MACE,MAAM,OAAO;AACX,cAAM,QAAQ,MAAM,UAAU;AAC9B,YAAI,CAAC,MAAO,QAAO;AACnB,cAAM,EAAE,OAAO,OAAO,IAAI,MAAM,SAAS,MAAM,SAAS,EAAE,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAO,IAAI,MAAM,UAAU,MAAM,GAAG;AAChI,eAAO,EAAE,KAAK,MAAM,KAAK,OAAO,OAAO;AAAA,MACzC;AAAA,IACF,IACA,CAAC;AAAA,IACL,GAAI,kBAAkB,QAAQ,EAAE,eAAe,MAAM,IAAI,CAAC;AAAA,IAC1D,QAAQ,KAAK;AACX,aAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,cAAM,OAAO,IAAI;AACjB,YAAI,CAAC,KAAM,QAAO,QAAQ,IAAI;AAC9B,aAAK,gBAAgB,CAAC,GAAG,GAAG,OAAO,WAAW,QAAQ,EAAE,GAAG,GAAG,OAAO,OAAO,CAAC,CAAC;AAAA,MAChF,CAAC;AAAA,IACH;AAAA,IACA,MAAM,KAAK,KAAK;AACd,YAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,aAAO,IAAI,KAAK;AAAA,IAClB;AAAA,EACF;AACF;AAYO,SAAS,wBAAyC;AACvD,QAAM,OAAO,oBAAI,IAA+B;AAChD,SAAO;AAAA,IACL,SAAS,KAAK;AACZ,WAAK,IAAI,GAAG;AACZ,aAAO,MAAM;AACX,aAAK,OAAO,GAAG;AAAA,MACjB;AAAA,IACF;AAAA,IACA,MAAM,MAAM,CAAC,GAAG,IAAI;AAAA,EACtB;AACF;AASO,IAAM,yBAAqB,4BAA0C,IAAI;AAEzE,SAAS,iBAA6C;AAC3D,aAAO,yBAAW,kBAAkB;AACtC;;;AC1KA,IAAAC,gBAA0C;;;ACkBnC,IAAM,IAAI;AAAA,EACf,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,cAAc;AAAA,IACd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,uBAAuB;AAAA,IACvB,qBAAqB;AAAA,IACrB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,EACR;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,MAAM,EAAE,QAAQ,IAAI,QAAQ,GAAG;AAAA,EAC/B,OAAO;AAAA,EACP,eAAe;AAAA,EACf,UAAU;AACZ;AAGO,IAAM,QAAQ;AAAA,EACnB,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,cAAc;AAAA,IACd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,uBAAuB;AAAA,IACvB,qBAAqB;AAAA,IACrB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,EACR;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,MAAM,EAAE,QAAQ,IAAI,QAAQ,GAAG;AAAA,EAC/B,OAAO;AAAA,EACP,eAAe;AAAA,EACf,UAAU;AACZ;AAGO,IAAM,mBAAmB;AAAA,EAC9B,IAAI;AAAA,IACF,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,WAAW,OAAO,UAAU;AAAA,IAC7C,OAAO,EAAE,MAAM,4CAAsC,OAAO,2CAAqC;AAAA,IACjG,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,IAC/C,OAAO,EAAE,MAAM,sDAA8C,OAAO,qDAA6C;AAAA,IACjH,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,YAAY,OAAO,WAAW;AAAA,IAC/C,OAAO,EAAE,MAAM,2CAAqC,OAAO,0CAAoC;AAAA,IAC/F,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,gBAAa,OAAO,SAAS;AAAA,IAC9C,OAAO,EAAE,MAAM,2CAAqC,OAAO,0CAAoC;AAAA,IAC/F,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,YAAY;AAAA,IACV,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,cAAc,OAAO,aAAa;AAAA,IACnD,OAAO,EAAE,MAAM,uDAAiD,OAAO,sDAAgD;AAAA,IACvH,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,IAC3C,OAAO,EAAE,MAAM,uDAAuD,OAAO,8BAA2B;AAAA,IACxG,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,UAAU,OAAO,SAAS;AAAA,IAC3C,OAAO,EAAE,MAAM,6BAA0B,OAAO,4BAAyB;AAAA,IACzE,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,IACR,YAAY;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,MAAM,mBAAgB,OAAO,kBAAe;AAAA,IACvD,OAAO,EAAE,MAAM,+CAA4C,OAAO,8CAA2C;AAAA,IAC7G,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AACF;AAiDO,IAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AACF;AAGO,IAAM,iBAAiB;AAGvB,IAAM,cAAc;AAAA,EACzB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,gBAAgB;AAClB;;;AD9SO,SAAS,SAAS,SAAwB,SAA2B,QAAc;AACxF,QAAM,OAAQ,WAAW,UAAU,QAAQ;AAC3C,MAAI,CAAC,QAAS,QAAO;AAErB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,OAAO,EAAE,GAAG,KAAK,OAAO,GAAG,QAAQ,MAAM;AAAA,EAC3C;AACF;AAEA,IAAM,kBAAc,6BAAoB,CAAoB;AAErD,IAAM,eAAe,YAAY;AAGjC,SAAS,UAAgB;AAC9B,aAAO,0BAAW,WAAW;AAC/B;;;AEhEA,IAAAC,eAUO;AACP,IAAAC,iBAA4E;AAC5E,IAAAC,uBAA6D;AAC7D,4CAA4D;;;ACb5D,IAAAC,gBAAkB;AAClB,8BAAuB;;;ACDvB;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;ACAA;;;A9B+II;AA1EG,IAAM,aAAa,CAAC,QAAgB,IAAI,QAAQ,6BAA6B,EAAE;AAEtF,IAAM,SAAiC,OAAO;AAAA,EAC5C,OAAO,QAAQ;AAAA,IACb,sBAAsB;AAAA,IACtB,iBAAiB;AAAA;AAAA,IAEjB;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,4BAA4B;AAAA,IAC5B,wBAAwB;AAAA,IACxB,sBAAsB;AAAA,IACtB,wBAAwB;AAAA,IACxB,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,IACnB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,uBAAuB;AAAA,IACvB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,yBAAyB;AAAA,IACzB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,EACrB,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AACjD;AAGO,IAAM,WAA8B,OAAO,KAAK,MAAM;AAYtD,SAAS,KAAK;AAAA,EACnB;AAAA,EACA,WAAAC,aAAY;AAAA,EACZ;AACF,GAWG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAM,OAAO,IAAI;AACvB,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,wBAAqB,IAAI,mCAAgC;AAEnF,QAAM,OACJA,eAAc,WAAW,KAAK,KAAK,SAASA,eAAc,SAAS,IAAI,KAAK,KAAK,SAAS,KAAK,KAAK;AACtG,SACE;AAAA,IAAC;AAAA;AAAA,MAIC,QAAQ,QAAQ,IAAI;AAAA,MACpB,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,SAAS,KAAK,MAAM;AAAA,MAI3B,MAAM,SAAS,KAAK,MAAM;AAAA,MAC1B,6BAA2B;AAAA,MAC3B,2BAA0B;AAAA;AAAA,EAC5B;AAEJ;;;A+B/JA,IAAAC,gBAAyC;AACzC,IAAAC,uBAA6D;;;ACF7D,IAAAC,gBAAuC;AACvC,IAAAC,uBAAkG;AA4D5F,IAAAC,sBAAA;AA3CC,SAAS,IAAI;AAAA,EAClB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAkBG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,IAAI,KAAK;AACf,QAAM,QAAQ,sBAAsB,SAAS,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC;AAEvE,QAAM,WACJ,YAAY,YAAY,EAAE,gBAAgB,YAAY,cAAc,EAAE,gBAAgB;AACxF,QAAM,aACJ,YAAY,YAAY,EAAE,kBAAkB,YAAY,WAAW,EAAE,SAAS,EAAE;AAClF,QAAM,OAAO,YAAY,UAAU,gBAAgB,YAAY,YAAY,EAAE,gBAAgB,EAAE;AAE/F,SACE,8CAAC,6BAAK,OAAO,OAAO,EAAE,MAAM,EAAE,IAAI,QAChC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,mBAAkB;AAAA,QAGlB,oBAAoB,uBAAuB,OAAO,GAAG,KAAK,KAAK,IAAI,KAAK;AAAA,QACxE,oBAAoB,EAAE,UAAU,CAAC,CAAC,UAAU,MAAM,CAAC,CAAC,KAAK;AAAA,QACzD;AAAA,QACA;AAAA,QACC,GAAI,qBAAqB,QAAQ,CAAC;AAAA,QACnC,OAAO;AAAA,UACL,WAAW,KAAK;AAAA,UAChB,cAAc,KAAK,OAAO;AAAA,UAC1B,aAAa,KAAK;AAAA,UAClB,aAAa;AAAA,UACb,iBAAiB,WAAW,EAAE,UAAU;AAAA,UACxC,mBAAmB,KAAK,MAAM;AAAA,UAC9B,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,eAAe;AAAA,UACf,KAAK,KAAK,MAAM;AAAA,UAChB,SAAS,WAAW,MAAM;AAAA,QAC5B;AAAA,QAEC;AAAA,iBAAO,6CAAC,QAAK,MAAM,MAAM,OAAO,WAAW,EAAE,eAAe,YAAY,IAAK;AAAA,UAC9E;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,WAAW,EAAE,eAAe;AAAA,gBACnC,UAAU,KAAK,KAAK;AAAA,gBACpB,YAAY,KAAK,OAAO;AAAA,cAC1B;AAAA,cAEC;AAAA;AAAA,UACH;AAAA;AAAA;AAAA,IACF;AAAA,IACC,OAAO,6CAAC,QAAM,gBAAK,IAAU;AAAA,KAChC;AAEJ;AAmBA,SAAS,sBAAsB,SAAmC,OAAgB,WAAmB;AACnG,QAAM,YAAQ,sBAAwC,IAAI;AAC1D,QAAM,oBAAgB,sBAAO,KAAK;AAElC,QAAM,YAAQ,sBAAO,EAAE,SAAS,MAAM,CAAC;AACvC,QAAM,UAAU,EAAE,SAAS,MAAM;AAEjC,aAAO;AAAA,IACL,OAAO;AAAA,MACL,WAAW,MAAM;AACf,sBAAc,UAAU;AAAA,MAC1B;AAAA,MACA,cAAc,CAAC,MAA6B;AAC1C,cAAM,UAAU,EAAE,GAAG,EAAE,YAAY,OAAO,GAAG,EAAE,YAAY,MAAM;AAAA,MACnE;AAAA,MACA,YAAY,CAAC,MAA6B;AACxC,cAAM,IAAI,MAAM;AAChB,cAAM,UAAU;AAChB,cAAM,WACJ,MAAM,QACN,KAAK,IAAI,EAAE,YAAY,QAAQ,EAAE,CAAC,KAAK,aACvC,KAAK,IAAI,EAAE,YAAY,QAAQ,EAAE,CAAC,KAAK;AACzC,mBAAW,MAAM;AACf,gBAAM,OAAO,cAAc;AAC3B,wBAAc,UAAU;AACxB,cAAI,CAAC,QAAQ,YAAY,CAAC,MAAM,QAAQ,MAAO,OAAM,QAAQ,UAAU;AAAA,QACzE,GAAG,CAAC;AAAA,MACN;AAAA,MACA,eAAe,MAAM;AACnB,cAAM,UAAU;AAChB,sBAAc,UAAU;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AACF;AAEO,SAAS,EAAE,EAAE,UAAU,IAAI,GAAuC;AACvE,QAAM,OAAO,QAAQ;AACrB,SACE,8CAAC,6BAAK,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAChC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,mBAAkB;AAAA,QAClB,OAAO;AAAA,UACL,OAAO,KAAK,MAAM;AAAA,UAClB,UAAU,KAAK,KAAK;AAAA,UACpB,YAAY,KAAK,WAAW;AAAA,UAC5B,YAAY,KAAK,OAAO;AAAA,QAC1B;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,IACC,MACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,OAAO,KAAK,MAAM;AAAA,UAClB,UAAU,KAAK,KAAK;AAAA,UACpB,YAAY,KAAK,WAAW;AAAA,QAC9B;AAAA,QAEC;AAAA;AAAA,IACH,IACE;AAAA,KACN;AAEJ;AAEO,SAAS,KAAK,EAAE,SAAS,GAAkC;AAChE,QAAM,OAAO,QAAQ;AACrB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO,KAAK,MAAM;AAAA,QAClB,UAAU,KAAK,KAAK;AAAA,QACpB,YAAY,KAAK,WAAW;AAAA,MAC9B;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,OAAO,QAAQ;AACrB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL;AAAA,UACE,iBAAiB,KAAK,MAAM;AAAA,UAC5B,cAAc,KAAK,OAAO;AAAA,UAC1B,aAAa,KAAK;AAAA,UAClB,aAAa,KAAK,MAAM;AAAA,UACxB,aAAa,SAAS,WAAW;AAAA,UACjC,SAAS,KAAK,MAAM;AAAA,UACpB,KAAK,KAAK,MAAM;AAAA,QAClB;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAOO,SAAS,WAAW,EAAE,MAAM,SAAS,IAAI,GAAG,GAA8D;AAC/G,QAAM,OAAO,QAAQ;AAGrB,QAAM,QAAQ,CAAC,MAAc,YAAqB,KAAK,MAAiC,IAAI,KAAK;AACjG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,KAAK,KAAK,MAAM;AAAA,QAChB,WAAW;AAAA,QACX,mBAAmB,KAAK,MAAM;AAAA,QAC9B,iBAAiB,KAAK,MAAM;AAAA,QAC5B,cAAc,KAAK,OAAO;AAAA,QAC1B,iBAAiB,MAAM,IAAI,KAAK,MAAM,SAAS;AAAA,MACjD;AAAA,MAEA;AAAA,qDAAC,QAAK,MAAM,MAAM,WAAU,UAAS,OAAO,MAAM,IAAI,KAAK,MAAM,aAAa,GAAG;AAAA,QACjF,6CAAC,6BAAK,OAAO,EAAE,OAAO,MAAM,IAAI,KAAK,MAAM,aAAa,GAAG,UAAU,KAAK,KAAK,OAAO,YAAY,KAAK,OAAO,OAAO,GAClH,mBACH;AAAA;AAAA;AAAA,EACF;AAEJ;AAMO,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,OAAO,QAAQ;AACrB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,eAAe;AAAA,QACf,KAAK,KAAK,MAAM;AAAA,QAChB,iBAAiB,KAAK,MAAM,GAAG,IAAI,IAA+B;AAAA,QAClE,cAAc,KAAK,OAAO;AAAA,QAC1B,SAAS,KAAK,MAAM;AAAA,MACtB;AAAA,MAEA;AAAA,qDAAC,QAAK,MAAM,MAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAAA,QAC3C;AAAA,UAAC;AAAA;AAAA,YACC,mBAAkB;AAAA,YAClB,yBAAyB,OAAO,WAAW;AAAA,YAC3C,OAAO;AAAA,cACL,MAAM;AAAA,cACN,OAAO,KAAK,MAAM,IAAI;AAAA,cACtB,UAAU,KAAK,KAAK;AAAA,cACpB,YAAY,KAAK,WAAW;AAAA,YAC9B;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACvRO,SAAS,OAAO,IAAoB;AACzC,QAAM,IAAI,GAAG,QAAQ,GAAG;AACxB,QAAM,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI;AACxC,SAAO,KAAK,SAAS,IAAI,KAAK,MAAM,EAAE,IAAI;AAC5C;AAEA,IAAM,OAAO,CAAC,MAAuB,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,IAAI;AAE3E,IAAM,QAAQ;AAAA;AAAA,EAEnB,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,eAAe;AAAA,EACf,WAAW;AAAA,EACX,gBAAgB;AAAA;AAAA,EAGhB,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS,CAAC,YAAoB,YAAY,OAAO;AAAA,EACjD,SAAS,CAAC,YAAoB,YAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjD,eAAe;AAAA,EACf,gBAAgB;AAAA;AAAA,EAEhB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,QAAQ;AAAA;AAAA,EAER,SAAS,CAAC,QAAgB,SAAS,GAAG;AAAA,EACtC,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,aAAa;AAAA,EACb,eAAe;AAAA,EACf,eACE;AAAA,EACF,WAAW,CAAC,WAAmB,mBAAgB,MAAM;AAAA,EACrD,YAAY;AAAA;AAAA,EAGZ,oBAAoB;AAAA,EACpB,aAAa;AAAA,EACb,WAAW;AAAA,EACX,eAAe;AAAA,EACf,yBAAyB;AAAA,EACzB,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AAAA,EACT,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,iBAAiB,CAAC,MAAc,MAAc,YAC5C,uCAAoC,OAAO,GAAG,IAAI,oDAAoD,EAAE,GAAG,OAAO,GAAG,IAAI,2BAA2B,EAAE,GAAG,UAAU,gCAAgC,EAAE;AAAA;AAAA,EAGvM,YAAY;AAAA,IACV,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA,cAAc;AAAA,EACd,eAAe;AAAA,EACf,mBAAmB;AAAA;AAAA,EAGnB,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,YAAY,CAAC,OAAe,OAAO,OAAO,EAAE,CAAC;AAAA,EAC7C,iBAAiB;AAAA;AAAA,EAEjB,yBAAyB;AAAA,EACzB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,uBAAuB,CAAC,OAAe,OAAO,OAAO,EAAE,CAAC;AAAA;AAAA,EAGxD,oBAAoB;AAAA,EACpB,eACE;AAAA,EACF,cAAc;AAAA;AAAA,EAEd,kBAAkB;AAAA,EAClB,iBAAiB,CAAC,UAAkB,qBAAqB,KAAK;AAAA,EAC9D,WAAW;AAAA;AAAA,EAGX,YAAY;AAAA;AAAA,EAEZ,eAAe,CAAC,MAAc,sBAAmB,CAAC;AAAA,EAClD,aAAa,CAAC,MAAc,kBAAkB,CAAC;AAAA,EAC/C,WAAW;AAAA,EACX,SAAS;AAAA,EACT,eAAe;AAAA,EACf,SAAS,CAAC,OAAe,OAAO,OAAO,EAAE,CAAC;AAAA;AAAA,EAE1C,SAAS,CAAC,MAAc,OAAe,GAAG,KAAK,IAAI,CAAC,aAAU,OAAO,EAAE,CAAC;AAAA;AAAA,EAExE,cAAc;AAAA,EACd,SAAS,CAAC,cAAsB,YAAY,SAAS;AAAA,EACrD,iBAAiB;AAAA,EACjB,UAAU;AAAA;AAAA,EAEV,YAAY;AAAA;AAAA,EAGZ,kBAAkB;AAAA,EAClB,eAAe,CAAC,SAAiB,oBAAiB,IAAI;AAAA,EACtD,qBAAqB,CAAC,SACpB,uBAAuB,IAAI;AAAA,EAC7B,QAAQ;AAAA,EACR,iBAAiB;AAAA;AAAA,EAGjB,WAAW;AAAA;AAAA,EAEX,YAAY,CAAC,UAAkB,UAAkBC,UAAiB,cAChE,GAAG,QAAQ,sBAAmB,QAAQ,kBAAeA,QAAO,cAAW,SAAS;AAAA,EAClF,gBAAgB;AAAA,EAChB,kBAAkB,CAAC,aAAqB,OAAO,QAAQ;AAAA,EACvD,kBAAkB,CAAC,WAAmB,gBAAgB,MAAM;AAAA,EAC5D,uBAAuB;AAAA,EACvB,kBAAkB;AAAA,EAClB,uBACE;AAAA,EACF,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,mBACE;AAAA,EACF,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA;AAAA,EAEZ,iBAAiB;AAAA,EACjB,YAAY,CAAC,UAAkB,uBAAuB,KAAK;AAAA;AAAA,EAG3D,kBAAkB;AAAA,EAClB,mBAAmB,CAACA,UAAiB,OAAe,SAClD,GAAGA,QAAO,6BAA0B,IAAI,kBAAa,KAAK;AAAA,EAC5D,0BAA0B;AAAA,EAC1B,OAAO;AAAA,EACP,aAAa;AAAA,EACb,YAAY,CAAC,SACX,6CAA0C,IAAI;AAAA,EAChD,aAAa;AAAA,EACb,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,mBAAmB,CAAC,WAAmB,UAAU,MAAM;AAAA,EACvD,iBAAiB,CAAC,WAAmB,iBAAW,MAAM;AAAA,EACtD,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,OAAO;AAAA,EACP,WAAW;AAAA;AAAA,EAEX,UAAU;AAAA,EACV,cAAc;AAAA,EACd,UAAU,CAAC,UAAkB,4BAA4B,KAAK;AAAA;AAAA,EAG9D,kBAAkB;AAAA,EAClB,mBAAmB,CAAC,IAAY,SAAiB,WAAW,EAAE,OAAO,IAAI;AAAA,EACzE,2BAA2B,CAAC,IAAY,SAAiB,WAAW,EAAE,OAAO,IAAI;AAAA,EACjF,sBAAsB,CAAC,IAAY,SAAiB,WAAW,EAAE,OAAO,IAAI;AAAA,EAC5E,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,gBAAgB;AAAA;AAAA,EAGhB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,eAAe;AAAA,EACf,MAAM;AAAA,EACN,OAAO;AACT;AAOO,IAAM,QAAQ;AAAA,EACnB,YAAY;AACd;;;AFjIU,IAAAC,sBAAA;AA/FH,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GA8BG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,MAAM,OAAO,QAAI,wBAAS,KAAK;AACtC,QAAM,CAAC,SAAS,UAAU,QAAI,wBAAmB,CAAC,CAAC;AAEnD,QAAM,QAAQ,MAAM;AACpB,QAAM,UAAU,QAAQ;AACxB,QAAM,OAAO,SAAS;AAGtB,QAAM,YAAY,SAAS,gBAAgB;AAE3C,QAAM,WAAW,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,SAAS,EAAE,KAAK,CAAC;AAE5D,QAAM,aAAS,uBAAQ,MAAM;AAC3B,UAAM,YAAoC;AAAA,MACxC,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AACA,WAAO,OAAO,QAAQ,SAAS,EAC5B,IAAI,CAAC,CAAC,MAAM,OAAO,MAAM;AACxB,YAAMC,SAAS,SAA2D,IAAI;AAC9E,aAAOA,UAAS,CAAC,eAAe,SAAS,IAAI,IAAI,EAAE,MAAM,SAAS,OAAAA,OAAM,IAAI;AAAA,IAC9E,CAAC,EACA,OAAO,CAAC,MAA6D,MAAM,IAAI;AAAA,EACpF,GAAG,CAAC,UAAU,cAAc,CAAC;AAM7B,SACE,8CAAC,6BAAK,QAAO,UAAS,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,KAAK,KAAK,MAAM,GAAG,GAC5E;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,OAAO,EAAE,UAAU,GAAG,YAAY,EAAE;AAAA,QACpC,uBAAuB,EAAE,KAAK,KAAK,MAAM,GAAG;AAAA,QAC5C,2BAA0B;AAAA,QAEzB;AAAA,sBACC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,eAAe;AAAA,gBACf,YAAY;AAAA,gBACZ,KAAK,KAAK,MAAM;AAAA,gBAChB,WAAW,KAAK;AAAA,gBAChB,aAAa,KAAK;AAAA,gBAClB,aAAa,KAAK,MAAM;AAAA,gBACxB,cAAc,KAAK,OAAO;AAAA,gBAC1B,aAAa,KAAK,MAAM;AAAA,gBACxB,cAAc,KAAK,MAAM;AAAA,cAC3B;AAAA,cAEA;AAAA,6DAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,GAC9E,gBAAM,UAAU,UAAU,KAAK,GAClC;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,QAAO;AAAA,oBACP,mBAAkB;AAAA,oBAClB,oBAAoB,MAAM;AAAA,oBAC1B,SAAS;AAAA,oBACT,OAAO,EAAE,UAAU,KAAK,OAAO,WAAW,KAAK,OAAO,YAAY,UAAU,gBAAgB,SAAS;AAAA,oBAErG,uDAAC,QAAK,MAAK,iBAAgB,OAAO,KAAK,MAAM,eAAe;AAAA;AAAA,gBAC9D;AAAA;AAAA;AAAA,UACF,IACE;AAAA,UAEH,WACC;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,KAAK,KAAK,MAAM;AAAA,gBAChB,iBAAiB,KAAK,MAAM;AAAA,gBAC5B,cAAc,KAAK,OAAO;AAAA,gBAC1B,SAAS,KAAK,MAAM;AAAA,cACtB;AAAA,cAEA;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,mBAAkB;AAAA,oBAClB,yBAAwB;AAAA,oBACxB,OAAO;AAAA,sBACL,OAAO,KAAK,MAAM;AAAA,sBAClB,UAAU,KAAK,KAAK;AAAA,sBACpB,YAAY,KAAK,WAAW;AAAA,sBAC5B,YAAY,KAAK,OAAO;AAAA,oBAC1B;AAAA,oBAEC,gBAAM,WAAW,SAAS,IAAI;AAAA;AAAA,gBACjC;AAAA,gBACA,8CAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GACtD;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAI;AAAA,sBACJ,SAAQ;AAAA,sBACR,QAAO;AAAA,sBACP,OAAO,MAAM;AAAA,sBACb,SAAS,MAAM,QAAQ,MAAM,MAAM,GAAG,SAAS,KAAK,IAAI,MAAM,MAAM,SAAS,GAAG,CAAC;AAAA;AAAA,kBACnF;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAI;AAAA,sBACJ,SAAQ;AAAA,sBACR,QAAO;AAAA,sBACP,OAAO,MAAM;AAAA,sBACb,SAAS,MAAM,WAAW,CAAC,MAAM,CAAC,GAAG,GAAG,SAAS,KAAK,CAAC;AAAA;AAAA,kBACzD;AAAA,mBACF;AAAA,gBACA,6CAAC,QAAM,gBAAM,mBAAkB;AAAA;AAAA;AAAA,UACjC,IACE;AAAA,UAEJ,6CAAC,KAAG,mBAAS,UAAU,MAAM,iBAAiB,MAAM,eAAc;AAAA,UAElE;AAAA,YAAC;AAAA;AAAA,cACC,QAAO;AAAA,cACP,oBAAoB,SAAS,UAAU,MAAM,iBAAiB,MAAM;AAAA,cACpE,OAAO;AAAA,cACP,cAAc;AAAA,cACd,WAAW;AAAA,cACX,WAAS;AAAA,cACT,eAAe;AAAA,cACf,aAAa,SAAS,UAAU,MAAM,mBAAmB,MAAM;AAAA,cAC/D,sBAAsB,KAAK,MAAM;AAAA,cACjC,OAAO;AAAA,gBACL,iBAAiB,KAAK,MAAM;AAAA,gBAC5B,aAAa,KAAK;AAAA,gBAClB,aAAa,OAAO,KAAK,MAAM,UAAU,KAAK,MAAM;AAAA,gBACpD,cAAc,KAAK,OAAO;AAAA,gBAC1B,SAAS,KAAK,MAAM;AAAA,gBACpB,OAAO,KAAK,MAAM;AAAA,gBAClB,UAAU,KAAK,KAAK;AAAA,gBACpB,YAAY,KAAK,WAAW;AAAA,gBAC5B,WAAW,KAAK,QAAQ;AAAA,gBACxB,mBAAmB;AAAA,cACrB;AAAA;AAAA,UACF;AAAA,UAEC,YACC;AAAA,YAAC;AAAA;AAAA,cACC,QAAO;AAAA,cACP,yBAAyB,OAAO,cAAc;AAAA,cAC9C,OAAO;AAAA,gBACL,WAAW;AAAA,gBACX,OAAO,OAAO,KAAK,MAAM,UAAU,KAAK,MAAM;AAAA,gBAC9C,UAAU,KAAK,KAAK;AAAA,cACtB;AAAA,cAEC;AAAA;AAAA,gBAAM;AAAA,gBAAI;AAAA,gBACV,OAAO,MAAM,aAAa;AAAA;AAAA;AAAA,UAC7B,IACE;AAAA,UAGH,aACC;AAAA,YAAC;AAAA;AAAA,cACC,QAAO;AAAA,cACP,OAAO;AAAA,gBACL,eAAe;AAAA,gBACf,YAAY;AAAA,gBACZ,KAAK,KAAK,MAAM;AAAA,gBAChB,WAAW,KAAK;AAAA,gBAChB,aAAa,KAAK;AAAA,gBAClB,aAAa,KAAK,MAAM;AAAA,gBACxB,cAAc,KAAK,OAAO;AAAA,gBAC1B,aAAa,KAAK,MAAM;AAAA,gBACxB,cAAc,KAAK,MAAM;AAAA,cAC3B;AAAA,cAEA;AAAA,6DAAC,QAAK,MAAK,iBAAgB,WAAU,UAAS,OAAO,KAAK,MAAM,aAAa;AAAA,gBAC7E,6CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,GAAI,gBAAM,cAAa;AAAA,gBACxG;AAAA,kBAAC;AAAA;AAAA,oBACC,QAAO;AAAA,oBACP,mBAAkB;AAAA,oBAClB,oBAAoB,MAAM;AAAA,oBAC1B,SAAS;AAAA,oBACT,OAAO,EAAE,UAAU,KAAK,OAAO,WAAW,KAAK,OAAO,YAAY,UAAU,gBAAgB,SAAS;AAAA,oBAErG,uDAAC,QAAK,MAAK,iBAAgB,OAAO,KAAK,MAAM,eAAe;AAAA;AAAA,gBAC9D;AAAA;AAAA;AAAA,UACF,IACE,iBAAiB,cACnB,8CAAC,6BAAK,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAC/B;AAAA,4BACC;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,OAAO,MAAM;AAAA,gBACb,MAAM,MAAM;AAAA,gBACZ,SAAS;AAAA;AAAA,YACX,IACE;AAAA,YACH,cACC;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,OAAO,MAAM;AAAA,gBACb,MAAM,MAAM;AAAA,gBACZ,SAAS;AAAA;AAAA,YACX,IACE;AAAA,YACH,aACC,6CAAC,6BAAK,QAAO,eACX,uDAAC,QAAM,sBAAW,GACpB,IACE;AAAA,aACN,IACE;AAAA,UAGJ,8CAAC,6BAAK,OAAO,EAAE,gBAAgB,KAAK,UAAU,gBAAgB,KAAK,MAAM,QAAQ,YAAY,KAAK,MAAM,GAAG,GACzG;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,QAAO;AAAA,gBACP,mBAAkB;AAAA,gBAClB,oBAAoB,EAAE,UAAU,KAAK;AAAA,gBACrC,oBAAoB,GAAG,MAAM,aAAa,GAAG,OAAO,KAAK,MAAM,WAAW;AAAA,gBAC1E,SAAS,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;AAAA,gBAChC,OAAO,EAAE,WAAW,KAAK,OAAO,gBAAgB,SAAS;AAAA,gBAIzD,wDAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM,GAAG,GAC5E;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAM,OAAO,uBAAuB;AAAA,sBACpC,WAAU;AAAA,sBACV,OAAO,KAAK,MAAM;AAAA;AAAA,kBACpB;AAAA,kBACA,8CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,eAAe,UAAU,KAAK,KAAK,MAAM,GAChF;AAAA,0BAAM;AAAA,oBACN,OAAO,KAAK,MAAM;AAAA,qBACrB;AAAA,mBACF;AAAA;AAAA,YACF;AAAA,YAEC,OACC,8CAAC,6BACE;AAAA,qBAAO,IAAI,CAAC,MACX;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO;AAAA,oBACL,eAAe;AAAA,oBACf,YAAY;AAAA,oBACZ,KAAK,KAAK,MAAM;AAAA,oBAChB,WAAW,KAAK;AAAA,oBAChB,mBAAmB,KAAK;AAAA,oBACxB,mBAAmB,KAAK,MAAM;AAAA,kBAChC;AAAA,kBAEA;AAAA,iEAAC,6BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,WAAW,UAAU,KAAK,KAAK,OAAO,UAAU,KAAK,QAAQ,EAAE,GAC7F,YAAE,SACL;AAAA,oBACA,6CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,GAAI,YAAE,OAAM;AAAA,oBAC7F;AAAA,sBAAC;AAAA;AAAA,wBACC,QAAQ,SAAS,EAAE,IAAI;AAAA,wBACvB,mBAAkB;AAAA,wBAClB,oBAAoB,GAAG,MAAM,aAAa,IAAI,EAAE,QAAQ,YAAY,CAAC;AAAA,wBACrE,SAAS,MAAM,gBAAgB,EAAE,IAAI;AAAA,wBACrC,OAAO,EAAE,UAAU,KAAK,OAAO,WAAW,KAAK,OAAO,YAAY,UAAU,gBAAgB,SAAS;AAAA,wBAErG,wDAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM,GAAG,GAC5E;AAAA,uEAAC,QAAK,MAAK,iBAAgB,WAAU,UAAS,OAAO,KAAK,MAAM,eAAe;AAAA,0BAC/E,6CAAC,6BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,eAAe,UAAU,KAAK,KAAK,MAAM,GACvE,gBAAM,eACT;AAAA,2BACF;AAAA;AAAA,oBACF;AAAA;AAAA;AAAA,gBA3BK,EAAE;AAAA,cA4BT,CACD;AAAA,cACD,6CAAC,6BAAK,OAAO,EAAE,YAAY,KAAK,MAAM,GAAG,GACvC,uDAAC,QAAM,gBAAM,eAAc,GAC7B;AAAA,eACF,IACE;AAAA,aACN;AAAA;AAAA;AAAA,IAEF;AAAA,IAEA,6CAAC,6BAAK,QAAO,cAAa,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,gBAAgB,WAAW,GACxF;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,OAAO,SAAS,MAAM,SAAS,UAAU,MAAM,YAAY,UAAU,MAAM,eAAe,MAAM;AAAA,QAChG,UAAU,WAAW;AAAA,QACrB,MAAM;AAAA,QACN,MAAM,UAAU,MAAM,QAAQ,aAAa,IAAI,aAAa,MAAM,mBAAmB;AAAA,QACrF,SAAS;AAAA,QAGT,oBAAkB;AAAA;AAAA,IACpB,GACF;AAAA,KACF;AAEJ;;;AGjXA,IAAAC,gBAAkB;AAClB,IAAAC,uBAAsC;AAiBlC,IAAAC,sBAAA;AAJG,SAAS,KAAK,EAAE,OAAO,GAAiD;AAC7E,QAAM,OAAO,QAAQ;AAErB,QAAM,QAAQ,CAAC,MAAwB,MAAc,OAAe,UAClE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,QAAQ,IAAI;AAAA,MACpB,mBAAkB;AAAA,MAClB,oBAAoB,GAAG,KAAK,KAAK,KAAK;AAAA,MACtC,SAAS,MAAM,OAAO,IAAI;AAAA,MAC1B,OAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW,KAAK,QAAQ;AAAA,QACxB,iBAAiB,KAAK,MAAM;AAAA,QAC5B,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK,MAAM;AAAA,QACxB,cAAc,KAAK,OAAO;AAAA,QAC1B,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,KAAK,KAAK,MAAM;AAAA,QAChB,SAAS,KAAK,MAAM;AAAA,MACtB;AAAA,MAKA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ,QAAQ,IAAI;AAAA,YACpB,OAAO;AAAA,cACL,OAAO,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,cAC7C,QAAQ,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,MAAM;AAAA,cAC9C,cAAc,KAAK,OAAO;AAAA,cAC1B,iBAAiB,KAAK,MAAM;AAAA,cAC5B,YAAY;AAAA,cACZ,gBAAgB;AAAA,YAClB;AAAA,YAEA,uDAAC,QAAK,MAAM,MAAM,WAAU,QAAO,OAAO,KAAK,MAAM,OAAO;AAAA;AAAA,QAC9D;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO,KAAK,MAAM;AAAA,cAClB,UAAU,KAAK,KAAK;AAAA,cACpB,YAAY,KAAK,OAAO;AAAA,cACxB,WAAW;AAAA,YACb;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACA,6CAAC,6BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,WAAW,UAAU,KAAK,KAAK,OAAO,WAAW,SAAS,GACxF,iBACH;AAAA;AAAA;AAAA,EACF;AAGF,SACE,8CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,GACzC;AAAA,iDAAC,KAAG,gBAAM,YAAW;AAAA,IACrB,6CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,gBAAgB,WAAW,GACjD,wDAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GACrD;AAAA,YAAM,QAAQ,OAAO,MAAM,UAAU,MAAM,aAAa;AAAA,MACxD,MAAM,SAAS,QAAQ,MAAM,WAAW,MAAM,cAAc;AAAA,OAC/D,GACF;AAAA,KACF;AAEJ;;;AC9EA,IAAAC,gBAAkB;AAClB,IAAAC,uBAA0D;AAiDpD,IAAAC,sBAAA;AA1CN,IAAM,YAAY;AAoBX,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASG;AACD,QAAM,OAAO,QAAQ;AAErB,MAAI,QAAQ;AACV,WACE,8CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,GACzC;AAAA,mDAAC,KAAE,KAAK,SAAS,UAAU,MAAM,uBAAuB,MAAM,qBAC3D,mBAAS,UAAU,MAAM,wBAAwB,MAAM,sBAC1D;AAAA,MACA,6CAAC,0CAAkB,oBAAmB,uBAAsB,OAAO,KAAK,MAAM,eAAe;AAAA,OAC/F;AAAA,EAEJ;AAIA,SACE,8CAAC,6BAAK,QAAO,eAAc,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,KAAK,KAAK,MAAM,GAAG,GACjF;AAAA,iDAAC,KAAE,KAAK,SAAS,UAAU,MAAM,uBAAuB,MAAM,qBAC3D,mBAAS,UAAU,MAAM,wBAAwB,MAAM,sBAC1D;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,OAAO,EAAE,UAAU,GAAG,YAAY,EAAE;AAAA,QACpC,uBAAuB,EAAE,KAAK,KAAK,MAAM,GAAG;AAAA,QAC5C,2BAA0B;AAAA,QAEzB,eAAK,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,MAAM;AAKnC,gBAAM,IAAI,iBAAiB,EAAE,MAAM,KAAK,iBAAiB;AACzD,gBAAM,UAAU,EAAE,UACd,EAAE,WAAW,WACX,MAAM,QAAQ,EAAE,OAAO,IACvB,MAAM,QAAQ,EAAE,OAAO,IACzB;AACJ,gBAAM,WAAW,UAAU,GAAG,EAAE,KAAK,KAAK,EAAE,OAAO,KAAK,OAAO,KAAK,GAAG,EAAE,KAAK,KAAK,EAAE,OAAO;AAE5F,iBACE,8CAAC,QACC;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,OAAO,KAAK,MAAM;AAAA,kBAClB,UAAU,KAAK,KAAK;AAAA,kBACpB,YAAY,KAAK,WAAW;AAAA,kBAC5B,YAAY,KAAK,OAAO;AAAA,gBAC1B;AAAA,gBAEC,YAAE;AAAA;AAAA,YACL;AAAA,YAEC,EAAE,aACD;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL,OAAO,KAAK,MAAM;AAAA,kBAClB,UAAU,KAAK,KAAK;AAAA,kBACpB,YAAY,KAAK,WAAW;AAAA,gBAC9B;AAAA,gBAEC;AAAA,wBAAM;AAAA,kBAAM;AAAA,kBAAE,EAAE;AAAA;AAAA;AAAA,YACnB,IACE;AAAA,YAEJ,8CAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM,IAAI,UAAU,OAAO,GAC9F;AAAA,2DAAC,cAAW,MAAM,EAAE,MAAM,SAAS,EAAE,SAAS,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI;AAAA,cACjE,UACC,6CAAC,6BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,eAAe,UAAU,KAAK,KAAK,MAAM,GAAI,mBAAQ,IACpF;AAAA,eACN;AAAA,YAEA,8CAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GACtD;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAI;AAAA,kBACJ,QAAQ,WAAW,EAAE,EAAE;AAAA,kBACvB,OAAO,MAAM;AAAA,kBACb,oBAAoB,GAAG,MAAM,MAAM,KAAK,QAAQ;AAAA,kBAChD,UAAU;AAAA,kBACV,MAAM;AAAA,kBACN,SAAS,MAAM,SAAS,CAAC;AAAA;AAAA,cAC3B;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAI;AAAA,kBACJ,SAAQ;AAAA,kBACR,QAAQ,UAAU,EAAE,EAAE;AAAA,kBACtB,OAAO,MAAM;AAAA,kBACb,oBAAoB,GAAG,MAAM,UAAU,KAAK,QAAQ;AAAA,kBACpD,UAAU;AAAA,kBACV,SAAS,MAAM,SAAS,CAAC;AAAA;AAAA,cAC3B;AAAA,eACF;AAAA,eAlDS,EAAE,EAmDb;AAAA,QAEJ,CAAC;AAAA;AAAA,IACH;AAAA,IAEA,6CAAC,6BAAK,QAAO,mBAAkB,OAAO,EAAE,YAAY,EAAE,GACpD,uDAAC,OAAI,SAAQ,aAAY,QAAO,iBAAgB,OAAO,MAAM,SAAS,UAAU,QAAQ,SAAS,OAAO,GAC1G;AAAA,KACF;AAEJ;;;ACrJA,IAAAC,gBAAkB;AAClB,IAAAC,uBAA2B;;;AC4BpB,SAAS,cAAc,KAAqB;AACjD,QAAM,IAAI,IAAI,KAAK,GAAG;AACtB,MAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,EAAG,QAAO;AACtC,SAAO,IAAI,KAAK,eAAe,SAAS,EAAE,KAAK,WAAW,OAAO,OAAO,CAAC,EAAE,OAAO,CAAC;AACrF;AASO,SAAS,cAAc,QAA0B,MAAsB,YAAoC;AAChH,QAAM,IAAI,iBAAiB,MAAM;AACjC,QAAM,OAAyB,SAAS,UAAU,UAAU;AAC5D,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IACR,SAAS,EAAE,QAAQ,IAAI;AAAA,IACvB,IAAI,EAAE;AAAA,IACN,IAAI,EAAE;AAAA,IACN,OAAO,aAAa,EAAE,MAAM,IAAI,GAAG,UAAU;AAAA,EAC/C;AACF;AAMA,SAAS,aAAa,KAAa,YAAwC;AACzE,MAAI,CAAC,IAAI,SAAS,SAAS,EAAG,QAAO;AACrC,SAAO,aAAa,IAAI,QAAQ,WAAW,cAAc,UAAU,CAAC,IAAI;AAC1E;AAGO,IAAM,gBAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO,MAAM;AACf;;;ADbM,IAAAC,sBAAA;AAjCC,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,QAAM,OAAO,QAAQ;AAErB,QAAM,UAAU;AAAA,IACd,MAAM,EAAE,GAAG,MAAM,iBAAiB,GAAG,MAAM,eAAe;AAAA;AAAA;AAAA,IAG1D,OAAO,EAAE,GAAG,MAAM,iBAAiB,GAAG,cAAc,YAAY,SAAS,KAAK,EAAE,MAAM;AAAA,IACtF,QAAQ,EAAE,GAAG,MAAM,sBAAsB,GAAG,MAAM,iBAAiB;AAAA;AAAA;AAAA,IAGnE,SAAI,EAAE,GAAG,MAAM,oBAAoB,GAAG,MAAM,cAAc;AAAA,EAC5D,EAAE,GAAG;AAEL,QAAM,aAAa,YAAY,WAAW,MAAM,0BAA0B,QAAQ;AAClF,QAAM,YAAY,YAAY,WAAW,GAAG,MAAM,eAAe,IAAI,QAAQ,CAAC,KAAK,QAAQ;AAE3F,SACE,8CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,gBAAgB,UAAU,KAAK,KAAK,MAAM,GAAG,GACnE;AAAA,kDAAC,6BAAK,OAAO,EAAE,YAAY,UAAU,KAAK,KAAK,MAAM,GAAG,GAEtD;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,QAAQ,UAAO,0BAA0B;AAAA,UAC/C,WAAU;AAAA,UACV,OAAO,QAAQ,UAAO,KAAK,MAAM,UAAU,KAAK,MAAM;AAAA;AAAA,MACxD;AAAA,MAEA,6CAAC,KAAG,sBAAW;AAAA,MAEd,YAAY,WACX,6CAAC,UAAO,MAAK,mBAAkB,MAAK,WAAU,UAAU,MAAM,qBAAqB,IACjF;AAAA,MACH,YAAY,cAAc,6CAAC,UAAO,MAAK,iBAAgB,MAAK,QAAO,UAAU,MAAM,kBAAkB,IAAK;AAAA,MAE3G;AAAA,QAAC;AAAA;AAAA,UACC,QAAO;AAAA,UACP,mBAAkB;AAAA,UAClB,yBAAwB;AAAA,UACxB,OAAO;AAAA,YACL,OAAO,KAAK,MAAM;AAAA,YAClB,UAAU,KAAK,KAAK;AAAA,YACpB,YAAY,KAAK,WAAW;AAAA,YAC5B,WAAW;AAAA,UACb;AAAA,UAEC;AAAA;AAAA,MACH;AAAA,MAEC,aACC,6CAAC,QAAM,sBAAY,WAAW,MAAM,sBAAsB,UAAU,IAAI,MAAM,WAAW,UAAU,GAAE,IACnG;AAAA,OACN;AAAA,IAEA,6CAAC,OAAI,QAAO,qBAAoB,OAAO,MAAM,iBAAiB,SAAS,QAAQ;AAAA,KACjF;AAEJ;;;AE7FA,IAAAC,gBAAkB;AAClB,IAAAC,uBAA0D;AAmCpD,IAAAC,sBAAA;AAfC,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,OAAO,QAAQ;AAErB,SACE,8CAAC,6BAAK,OAAO,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,GACzC;AAAA,iDAAC,KAAE,KAAK,MAAM,WAAY,gBAAM,YAAW;AAAA,IAE1C,SACC,6CAAC,0CAAkB,oBAAmB,2BAA0B,OAAO,KAAK,MAAM,eAAe,IAC/F,MAAM,WAAW,IACnB,6CAAC,QAAM,gBAAM,SAAQ,IAErB,6CAAC,mCAAW,OAAO,EAAE,MAAM,EAAE,GAAG,uBAAuB,EAAE,KAAK,KAAK,MAAM,GAAG,GACzE,gBAAM,IAAI,CAAC,QAAQ;AAClB,YAAM,SAAS,IAAI,YAAY;AAC/B,YAAM,IAAI,SAAS,gBAAgB,cAAc,IAAI,QAAQ,IAAI,MAAM,IAAI,UAAU;AACrF,YAAM,SAAS,SAAS,IAAI,YAAY,IAAI;AAC5C,YAAM,OAAO,SAAS,SAAY,IAAI;AAEtC,aACE,8CAAC,QAAkB,QAAQ,QACzB;AAAA,qDAAC,QACE,mBACG,GAAG,MAAM,aAAa,SAAM,IAAI,SAAS,UAAU,MAAM,QAAQ,MAAM,IAAI,KAC3E,MAAM,QAAQ,IAAI,SAAS,UAAU,MAAM,QAAQ,MAAM,MAAM,IAAI,EAAE,GAC3E;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,OAAO,KAAK,MAAM;AAAA,cAClB,UAAU,KAAK,KAAK;AAAA,cACpB,YAAY,KAAK,WAAW;AAAA,YAC9B;AAAA,YAEC,cAAI;AAAA;AAAA,QACP;AAAA,QAEA,8CAAC,6BAAK,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAChC;AAAA,uDAAC,cAAW,MAAM,EAAE,MAAM,SAAS,EAAE,SAAS,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI;AAAA,UAClE,6CAAC,QAAM,YAAE,OAAM;AAAA,WACjB;AAAA,QAEC,CAAC,UAAU,IAAI,oBACd,8CAAC,6BAAK,QAAQ,iBAAiB,IAAI,EAAE,IAAI,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,IAAI,YAAY,SAAS,GAC/G;AAAA,uDAAC,QAAK,MAAK,iBAAgB,WAAU,UAAS,OAAO,KAAK,MAAM,WAAW;AAAA,UAC3E,6CAAC,QAAM,gBAAM,cAAa;AAAA,WAC5B,IACE;AAAA,QAEH,OACC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,iBAAiB,KAAK,WAAW;AAAA,cACjC,iBAAiB,KAAK,MAAM;AAAA,cAC5B,aAAa,KAAK,MAAM;AAAA,cACxB,KAAK,KAAK,MAAM;AAAA,YAClB;AAAA,YAEA;AAAA,2DAAC,6BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,eAAe,UAAU,KAAK,KAAK,MAAM,GACvE,uBAAa,MAAM,QAAQ,UAAU,IAAI,MAAM,iBAClD;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,OAAO,KAAK,MAAM;AAAA,oBAClB,UAAU,KAAK,KAAK;AAAA,oBACpB,YAAY,KAAK,WAAW;AAAA,kBAC9B;AAAA,kBAEC,eAAK;AAAA;AAAA,cACR;AAAA;AAAA;AAAA,QACF,IACE;AAAA,WAnDK,MAoDX;AAAA,IAEJ,CAAC,GACH;AAAA,IAGF,6CAAC,OAAI,QAAO,aAAY,OAAO,MAAM,WAAW,IAAI,MAAM,aAAa,MAAM,UAAU,SAAS,QAAQ;AAAA,KAC1G;AAEJ;;;ACjHA,kBAA6F;AAC7F,IAAAC,iBAA8E;AAC9E,IAAAC,uBAA6G;AA2GvG,IAAAC,sBAAA;AAlFC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AACF,GAaG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAsB,QAAQ;AAC5D,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAS,KAAK;AAC9C,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAqB,CAAC,CAAC;AAC/C,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAmD,IAAI;AACjF,QAAM,YAAQ,uBAAoB,CAAC,CAAC;AAGpC,QAAM,cAAU,wBAAQ,MAAM;AAC5B,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,IAAI,KAAK,IAAI,MAAM,QAAQ,MAAM,OAAO,MAAM,SAAS,MAAM,MAAM;AACzE,WAAO,EAAE,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC,GAAG,QAAQ,KAAK,MAAM,MAAM,SAAS,CAAC,EAAE;AAAA,EACpF,GAAG,CAAC,OAAO,MAAM,OAAO,MAAM,MAAM,CAAC;AAErC,QAAM,iBAAa;AAAA,IACjB,MAAO,UAAU,cAAc,IAAI,CAAC,UAAM,oBAAO,GAAG,cAAc,OAAO,CAAC,IAAI,CAAC;AAAA,IAC/E,CAAC,eAAe,cAAc,OAAO;AAAA,EACvC;AAEA,QAAM,eAAW,4BAAY,CAAC,MAAyB;AACrD,UAAM,EAAE,OAAO,OAAO,IAAI,EAAE,YAAY;AACxC,aAAS,EAAE,OAAO,OAAO,CAAC;AAAA,EAC5B,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ,CAAC,OAAyC,EAAE,GAAG,EAAE,YAAY,WAAW,GAAG,EAAE,YAAY,UAAU;AAEjH,QAAM,UAAU,CAAC,MAA6B;AAC5C,QAAI,CAAC,QAAS;AACd,UAAM,IAAI,MAAM,CAAC;AAEjB,UAAM,QAAQ,KAAK,UAAU,CAAC,UAAM,qBAAQ,GAAG,CAAC,CAAC;AACjD,QAAI,SAAS,GAAG;AACd,cAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC;AAC9C;AAAA,IACF;AACA,QAAI,YAAY,QAAQ;AACtB,YAAM,QAAI,0BAAa,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,QAAQ,KAAK,MAAM,GAAG,OAAO;AAChF,UAAI,EAAG,SAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;AAC/B;AAAA,IACF;AACA,UAAM,UAAU,CAAC,CAAC;AAAA,EACpB;AAEA,QAAM,SAAS,CAAC,MAA6B;AAC3C,QAAI,YAAY,YAAY,MAAM,QAAQ,WAAW,EAAG;AACxD,UAAM,QAAQ,KAAK,MAAM,CAAC,CAAC;AAAA,EAC7B;AAEA,QAAM,YAAY,MAAM;AACtB,QAAI,YAAY,YAAY,CAAC,WAAW,MAAM,QAAQ,WAAW,EAAG;AACpE,UAAM,aAAS,4BAAe,MAAM,SAAS,YAAY,YAAY,OAAO;AAC5E,UAAM,UAAU,CAAC;AACjB,QAAI,OAAO,OAAQ,SAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC;AAAA,EACrD;AAEA,QAAM,QAAQ,CAAC,IAA8B,MAAc,UAAkB;AAC3E,UAAM,QAAQ,OAAO,aAAa,WAAW,YAAY,MAAM,CAAC;AAChE,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,QAAQ,WAAW,EAAE;AAAA,QACrB,mBAAkB;AAAA,QAClB,oBAAoB;AAAA,QACpB,oBAAoB,EAAE,UAAU,MAAM;AAAA,QACtC,SAAS,MAAO,OAAO,aAAa,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,WAAW,EAAE;AAAA,QAC1E,OAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,KAAK;AAAA,UAChB,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,KAAK,KAAK,MAAM;AAAA,UAChB,SAAS,KAAK,MAAM;AAAA,UACpB,cAAc,KAAK,OAAO;AAAA,UAC1B,aAAa,KAAK;AAAA,UAClB,aAAa,KAAK,MAAM;AAAA,UACxB,mBAAmB,QAAQ,KAAK,WAAW,IAAI,KAAK;AAAA,UACpD,mBAAmB,QAAQ,KAAK,MAAM,cAAc,KAAK,MAAM;AAAA,UAC/D,iBAAiB,QAAQ,KAAK,MAAM,gBAAgB;AAAA,QACtD;AAAA,QAEA;AAAA,uDAAC,QAAK,MAAM,MAAM,OAAO,KAAK,MAAM,aAAa;AAAA,UACjD;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,KAAK,MAAM;AAAA,gBAClB,UAAU,KAAK,KAAK;AAAA,gBACpB,YAAY,QAAQ,KAAK,OAAO,WAAW,KAAK,OAAO;AAAA,cACzD;AAAA,cAEC;AAAA;AAAA,UACH;AAAA;AAAA;AAAA,MA9BK;AAAA,IA+BP;AAAA,EAEJ;AAEA,QAAM,OAAO,MAAM,gBAAgB,WAAW,QAAQ,KAAK,QAAQ,QAAQ;AAO3E,SACE,8CAAC,6BAAK,QAAO,oBAAmB,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,KAAK,KAAK,MAAM,GAAG,GACtF;AAAA,iDAAC,KAAE,KAAK,UAAU,YAAY,MAAM,0BAA0B,MAAM,kBAAmB,gBAAM,mBAAkB;AAAA,IAC9G,QACC,6CAAC,6BAAK,QAAO,eACX,uDAAC,QAAM,iBAAM,GACf,IACE;AAAA,IAEJ,8CAAC,6BAAK,mBAAkB,WAAU,oBAAoB,MAAM,WAAW,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GACtH;AAAA,YAAM,QAAQ,gBAAgB,MAAM,UAAU;AAAA,MAC9C,MAAM,UAAU,iBAAiB,MAAM,QAAQ;AAAA,MAC/C,MAAM,YAAY,gBAAgB,MAAM,cAAc;AAAA,OACzD;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP;AAAA,QACA,OAAO;AAAA,UACL,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,WAAW,KAAK,QAAQ;AAAA,UACxB,iBAAiB,YAAY;AAAA,UAC7B,cAAc,KAAK,OAAO;AAAA,UAC1B,UAAU;AAAA,QACZ;AAAA,QAEA,uDAAC,6BAAK,QAAO,qBAAoB,eAAc,YAAW,OAAO,CAAC,gCAAW,cAAc,EAAE,YAAY,UAAU,gBAAgB,SAAS,CAAC,GAC1I,oBACC;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,aAAa;AAAA,YACb,QAAO;AAAA,YACP,mBAAkB;AAAA,YAClB,oBAAoB;AAAA,YACpB,2BAA2B,MAAM,CAAC;AAAA,YAClC,0BAA0B,MAAM,CAAC;AAAA,YACjC,kBAAkB;AAAA,YAClB,iBAAiB;AAAA,YACjB,oBAAoB;AAAA,YACpB,sBAAsB;AAAA,YACtB,OAAO,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,iBAAiB,YAAY,gBAAgB;AAAA,YAEpG;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,QAAO;AAAA,kBACP,QAAQ,EAAE,KAAK,MAAM,IAAI;AAAA,kBACzB,YAAY,WAAW,YAAY,iBAAiB;AAAA,kBACpD,OAAO,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AAAA,kBACtD,kCAAgC;AAAA;AAAA,cAClC;AAAA,cAEC,WAAW,IAAI,CAAC,GAAG,MAClB;AAAA,gBAAC;AAAA;AAAA,kBAEC,QAAQ,YAAY,CAAC;AAAA,kBACrB,eAAc;AAAA,kBACd,OAAO;AAAA,oBACL,UAAU;AAAA,oBACV,MAAM,EAAE;AAAA,oBACR,KAAK,EAAE;AAAA,oBACP,OAAO,EAAE;AAAA,oBACT,QAAQ,EAAE;AAAA,oBACV,iBAAiB,YAAY;AAAA,oBAC7B,aAAa,KAAK,WAAW;AAAA,oBAC7B,aAAa,YAAY;AAAA,oBACzB,YAAY;AAAA,oBACZ,gBAAgB;AAAA,kBAClB;AAAA,kBAEC,WAAC;AAAA;AAAA;AAAA;AAAA;AAAA,oBAKA,8CAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM,GAAG,GAC5E;AAAA,mEAAC,QAAK,MAAK,uBAAsB,WAAU,UAAS,OAAO,YAAY,cAAc;AAAA,sBACrF,6CAAC,6BAAK,OAAO,EAAE,OAAO,YAAY,cAAc,UAAU,KAAK,KAAK,MAAM,GAAG,eAAe,GACzF,gBAAM,gBACT;AAAA,uBACF;AAAA,sBACE;AAAA;AAAA,gBA3BC,QAAQ,CAAC;AAAA,cA4BhB,CACD;AAAA,cAEA,KAAK,IAAI,CAAC,GAAG,MACZ;AAAA,gBAAC;AAAA;AAAA,kBAEC,QAAQ,SAAS,CAAC;AAAA,kBAClB,eAAc;AAAA,kBACd,OAAO,EAAE,UAAU,YAAY,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,QAAQ,iBAAiB,YAAY,UAAU;AAAA;AAAA,gBAHxH,QAAQ,CAAC;AAAA,cAIhB,CACD;AAAA;AAAA;AAAA,QACH,IACE,MACN;AAAA;AAAA,IACF;AAAA,IAEC,WAAW,SACV,8CAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM,GAAG,GAC5E;AAAA,mDAAC,QAAK,MAAK,uBAAsB,WAAU,UAAS,OAAO,KAAK,MAAM,WAAW;AAAA,MACjF,6CAAC,QAAM,gBAAM,oBAAmB;AAAA,OAClC,IACE;AAAA,IACH,KAAK,SAAS,6CAAC,QAAM,gBAAM,WAAU,IAAU;AAAA,IAC/C,WAAW,6CAAC,QAAM,gBAAM,cAAa,IAAU;AAAA,IAEhD,8CAAC,6BAAK,QAAO,mBAAkB,OAAO,EAAE,YAAY,GAAG,KAAK,KAAK,MAAM,GAAG,GAIxE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,QAAO;AAAA,UACP,OAAO,MAAM;AAAA,UACb,oBAAoB,MAAM;AAAA,UAC1B,UAAU,cAAc,KAAK,WAAW;AAAA,UACxC,SAAS,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA;AAAA,MAC9C;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,QAAO;AAAA,UACP,MAAK;AAAA,UACL,OAAO,MAAM;AAAA,UACb,SAAS;AAAA,UACT,UAAU;AAAA;AAAA,MACZ;AAAA,MACA,6CAAC,OAAI,QAAO,YAAW,OAAO,MAAM,SAAS,SAAS,WAAW,UAAU,cAAc,CAAC,SAAS;AAAA,OACrG;AAAA,KACF;AAEJ;;;AxC+KU,IAAAC,sBAAA;AA7aV,IAAM,SAAS,EAAE,QAAQ,OAAO,SAAS,KAAK;AAuBvC,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,OAAO,QAAQ;AAIrB,QAAM,aAAS,2BAAW,2DAAqB,KAAK,4DAAsB,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,EAAE;AAC3H,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAa,uBAAuB,IAAI;AAE9C,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAe,MAAM;AAC7C,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA2B,MAAM;AACzD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAS,EAAE;AACrC,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA2B,CAAC,CAAC;AACrD,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAClD,QAAM,CAAC,WAAW,YAAY,QAAI,yBAAqC;AACvE,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA2B,CAAC,CAAC;AACrD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAAmB,CAAC,CAAC;AACrD,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,SAAS,cAAc,MAAM;AACnC,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA6B;AACrD,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAgG;AACpI,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAyB,CAAC,CAAC;AACnD,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAIlD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAwC;AAClE,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAqB,CAAC,CAAC;AAC3D,QAAM,CAAC,cAAc,eAAe,QAAI,yBAAS,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AACxE,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAA+B,QAAQ;AACjE,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAsC;AAGpE,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAS,EAAE,GAAG,OAAO,SAAS,CAAC;AAGzE,QAAM,mBAAmB,cAAc,sBAAsB,aAAa,WAAW;AACrF,QAAM,cAAc,oBAAoB,aAAa,SAAS,kBAAkB;AAChF,QAAM,eAAe,oBAAoB,OAAO,aAAa,SAAS,SAAS;AAE/E,QAAM,aAAa,OAAO,kBAAkB,WAAW,gBAAgB,gBAAgB,IAAI;AAE3F,QAAM,gBAAY,4BAAY,MAAM;AAClC,YAAQ,MAAM;AACd,YAAQ,MAAM;AACd,aAAS,EAAE;AACX,YAAQ,CAAC,CAAC;AACV,iBAAa,MAAS;AACtB,YAAQ,CAAC,CAAC;AACV,gBAAY,CAAC,CAAC;AACd,YAAQ,MAAS;AACjB,kBAAc,MAAS;AACvB,aAAS,MAAS;AAClB,kBAAc,CAAC,CAAC;AAChB,eAAW,MAAS;AACpB,kBAAc,KAAK;AAAA,EACrB,GAAG,CAAC,CAAC;AAKL,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAe,MAAM;AAC3D,QAAM,cAAU,uBAAO,IAAI;AAC3B,UAAQ,UAAU;AAGlB,QAAM,YAAY,MAAM,KAAK,EAAE,SAAS,KAAK,YAAY;AAMzD,QAAM,WAAO,4BAAY,MAAM;AAC7B,WAAO;AACP,QAAI,QAAQ,YAAY,UAAU,aAAa;AAC7C,cAAQ,WAAW;AACnB,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,QAAQ,aAAa,WAAW,CAAC;AAGrC,QAAM,sBAAkB,4BAAY,MAAM;AACxC,WAAO;AACP,cAAU;AACV,mBAAe,KAAK;AACpB,mBAAe,MAAM;AAAA,EACvB,GAAG,CAAC,QAAQ,SAAS,CAAC;AAItB,gCAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACtC,SAAK,OAAO,MAAM,MAAM,EAAE,MAAM,MAAM,MAAS;AAE/C,SAAK,OAAO,aAAa,EAAE,KAAK,CAAC,MAAM,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,MAAM,MAAS;AAIxF,QAAI,CAAC,OAAO,aAAa;AACvB,WAAK,OAAO,SACT,YAAY,EACZ,KAAK,OAAO,EACZ,MAAM,MAAM,MAAS;AAAA,IAC1B;AAIA,QAAI,cAAc,SAAS,UAAU,CAAC,OAAO,YAAa,MAAK,QAAQ,IAAI;AAAA,aAClE,cAAc,SAAS,CAAC,UAAW,MAAK,SAAS,aAAa,KAAK;AAAA,EAE9E,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,eAAW,4BAAY,YAAY;AACvC,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,IAAI,cAAc,SAAS,EAAE,QAAQ,aAAa,OAAO,IAAI,CAAC;AACpE,cAAQ,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC;AAAA,IACzC,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,QAAQ,cAAc,MAAM,CAAC;AAEjC,QAAM,eAAW;AAAA,IACf,OAAO,UAA4B;AACjC,cAAQ,KAAK;AACb,aAAO,MAAM,EAAE,MAAM,kBAAkB,MAAM,MAAM,CAAC;AAEpD,UAAI,UAAU,SAAS;AAErB,gBAAQ,MAAM;AACd;AAAA,MACF;AAEA,cAAQ,YAAY;AACpB,YAAM,SAAS;AAAA,IACjB;AAAA,IACA,CAAC,QAAQ,QAAQ;AAAA,EACnB;AAIA,gCAAU,MAAM;AACd,QAAI,SAAS,gBAAgB,CAAC,cAAc,KAAK,WAAW,EAAG,SAAQ,MAAM;AAAA,EAC/E,GAAG,CAAC,MAAM,YAAY,KAAK,MAAM,CAAC;AAElC,QAAM,iBAAa;AAAA,IACjB,CAAC,MAAc;AACb,eAAS,CAAC;AACV,cAAQ,OAAO,SAAS,CAAC,CAAC;AAAA,IAC5B;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAOA,QAAM,oBAAgB,4BAAY,YAAY;AAC5C,QAAI,CAAC,aAAa,QAAS;AAC3B,UAAM,EAAE,SAAS,SAAS,OAAO,IAAI;AACrC,YAAQ,MAAS;AACjB,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,QAAQ,SAAS,MAAM;AACpD,YAAM,MAAM,MAAM,QAAQ,QAAQ,OAAO;AACzC,YAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,KAAK,EAAE,IAAI,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC,CAAC;AAC/E,UAAI,KAAK;AACP,wBAAgB,EAAE,OAAO,IAAI,OAAO,QAAQ,IAAI,OAAO,CAAC;AACxD;AAAA,UACE,SACG,OAAO,CAAC,MAAqB,MAAM,IAAI,EACvC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,IAAI,GAAG,GAAG,EAAE,IAAI,IAAI,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO,EAAE;AAAA,QACtF;AAAA,MACF,OAAO;AACL,wBAAgB,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO,CAAC;AAC9D,sBAAc,CAAC,CAAC;AAAA,MAClB;AACA,eAAS,MAAM;AACf,eAAS,QAAQ;AACjB,cAAQ,aAAa;AAAA,IACvB,QAAQ;AACN,cAAQ,MAAM,iBAAiB;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAOhB,QAAM,gBAAY,4BAAY,YAAY;AACxC,UAAM,OAAO,aAAa,SAAS;AACnC,QAAI,CAAC,KAAM;AACX,YAAQ,MAAS;AACjB,QAAI;AACF,YAAM,QAAQ,MAAM,KAAK,KAAK,YAAY,OAAO;AACjD,UAAI,CAAC,MAAO;AACZ,sBAAgB,EAAE,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAO,CAAC;AAC5D,oBAAc,CAAC,CAAC;AAChB,eAAS,KAAK;AACd,eAAS,SAAS;AAClB,cAAQ,aAAa;AAAA,IACvB,QAAQ;AACN,cAAQ,MAAM,WAAW;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAMhB,QAAM,mBAAe,4BAAY,YAAY;AAC3C,QAAI,CAAC,aAAa,QAAS;AAC3B,kBAAc,IAAI;AAClB,QAAI;AACF,YAAM,WAAW,MAAM,YAAY,QAAQ,QAAQ,YAAY,MAAM;AACrE,YAAM,OAAO,MAAM,YAAY,QAAQ,KAAK,SAAS,GAAG;AACxD,iBAAW,EAAE,MAAM,cAAc,MAAM,OAAO,SAAS,OAAO,QAAQ,SAAS,OAAO,CAAC;AACvF,eAAS,MAAS;AAClB,cAAQ,MAAM;AAAA,IAChB,QAAQ;AACN,cAAQ,MAAM,iBAAiB;AAC/B,cAAQ,MAAM;AAAA,IAChB,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,iBAAa,4BAAY,MAAM;AACnC,aAAS,MAAS;AAClB,kBAAc,CAAC,CAAC;AAChB,eAAW,MAAS;AACpB,YAAQ,MAAM;AAAA,EAChB,GAAG,CAAC,CAAC;AAQL,QAAM,iBAAa,4BAAY,MAAM;AACnC,YAAQ,MAAS;AAEjB,QAAI,SAAS,QAAQ;AACnB,UAAI,YAAa,MAAK;AAAA,UACjB,SAAQ,MAAM;AACnB;AAAA,IACF;AACA,QAAI,SAAS,eAAe;AAC1B,eAAS,MAAS;AAClB,oBAAc,CAAC,CAAC;AAChB,cAAQ,MAAM;AACd;AAAA,IACF;AACA,QAAI,SAAS,UAAU,SAAS,UAAU,KAAK,SAAS,GAAG;AACzD,cAAQ,YAAY;AACpB;AAAA,IACF;AACA,YAAQ,MAAM;AAAA,EAChB,GAAG,CAAC,MAAM,MAAM,KAAK,QAAQ,aAAa,IAAI,CAAC;AAM/C,QAAM,qBAAiB,4BAAY,MAAM;AACvC,QAAI,SAAS,OAAQ,MAAK;AAAA,aACjB,SAAS,aAAc,iBAAgB;AAAA,QAC3C,YAAW;AAAA,EAClB,GAAG,CAAC,MAAM,MAAM,iBAAiB,UAAU,CAAC;AAE5C,QAAM,WAAO,4BAAY,YAAY;AAInC,cAAU,IAAI;AACd,YAAQ,MAAS;AACjB,QAAI;AACF,YAAM,MAAM,MAAM,OAAO,QAAQ;AAAA,QAC/B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,GAAI,UAAU,EAAE,YAAY,QAAQ,IAAI,CAAC;AAAA,QACzC,GAAI,SAAS,UAAU,YAAY,EAAE,qBAAqB,UAAU,GAAG,IAAI,CAAC;AAAA,QAC5E,GAAI,SAAS,SAAS,EAAE,SAAS,gBAAgB,QAAQ,QAAQ,EAAE,IAAI,CAAC;AAAA,MAC1E,CAAU;AAEV,UAAI,IAAI,WAAW,UAAU;AAC3B,sBAAc,EAAE,KAAK,SAAM,GAAI,IAAI,aAAa,EAAE,SAAS,YAAqB,IAAI,CAAC,EAAG,CAAC;AAAA,MAC3F,OAAO;AACL,sBAAc;AAAA,UACZ,KAAK;AAAA,UACL,IAAI,IAAI,WAAW;AAAA;AAAA,UAEnB,GAAI,IAAI,WAAW,aAAa,EAAE,OAAO,IAAI,WAAW,WAAW,IAAI,CAAC;AAAA,UACxE,GAAI,IAAI,YAAY,WAAW,WAAW,EAAE,SAAS,SAAkB,IAAI,CAAC;AAAA,QAC9E,CAAC;AAAA,MACH;AACA,cAAQ,YAAY;AAAA,IACtB,SAAS,GAAG;AAEV,UAAI,aAAa,mCAAuB,SAAQ,EAAE,WAAW;AAAA,eACpD,aAAa,6BAAiB,SAAQ,EAAE,OAAO;AAAA,UACnD,SAAQ,uBAAuB;AAAA,IACtC,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,QAAQ,MAAM,OAAO,SAAS,WAAW,QAAQ,CAAC;AAEtD,QAAM,aAAS;AAAA,IACb,OAAO,MAAsB;AAC3B,gBAAU,IAAI;AACd,UAAI;AACF,cAAM,MAAM,MAAM,OAAO,YAAY,QAAQ,EAAE,EAAE;AACjD,sBAAc,EAAE,KAAK,UAAU,IAAI,IAAI,GAAG,CAAC;AAC3C,gBAAQ,YAAY;AAAA,MACtB,SAAS,GAAG;AACV,gBAAQ,aAAa,+BAAkB,EAAE,UAAU,uBAAuB;AAAA,MAC5E,UAAE;AACA,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAGA,QAAM,cAAU,4BAAY,OAAO,UAAU,UAAU;AACrD,QAAI,SAAS;AACX,UAAI,QAAQ,YAAY,OAAQ,gBAAe,QAAQ,OAAO;AAAA,IAChE,OAAO;AACL,qBAAe,MAAM;AAAA,IACvB;AACA,mBAAe,OAAO;AACtB,YAAQ,MAAM;AACd,kBAAc,IAAI;AAClB,QAAI;AACF,cAAQ,MAAM,OAAO,SAAS,YAAY,CAAC;AAAA,IAC7C,QAAQ;AACN,cAAQ,CAAC,CAAC;AAAA,IACZ,UAAE;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,kBAAc,4BAAY,MAAM;AACpC,mBAAe,KAAK;AACpB,QAAI,UAAW,SAAQ,WAAW;AAAA,QAC7B,WAAU;AAAA,EACjB,GAAG,CAAC,WAAW,aAAa,SAAS,CAAC;AAEtC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,aAAW;AAAA,MACX,eAAc;AAAA,MAGd,gBAAgB;AAAA,MAChB,0BAAwB;AAAA,MAKxB;AAAA,QAAC;AAAA;AAAA,UACC,UAAS;AAAA,UACT,wBAAwB,CAAC,OAAO;AAAA,UAChC,OAAO,EAAE,MAAM,GAAG,iBAAiB,KAAK,MAAM,OAAO,gBAAgB,YAAY,YAAY,OAAO,IAAI;AAAA,UAExG;AAAA,YAAC;AAAA;AAAA,cACC,QAAO;AAAA,cACP,0BAAwB;AAAA,cACxB,mBAAkB;AAAA,cAClB,OAAO;AAAA,gBACL,iBAAiB,KAAK,MAAM;AAAA,gBAC5B,qBAAqB,KAAK,OAAO,KAAK;AAAA,gBACtC,sBAAsB,KAAK,OAAO,KAAK;AAAA,gBACvC,SAAS,KAAK;AAAA,gBACd,eAAe,KAAK,gBAAgB,OAAO;AAAA,gBAC3C,aAAa,KAAK,gBAAgB,OAAO;AAAA,gBACzC,cAAc,KAAK,gBAAgB,OAAO;AAAA,gBAC1C,KAAK,KAAK,MAAM;AAAA,gBAChB,WAAW;AAAA,gBACX,WAAW;AAAA;AAAA;AAAA,gBAGX,GAAI,SAAS,gBAAgB,EAAE,QAAQ,MAAe,IAAI,CAAC;AAAA,cAC7D;AAAA,cAEA;AAAA,8DAAC,6BAAK,OAAO,EAAE,eAAe,OAAO,gBAAgB,iBAAiB,YAAY,SAAS,GACxF;AAAA,2BAAS,UAAU,SAAS,eAC3B,6CAAC,OAAI,SAAQ,SAAQ,QAAO,WAAU,MAAK,sBAAqB,OAAO,MAAM,SAAS,SAAS,YAAY,IAE3G,6CAAC,6BAAK;AAAA,kBAER;AAAA,oBAAC;AAAA;AAAA,sBACC,QAAO;AAAA,sBACP,mBAAkB;AAAA,sBAClB,oBAAoB,MAAM;AAAA,sBAC1B,SAAS,SAAS,eAAe,kBAAkB;AAAA,sBACnD,OAAO,EAAE,UAAU,KAAK,OAAO,WAAW,KAAK,OAAO,YAAY,UAAU,gBAAgB,SAAS;AAAA,sBAErG,uDAAC,QAAK,MAAK,iBAAgB,OAAO,KAAK,MAAM,eAAe;AAAA;AAAA,kBAC9D;AAAA,mBACF;AAAA,gBAEC,OAAO,6CAAC,UAAO,MAAI,MAAC,MAAK,mBAAkB,MAAK,UAAS,UAAU,MAAM,gBAAgB,IAAI,GAAG,IAAK;AAAA,gBAErG,CAAC,UAAU,SAAS,gBAAgB,SAAS,SAC5C,6CAAC,UAAO,MAAK,yBAAwB,MAAK,QAAO,QAAO,kBAAiB,UAAU,MAAM,eAAe,IACtG;AAAA,gBAEH,SAAS,SACR,8EACE;AAAA,+DAAC,QAAK,QAAQ,UAAU;AAAA,kBAEvB,CAAC,OAAO,cACP;AAAA,oBAAC;AAAA;AAAA,sBACC,SAAS,KAAK,SAAS,IAAI,cAAc;AAAA,sBACzC,QAAO;AAAA,sBACP,MAAK;AAAA,sBACL,OAAO,KAAK,SAAS,IAAI,MAAM,cAAc,KAAK,MAAM,IAAI,MAAM;AAAA,sBAClE,oBAAoB,KAAK,SAAS,IAAI,MAAM,YAAY,KAAK,MAAM,IAAI,MAAM;AAAA,sBAC7E,SAAS,MAAM,KAAK,QAAQ;AAAA;AAAA,kBAC9B,IACE;AAAA,mBACN,IACE;AAAA,gBAEH,SAAS,eACR;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA;AAAA,oBACA,QAAQ;AAAA,oBACR;AAAA,oBACA,UAAU;AAAA,oBACV,UAAU,CAAC,MAAM;AACf,mCAAa,CAAC;AACd,8BAAQ,MAAM;AAAA,oBAChB;AAAA,oBACA,OAAO,MAAM,QAAQ,MAAM;AAAA;AAAA,gBAC7B,IACE;AAAA,gBAEH,SAAS,SACR;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA;AAAA,oBACA,SAAS;AAAA,oBACT,eAAe,cAAc;AAAA,oBAC7B,eAAe,cAAc;AAAA,oBAC7B,UAAU,OAAO;AAAA,oBACjB,gBAAgB;AAAA,oBAChB,iBAAiB,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,oBACnD,GAAI,YAAY,EAAE,WAAW,cAAc,MAAM,aAAa,MAAS,EAAE,IAAI,CAAC;AAAA,oBAC/E;AAAA,oBACA,QAAQ;AAAA,oBACR;AAAA,oBACA,SAAS,SAAS;AAAA,oBAClB,SAAS,CAAC;AAAA,oBACT,GAAI,cAAc,EAAE,eAAe,cAAc,IAAI,CAAC;AAAA,oBACtD,GAAI,eAAe,EAAE,aAAa,UAAU,IAAI,CAAC;AAAA,oBACjD,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,oBACpC,YAAY,YAAY;AAAA,oBACxB,gBAAgB;AAAA;AAAA,gBAClB,IACE;AAAA,gBAEH,SAAS,iBAAiB,QACzB;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA,eAAe;AAAA,oBACf;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACC,GAAI,aAAa,EAAE,OAAO,WAAW,IAAI,CAAC;AAAA,oBAC3C,SAAS;AAAA,oBACT,WAAW;AAAA;AAAA,gBACb,IACE;AAAA,gBAEH,SAAS,gBAAgB,aACxB;AAAA,kBAAC;AAAA;AAAA,oBACC,KAAK,WAAW;AAAA,oBACf,GAAI,WAAW,KAAK,EAAE,YAAY,WAAW,GAAG,IAAI,CAAC;AAAA,oBACrD,GAAI,WAAW,UAAU,EAAE,SAAS,WAAW,QAAQ,IAAI,CAAC;AAAA,oBAC5D,GAAI,WAAW,QAAQ,EAAE,OAAO,WAAW,MAAM,IAAI,CAAC;AAAA,oBACvD,QAAQ;AAAA;AAAA,gBACV,IACE;AAAA,gBAEH,SAAS,SACR;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,oBACP,QAAQ;AAAA,oBACP,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,oBACpC,QAAQ;AAAA;AAAA,gBACV,IACE;AAAA;AAAA;AAAA,UACN;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAaA,SAAS,cAAc,QAAgC;AACrD,QAAM,IAAI,OAAO;AACjB,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,MAAM,GAAG,SAAS,KAAK,IAAI;AAChE,gCAAU,MAAM;AACd,QAAI,CAAC,EAAG,QAAO;AACf,cAAU,EAAE,SAAS,CAAC;AACtB,WAAO,EAAE,YAAY,CAAC,MAAM,UAAU,CAAC,CAAC;AAAA,EAC1C,GAAG,CAAC,CAAC,CAAC;AACN,SAAO;AACT;AAEA,SAAS,gBAAgB,QAAuB,UAAoB;AAClE,QAAM,KAA8B,CAAC;AACrC,aAAW,KAAK,OAAO,KAAK,OAAO,OAAO,GAAG;AAC3C,QAAI,MAAM,gBAAgB,SAAS,SAAS,CAAC,EAAG,IAAG,CAAC,IAAI;AAAA,EAC1D;AACA,SAAO;AACT;;;AJrfQ,IAAAC,uBAAA;AAxFR,IAAM,eAAW,8BAAsC,IAAI;AAwBpD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AACF,GAqBG;AACD,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,CAAC,cAAc,eAAe,QAAI,yBAA0C;AAClF,QAAM,iBAAa,uBAAO,KAAK;AAC/B,QAAM,cAAU,uBAAuB,IAAI;AAC3C,QAAM,aAAS,wBAAQ,uBAAuB,CAAC,CAAC;AAEhD,QAAM,WAAO;AAAA,IACX,OAAO,YAAkC;AACvC,sBAAgB,OAAO;AACvB,gBAAU,IAAI;AAAA,IAChB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,YAAQ,4BAAY,MAAM,UAAU,KAAK,GAAG,CAAC,CAAC;AAKpD,MAAI,CAAC,WAAW,SAAS;AACvB,WAAO,kBAAkB,EAAE,KAAK,CAAC;AACjC,eAAW,UAAU;AAAA,EACvB;AAEA,QAAM,WAAO,wBAAQ,MAAM,SAAS,OAAO,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC;AAC7E,QAAM,YAAQ,wBAAyB,OAAO,EAAE,QAAQ,MAAM,MAAM,IAAI,CAAC,QAAQ,MAAM,KAAK,CAAC;AAC7F,QAAM,kBAAc;AAAA,IAClB,OAAO,EAAE,SAAS,cAAc,MAAM,SAAS,OAAO;AAAA,IACtD,CAAC,YAAY,MAAM;AAAA,EACrB;AAEA,SACE,8CAAC,SAAS,UAAT,EAAkB,OAAO,OACxB,wDAAC,mBAAmB,UAAnB,EAA4B,OAAO,aAClC,yDAAC,gBAAa,OAAO,MACnB;AAAA,kDAAC,8BAAK,KAAK,SAAS,aAAa,OAAO,OAAO,EAAE,MAAM,EAAE,GAAG,QAAO,eAChE,UACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACC,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,QACvC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,QACnC,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,QAC1C,QAAQ;AAAA;AAAA,IACV;AAAA,KACF,GACF,GACF;AAEJ;AASO,SAAS,aAA8B;AAC5C,QAAM,QAAI,2BAAW,QAAQ;AAC7B,MAAI,CAAC,GAAG;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;A6CvIA,IAAAC,iBAAyC;AACzC,IAAAC,wBAAqD;AA6BjD,IAAAC,uBAAA;AAbG,SAAS,eAAe,EAAE,UAAU,MAAM,GAAiE;AAChH,QAAM,UAAM,uBAAuB,IAAI;AACvC,QAAM,WAAW,eAAe;AAChC,QAAM,YAAY,UAAU,OAAO;AAEnC,gCAAU,MAAM;AACd,QAAI,CAAC,UAAW;AAChB,WAAO,UAAU,GAAG;AAAA,EACtB,GAAG,CAAC,SAAS,CAAC;AAId,SACE,8CAAC,8BAAK,KAAU,aAAa,OAAO,OAAc,QAAO,kBACtD,UACH;AAEJ;;;AClCA,IAAAC,eAQO;AACP,IAAAC,iBAAwD;AACxD,IAAAC,wBAA6C;;;ACT7C,IAAAC,iBAAkB;AAClB,IAAAC,wBAAkE;;;ACGlE,IAAM,UAAU;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,QAAQ,SAAiB,UAA0B;AACjE,QAAM,MAAM,IAAI,KAAK,OAAO;AAC5B,QAAM,MAAM,IAAI,KAAK,QAAQ;AAC7B,MAAI,OAAO,MAAM,IAAI,QAAQ,CAAC,KAAK,OAAO,MAAM,IAAI,QAAQ,CAAC,EAAG,QAAO;AAEvE,QAAM,aAAa,IAAI,SAAS,MAAM,IAAI,SAAS,KAAK,IAAI,YAAY,MAAM,IAAI,YAAY;AAC9F,SAAO,aACH,GAAG,IAAI,QAAQ,CAAC,UAAK,IAAI,QAAQ,CAAC,KAAK,QAAQ,IAAI,SAAS,CAAC,CAAC,KAC9D,GAAG,IAAI,QAAQ,CAAC,KAAK,QAAQ,IAAI,SAAS,CAAC,CAAC,WAAM,IAAI,QAAQ,CAAC,KAAK,QAAQ,IAAI,SAAS,CAAC,CAAC;AACjG;AAGO,SAAS,mBAAmB,OAA4D;AAC7F,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,KAAK,MAAM,MAAM,OAAO,CAAC,KAAKC,OAAM,MAAMA,GAAE,kBAAkB,CAAC,IAAI,MAAM,MAAM;AACxF;;;AD4BU,IAAAC,uBAAA;AAvCH,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,mBAAmB,QAAQ,KAAK;AAAA,IAChC,QAAQ,QAAQ,SAAS,QAAQ,QAAQ;AAAA,IACzC,QAAQ;AAAA,EACV;AAEA,SACE,8CAAC,+BAAM,SAAO,MAAC,aAAW,MAAC,eAAc,SAAQ,gBAAgB,QAAQ,0BAAwB,MAC/F,wDAAC,8BAAK,OAAO,EAAE,MAAM,GAAG,iBAAiB,KAAK,MAAM,OAAO,gBAAgB,WAAW,GACpF;AAAA,IAAC;AAAA;AAAA,MACC,QAAO;AAAA,MACP,0BAAwB;AAAA,MACxB,OAAO;AAAA,QACL,iBAAiB,KAAK,MAAM;AAAA,QAC5B,qBAAqB,KAAK,OAAO,KAAK;AAAA,QACtC,sBAAsB,KAAK,OAAO,KAAK;AAAA,QACvC,SAAS,KAAK;AAAA,QACd,KAAK,KAAK,MAAM;AAAA,QAChB,WAAW;AAAA,QACX,WAAW;AAAA,MACb;AAAA,MAEA;AAAA,uDAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,gBAAgB,iBAAiB,YAAY,SAAS,GACzF;AAAA,wDAAC,OAAI,SAAQ,SAAQ,QAAO,kBAAiB,MAAK,sBAAqB,OAAO,MAAM,SAAS,SAAS,QAAQ;AAAA,UAC9G,8CAAC,8BAAK;AAAA,WACR;AAAA,QAEC,OAAO,8CAAC,UAAO,MAAI,MAAC,MAAK,mBAAkB,MAAK,UAAS,UAAU,MAAM,WAAW,IAAI,GAAG,IAAK;AAAA,QAEjG,+CAAC,oCAAW,uBAAuB,EAAE,KAAK,KAAK,MAAM,GAAG,GACtD;AAAA,wDAAC,KAAE,KAAK,MAAM,WAAY,kBAAQ,MAAK;AAAA,UAGvC;AAAA,YAAC;AAAA;AAAA,cACC,mBAAkB;AAAA,cAClB,OAAO;AAAA,gBACL,OAAO,KAAK,MAAM;AAAA,gBAClB,UAAU,KAAK,KAAK;AAAA,gBACpB,YAAY,KAAK,WAAW;AAAA,gBAC5B,YAAY,KAAK,OAAO;AAAA,cAC1B;AAAA,cAEC;AAAA;AAAA,UACH;AAAA,UAEA,8CAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK,GACtG,kBAAQ,YACX;AAAA,UAEA,+CAAC,QACC;AAAA,0DAAC,KAAG,gBAAM,gBAAe;AAAA,YACxB,QAAQ,MAAM,IAAI,CAAC,MAClB,+CAAC,8BAAgB,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAC3C;AAAA,4DAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK,GACtG,YAAE,OACL;AAAA,cACA,+CAAC,QACE;AAAA,sBAAM,iBAAiB,EAAE,gBAAgB;AAAA,gBACzC,EAAE,aAAa,SAAM,EAAE,UAAU,KAAK;AAAA,iBACzC;AAAA,iBAPS,EAAE,EAQb,CACD;AAAA,aACH;AAAA,UAEC,QAAQ,YAAY,SAAS,IAC5B,+CAAC,QACC;AAAA,0DAAC,KAAE,KAAK,MAAM,uBAAwB,gBAAM,iBAAiB,QAAQ,YAAY,MAAM,GAAE;AAAA,YACxF,QAAQ,YAAY,IAAI,CAAC,MAAM;AAC9B,oBAAM,IAAI,iBAAiB,EAAE,MAAM,KAAK,iBAAiB;AACzD,qBACA,+CAAC,8BAAgB,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAC3C;AAAA,8DAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,OAAO,YAAY,KAAK,WAAW,MAAM,GACxG,YAAE,OACL;AAAA,gBACC,EAAE,aACD,+CAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,eAAe,UAAU,KAAK,KAAK,OAAO,YAAY,KAAK,WAAW,MAAM,GAC1G;AAAA,wBAAM;AAAA,kBAAM;AAAA,kBAAE,EAAE;AAAA,mBACnB,IACE;AAAA,gBAGH,EAAE,UACD;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAM,EAAE;AAAA,oBACR,SAAS,EAAE,WAAW,WAAW,MAAM,QAAQ,EAAE,OAAO,IAAI,MAAM,QAAQ,EAAE,OAAO;AAAA,oBACnF,IAAI,EAAE;AAAA,oBACN,IAAI,EAAE;AAAA;AAAA,gBACR,IACE;AAAA,mBAlBK,EAAE,EAmBb;AAAA,YAEF,CAAC;AAAA,aACH,IACE;AAAA,UAEJ,+CAAC,QACC;AAAA,0DAAC,KAAE,KAAK,MAAM,uBAAwB,gBAAM,kBAAiB;AAAA,YAC7D,8CAAC,QAAM,gBAAM,eAAc;AAAA,aAC7B;AAAA,UAGC,QAAQ,YAAY,CAAC,QAAQ,iBAC5B,+CAAC,8BAAK,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAChC;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,QAAO;AAAA,gBACP,mBAAkB;AAAA,gBAClB,oBAAoB,MAAM;AAAA,gBAC1B,SAAS,MAAM,KAAK,8BAAQ,QAAQ,OAAO,QAAQ,QAAQ,CAAC;AAAA,gBAC5D,OAAO,EAAE,WAAW,KAAK,OAAO,gBAAgB,SAAS;AAAA,gBAEzD,yDAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM,GAAG,GAC5E;AAAA,gEAAC,QAAK,MAAK,gBAAe,OAAO,KAAK,MAAM,aAAa;AAAA,kBACzD;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,oBAAoB,YAAY;AAAA,sBAEjG,gBAAM;AAAA;AAAA,kBACT;AAAA,mBACF;AAAA;AAAA,YACF;AAAA,YACA,8CAAC,QAAM,gBAAM,kBAAiB;AAAA,aAChC,IAEA,8CAAC,QAAM,gBAAM,mBAAkB;AAAA,UAGjC,+CAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,YAAY,cAAc,KAAK,KAAK,MAAM,GAAG,GAChF;AAAA,0DAAC,QAAK,MAAK,gBAAe,OAAO,KAAK,MAAM,aAAa;AAAA,YACzD;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK;AAAA,gBAE3G,gBAAM;AAAA;AAAA,YACT;AAAA,aACF;AAAA,WACF;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,QAAO;AAAA,YACP,OAAO,MAAM;AAAA,YACb,UAAU,CAAC,YAAY;AAAA,YACvB,MAAM,WAAW,MAAM,aAAa,MAAM;AAAA,YAC1C,SAAS;AAAA;AAAA,QACX;AAAA;AAAA;AAAA,EACF,GACF,GACF;AAEJ;;;AE1LA,IAAAC,iBAAgC;AAChC,IAAAC,wBAAwD;AA8D9C,IAAAC,uBAAA;AAvDH,IAAM,SAA+E;AAAA,EAC1F,EAAE,OAAO,YAAY,MAAM,4BAA4B,SAAS,MAAM,eAAe;AAAA,EACrF,EAAE,OAAO,UAAU,MAAM,oBAAoB,SAAS,MAAM,aAAa;AAAA,EACzE,EAAE,OAAO,QAAQ,MAAM,wBAAwB,SAAS,MAAM,WAAW;AAC3E;AAEO,IAAM,eAAe;AAErB,SAAS,cAAc,OAA4B;AACxD,SAAO,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,GAAG,WAAW;AAC3D;AAYO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,OAAO,QAAQ,QAAI,yBAAkC;AAC5D,QAAM,CAAC,SAAS,UAAU,QAAI,yBAAS,EAAE;AAEzC,SACE,8CAAC,+BAAM,SAAO,MAAC,aAAW,MAAC,eAAc,QAAO,gBAAgB,QAAQ,0BAAwB,MAC9F,wDAAC,8BAAK,OAAO,EAAE,MAAM,GAAG,iBAAiB,KAAK,MAAM,OAAO,gBAAgB,YAAY,SAAS,KAAK,MAAM,GAAG,GAC5G;AAAA,IAAC;AAAA;AAAA,MACC,QAAO;AAAA,MACP,0BAAwB;AAAA,MACxB,OAAO;AAAA,QACL,iBAAiB,KAAK,MAAM;AAAA,QAC5B,cAAc,KAAK,OAAO;AAAA,QAC1B,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK,MAAM;AAAA,QACxB,SAAS,KAAK,MAAM;AAAA,QACpB,KAAK,KAAK,MAAM;AAAA,MAClB;AAAA,MAEA;AAAA,sDAAC,OAAI,SAAQ,SAAQ,QAAO,mBAAkB,MAAK,sBAAqB,OAAO,MAAM,SAAS,SAAS,QAAQ;AAAA,QAC/G,8CAAC,QAAM,iBAAM;AAAA,QACb,8CAAC,KAAG,gBAAM,gBAAe;AAAA,QAEzB,8CAAC,8BAAK,QAAO,iBAAgB,mBAAkB,cAAa,oBAAoB,MAAM,gBAAgB,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GACrJ,iBAAO,IAAI,CAAC,MAAM;AACjB,gBAAM,QAAQ,UAAU,EAAE;AAC1B,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,QAAQ,UAAU,EAAE,KAAK;AAAA,cACzB,mBAAkB;AAAA,cAClB,oBAAoB,EAAE;AAAA,cACtB,oBAAoB,EAAE,SAAS,MAAM;AAAA,cACrC,SAAS,MAAM,SAAS,EAAE,KAAK;AAAA,cAC/B,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,WAAW,KAAK;AAAA,gBAChB,YAAY;AAAA,gBACZ,gBAAgB;AAAA,gBAChB,KAAK,KAAK,MAAM;AAAA,gBAChB,SAAS,KAAK,MAAM;AAAA,gBACpB,cAAc,KAAK,OAAO;AAAA,gBAC1B,aAAa,KAAK;AAAA,gBAClB,aAAa,QAAQ,KAAK,MAAM,QAAQ,KAAK,MAAM;AAAA,gBACnD,iBAAiB,QAAQ,KAAK,MAAM,UAAU,KAAK,MAAM;AAAA,cAC3D;AAAA,cAEA;AAAA,8DAAC,QAAK,MAAM,EAAE,MAAM,OAAO,KAAK,MAAM,aAAa;AAAA,gBACnD,8CAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,OAAO,YAAY,QAAQ,KAAK,OAAO,WAAW,KAAK,OAAO,QAAQ,GACrI,YAAE,SACL;AAAA;AAAA;AAAA,YAtBK,EAAE;AAAA,UAuBT;AAAA,QAEJ,CAAC,GACH;AAAA,QAEA,+CAAC,8BAAK,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAChC;AAAA,wDAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,eAAe,UAAU,KAAK,KAAK,MAAM,GAAI,gBAAM,cAAa;AAAA,UACjG;AAAA,YAAC;AAAA;AAAA,cACC,QAAO;AAAA,cACP,oBAAoB,MAAM;AAAA,cAC1B,OAAO;AAAA,cACP,cAAc;AAAA,cACd,WAAW;AAAA,cACX,WAAS;AAAA,cACT,eAAe;AAAA,cACf,aAAa,MAAM;AAAA,cACnB,sBAAsB,KAAK,MAAM;AAAA,cACjC,OAAO;AAAA,gBACL,iBAAiB,KAAK,MAAM;AAAA,gBAC5B,aAAa,KAAK;AAAA,gBAClB,aAAa,KAAK,MAAM;AAAA,gBACxB,cAAc,KAAK,OAAO;AAAA,gBAC1B,SAAS,KAAK,MAAM;AAAA,gBACpB,OAAO,KAAK,MAAM;AAAA,gBAClB,UAAU,KAAK,KAAK;AAAA,gBACpB,YAAY,KAAK,WAAW;AAAA,gBAC5B,WAAW,KAAK,QAAQ;AAAA,gBACxB,mBAAmB;AAAA,cACrB;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QAEC,OAAO,8CAAC,UAAO,MAAI,MAAC,MAAK,mBAAkB,MAAK,UAAS,UAAU,MAAM,SAAS,IAAI,GAAG,IAAK;AAAA,QAE/F;AAAA,UAAC;AAAA;AAAA,YACC,QAAO;AAAA,YACP,OAAO,MAAM;AAAA,YACb,MAAM,MAAM;AAAA,YACZ,UAAU,UAAU,UAAa;AAAA,YACjC,SAAS,MAAM;AACb,kBAAI,UAAU,OAAW;AACzB,oBAAM,UAAU,QAAQ,KAAK;AAC7B,sBAAQ,OAAO,QAAQ,SAAS,IAAI,UAAU,MAAS;AAAA,YACzD;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF,GACF,GACF;AAEJ;;;AChJA,IAAAC,iBAAkB;AAClB,IAAAC,wBAA2B;AA4DnB,IAAAC,uBAAA;AArDD,SAAS,QAAQ,MAAqC;AAC3D,SAAO,SAAS,sBAAsB,SAAS;AACjD;AAUO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAM,QAAQ,WAAW,IAAI,IAAI,eAAe,WAAW,SAAS,qBAAqB,WAAW;AAC1G,QAAM,OAAO,QAAQ,eAAe,kBAAkB,QAAQ,WAAW,iBAAiB;AAC1F,QAAM,OACJ,QAAQ,eACJ,MAAM,kBAAkB,WAAW,aAAa,IAChD,QAAQ,WACN,MAAM,qBAAqB,WAAW,aAAa,IACnD,MAAM,0BAA0B,WAAW,aAAa;AAEhE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,cAAc,WAAW,EAAE;AAAA,MACnC,oBAAoB,MAAM;AAAA,MAC1B,OAAO;AAAA,QACL,iBAAiB,KAAK,MAAM;AAAA,QAC5B,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK,MAAM;AAAA,QACxB,cAAc,KAAK,OAAO;AAAA,QAC1B,SAAS,KAAK,MAAM;AAAA,QACpB,KAAK,KAAK,MAAM;AAAA,MAClB;AAAA,MAEA;AAAA,uDAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,IAAI,YAAY,aAAa,GAChF;AAAA,wDAAC,QAAK,MAAM,MAAM,OAAO,KAAK,MAAM,aAAa;AAAA,UACjD,+CAAC,8BAAK,OAAO,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,GACzC;AAAA,0DAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK,GAAI,qBAAW,UAAS;AAAA,YACjI,8CAAC,QAAM,gBAAK;AAAA,aACd;AAAA,WACF;AAAA,QACA,8CAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GACrD,kBAAQ,WACP,gFAEE;AAAA,wDAAC,OAAI,MAAI,MAAC,SAAQ,aAAY,QAAQ,gBAAgB,WAAW,EAAE,IAAI,OAAO,MAAM,aAAa,SAAS,UAAU;AAAA,UACpH;AAAA,YAAC;AAAA;AAAA,cACC,MAAI;AAAA,cACJ,SAAQ;AAAA,cACR,QAAQ,UAAU,WAAW,EAAE;AAAA,cAC/B,MAAK;AAAA,cACL,OAAO,MAAM;AAAA,cACb,SAAS;AAAA;AAAA,UACX;AAAA,WACF,IAEA,gFACE;AAAA,wDAAC,OAAI,MAAI,MAAC,SAAQ,aAAY,QAAQ,UAAU,WAAW,EAAE,IAAI,OAAO,MAAM,QAAQ,SAAS,UAAU;AAAA,UACxG,QAAQ,eACP,8CAAC,OAAI,MAAI,MAAC,QAAQ,YAAY,WAAW,EAAE,IAAI,OAAO,MAAM,SAAS,SAAS,QAAQ,IAEtF,8CAAC,OAAI,MAAI,MAAC,QAAQ,mBAAmB,WAAW,EAAE,IAAI,OAAO,MAAM,gBAAgB,SAAS,kBAAkB;AAAA,WAElH,GAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;;;AC9FA,IAAAC,iBAAkB;AAClB,IAAAC,wBAA2B;AA6CX,IAAAC,uBAAA;AAhCT,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,IAAI,IAAgC,YAAY,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAExF,SACE,8CAAC,8BAAK,QAAO,YAAW,oBAAoB,MAAM,gBAAgB,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAC3F,WAAC,GAAG,KAAK,EACP,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,IAAI,CAAC,MAAM;AACV,UAAM,IAAI,OAAO,IAAI,EAAE,EAAE;AACzB,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,QAAQ,WAAW,EAAE,EAAE;AAAA,QACvB,OAAO;AAAA,UACL,eAAe;AAAA,UACf,YAAY;AAAA,UACZ,KAAK,KAAK,MAAM;AAAA,UAChB,iBAAiB,KAAK,MAAM;AAAA,UAC5B,mBAAmB,KAAK;AAAA,UACxB,mBAAmB,KAAK,MAAM;AAAA,QAChC;AAAA,QAEA;AAAA,yDAAC,8BAAK,OAAO,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,GACzC;AAAA,0DAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK,GAAI,YAAE,OAAM;AAAA,YACrH,+CAAC,QACE;AAAA,kBAAI,MAAM,gBAAgB,cAAc,EAAE,OAAO,CAAC,IAAI,GAAG,MAAM,iBAAiB,SAAM,MAAM,iBAAiB,EAAE,gBAAgB,CAAC;AAAA,cAChI,GAAG,OAAO,aAAO,EAAE,IAAI,SAAM;AAAA,eAChC;AAAA,aACF;AAAA,UACC;AAAA;AAAA;AAAA,YAGC,8CAAC,8BAAK,oBAAoB,MAAM,gBAAgB,cAAc,EAAE,OAAO,CAAC,GAAG,YAAU,MACnF,wDAAC,QAAK,MAAK,4BAA2B,OAAO,KAAK,MAAM,SAAS,GACnE;AAAA,cAEA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,QAAQ,SAAS,EAAE,EAAE;AAAA,cACrB,MAAK;AAAA,cACL,OAAO,MAAM;AAAA,cACb,oBAAoB,MAAM,kBAAkB,EAAE,KAAK;AAAA,cACnD,SAAS,MAAM,QAAQ,CAAC;AAAA;AAAA,UAC1B;AAAA;AAAA;AAAA,MAhCG,EAAE;AAAA,IAkCT;AAAA,EAEJ,CAAC,GACL;AAEJ;;;ALgGU,IAAAC,uBAAA;AA5HH,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,EAAE,OAAO,IAAI,WAAW;AAC9B,QAAM,OAAO,QAAQ;AAErB,QAAM,CAAC,MAAM,OAAO,QAAI,yBAAiC;AACzD,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAwC;AAC5E,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAS,KAAK;AACpD,QAAM,CAAC,YAAY,aAAa,QAAI,yBAAS,KAAK;AAClD,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAAS,KAAK;AAC1C,QAAM,CAAC,MAAM,OAAO,QAAI,yBAA6B;AACrD,QAAM,CAAC,QAAQ,SAAS,QAAI,yBAA6B;AACzD,QAAM,CAAC,UAAU,WAAW,QAAI,yBAA6B;AAC7D,QAAM,CAAC,UAAU,WAAW,QAAI,yBAA8B,oBAAI,IAAI,CAAC;AACvE,QAAM,CAAC,aAAa,cAAc,QAAI,yBAAkC;AAExE,QAAM,eAAW,4BAAY,CAAC,OAAe,YAAY,CAAC,MAAM,oBAAI,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;AAIxF,QAAM,gBAAY;AAAA,IAChB,OAAO,SAAsB,SAA6B;AACxD,UAAI,CAAC,UAAU,CAAC,WAAY;AAC5B,gBAAU,IAAI;AACd,kBAAY,MAAS;AACrB,UAAI;AACF,YAAI,OAAO,SAAS,WAAW;AAC7B,gBAAM,KAAK,MAAM,OAAO,SAAS,aAAa,OAAO,KAAK,IAAI,EAAE,SAAS,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC;AACpG,wBAAc,EAAE,GAAG,YAAY,aAAa,CAAC,GAAG,WAAW,aAAa,EAAE,EAAE,CAAC;AAC7E,cAAI,YAAY,UAAU,WAAY,gBAAe,OAAO,IAAI;AAAA,QAClE,OAAO;AACL,gBAAM,OAAO,SAAS,QAAQ,OAAO,WAAW,IAAI,EAAE,SAAS,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC;AAC1F,kBAAQ,CAAC,MAAO,IAAI,EAAE,GAAG,GAAG,kBAAkB,EAAE,iBAAiB,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,WAAW,EAAE,EAAE,IAAI,CAAE;AAAA,QACtH;AACA,kBAAU,MAAS;AAAA,MACrB,SAAS,GAAG;AACV,oBAAY,aAAa,+BAAkB,EAAE,UAAU,uBAAuB;AAAA,MAChF,UAAE;AACA,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,YAAY,QAAQ,UAAU;AAAA,EACzC;AAIA,gCAAU,MAAM;AACd,QAAI,OAAO,YAAa;AACxB,QAAI,UAAU;AACd,SAAK,OAAO,SACT,KAAK,EACL,KAAK,CAAC,SAAS;AACd,UAAI,CAAC,QAAS;AACd,cAAQ,IAAI;AAEZ,oBAAc,KAAK,eAAe,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAAA,IACvE,CAAC,EAGA,MAAM,MAAM,MAAS;AACxB,WAAO,MAAM;AACX,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,aAAS,4BAAY,YAAY;AACrC,QAAI,CAAC,gBAAiB;AACtB,cAAU,IAAI;AACd,YAAQ,MAAS;AACjB,QAAI;AACF,YAAM,KAAK,MAAM,OAAO,SAAS,OAAO,eAAe;AACvD,oBAAc,EAAE;AAChB,qBAAe,KAAK;AACpB,kBAAY,EAAE;AAAA,IAChB,SAAS,GAAG;AACV,cAAQ,aAAa,+BAAkB,EAAE,UAAU,uBAAuB;AAAA,IAC5E,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,QAAQ,iBAAiB,SAAS,CAAC;AAEvC,QAAM,YAAQ,4BAAY,YAAY;AACpC,QAAI,CAAC,WAAY;AACjB,cAAU,IAAI;AACd,QAAI;AACF,YAAM,OAAO,SAAS,SAAS,WAAW,EAAE;AAC5C,oBAAc,MAAS;AACvB,oBAAc,KAAK;AACnB,kBAAY,IAAI;AAAA,IAClB,SAAS,GAAG;AACV,cAAQ,aAAa,+BAAkB,EAAE,UAAU,uBAAuB;AAAA,IAC5E,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,QAAQ,YAAY,SAAS,CAAC;AAGlC,QAAM,aAAa,aAAa,SAAY,MAAM,YAAY,CAAC;AAC/D,QAAM,UAAmC,YAAY,WAAW,YAAY;AAE5E,MAAI,CAAC,QAAS,QAAO;AAErB,MAAI,YAAY;AAGd,UAAM,QAAQ,MAAM,oBAAoB,CAAC,GACtC,OAAO,CAAC,MAAM,EAAE,cAAc,QAAQ,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC,EAC/D,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AACxD,UAAM,kBAAkB,KAAK,IAAI,GAAG,WAAW,eAAe,KAAK,SAAS,CAAC;AAE7E,WACE,+CAAC,8BAAK,QAAO,sBAAqB,oBAAoB,MAAM,kBAAkB,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GACvG;AAAA,WAAK,IAAI,CAAC,GAAG,MACZ;AAAA,QAAC;AAAA;AAAA,UAEC,YAAY;AAAA,UACZ,WAAW,kBAAkB;AAAA,UAC7B,eAAe,QAAQ;AAAA,UACvB,UAAU,MAAM,SAAS,EAAE,EAAE;AAAA,UAC7B,QAAQ,MAAM;AACZ,wBAAY,MAAS;AACrB,sBAAU,EAAE,MAAM,cAAc,YAAY,EAAE,CAAC;AAAA,UACjD;AAAA,UACA,kBAAkB,MAAM,SAAS,EAAE,EAAE;AAAA,UACrC,SAAS,MAAM,cAAc,IAAI;AAAA;AAAA,QAV5B,EAAE;AAAA,MAWT,CACD;AAAA,MAED,+CAAC,QACC;AAAA,sDAAC,KAAE,KAAK,MAAM,kBAAkB,QAAQ,QAAQ,SAAS,QAAQ,QAAQ,GAAG,WAAW,cAAc,QAAQ,WAAW,GACrH,kBAAQ,MACX;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,QAAQ;AAAA,YACf,aAAa,WAAW;AAAA,YACxB,SAAS,CAAC,SAAS;AACjB,0BAAY,MAAS;AACrB,wBAAU,EAAE,MAAM,WAAW,KAAK,CAAC;AAAA,YACrC;AAAA;AAAA,QACF;AAAA,QACC,eAAe,aACd,+CAAC,8BAAK,OAAO,EAAE,KAAK,KAAK,MAAM,GAAG,GAChC;AAAA,wDAAC,QAAM,gBAAM,cAAa;AAAA,UAC1B;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,QAAO;AAAA,cACP,MAAK;AAAA,cACL,OAAO,MAAM;AAAA,cACb,SAAS,MAAM;AACb,sBAAM,OAAO;AACb,+BAAe,MAAS;AACxB,2BAAW,IAAI;AAAA,cACjB;AAAA;AAAA,UACF;AAAA,WACF,IACE;AAAA,QAEJ,8CAAC,OAAI,SAAQ,SAAQ,QAAO,UAAS,MAAK,gBAAe,OAAO,MAAM,OAAO,SAAS,MAAM,cAAc,IAAI,GAAG;AAAA,SACnH;AAAA,MAEC,SACC;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,QAAQ,OAAO,WAAW;AAAA,UACzE;AAAA,UACC,GAAI,WAAW,EAAE,MAAM,SAAS,IAAI,CAAC;AAAA,UACtC,SAAS,CAAC,SAAS,SAAS,KAAK,UAAU,SAAS,IAAI;AAAA,UACxD,QAAQ,MAAM,UAAU,MAAS;AAAA;AAAA,MACnC,IACE;AAAA,MAEH,aACC,8CAAC,+BAAM,SAAO,MAAC,aAAW,MAAC,eAAc,QAAO,gBAAgB,MAAM,cAAc,KAAK,GAAG,0BAAwB,MAClH,wDAAC,8BAAK,OAAO,EAAE,MAAM,GAAG,iBAAiB,KAAK,MAAM,OAAO,gBAAgB,YAAY,SAAS,KAAK,MAAM,GAAG,GAC5G;AAAA,QAAC;AAAA;AAAA,UACC,QAAO;AAAA,UACP,0BAAwB;AAAA,UACxB,OAAO;AAAA,YACL,iBAAiB,KAAK,MAAM;AAAA,YAC5B,cAAc,KAAK,OAAO;AAAA,YAC1B,aAAa,KAAK;AAAA,YAClB,aAAa,KAAK,MAAM;AAAA,YACxB,SAAS,KAAK,MAAM;AAAA,YACpB,KAAK,KAAK,MAAM;AAAA,UAClB;AAAA,UAEA;AAAA,0DAAC,KAAG,gBAAM,aAAY;AAAA,YACtB,8CAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK,GACtG,gBAAM,WAAW,QAAQ,IAAI,GAChC;AAAA,YACA,+CAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,GAAG,GAEtD;AAAA,4DAAC,OAAI,MAAI,MAAC,SAAQ,aAAY,QAAO,gBAAe,OAAO,MAAM,aAAa,SAAS,MAAM,cAAc,KAAK,GAAG;AAAA,cACnH;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAI;AAAA,kBACJ,SAAQ;AAAA,kBACR,QAAO;AAAA,kBACP,MAAK;AAAA,kBACL,OAAO,MAAM;AAAA,kBACb,UAAU;AAAA,kBACV,SAAS,MAAM,KAAK,MAAM;AAAA;AAAA,cAC5B;AAAA,eACF;AAAA;AAAA;AAAA,MACF,GACF,GACF,IACE;AAAA,OACN;AAAA,EAEJ;AAEA,MAAI,CAAC,cAAc,OAAQ,QAAO;AAElC,SACE,gFACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,QAAO;AAAA,QACP,oBAAoB,MAAM;AAAA,QAC1B,OAAO;AAAA,UACL,iBAAiB,KAAK,MAAM;AAAA,UAC5B,cAAc,KAAK,OAAO;AAAA,UAC1B,aAAa,KAAK;AAAA,UAClB,aAAa,KAAK,MAAM;AAAA,UACxB,SAAS,KAAK,MAAM;AAAA,UACpB,KAAK,KAAK,MAAM;AAAA,QAClB;AAAA,QAEA;AAAA,yDAAC,8BAAK,OAAO,EAAE,eAAe,OAAO,KAAK,KAAK,MAAM,IAAI,YAAY,aAAa,GAChF;AAAA,0DAAC,QAAK,MAAK,iBAAgB,OAAO,KAAK,MAAM,aAAa;AAAA,YAC1D,+CAAC,8BAAK,OAAO,EAAE,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,GACzC;AAAA,4DAAC,8BAAK,OAAO,EAAE,OAAO,KAAK,MAAM,aAAa,UAAU,KAAK,KAAK,MAAM,YAAY,KAAK,WAAW,KAAK,GACtG,gBAAM,cAAc,QAAQ,IAAI,GACnC;AAAA,cACA,8CAAC,QAAM,gBAAM,oBAAoB,QAAQ,WAAW,GAAE;AAAA,eACxD;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC,QAAO;AAAA,gBACP,mBAAkB;AAAA,gBAClB,oBAAoB,MAAM;AAAA,gBAC1B,SAAS,MAAM,UAAU,IAAI;AAAA,gBAC7B,OAAO,EAAE,UAAU,KAAK,OAAO,WAAW,KAAK,OAAO,YAAY,UAAU,gBAAgB,SAAS;AAAA,gBAErG,wDAAC,QAAK,MAAK,iBAAgB,OAAO,KAAK,MAAM,eAAe;AAAA;AAAA,YAC9D;AAAA,aACF;AAAA,UACC,QAAQ,CAAC,cACR,8CAAC,UAAO,MAAI,MAAC,MAAK,mBAAkB,MAAK,UAAS,UAAU,MAAM,WAAW,IAAI,GAAG,IAClF;AAAA,UACJ,8CAAC,OAAI,SAAQ,aAAY,QAAO,WAAU,OAAO,MAAM,QAAQ,SAAS,MAAM,eAAe,IAAI,GAAG;AAAA;AAAA;AAAA,IACtG;AAAA,IAEC,cACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU,CAAC,CAAC;AAAA,QACZ;AAAA,QACC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,QACxB,UAAU,MAAM,KAAK,OAAO;AAAA,QAC5B,QAAQ,MAAM,eAAe,KAAK;AAAA;AAAA,IACpC,IACE;AAAA,KACN;AAEJ;;;AMpSO,SAAS,cAAc,OAAyC;AACrE,SAAO;AAAA,IACL,KAAK,CAAC,QAAQ,MAAM,QAAQ,GAAG;AAAA,IAC/B,KAAK,CAAC,KAAK,UAAU,MAAM,QAAQ,KAAK,KAAK;AAAA,IAC7C,QAAQ,CAAC,QAAQ,MAAM,WAAW,GAAG;AAAA,EACvC;AACF;AAOO,SAAS,sBAAsC;AACpD,QAAM,QAAQ,oBAAI,IAAoB;AACtC,SAAO;AAAA,IACL,KAAK,OAAO,QAAQ,MAAM,IAAI,GAAG,KAAK;AAAA,IACtC,KAAK,OAAO,KAAK,UAAU;AACzB,YAAM,IAAI,KAAK,KAAK;AAAA,IACtB;AAAA,IACA,QAAQ,OAAO,QAAQ;AACrB,YAAM,OAAO,GAAG;AAAA,IAClB;AAAA,EACF;AACF;","names":["import_react","import_react_native","import_react","import_core","import_react","import_react_native","import_react","storrelse","import_react","import_react_native","import_react","import_react_native","import_jsx_runtime","periode","import_jsx_runtime","verdi","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_core","import_react","import_react_native","import_react","import_react_native","t","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/InnspelProvider.tsx","../src/skjermbilde.ts","../src/tema.ts","../src/generated/tokens.ts","../src/widget/Widget.tsx","../src/Ikon.tsx","../../../node_modules/ionicons/dist/svg/arrow-back-outline.svg","../../../node_modules/ionicons/dist/svg/brush-outline.svg","../../../node_modules/ionicons/dist/svg/bug.svg","../../../node_modules/ionicons/dist/svg/bug-outline.svg","../../../node_modules/ionicons/dist/svg/bulb.svg","../../../node_modules/ionicons/dist/svg/calendar-outline.svg","../../../node_modules/ionicons/dist/svg/camera-outline.svg","../../../node_modules/ionicons/dist/svg/checkmark-circle-outline.svg","../../../node_modules/ionicons/dist/svg/chevron-down-outline.svg","../../../node_modules/ionicons/dist/svg/chevron-up-outline.svg","../../../node_modules/ionicons/dist/svg/close-circle-outline.svg","../../../node_modules/ionicons/dist/svg/close-outline.svg","../../../node_modules/ionicons/dist/svg/cloud-offline-outline.svg","../../../node_modules/ionicons/dist/svg/construct-outline.svg","../../../node_modules/ionicons/dist/svg/contrast-outline.svg","../../../node_modules/ionicons/dist/svg/ellipse-outline.svg","../../../node_modules/ionicons/dist/svg/exit-outline.svg","../../../node_modules/ionicons/dist/svg/flask-outline.svg","../../../node_modules/ionicons/dist/svg/grid-outline.svg","../../../node_modules/ionicons/dist/svg/hourglass-outline.svg","../../../node_modules/ionicons/dist/svg/image-outline.svg","../../../node_modules/ionicons/dist/svg/images-outline.svg","../../../node_modules/ionicons/dist/svg/list-outline.svg","../../../node_modules/ionicons/dist/svg/lock-closed-outline.svg","../../../node_modules/ionicons/dist/svg/git-merge-outline.svg","../../../node_modules/ionicons/dist/svg/open-outline.svg","../../../node_modules/ionicons/dist/svg/scan-outline.svg","../../../node_modules/ionicons/dist/svg/swap-vertical-outline.svg","../../../node_modules/ionicons/dist/svg/trash-outline.svg","../../../node_modules/ionicons/dist/svg/warning-outline.svg","../src/widget/Felt.tsx","../src/widget/primitiver.tsx","../src/widget/tekster.ts","../src/widget/Valg.tsx","../src/widget/KjenteFeil.tsx","../src/widget/Kvittering.tsx","../src/widget/status.ts","../src/widget/MineInnspill.tsx","../src/widget/nyttSvar.ts","../src/widget/Skjermbilde.tsx","../src/InnspelPrivate.tsx","../src/program/InnspelProgram.tsx","../src/program/Aksept.tsx","../src/program/periode.ts","../src/program/HvordanGikkDet.tsx","../src/program/Oppfolging.tsx","../src/program/Oppgaver.tsx","../src/lagring.ts"],"sourcesContent":["/**\n * `@innspel/react-native` — innsendingswidgeten.\n *\n * Widgeten lever inne i vertsappen og arver dens flate (DD-21). Den er en\n * dialog med fokusfelle, tilbake-knapp og live-region (DD-47), viser kjente\n * feil før feltet i feilsporet (DD-03, DD-29), krever bare et minimum antall\n * tegn (DD-44), varsler om PII uten å fjerne noe (DD-46) og gjør offline-køen\n * synlig (DD-41).\n *\n * Se README.md for quickstart, og `docs/sdk/README.md` for det verten må levere.\n */\n\nexport { InnspelProvider, useInnspel } from './InnspelProvider.js';\nexport type { SubmittedInfo } from './widget/Widget.js';\nexport { InnspelPrivate } from './InnspelPrivate.js';\nexport { InnspelProgram } from './program/InnspelProgram.js';\nexport {\n createScreenshotAdapter,\n type CaptureOptions,\n type CaptureRefFn,\n type ImageStepNote,\n type PickImageFn,\n type ScreenshotAdapter,\n type ScreenshotAdapterOptions,\n type ScreenshotCapture,\n} from './skjermbilde.js';\nexport { createMemoryStorage, createStorage, type AsyncStorageLike } from './lagring.js';\nexport { byggTema, useTema, type PartialTheme, type Tema } from './tema.js';\nexport { light, screenRules, t as darkTokens, type InnspelColors, type InnspelTheme } from './generated/tokens.js';\nexport { statusVisning, venterVisning, type StatusVisning } from './widget/status.js';\nexport { lofte, tekst } from './widget/tekster.js';\n\n// Videresendt fra kjernen, så verten slipper å installere begge for typene.\nexport type {\n AttachmentInput,\n AttachmentOutcome,\n CaptureInput,\n ContextInput,\n InnspelClient,\n InnspelOptions,\n InnspelStorage,\n InvitationView,\n MyPrograms,\n MySubmission,\n OpenFeedbackOptions,\n ParticipationView,\n ProgramTask,\n ProgramView,\n SubmissionStatusView,\n} from '@innspel/core';\n","import type { InnspelClient, OpenFeedbackOptions } from '@innspel/core';\nimport React, { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';\nimport { View } from 'react-native';\nimport { createPrivateRegistry, SkjermbildeContext, type ImageStepNote, type ScreenshotAdapter, type SkjermbildeKontekst, type ViewRef } from './skjermbilde.js';\nimport { byggTema, TemaProvider, type PartialTheme } from './tema.js';\nimport { Widget, type SubmittedInfo } from './widget/Widget.js';\n\ninterface InnspelKontekst {\n client: InnspelClient;\n /** Åpner widgeten. Samme som `client.openFeedback()`. */\n open: (options?: OpenFeedbackOptions) => Promise<void>;\n close: () => void;\n}\n\nconst Kontekst = createContext<InnspelKontekst | null>(null);\n\n/**\n * Pakk appen i denne, og widgeten finnes.\n *\n * Provideren gjør fire ting: den registrerer visningen hos kjernen (så\n * `client.openFeedback()` virker hvor som helst i appen, også utenfor React),\n * den holder temaet, den rendrer selve arket — og den pakker vertsappen i én\n * `View` med referanse, som er det skjermbildet tas av (K4). Modalen ligger\n * utenfor den viewen og kommer aldri med på bildet.\n *\n * @example\n * ```tsx\n * const innspel = init({ … });\n *\n * export default function App() {\n * return (\n * <InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef)}>\n * <MinApp />\n * </InnspelProvider>\n * );\n * }\n * ```\n */\nexport function InnspelProvider({\n client,\n children,\n theme,\n colorScheme = 'dark',\n tenantName,\n screenshot,\n imageStepNote,\n onSubmitted,\n}: {\n client: InnspelClient;\n children?: React.ReactNode;\n /** Vertens egne tokens. Alt som utelates faller tilbake på Innspels tema. */\n theme?: PartialTheme;\n colorScheme?: 'dark' | 'light';\n /** Navnet som står på svaret i «Mine innspill» — leietakerens, ikke Innspels. */\n tenantName?: string;\n /**\n * Fangst av skjermbilde, typisk `createScreenshotAdapter(captureRef)` fra\n * react-native-view-shot. Uten den finnes ikke skjermbilde-steget (DD-26) —\n * og det finnes uansett ikke når `screenshotsEnabled` er av (K18).\n */\n screenshot?: ScreenshotAdapter;\n /**\n * Leietakerens egen setning ved bildesteget, f.eks. «Legg ved et skjermbilde av feilen.\n * Ikke send bilder av andre personer.» Står ved knappene og i forhåndsvisningen. Én\n * streng gjelder begge spor; `{ feil, onske }` gir hvert spor sin. Leietakeren kjenner\n * brukerne sine; plattformen eier ikke den setningen.\n */\n imageStepNote?: ImageStepNote;\n /**\n * Kalles når et innspill er sendt — eller lagt i køen fordi nettet var borte (F26).\n * `type`, `queued`, og `id` når saken finnes hos tjeneren. Ingen identitet: saksnummeret\n * er sakens, og det innsenderen alt ser i kvitteringen. Bruk det til å hente tellingen\n * på «Mine innspill» på nytt, eller til å be om varsler i det riktige øyeblikket —\n * rett etter første innsending, ikke ved oppstart. Kalles ikke for «Ja, jeg også».\n */\n onSubmitted?: (info: SubmittedInfo) => void;\n}) {\n const [synlig, setSynlig] = useState(false);\n const [apneOpsjoner, setApneOpsjoner] = useState<OpenFeedbackOptions | undefined>();\n const registrert = useRef(false);\n const rootRef = useRef<ViewRef | null>(null);\n const privat = useMemo(createPrivateRegistry, []);\n\n const open = useCallback(\n async (options?: OpenFeedbackOptions) => {\n setApneOpsjoner(options);\n setSynlig(true);\n },\n [],\n );\n\n const close = useCallback(() => setSynlig(false), []);\n\n // Registreres én gang. Kjernen kaller `presenter.open()` fra\n // `client.openFeedback()`, som er veien inn for kode som ikke er en\n // React-komponent — en navigasjonshandler, en krasjlytter hos verten.\n if (!registrert.current) {\n client.registerPresenter({ open });\n registrert.current = true;\n }\n\n const tema = useMemo(() => byggTema(theme, colorScheme), [theme, colorScheme]);\n const verdi = useMemo<InnspelKontekst>(() => ({ client, open, close }), [client, open, close]);\n const skjermbilde = useMemo<SkjermbildeKontekst>(\n () => ({ adapter: screenshot ?? null, rootRef, privat }),\n [screenshot, privat],\n );\n\n return (\n <Kontekst.Provider value={verdi}>\n <SkjermbildeContext.Provider value={skjermbilde}>\n <TemaProvider value={tema}>\n <View ref={rootRef} collapsable={false} style={{ flex: 1 }} testID=\"innspel-rot\">\n {children}\n </View>\n <Widget\n client={client}\n synlig={synlig}\n {...(apneOpsjoner ? { apneOpsjoner } : {})}\n {...(tenantName ? { tenantName } : {})}\n {...(imageStepNote ? { imageStepNote } : {})}\n {...(onSubmitted ? { onSubmitted } : {})}\n onLukk={close}\n />\n </TemaProvider>\n </SkjermbildeContext.Provider>\n </Kontekst.Provider>\n );\n}\n\n/**\n * Klienten og `open` fra nærmeste {@link InnspelProvider}.\n *\n * Kaster utenfor provideren i stedet for å gi `null`: en knapp som stille ikke\n * gjør noe er verre enn en feil under utvikling (tech-decisions.md, «Feil bruk\n * feiler høyt og tidlig»).\n */\nexport function useInnspel(): InnspelKontekst {\n const k = useContext(Kontekst);\n if (!k) {\n throw new Error(\n '[innspel] useInnspel() ble kalt utenfor <InnspelProvider>. Pakk appen din i den — se README.md.',\n );\n }\n return k;\n}\n","import type { MaskRect } from '@innspel/core';\nimport { createContext, useContext, type ComponentRef, type RefObject } from 'react';\nimport { Image, type View } from 'react-native';\n\n/** Host-elementet bak en `View` — det som kan måles og fanges. RN 0.87: `View` er en funksjonskomponent, så typen hentes herfra. */\nexport type ViewRef = ComponentRef<typeof View>;\n\n/**\n * Fangst av skjermbilde er det ene stedet widgeten trenger noe React Native\n * ikke har innebygd. Pakken tar INGEN avhengighet på det (K19, samme mønster som\n * `createStorage`): verten sender inn `captureRef` fra `react-native-view-shot`,\n * og uten adapter finnes ikke skjermbilde-steget (DD-26) — ikke som en grå\n * knapp, det finnes ikke.\n *\n * Alt som rører plattformen går gjennom adapteren, også måling og fillesing, så\n * widgeten kan testes med en fake og maskeringen bevises uten native kode.\n */\n\nexport interface ScreenshotCapture {\n /** Fil-URI fra fangsten. Forlater aldri enheten før den er maskert og rekomponert. */\n uri: string;\n /** Bitmapens størrelse i piksler. */\n width: number;\n height: number;\n}\n\nexport interface CaptureOptions {\n format: 'jpg' | 'png';\n /** 0–1, kun JPEG. */\n quality: number;\n}\n\nexport interface ScreenshotAdapter {\n /** Fanger viewen bak referansen til en fil. Kalles ved «Legg ved skjermbilde» (K4), og igjen på forhåndsvisningen for å rekomponere. */\n capture(ref: RefObject<ViewRef | null>, options: CaptureOptions): Promise<ScreenshotCapture>;\n /**\n * Velger et bilde fra enhetens bildebibliotek — «Velg bilde». `null` når innsenderen\n * avbryter. Uten metoden finnes ikke valget. Bildet går gjennom samme forhåndsvisning\n * og maskering, og det som lastes opp er komposittet fra `capture`, aldri fila.\n */\n pick?(): Promise<ScreenshotCapture | null>;\n /**\n * `false` fjerner «Legg ved skjermbilde» og lar bare «Velg bilde» stå — når skjermen\n * widgeten åpnes fra sjelden er der feilen er. `capture` trengs likevel til å\n * rekomponere forhåndsvisningen. Standard er `true`.\n */\n captureScreen?: boolean;\n /** Viewens rektangel i vinduskoordinater, i punkter. Null når den ikke er montert. */\n measure(ref: RefObject<ViewRef | null>): Promise<MaskRect | null>;\n /** Leser en fangst som Blob for opplasting. */\n read(uri: string): Promise<Blob>;\n}\n\n/** Signaturen til `captureRef` i react-native-view-shot — det eneste verten trenger å sende inn. */\nexport type CaptureRefFn = (\n ref: RefObject<ViewRef | null> | ViewRef,\n options: { format: 'jpg' | 'png'; quality: number; result: 'tmpfile' },\n) => Promise<string>;\n\n/**\n * Vertens bildevelger. Resultatet trenger bare `uri`; mangler størrelsen, måles den.\n * Returner `null` når innsenderen avbryter.\n *\n * @example\n * ```ts\n * import * as ImagePicker from 'expo-image-picker';\n * const pickImage: PickImageFn = async () => {\n * const r = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], exif: false });\n * return r.canceled ? null : { uri: r.assets[0]!.uri, width: r.assets[0]!.width, height: r.assets[0]!.height };\n * };\n * ```\n */\nexport type PickImageFn = () => Promise<{ uri: string; width?: number; height?: number } | null>;\n\n/**\n * Leietakerens setning ved bildesteget: én for begge spor, eller én per spor.\n * Et spor uten setning viser ingen.\n */\nexport type ImageStepNote = string | { feil?: string; onske?: string };\n\nexport interface ScreenshotAdapterOptions {\n /** Gir «Velg bilde». Pakken tar ingen avhengighet på en velger (K19). */\n pickImage?: PickImageFn;\n /** `false` fjerner «Legg ved skjermbilde». Standard er `true`. */\n captureScreen?: boolean;\n}\n\nfunction storrelse(uri: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => Image.getSize(uri, (w, h) => resolve({ width: w, height: h }), reject));\n}\n\n/**\n * Lager adapteren av vertens `captureRef`. Dimensjonene hentes med `Image.getSize`,\n * målingen med `measureInWindow`, og fila leses med `fetch(uri).blob()` — alt fra\n * React Native selv.\n *\n * @example\n * ```tsx\n * import { captureRef } from 'react-native-view-shot';\n * <InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef)}>\n * // Med bildevelger, og uten fangst av skjermen widgeten åpnes fra:\n * <InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef, { pickImage, captureScreen: false })}>\n * ```\n */\nexport function createScreenshotAdapter(captureRef: CaptureRefFn, options: ScreenshotAdapterOptions = {}): ScreenshotAdapter {\n const { pickImage, captureScreen } = options;\n return {\n async capture(ref, opts) {\n const uri = await captureRef(ref, { format: opts.format, quality: opts.quality, result: 'tmpfile' });\n return { uri, ...(await storrelse(uri)) };\n },\n ...(pickImage\n ? {\n async pick() {\n const valgt = await pickImage();\n if (!valgt) return null;\n const { width, height } = valgt.width && valgt.height ? { width: valgt.width, height: valgt.height } : await storrelse(valgt.uri);\n return { uri: valgt.uri, width, height };\n },\n }\n : {}),\n ...(captureScreen === false ? { captureScreen: false } : {}),\n measure(ref) {\n return new Promise((resolve) => {\n const view = ref.current;\n if (!view) return resolve(null);\n view.measureInWindow((x, y, width, height) => resolve({ x, y, width, height }));\n });\n },\n async read(uri) {\n const res = await fetch(uri);\n return res.blob();\n },\n };\n}\n\n/**\n * Private views (DD-39): det verten har merket med `<InnspelPrivate>`. Registeret\n * lever i provideren; widgeten måler hver av dem i fangstøyeblikket og legger en\n * maske brukeren ikke kan fjerne.\n */\nexport interface PrivateRegistry {\n register(ref: RefObject<ViewRef | null>): () => void;\n refs(): ReadonlyArray<RefObject<ViewRef | null>>;\n}\n\nexport function createPrivateRegistry(): PrivateRegistry {\n const alle = new Set<RefObject<ViewRef | null>>();\n return {\n register(ref) {\n alle.add(ref);\n return () => {\n alle.delete(ref);\n };\n },\n refs: () => [...alle],\n };\n}\n\nexport interface SkjermbildeKontekst {\n adapter: ScreenshotAdapter | null;\n /** Vertsappen — det som fanges. Modalen ligger utenfor og kommer aldri med. */\n rootRef: RefObject<ViewRef | null>;\n privat: PrivateRegistry;\n}\n\nexport const SkjermbildeContext = createContext<SkjermbildeKontekst | null>(null);\n\nexport function useSkjermbilde(): SkjermbildeKontekst | null {\n return useContext(SkjermbildeContext);\n}\n","import { createContext, useContext } from 'react';\nimport { light, t, type InnspelColors, type InnspelTheme } from './generated/tokens.js';\n\n/**\n * Widgeten lever INNE i vertsappen (DD-21) og skal arve dens flate. Verten\n * sender et delvis tema; alt den ikke sender faller tilbake på Innspels eget\n * (M0.4), som er generert fra `theme/theme.ts` og målt mot WCAG AA.\n *\n * Ingen hex-verdi, px-verdi eller fontstørrelse skrives i en komponent — alt\n * hentes herfra (CLAUDE.md, «Styling»). `fontFamily` finnes ikke: systemfonten\n * er standard i React Native, og å sette den ville brutt med vertsappen.\n */\n\n/**\n * De genererte tokenene er `as const`, så `t.touch` har typen `48` og ikke\n * `number`. Det er riktig for KILDEN — den skal ikke kunne endres ved et uhell\n * — men gjør temaet umulig å overstyre: verten ville måttet sende nøyaktig 48.\n * Denne typen åpner verdiene uten å åpne nøkkelsettet: en vert kan bytte en\n * farge, men ikke finne på en ny.\n */\nexport type Tema = Omit<\n InnspelTheme,\n 'color' | 'space' | 'radius' | 'font' | 'lineHeight' | 'motion' | 'touch' | 'screenPadding' | 'hairline'\n> & {\n color: Record<keyof InnspelColors, string>;\n space: Record<keyof InnspelTheme['space'], number>;\n radius: Record<keyof InnspelTheme['radius'], number>;\n font: Record<keyof InnspelTheme['font'], number>;\n lineHeight: Record<keyof InnspelTheme['lineHeight'], number>;\n motion: Record<keyof InnspelTheme['motion'], number>;\n touch: number;\n screenPadding: number;\n hairline: number;\n};\n\nexport type PartialTheme = {\n color?: Partial<Tema['color']>;\n} & Partial<Omit<Tema, 'color'>>;\n\n/**\n * Fletter vertens tokens over Innspels egne.\n *\n * @param vertens Delvis tema fra `<InnspelProvider theme={…}>`.\n * @param palett `dark` er standard: widgeten åpnes oftest over en app i mørk\n * modus, og et lyst ark over en mørk app blender.\n */\nexport function byggTema(vertens?: PartialTheme, palett: 'dark' | 'light' = 'dark'): Tema {\n const bunn = (palett === 'light' ? light : t) as unknown as Tema;\n if (!vertens) return bunn;\n\n return {\n ...bunn,\n ...vertens,\n color: { ...bunn.color, ...vertens.color },\n };\n}\n\nconst TemaContext = createContext<Tema>(t as unknown as Tema);\n\nexport const TemaProvider = TemaContext.Provider;\n\n/** Tokenene som gjelder her. Bruk ALDRI en literal farge eller avstand i stedet. */\nexport function useTema(): Tema {\n return useContext(TemaContext);\n}\n","/**\n * tokens.ts — GENERERT fra theme/theme.ts (avtrykk 6a743a62a4fd).\n * Rediger aldri denne filen. Endre temaet i kilden og kjør\n * `node scripts/generate-tokens.ts`, som CI verifiserer med `--check`.\n *\n * Tokenene @innspel/react-native faller tilbake på når verten ikke sender egne.\n * Widgeten lever inne i vertsappen og skal arve dens flate (DD-21); dette er\n * bunnen, ikke fasiten.\n *\n * 73 kontrastpar er målt mot WCAG AA i begge paletter, og generatoren\n * nekter å skrive hvis ett faller under kravet. Farge bærer aldri mening alene\n * — hver status har ikon og tekstetikett (DD-08).\n *\n * fontFamily finnes ikke her med vilje: systemfonten er standard i React\n * Native, og å sette den ville brutt med vertsappen.\n */\n\n/** Mørk palett — fallback når verten ikke sender egne tokens. */\nexport const t = {\n color: {\n bg: \"#111417\",\n surface: \"#1A1E22\",\n surfaceRaised: \"#232830\",\n border: \"#2E343B\",\n borderStrong: \"#3D444D\",\n borderInteractive: \"#7C8894\",\n textPrimary: \"#F2F4F6\",\n textSecondary: \"#B4BCC5\",\n textMuted: \"#8D96A1\",\n textDisabled: \"#5A626B\",\n actionPrimary: \"#5AD3E2\",\n onActionPrimary: \"#04252A\",\n actionSecondaryBorder: \"#7C8894\",\n actionSecondaryText: \"#F2F4F6\",\n brand: \"#5AD3E2\",\n onBrand: \"#04252A\",\n brandFill: \"#0E7C8C\",\n onBrandFill: \"#FFFFFF\",\n brandBg: \"#0C2A30\",\n danger: \"#FF7A8C\",\n dangerFill: \"#C4001F\",\n onDangerFill: \"#FFFFFF\",\n dangerBg: \"#2C1116\",\n success: \"#3ED88A\",\n onSuccess: \"#062015\",\n successBg: \"#0E2A1E\",\n warning: \"#FFC24D\",\n onWarning: \"#2A1C02\",\n warningBg: \"#2C2107\",\n info: \"#5CC0FF\",\n onInfo: \"#04222F\",\n infoBg: \"#0E2531\",\n neutral: \"#A3ACB6\",\n onNeutral: \"#111417\",\n neutralBg: \"#242A31\",\n scrim: \"rgba(0, 0, 0, 0.72)\",\n },\n space: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n xxl: 48,\n },\n radius: {\n sm: 6,\n md: 8,\n lg: 12,\n pill: 999,\n },\n font: {\n display: 40,\n h1: 24,\n h2: 21,\n h3: 18,\n body: 16,\n small: 13,\n tiny: 11,\n },\n lineHeight: {\n display: 48,\n h1: 30,\n h2: 27,\n h3: 24,\n body: 24,\n small: 18,\n tiny: 16,\n },\n weight: {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n },\n motion: {\n fast: 120,\n base: 200,\n slow: 320,\n },\n icon: { inline: 20, minste: 16 },\n touch: 48,\n screenPadding: 24,\n hairline: 1,\n} as const;\n\n/** Lys palett. */\nexport const light = {\n color: {\n bg: \"#F6F7F9\",\n surface: \"#FFFFFF\",\n surfaceRaised: \"#EDEFF3\",\n border: \"#D2D7DE\",\n borderStrong: \"#B9C0C9\",\n borderInteractive: \"#6F7883\",\n textPrimary: \"#14181D\",\n textSecondary: \"#454D57\",\n textMuted: \"#5C6470\",\n textDisabled: \"#9AA2AD\",\n actionPrimary: \"#0A6673\",\n onActionPrimary: \"#FFFFFF\",\n actionSecondaryBorder: \"#6F7883\",\n actionSecondaryText: \"#14181D\",\n brand: \"#0A6673\",\n onBrand: \"#FFFFFF\",\n brandFill: \"#0A6673\",\n onBrandFill: \"#FFFFFF\",\n brandBg: \"#E0F0F2\",\n danger: \"#B3001B\",\n dangerFill: \"#B3001B\",\n onDangerFill: \"#FFFFFF\",\n dangerBg: \"#FCE8EA\",\n success: \"#04693C\",\n onSuccess: \"#FFFFFF\",\n successBg: \"#E4F4EC\",\n warning: \"#7A5200\",\n onWarning: \"#FFFFFF\",\n warningBg: \"#FBF1DE\",\n info: \"#00588F\",\n onInfo: \"#FFFFFF\",\n infoBg: \"#E4F0F8\",\n neutral: \"#5C6470\",\n onNeutral: \"#FFFFFF\",\n neutralBg: \"#EEF0F3\",\n scrim: \"rgba(10, 14, 18, 0.45)\",\n },\n space: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n xxl: 48,\n },\n radius: {\n sm: 6,\n md: 8,\n lg: 12,\n pill: 999,\n },\n font: {\n display: 40,\n h1: 24,\n h2: 21,\n h3: 18,\n body: 16,\n small: 13,\n tiny: 11,\n },\n lineHeight: {\n display: 48,\n h1: 30,\n h2: 27,\n h3: 24,\n body: 24,\n small: 18,\n tiny: 16,\n },\n weight: {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n },\n motion: {\n fast: 120,\n base: 200,\n slow: 320,\n },\n icon: { inline: 20, minste: 16 },\n touch: 48,\n screenPadding: 24,\n hairline: 1,\n} as const;\n\n/** Innspillets statuser. `fg`/`bg` er TOKENNAVN og slås opp i den aktive paletten. Nøklene er Submissions.SubmissionStatus i contracts/. */\nexport const submissionStatus = {\n ny: {\n statusType: \"reviewing\",\n ikon: \"ellipse-outline\",\n etikett: { feil: \"Mottatt\", onske: \"Mottatt\" },\n lofte: { feil: \"Vi har fått den. Du hører fra oss.\", onske: \"Vi har fått den. Du hører fra oss.\" },\n fg: \"textSecondary\",\n bg: \"neutralBg\",\n variant: \"outline\",\n },\n vurderes: {\n statusType: \"reviewing\",\n ikon: \"hourglass-outline\",\n etikett: { feil: \"Vurderes\", onske: \"Vurderes\" },\n lofte: { feil: \"Svar innen {frist} — også hvis det er nei.\", onske: \"Svar innen {frist} — også hvis det er nei.\" },\n fg: \"info\",\n bg: \"infoBg\",\n variant: \"outline\",\n },\n planlagt: {\n statusType: \"active\",\n ikon: \"calendar-outline\",\n etikett: { feil: \"Planlagt\", onske: \"Planlagt\" },\n lofte: { feil: \"Du får beskjed når den er rettet.\", onske: \"Du får beskjed når det er levert.\" },\n fg: \"brand\",\n bg: \"brandBg\",\n variant: \"outline\",\n },\n bygges: {\n statusType: \"active\",\n ikon: \"construct-outline\",\n etikett: { feil: \"Retter nå\", onske: \"Bygger\" },\n lofte: { feil: \"Du får beskjed når den er rettet.\", onske: \"Du får beskjed når det er levert.\" },\n fg: \"brand\",\n bg: \"brandBg\",\n variant: \"filled\",\n },\n kjent_feil: {\n statusType: \"active\",\n ikon: \"warning-outline\",\n etikett: { feil: \"Kjent feil\", onske: \"Kjent feil\" },\n lofte: { feil: \"Kjent feil. Du får beskjed når den er rettet.\", onske: \"Kjent feil. Du får beskjed når den er rettet.\" },\n fg: \"warning\",\n bg: \"warningBg\",\n variant: \"outline\",\n },\n levert: {\n statusType: \"complete\",\n ikon: \"checkmark-circle-outline\",\n etikett: { feil: \"Rettet\", onske: \"Levert\" },\n lofte: { feil: \"Ferdig. Ser du feilen igjen, send et nytt innspill.\", onske: \"Ferdig. Takk for ønsket.\" },\n fg: \"success\",\n bg: \"successBg\",\n variant: \"outline\",\n },\n avvist: {\n statusType: \"closed\",\n ikon: \"close-circle-outline\",\n etikett: { feil: \"Avvist\", onske: \"Avvist\" },\n lofte: { feil: \"Vi har svart på denne.\", onske: \"Vi har svart på denne.\" },\n fg: \"danger\",\n bg: \"dangerBg\",\n variant: \"outline\",\n },\n duplikat: {\n statusType: \"closed\",\n ikon: \"git-merge-outline\",\n etikett: { feil: \"Slått sammen\", onske: \"Slått sammen\" },\n lofte: { feil: \"Slått sammen med et innspill som ligner.\", onske: \"Slått sammen med et innspill som ligner.\" },\n fg: \"neutral\",\n bg: \"neutralBg\",\n variant: \"outline\",\n },\n} as const;\n\n/** Programmets statuser. Nøklene er Programs.ProgramStatus i contracts/. */\nexport const programStatus = {\n utkast: {\n ikon: \"create-outline\",\n etikett: \"Utkast\",\n fg: \"textSecondary\",\n bg: \"neutralBg\",\n variant: \"dashed\",\n },\n aapen: {\n ikon: \"ellipse-outline\",\n etikett: \"Åpen — invitasjoner kan sendes\",\n fg: \"info\",\n bg: \"infoBg\",\n variant: \"outline\",\n },\n aktiv: {\n ikon: \"checkmark-circle-outline\",\n etikett: \"Aktiv\",\n fg: \"success\",\n bg: \"successBg\",\n variant: \"outline\",\n },\n avsluttes: {\n ikon: \"time-outline\",\n etikett: \"Avsluttes — oppfølginger går ut\",\n fg: \"warning\",\n bg: \"warningBg\",\n variant: \"outline\",\n },\n avsluttet: {\n ikon: \"checkmark-circle-outline\",\n etikett: \"Avsluttet — rapport fryst\",\n fg: \"neutral\",\n bg: \"neutralBg\",\n variant: \"outline\",\n },\n avbrutt: {\n ikon: \"close-circle\",\n etikett: \"Avbrutt\",\n fg: \"dangerFill\",\n bg: \"onDangerFill\",\n variant: \"filled\",\n },\n} as const;\n\n/** Kjent feil-statusene (M2.4). Nøklene er KnownIssues.KnownIssueStatus i contracts/; «fikset» heter «Rettet» (DD-22). */\nexport const knownIssueStatus = {\n aktiv: {\n ikon: \"warning-outline\",\n etikett: \"Aktiv\",\n fg: \"warning\",\n bg: \"warningBg\",\n variant: \"outline\",\n },\n fikset: {\n ikon: \"checkmark-circle-outline\",\n etikett: \"Rettet\",\n fg: \"success\",\n bg: \"successBg\",\n variant: \"dashed\",\n },\n} as const;\n\n/** Løftet for `vurderes` uten frist: svaret loves, tidspunktet ikke (DD-07, DD-28). */\nexport const lofteUtenFrist = \"Du får svar — også hvis det er nei.\";\n\n/** Skjermbilde-maskering. Faste signalfarger, uavhengig av palett (DD-39, DD-40). Vedlegg er M1.3. */\nexport const screenRules = {\n brushFill: \"#E5007D\",\n autoMaskFill: \"#101114\",\n autoMaskStroke: \"#E5007D\",\n autoMaskText: \"#FFFFFF\",\n previewBackdrop: \"#000000\",\n qrBackdrop: \"#FFFFFF\",\n brushWidth: 28,\n textBlurRadius: 24,\n} as const;\n\n/** Formen widgeten tar imot. Verten sender et delvis tema; resten faller tilbake hit. */\nexport type InnspelTheme = typeof t;\nexport type InnspelColors = InnspelTheme['color'];\n","import {\n InnspelApiError,\n InnspelQueueFullError,\n type AttachmentInput,\n type InnspelClient,\n type KnownIssueCard,\n type MaskRect,\n type MySubmission,\n type OpenFeedbackOptions,\n type PatternFinding,\n} from '@innspel/core';\nimport React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { KeyboardAvoidingView, Modal, Pressable, View } from 'react-native';\nimport { initialWindowMetrics, SafeAreaInsetsContext } from 'react-native-safe-area-context';\nimport { Ikon } from '../Ikon.js';\nimport { useSkjermbilde, type ImageStepNote, type ScreenshotCapture, type ViewRef } from '../skjermbilde.js';\nimport { useTema } from '../tema.js';\nimport { Felt } from './Felt.js';\nimport { Valg } from './Valg.js';\nimport { KjenteFeil } from './KjenteFeil.js';\nimport { Kvittering, type KvitteringArt } from './Kvittering.js';\nimport { MineInnspill } from './MineInnspill.js';\nimport { Skjermbilde } from './Skjermbilde.js';\nimport { Banner, Btn } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\nexport type Steg = 'valg' | 'kjenteFeil' | 'felt' | 'skjermbilde' | 'kvittering' | 'mine';\n\n/**\n * Det verten får vite når et innspill er sendt (F26). Sakens nummer, aldri innsenderens\n * identitet — nummeret er det hun alt ser i kvitteringen. `queued` når nettet var borte\n * og innspillet ligger i køen: hun trykket Send, og det teller. «Ja, jeg også» på en kjent\n * feil gir ikke dette kallet — det er Reach, ikke en ny sak.\n */\nexport interface SubmittedInfo {\n type: 'feil' | 'onske';\n queued: boolean;\n /** Finnes når saken er opprettet hos tjeneren; mangler i køen. */\n id?: string;\n}\n\n/** JPEG med denne kvaliteten holder et 3×-skjermbilde godt under 5 MB (K9) og gjør uskarphet irreversibel i praksis. */\nconst FANGST = { format: 'jpg', quality: 0.85 } as const;\n\n/**\n * Widgeten. Ett ark over vertsappen — aldri en flytende knapp over innhold\n * (DD-21).\n *\n * **DD-47, og hvorfor det står her og ikke i en TODO:** arket er en dialog og\n * oppfører seg som en. `<Modal>` gir fokusfellen; `onRequestClose` er\n * Android-tilbake og ESC på tastatur; `accessibilityViewIsModal` skjuler\n * vertsappen for skjermlesere på iOS; kvitteringen er en live-region. Sentrys\n * crash-modal mangler alle fire (issue #23288, #9291) — den er leverandøren som\n * dokumenterer både løsningen og mangelen.\n *\n * **Flyten er ikke symmetrisk.** Feilsporet møter kjente feil FØR feltet: den\n * som står i en feil skal slippe å skrive noe hvis svaret allerede finnes.\n * Ønskesporet møter dem ETTER: et ønske må formuleres før det kan sammenlignes.\n *\n * **Skjermbildet (2f, K4):** tas først når innsenderen trykker, aldri ved åpning.\n * Steget finnes bare når leietakeren har skjermbilde på OG verten har gitt en\n * adapter (DD-26). Private views måles i fangstøyeblikket (DD-39). Det som\n * lastes opp er komposittet av forhåndsvisningen med maskene — rå-URI-en går\n * aldri videre. Teksten sendes først; bildet kan feile alene (DD-42).\n */\nexport function Widget({\n client,\n synlig,\n apneOpsjoner,\n onLukk,\n tenantName,\n imageStepNote,\n onSubmitted,\n}: {\n client: InnspelClient;\n synlig: boolean;\n apneOpsjoner?: OpenFeedbackOptions;\n onLukk: () => void;\n tenantName?: string;\n imageStepNote?: ImageStepNote;\n /** F26: kalles etter en innsending — sendt eller køet. Aldri for «ja, jeg også». */\n onSubmitted?: (info: SubmittedInfo) => void;\n}) {\n const tema = useTema();\n // Edge-to-edge (Android 15+, Expo SDK 53+): Modal tegner under status- og\n // navigasjonslinja uansett props. Insets fra vertens SafeAreaProvider, ellers\n // vinduets fra oppstart; useSafeAreaInsets ville kastet uten provider.\n const insets = useContext(SafeAreaInsetsContext) ?? initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };\n const skjermbilde = useSkjermbilde();\n const previewRef = useRef<ViewRef | null>(null);\n\n const [steg, setSteg] = useState<Steg>('valg');\n const [spor, setSpor] = useState<'feil' | 'onske'>('feil');\n const [verdi, setVerdi] = useState('');\n const [kort, setKort] = useState<KnownIssueCard[]>([]);\n const [lasterKort, setLasterKort] = useState(false);\n const [lenketTil, setLenketTil] = useState<KnownIssueCard | undefined>();\n const [funn, setFunn] = useState<PatternFinding[]>([]);\n const [fjernede, setFjernede] = useState<string[]>([]);\n const [sender, setSender] = useState(false);\n const online = useNettstatus(client);\n const [feil, setFeil] = useState<string | undefined>();\n const [kvittering, setKvittering] = useState<{ art: KvitteringArt; nr?: string; vedlegg?: 'feilet' | 'forkastet'; frist?: string }>();\n const [mine, setMine] = useState<MySubmission[]>([]);\n const [lasterMine, setLasterMine] = useState(false);\n\n // Skjermbildet: rå fangst til forhåndsvisning, private views i rotens punkter,\n // og det ferdige, maskerte vedlegget som sendes med teksten.\n const [bilde, setBilde] = useState<ScreenshotCapture | undefined>();\n const [automasker, setAutomasker] = useState<MaskRect[]>([]);\n const [rotStorrelse, setRotStorrelse] = useState({ width: 1, height: 1 });\n const [komponerer, setKomponerer] = useState(false);\n const [kilde, setKilde] = useState<'skjerm' | 'galleri'>('skjerm');\n const [vedlegg, setVedlegg] = useState<AttachmentInput | undefined>();\n\n // Leietakerens grenser: startverdiene fra init(), oppdatert fra plattformen ved åpning (M2.5).\n const [innstillinger, setInnstillinger] = useState({ ...client.settings });\n\n // DD-26: steget finnes ikke uten begge. Aldri en deaktivert knapp.\n const skjermbildeMulig = innstillinger.screenshotsEnabled && skjermbilde?.adapter != null;\n const fangstMulig = skjermbildeMulig && skjermbilde?.adapter?.captureScreen !== false;\n const galleriMulig = skjermbildeMulig && typeof skjermbilde?.adapter?.pick === 'function';\n // Vertens setning for sporet innsenderen står i.\n const bildeNotat = typeof imageStepNote === 'string' ? imageStepNote : imageStepNote?.[spor];\n\n const nullstill = useCallback(() => {\n setSteg('valg');\n setSpor('feil');\n setVerdi('');\n setKort([]);\n setLenketTil(undefined);\n setFunn([]);\n setFjernede([]);\n setFeil(undefined);\n setKvittering(undefined);\n setBilde(undefined);\n setAutomasker([]);\n setVedlegg(undefined);\n setKomponerer(false);\n }, []);\n\n // «Mine innspill» åpnet av verten (`view: 'mine'`) er en visning OVER det innsenderen\n // holdt på, ikke et steg i skjemaet (F3). `stegForMine` er steget under — det lukking\n // og «Tilbake» fører tilbake til, så et utkast i feltet står der ved neste åpning.\n const [mineDirekte, setMineDirekte] = useState(false);\n const [stegForMine, setStegForMine] = useState<Steg>('valg');\n const stegRef = useRef(steg);\n stegRef.current = steg;\n\n /** Noe innsenderen har laget og ikke sendt. Det vinner over vertens `track` (F1). */\n const harUtkast = verdi.trim().length > 0 || vedlegg !== undefined;\n\n /**\n * Lukking beholder spor, steg og tekst (F1, samme modell som `@innspel/web`). Fram til\n * 2026-09-15 nullstilte den, og Android-tilbake kastet teksten på ett trykk.\n */\n const lukk = useCallback(() => {\n onLukk();\n if (stegRef.current === 'mine' && mineDirekte) {\n setSteg(stegForMine);\n setMineDirekte(false);\n }\n }, [onLukk, mineDirekte, stegForMine]);\n\n /** Kvitteringen er det ene stedet som nullstiller — der er innspillet sendt. */\n const lukkOgNullstill = useCallback(() => {\n onLukk();\n nullstill();\n setMineDirekte(false);\n setStegForMine('valg');\n }, [onLukk, nullstill]);\n\n // Køen tømmes når widgeten ÅPNES — aldri ved oppstart (DD-41). Resultatet\n // vises ikke: en flush som lykkes er ikke en hendelse innsenderen ba om.\n useEffect(() => {\n if (!synlig) return;\n client.track({ name: 'widget_opened' });\n void client.queue.flush().catch(() => undefined);\n // Konfigurasjonen er et tilbud: svarer den, oppdateres grensene; ellers står de.\n void client.loadSettings().then((s) => setInnstillinger({ ...s })).catch(() => undefined);\n\n // «Mine innspill» (DD-62): tellingen på knappen hentes ved åpning, stille — feiler\n // kallet, står knappen uten tall. Anonym modus har ingen liste og kalles aldri.\n if (!client.isAnonymous) {\n void client.subjects\n .submissions()\n .then(setMine)\n .catch(() => undefined);\n }\n\n // Et utkast vinner over vertens `track`: å bytte spor under en skrevet tekst ville\n // sendt en feil som ønske. «Mine innspill» legges over utkastet og tar det ikke bort.\n if (apneOpsjoner?.view === 'mine' && !client.isAnonymous) void visMine(true);\n else if (apneOpsjoner?.track && !harUtkast) void velgSpor(apneOpsjoner.track);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [synlig]);\n\n const hentKort = useCallback(async () => {\n setLasterKort(true);\n try {\n const q = apneOpsjoner?.screen ? { screen: apneOpsjoner.screen } : {};\n setKort(await client.knownIssues.for(q));\n } finally {\n setLasterKort(false);\n }\n }, [client, apneOpsjoner?.screen]);\n\n const velgSpor = useCallback(\n async (valgt: 'feil' | 'onske') => {\n setSpor(valgt);\n client.track({ name: 'track_selected', type: valgt });\n\n if (valgt === 'onske') {\n // Ønskesporet skriver først; sammenligningen kommer etterpå.\n setSteg('felt');\n return;\n }\n\n setSteg('kjenteFeil');\n await hentKort();\n },\n [client, hentKort],\n );\n\n // Treffene er et tilbud, aldri en sperre (wireframe 2c): er lista tom når\n // oppslaget er ferdig, hoppes skjermen over — rett til feltet, ingen melding.\n useEffect(() => {\n if (steg === 'kjenteFeil' && !lasterKort && kort.length === 0) setSteg('felt');\n }, [steg, lasterKort, kort.length]);\n\n const endreTekst = useCallback(\n (v: string) => {\n setVerdi(v);\n setFunn(client.scanText(v));\n },\n [client],\n );\n\n /**\n * «Legg ved skjermbilde» (K4): fangsten skjer HER, ved trykket, av vertsappen\n * bak arket. Private views måles i samme øyeblikk (DD-39) og regnes om til\n * rotens punkter. Feiler fangsten, kan innsenderen sende uten.\n */\n const taSkjermbilde = useCallback(async () => {\n if (!skjermbilde?.adapter) return;\n const { adapter, rootRef, privat } = skjermbilde;\n setFeil(undefined);\n try {\n const fangst = await adapter.capture(rootRef, FANGST);\n const rot = await adapter.measure(rootRef);\n const private_ = await Promise.all(privat.refs().map((r) => adapter.measure(r)));\n if (rot) {\n setRotStorrelse({ width: rot.width, height: rot.height });\n setAutomasker(\n private_\n .filter((r): r is MaskRect => r !== null)\n .map((r) => ({ x: r.x - rot.x, y: r.y - rot.y, width: r.width, height: r.height })),\n );\n } else {\n setRotStorrelse({ width: fangst.width, height: fangst.height });\n setAutomasker([]);\n }\n setBilde(fangst);\n setKilde('skjerm');\n setSteg('skjermbilde');\n } catch {\n setFeil(tekst.skjermbildeFeilet);\n }\n }, [skjermbilde]);\n\n /**\n * «Velg bilde»: vertens velger, ved trykket. Ingen private views — de hører til\n * skjermen bak arket, ikke til et bilde fra et annet sted — og rot-viewen fanges\n * aldri. Avbryter innsenderen, skjer ingenting.\n */\n const velgBilde = useCallback(async () => {\n const pick = skjermbilde?.adapter?.pick;\n if (!pick) return;\n setFeil(undefined);\n try {\n const valgt = await pick.call(skjermbilde.adapter);\n if (!valgt) return;\n setRotStorrelse({ width: valgt.width, height: valgt.height });\n setAutomasker([]);\n setBilde(valgt);\n setKilde('galleri');\n setSteg('skjermbilde');\n } catch {\n setFeil(tekst.bildeFeilet);\n }\n }, [skjermbilde]);\n\n /**\n * «Legg ved og fortsett»: forhåndsvisningen MED maskene fanges på nytt, og det\n * er komposittet som blir vedlegget. Rå-URI-en brukes aldri etter dette.\n */\n const leggVedBilde = useCallback(async () => {\n if (!skjermbilde?.adapter) return;\n setKomponerer(true);\n try {\n const komposit = await skjermbilde.adapter.capture(previewRef, FANGST);\n const body = await skjermbilde.adapter.read(komposit.uri);\n setVedlegg({ mime: 'image/jpeg', body, width: komposit.width, height: komposit.height });\n setBilde(undefined);\n setSteg('felt');\n } catch {\n setFeil(tekst.skjermbildeFeilet);\n setSteg('felt');\n } finally {\n setKomponerer(false);\n }\n }, [skjermbilde]);\n\n const fjernBilde = useCallback(() => {\n setBilde(undefined);\n setAutomasker([]);\n setVedlegg(undefined);\n setSteg('felt');\n }, []);\n\n /**\n * Ett steg tilbake, ALDRI en nullstilling (UX-gjennomgangen C1). Fra feltet er\n * forrige steg kjente feil i feilsporet når det fantes treff — ellers valget.\n * Fram til 2026-09-14 kalte «Tilbake» `nullstill`, og 120 tegn forsvant på ett\n * trykk.\n */\n const gaaTilbake = useCallback(() => {\n setFeil(undefined);\n // F3: åpnet verten lista direkte, finnes det ikke noe forrige steg i widgeten.\n if (steg === 'mine') {\n if (mineDirekte) lukk();\n else setSteg('valg');\n return;\n }\n if (steg === 'skjermbilde') {\n setBilde(undefined);\n setAutomasker([]);\n setSteg('felt');\n return;\n }\n if (steg === 'felt' && spor === 'feil' && kort.length > 0) {\n setSteg('kjenteFeil');\n return;\n }\n setSteg('valg');\n }, [steg, spor, kort.length, mineDirekte, lukk]);\n\n /**\n * Android-tilbake og ESC (`onRequestClose`). Er det et forrige steg, er det «Tilbake»;\n * på første steg lukker den; på kvitteringen er innspillet sendt, og den nullstiller.\n */\n const androidTilbake = useCallback(() => {\n if (steg === 'valg') lukk();\n else if (steg === 'kvittering') lukkOgNullstill();\n else gaaTilbake();\n }, [steg, lukk, lukkOgNullstill, gaaTilbake]);\n\n const send = useCallback(async () => {\n // Ønskesporet sendes rett fra feltet: kontrakten har ingen ønskekort, og steget\n // «Har noen ønsket dette?» kommer tilbake når den har det (DD-03, presisert\n // 2026-09-14 — fram til da gikk Send i ring uten treff).\n setSender(true);\n setFeil(undefined);\n try {\n const res = await client.capture({\n type: spor,\n text: verdi,\n ...(vedlegg ? { attachment: vedlegg } : {}),\n ...(spor === 'feil' && lenketTil ? { relatedKnownIssueId: lenketTil.id } : {}),\n context: fjernetKontekst(client, fjernede, apneOpsjoner?.screen),\n } as never);\n\n if (res.status === 'queued') {\n setKvittering({ art: 'kø', ...(res.attachment ? { vedlegg: 'forkastet' as const } : {}) });\n } else {\n setKvittering({\n art: spor,\n nr: res.submission.id,\n // Tidsløftet i kvitteringen er DATOEN fra svaret, aldri «innen 90 dager» (DD-07, DD-28).\n ...(res.submission.deadlineAt ? { frist: res.submission.deadlineAt } : {}),\n ...(res.attachment?.status === 'failed' ? { vedlegg: 'feilet' as const } : {}),\n });\n }\n setSteg('kvittering');\n // F26: verten får vite at det skjedde — etter kvitteringen, så et kast i vertens\n // kode aldri kan holde innsenderen fra å se at innspillet gikk.\n onSubmitted?.(res.status === 'queued' ? { type: spor, queued: true } : { type: spor, queued: false, id: res.submission.id });\n } catch (e) {\n // Teksten mistes ALDRI: den står i feltet, og årsaken er i klartekst.\n if (e instanceof InnspelQueueFullError) setFeil(e.userMessage);\n else if (e instanceof InnspelApiError) setFeil(e.message);\n else setFeil('tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n }, [client, spor, verdi, vedlegg, lenketTil, fjernede, apneOpsjoner?.screen, onSubmitted]);\n\n const jaOgsa = useCallback(\n async (k: KnownIssueCard) => {\n setSender(true);\n try {\n const res = await client.knownIssues.confirm(k.id);\n setKvittering({ art: 'jaOgsa', nr: res.id });\n setSteg('kvittering');\n } catch (e) {\n setFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n },\n [client],\n );\n\n /** `direkte`: verten åpnet lista (`view: 'mine'`). Ellers kom innsenderen via knappen på valget. */\n const visMine = useCallback(async (direkte = false) => {\n if (direkte) {\n if (stegRef.current !== 'mine') setStegForMine(stegRef.current);\n } else {\n setStegForMine('valg');\n }\n setMineDirekte(direkte);\n setSteg('mine');\n setLasterMine(true);\n try {\n setMine(await client.subjects.submissions());\n } catch {\n setMine([]);\n } finally {\n setLasterMine(false);\n }\n }, [client]);\n\n /** «Send nytt innspill» i lista: til utkastet om det finnes, ellers et nytt skjema. */\n const nyttFraMine = useCallback(() => {\n setMineDirekte(false);\n if (harUtkast) setSteg(stegForMine);\n else nullstill();\n }, [harUtkast, stegForMine, nullstill]);\n\n return (\n <Modal\n visible={synlig}\n transparent\n animationType=\"slide\"\n // Android-tilbake og ESC. Uten den er dialogen en felle (DD-47); med `lukk` direkte\n // kastet den teksten (F1). Den er «Tilbake» så lenge det finnes et forrige steg.\n onRequestClose={androidTilbake}\n accessibilityViewIsModal\n >\n {/* Vinduet krymper ikke lenger for tastaturet på edge-to-edge, så arket løftes\n her. Offseten trekker fra navigasjonslinja: arket har den alt som padding,\n og tastaturet dekker den. */}\n <KeyboardAvoidingView\n behavior=\"padding\"\n keyboardVerticalOffset={-insets.bottom}\n style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end', paddingTop: insets.top }}\n >\n <View\n testID=\"innspel-widget\"\n accessibilityViewIsModal\n accessibilityRole=\"none\"\n style={{\n backgroundColor: tema.color.bg,\n borderTopLeftRadius: tema.radius.lg * 2,\n borderTopRightRadius: tema.radius.lg * 2,\n padding: tema.screenPadding,\n paddingBottom: tema.screenPadding + insets.bottom,\n paddingLeft: tema.screenPadding + insets.left,\n paddingRight: tema.screenPadding + insets.right,\n gap: tema.space.md,\n maxHeight: '92%',\n minHeight: '60%',\n // Bildesteget får fast høyde: forhåndsvisningen tilpasses plassen som er igjen, og\n // uten en kjent høyde har den ingen øvre grense (se Skjermbilde.tsx).\n ...(steg === 'skjermbilde' ? { height: '92%' as const } : {}),\n }}\n >\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>\n {steg !== 'valg' && steg !== 'kvittering' ? (\n <Btn variant=\"ghost\" testID=\"tilbake\" ikon=\"arrow-back-outline\" label={tekst.tilbake} onPress={gaaTilbake} />\n ) : (\n <View />\n )}\n <Pressable\n testID=\"lukk\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.lukk}\n onPress={steg === 'kvittering' ? lukkOgNullstill : lukk}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n\n {feil ? <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.sendefeilBanner(feil)} /> : null}\n {/* `cloud-offline-outline` er samme ikon portalens offline-banner bruker. */}\n {!online && steg !== 'kvittering' && steg !== 'mine' ? (\n <Banner ikon=\"cloud-offline-outline\" tone=\"info\" testID=\"offline-banner\" children={tekst.offlineBanner} />\n ) : null}\n\n {steg === 'valg' ? (\n <>\n <Valg onVelg={velgSpor} />\n {/* DD-62: med innspill fra før er dette en inngang på linje med sporene — flate og telling; uten står den dempet. Anonym: ingen liste, ingen knapp (DD-02). */}\n {!client.isAnonymous ? (\n <Btn\n variant={mine.length > 0 ? 'secondary' : 'ghost'}\n testID=\"mine-innspill\"\n ikon=\"list-outline\"\n label={mine.length > 0 ? tekst.mineMedAntall(mine.length) : tekst.mineTittel}\n accessibilityLabel={mine.length > 0 ? tekst.mineEtikett(mine.length) : tekst.mineTittel}\n onPress={() => void visMine()}\n />\n ) : null}\n </>\n ) : null}\n\n {steg === 'kjenteFeil' ? (\n <KjenteFeil\n kort={kort}\n spor={spor}\n laster={lasterKort}\n sender={sender}\n onJaOgsa={jaOgsa}\n onLigner={(k) => {\n setLenketTil(k);\n setSteg('felt');\n }}\n onNei={() => setSteg('felt')}\n />\n ) : null}\n\n {steg === 'felt' ? (\n <Felt\n spor={spor}\n verdi={verdi}\n onEndre={endreTekst}\n minTextLength={innstillinger.minTextLength}\n textMaxLength={innstillinger.textMaxLength}\n // Åpningsskjermen står i lista innsenderen ser, ikke bare i det som sendes:\n // det hun ikke ser, kan hun ikke fjerne (DD-05, K5). Web-widgeten gjør det\n // samme — RN sendte den ikke i det hele tatt før F23.\n kontekst={{ ...client.context, ...(apneOpsjoner?.screen ? { screen: apneOpsjoner.screen } : {}) }}\n fjernedeFelter={fjernede}\n onFjernKontekst={(f) => setFjernede((x) => [...x, f])}\n {...(lenketTil ? { lenketTil, onFjernLenke: () => setLenketTil(undefined) } : {})}\n funn={funn}\n onSend={send}\n sender={sender}\n harFeil={feil !== undefined}\n offline={!online}\n {...(fangstMulig ? { onSkjermbilde: taSkjermbilde } : {})}\n {...(galleriMulig ? { onVelgBilde: velgBilde } : {})}\n {...(bildeNotat ? { bildeNotat } : {})}\n harVedlegg={vedlegg !== undefined}\n onFjernVedlegg={fjernBilde}\n />\n ) : null}\n\n {steg === 'skjermbilde' && bilde ? (\n <Skjermbilde\n bilde={bilde}\n automaskerRot={automasker}\n rotStorrelse={rotStorrelse}\n previewRef={previewRef}\n komponerer={komponerer}\n kilde={kilde}\n {...(bildeNotat ? { notat: bildeNotat } : {})}\n onFjern={fjernBilde}\n onLeggVed={leggVedBilde}\n />\n ) : null}\n\n {steg === 'kvittering' && kvittering ? (\n <Kvittering\n art={kvittering.art}\n {...(kvittering.nr ? { saksnummer: kvittering.nr } : {})}\n {...(kvittering.vedlegg ? { vedlegg: kvittering.vedlegg } : {})}\n {...(kvittering.frist ? { frist: kvittering.frist } : {})}\n onLukk={lukkOgNullstill}\n />\n ) : null}\n\n {steg === 'mine' ? (\n <MineInnspill\n storage={client.storage}\n rader={mine}\n laster={lasterMine}\n {...(tenantName ? { tenantName } : {})}\n onNytt={nyttFraMine}\n />\n ) : null}\n </View>\n </KeyboardAvoidingView>\n </Modal>\n );\n}\n\n/**\n * Konteksten uten linjene innsenderen har fjernet (DD-05). Et fjernet felt\n * settes til `undefined` — det er slik kjernen (0.2.1) skiller «fjern» fra\n * «behold fra init»; å bare utelate nøkkelen ville fylt feltet igjen. Feltene\n * er en lukket hviteliste, så det som ikke står i `client.context` finnes ikke\n * å fjerne.\n */\n/**\n * Nettstatus fra verten (`init({ connectivity })`). Uten den er svaret alltid «på nett»:\n * widgeten vet da om nettet først når et kall feiler, og køen tar over (DD-41).\n */\nfunction useNettstatus(client: InnspelClient): boolean {\n const c = client.connectivity;\n const [online, setOnline] = useState(() => c?.isOnline() ?? true);\n useEffect(() => {\n if (!c) return undefined;\n setOnline(c.isOnline());\n return c.subscribe?.((v) => setOnline(v));\n }, [c]);\n return online;\n}\n\n/**\n * Konteksten som sendes med innsendingen: skjermen verten åpnet med, minus det innsenderen\n * har fjernet. Samme form som web-widgeten (F23) — skjermen lå bare i kjente feil-oppslaget\n * her, så panelet fikk «Skjerm —» på hver sak fra appen.\n *\n * `screen` står FØR fjern-logikken med vilje: en fjernet skjermlinje skal bli borte selv om\n * verten åpnet med et skjermnavn (DD-05). Åpningsskjermen er ikke et smutthull.\n */\nfunction fjernetKontekst(client: InnspelClient, fjernede: string[], skjerm: string | undefined) {\n const ut: Record<string, unknown> = {};\n if (skjerm) ut['screen'] = skjerm;\n for (const k of [...Object.keys(client.context), 'screen']) {\n if (k !== 'sdkVersion' && fjernede.includes(k)) ut[k] = undefined;\n }\n return ut;\n}\n","import React from 'react';\nimport { SvgXml } from 'react-native-svg';\nimport { useTema } from './tema.js';\n\nimport arrowBackOutline from '../../../node_modules/ionicons/dist/svg/arrow-back-outline.svg';\nimport brushOutline from '../../../node_modules/ionicons/dist/svg/brush-outline.svg';\nimport bug from '../../../node_modules/ionicons/dist/svg/bug.svg';\nimport bugOutline from '../../../node_modules/ionicons/dist/svg/bug-outline.svg';\nimport bulb from '../../../node_modules/ionicons/dist/svg/bulb.svg';\nimport calendarOutline from '../../../node_modules/ionicons/dist/svg/calendar-outline.svg';\nimport cameraOutline from '../../../node_modules/ionicons/dist/svg/camera-outline.svg';\nimport checkmarkCircleOutline from '../../../node_modules/ionicons/dist/svg/checkmark-circle-outline.svg';\nimport chevronDownOutline from '../../../node_modules/ionicons/dist/svg/chevron-down-outline.svg';\nimport chevronUpOutline from '../../../node_modules/ionicons/dist/svg/chevron-up-outline.svg';\nimport closeCircleOutline from '../../../node_modules/ionicons/dist/svg/close-circle-outline.svg';\nimport closeOutline from '../../../node_modules/ionicons/dist/svg/close-outline.svg';\nimport cloudOfflineOutline from '../../../node_modules/ionicons/dist/svg/cloud-offline-outline.svg';\nimport constructOutline from '../../../node_modules/ionicons/dist/svg/construct-outline.svg';\nimport contrastOutline from '../../../node_modules/ionicons/dist/svg/contrast-outline.svg';\nimport ellipseOutline from '../../../node_modules/ionicons/dist/svg/ellipse-outline.svg';\nimport exitOutline from '../../../node_modules/ionicons/dist/svg/exit-outline.svg';\nimport flaskOutline from '../../../node_modules/ionicons/dist/svg/flask-outline.svg';\nimport gridOutline from '../../../node_modules/ionicons/dist/svg/grid-outline.svg';\nimport hourglassOutline from '../../../node_modules/ionicons/dist/svg/hourglass-outline.svg';\nimport imageOutline from '../../../node_modules/ionicons/dist/svg/image-outline.svg';\nimport imagesOutline from '../../../node_modules/ionicons/dist/svg/images-outline.svg';\nimport listOutline from '../../../node_modules/ionicons/dist/svg/list-outline.svg';\nimport lockClosedOutline from '../../../node_modules/ionicons/dist/svg/lock-closed-outline.svg';\nimport mergeOutline from '../../../node_modules/ionicons/dist/svg/git-merge-outline.svg';\nimport openOutline from '../../../node_modules/ionicons/dist/svg/open-outline.svg';\nimport scanOutline from '../../../node_modules/ionicons/dist/svg/scan-outline.svg';\nimport swapVerticalOutline from '../../../node_modules/ionicons/dist/svg/swap-vertical-outline.svg';\nimport trashOutline from '../../../node_modules/ionicons/dist/svg/trash-outline.svg';\nimport warningOutline from '../../../node_modules/ionicons/dist/svg/warning-outline.svg';\n\n/**\n * Ionicons som inline SVG i React Native. «Emoji brukes aldri i\n * implementasjonen» (brand-ui-guidelines): en emoji tegnes av operativsystemet\n * i sine egne faste farger — den følger verken vertens palett eller temaets\n * ikonmål, den ser ulik ut på iOS og Android, og 🐞 leses opp som «marihøne».\n *\n * Navnene er de SAMME som i `submissionStatus`/`knownIssueStatus` i\n * `theme/theme.ts` (gjennom `src/generated/tokens.ts`), i ikonkartene i\n * `design/wireframes/innsending-widget.jsx` og `betaprogram-tester.jsx`, og i\n * `portal/src/lib/Ikon.tsx` og `panel/src/status/Ikon.tsx` — ett ikonkart for\n * hele produktet, tre rendrere.\n *\n * Stiene går via `node_modules` fordi ioniconss `exports` ikke eksponerer\n * SVG-filene. Strengene INLINES ved bygg av esbuild-lasteren `.svg: text` i\n * `tsup.config.ts`, så pakken får ingen runtime-avhengighet av `ionicons` —\n * bare av `react-native-svg`, som er en peer.\n *\n * **Importen er statisk og uten `try`.** Mangler verten `react-native-svg`,\n * feiler Metro ved bygg med navnet på pakken. Det er riktig sted: et manglende\n * peer skal stoppe bygget, ikke bli til et usynlig ikon i en widget som er i\n * drift. Se «`react-native-svg` som peer i @innspel/react-native» i\n * `docs/tech-decisions.md`.\n */\n\n/**\n * En `<title>` i en SVG leses opp — «Bug» foran teksten — og ikonet er\n * dekorativt: teksten ved siden av bærer meningen (DD-08). Samme stripping som\n * `portal/src/lib/Ikon.tsx` og `panel/src/status/Ikon.tsx`.\n *\n * Ionicons 8.1.0 leverer ingen titler (målt: 0 av 1357 filer), så steget er\n * forebyggende — det finnes fordi en oppgradering som legger dem tilbake ellers\n * ville endret opplesningsrekkefølgen i widgeten uten at noe ble rødt.\n * Eksportert for at testen skal kunne bevise at det faktisk fjerner noe.\n */\nexport const utenTittel = (svg: string) => svg.replace(/<title>[\\s\\S]*?<\\/title>/g, '');\n\nconst IKONER: Record<string, string> = Object.fromEntries(\n Object.entries({\n 'arrow-back-outline': arrowBackOutline,\n 'brush-outline': brushOutline,\n // Fylte varianter: bare på sporvalgets to kort (DD-63), der ikonet bærer stemningen.\n bug,\n bulb,\n 'bug-outline': bugOutline,\n 'calendar-outline': calendarOutline,\n 'camera-outline': cameraOutline,\n 'checkmark-circle-outline': checkmarkCircleOutline,\n 'chevron-down-outline': chevronDownOutline,\n 'chevron-up-outline': chevronUpOutline,\n 'close-circle-outline': closeCircleOutline,\n 'close-outline': closeOutline,\n 'cloud-offline-outline': cloudOfflineOutline,\n 'construct-outline': constructOutline,\n 'contrast-outline': contrastOutline,\n 'ellipse-outline': ellipseOutline,\n 'exit-outline': exitOutline,\n 'flask-outline': flaskOutline,\n 'git-merge-outline': mergeOutline,\n 'grid-outline': gridOutline,\n 'hourglass-outline': hourglassOutline,\n 'image-outline': imageOutline,\n 'images-outline': imagesOutline,\n 'list-outline': listOutline,\n 'lock-closed-outline': lockClosedOutline,\n 'open-outline': openOutline,\n 'scan-outline': scanOutline,\n 'swap-vertical-outline': swapVerticalOutline,\n 'trash-outline': trashOutline,\n 'warning-outline': warningOutline,\n }).map(([navn, svg]) => [navn, utenTittel(svg)]),\n);\n\n/** Navnene `Ikon` kjenner. Et navn som ikke står her kaster ved rendring, aldri stille. */\nexport const IKONNAVN: readonly string[] = Object.keys(IKONER);\n\n/**\n * Dekorativt ikon — alltid ved siden av tekst, aldri alene. Farge og form\n * bærer ikke mening alene (DD-08), så ikonet er skjult for skjermlesere og\n * teksten sier alt.\n *\n * Målet kommer fra `icon` i temaet, aldri fra et tall her: Ionicons tegner med\n * 6,25 % av boksen, så strektykkelsen følger målet, og `minste` (16) er gulvet\n * der streken treffer 1,00 px. Fargen settes som `color`, som er det\n * `currentColor` i SVG-en løses mot.\n */\nexport function Ikon({\n navn,\n storrelse = 'inline',\n farge,\n}: {\n navn: string;\n /**\n * `minste` i piller, hint og chips · `inline` ved siden av brødtekst · `stor`\n * de to stedene ikonet står ALENE og bærer stemningen: sporvalgets flater og\n * kvitteringen. `stor` er et MULTIPLUM av tokenet, ikke et nytt tall — samme\n * regel som `.innspel-flate-ikon` og `.innspel-kvittering-ikon` på web.\n */\n storrelse?: 'stor' | 'inline' | 'minste';\n /** En farge fra temaet. Uten: `textPrimary`. Aldri en literal. */\n farge?: string;\n}) {\n const tema = useTema();\n const svg = IKONER[navn];\n if (!svg) throw new Error(`[innspel] Ikonet «${navn}» er ikke tatt med i Ikon.tsx.`);\n\n const maal =\n storrelse === 'minste' ? tema.icon.minste : storrelse === 'stor' ? 2 * tema.icon.inline : tema.icon.inline;\n return (\n <SvgXml\n // `testID` er navnet: en test kan da slå fast HVILKET ikon en flate tegner,\n // ikke bare at den tegner ett. @testing-library/react-native v14 har ingen\n // spørring på komponenttype lenger, så uten den ville ikonet vært usynlig i test.\n testID={`ikon-${navn}`}\n xml={svg}\n width={maal}\n height={maal}\n color={farge ?? tema.color.textPrimary}\n // Konturikonene har `fill=\"none\"` og `stroke=\"currentColor\"` selv. De fylte (DD-63)\n // har ingen fill på stiene, og react-native-svg tegner dem da svarte — fargen arves\n // fra rota her, og rører ikke en sti som alt sier «none».\n fill={farge ?? tema.color.textPrimary}\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n />\n );\n}\n","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M244 400 100 256l144-144M120 256h292\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M452.37 59.63a40.49 40.49 0 0 0-57.26 0L184 294.74c23.08 4.7 46.12 27.29 49.26 49.26l219.11-227.11a40.49 40.49 0 0 0 0-57.26M138 336c-29.88 0-54 24.5-54 54.86 0 23.95-20.88 36.57-36 36.57C64.56 449.74 92.82 464 120 464c39.78 0 72-32.73 72-73.14 0-30.36-24.12-54.86-54-54.86\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M463.55 272.13H400v-48.2q0-4.32-.27-8.47c29.57-27.88 32.25-64.63 32.27-103 0-8.61-6.64-16-15.25-16.41A16 16 0 0 0 400 112c0 28-1.86 48.15-9.9 63.84-19.22-41.15-65.78-63.91-134.1-63.91-39.8 0-74.19 9.13-99.43 26.39-14.9 10.19-26.2 22.91-33.7 37.72C114 160.65 112 141 112 112.46c0-8.61-6.6-16-15.2-16.44A16 16 0 0 0 80 112c0 37.63 2.61 73.73 32.44 101.63q-.43 5.06-.44 10.3v48.2H48.45c-8.61 0-16 6.62-16.43 15.23a16 16 0 0 0 16 16.77h64V320a143.3 143.3 0 0 0 10.39 53.69C96.74 396.64 80.18 422 80 463.34c0 8.74 6.62 16.3 15.36 16.65A16 16 0 0 0 112 464c0-27.66 9.1-44.71 26.17-61.32A144.37 144.37 0 0 0 220 459.42a16 16 0 0 0 20-15.49V192.45c0-8.61 6.62-16 15.23-16.43A16 16 0 0 1 272 192v251.93a16 16 0 0 0 20 15.49 144.4 144.4 0 0 0 81.82-56.74c17 16.54 26.09 33.52 26.17 60.95a16.27 16.27 0 0 0 15.1 16.37A16 16 0 0 0 432 464c0-41.68-16.6-67.23-42.39-90.31A143.3 143.3 0 0 0 400 320v-15.87h64a16 16 0 0 0 16-16.77c-.42-8.61-7.84-15.23-16.45-15.23\"/><path d=\"m321.39 104 .32.09c13.57 3.8 25.07-10.55 18.2-22.85A95.86 95.86 0 0 0 256.21 32h-.42a95.87 95.87 0 0 0-84.19 50.13c-6.84 12.58 5.14 27 18.84 22.86 19.71-6 41.79-9.06 65.56-9.06 24.09 0 46.09 2.72 65.39 8.07\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M370 378c28.89 23.52 46 46.07 46 86M142 378c-28.89 23.52-46 46.06-46 86M384 208c28.89-23.52 32-56.07 32-96M128 206c-28.89-23.52-32-54.06-32-94M464 288.13h-80M128 288.13H48M256 192v256\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M256 448c-70.4 0-128-57.6-128-128v-96.07c0-65.07 57.6-96 128-96h0c70.4 0 128 25.6 128 96V320c0 70.4-57.6 128-128 128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M179.43 143.52a49.1 49.1 0 0 1-3.43-15.73A80 80 0 0 1 255.79 48h.42A80 80 0 0 1 336 127.79a41.9 41.9 0 0 1-3.12 14.3\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M288 464h-64a16 16 0 0 0 0 32h64a16 16 0 0 0 0-32M304 416h-96a16 16 0 0 0 0 32h96a16 16 0 0 0 0-32M369.42 62.69C339.35 32.58 299.07 16 256 16A159.62 159.62 0 0 0 96 176c0 46.62 17.87 90.23 49 119.64l4.36 4.09C167.37 316.57 192 339.64 192 360v24a16 16 0 0 0 16 16h24a8 8 0 0 0 8-8V274.82a8 8 0 0 0-5.13-7.47A130.7 130.7 0 0 1 208.71 253a16 16 0 1 1 18.58-26c7.4 5.24 21.65 13 28.71 13s21.31-7.78 28.73-13a16 16 0 0 1 18.56 26 130.7 130.7 0 0 1-26.16 14.32 8 8 0 0 0-5.13 7.47V392a8 8 0 0 0 8 8h24a16 16 0 0 0 16-16v-24c0-19.88 24.36-42.93 42.15-59.77l4.91-4.66C399.08 265 416 223.61 416 176a159.16 159.16 0 0 0-46.58-113.31\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><rect width=\"416\" height=\"384\" x=\"48\" y=\"80\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32\" rx=\"48\"/><circle cx=\"296\" cy=\"232\" r=\"24\"/><circle cx=\"376\" cy=\"232\" r=\"24\"/><circle cx=\"296\" cy=\"312\" r=\"24\"/><circle cx=\"376\" cy=\"312\" r=\"24\"/><circle cx=\"136\" cy=\"312\" r=\"24\"/><circle cx=\"216\" cy=\"312\" r=\"24\"/><circle cx=\"136\" cy=\"392\" r=\"24\"/><circle cx=\"216\" cy=\"392\" r=\"24\"/><circle cx=\"296\" cy=\"392\" r=\"24\"/><path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32\" d=\"M128 48v32M384 48v32\"/><path fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32\" d=\"M464 160H48\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m350.54 148.68-26.62-42.06C318.31 100.08 310.62 96 302 96h-92c-8.62 0-16.31 4.08-21.92 10.62l-26.62 42.06C155.85 155.23 148.62 160 140 160H80a32 32 0 0 0-32 32v192a32 32 0 0 0 32 32h352a32 32 0 0 0 32-32V192a32 32 0 0 0-32-32h-59c-8.65 0-16.85-4.77-22.46-11.32\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"256\" cy=\"272\" r=\"80\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M124 158v-22h-24v22\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192Z\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M352 176 217.6 336 160 272\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m112 184 144 144 144-144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m112 328 144-144 144 144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"48px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192Z\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M320 320 192 192M192 320l128-128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M368 368 144 144M368 144 144 368\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M93.72 183.25C49.49 198.05 16 233.1 16 288c0 66 54 112 120 112h184.37M467.82 377.74C485.24 363.3 496 341.61 496 312c0-59.82-53-85.76-96-88-8.89-89.54-71-144-144-144-26.16 0-48.79 6.93-67.6 18.14\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M448 448 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M436.67 184.11a27.17 27.17 0 0 1-38.3 0l-22.48-22.49a27.15 27.15 0 0 1 0-38.29l50.89-50.89a.85.85 0 0 0-.26-1.38C393.68 57 351.09 64.15 324.05 91c-25.88 25.69-27.35 64.27-17.87 98a27 27 0 0 1-7.67 27.14l-173 160.76a40.76 40.76 0 1 0 57.57 57.54l162.15-173.3a27 27 0 0 1 26.77-7.7c33.46 8.94 71.49 7.26 97.07-17.94 27.49-27.08 33.42-74.94 20.1-102.33a.85.85 0 0 0-1.36-.22Z\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M224 284c-17.48-17-25.49-24.91-31-30.29a18.24 18.24 0 0 1-3.33-21.35 20.8 20.8 0 0 1 3.5-4.62l15.68-15.29a18.7 18.7 0 0 1 5.63-3.87 18.11 18.11 0 0 1 20 3.62c5.45 5.29 15.43 15 33.41 32.52M317.07 291.3c40.95 38.1 90.62 83.27 110 99.41a13.46 13.46 0 0 1 .94 19.92L394.63 444a14 14 0 0 1-20.29-.76c-16.53-19.18-61.09-67.11-99.27-107\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"m17.34 193.5 29.41-28.74a4.7 4.7 0 0 1 3.41-1.35 4.85 4.85 0 0 1 3.41 1.35h0a9.86 9.86 0 0 0 8.19 2.77c3.83-.42 7.92-1.6 10.57-4.12 6-5.8-.94-17.23 4.34-24.54a207 207 0 0 1 19.78-22.6c6-5.88 29.84-28.32 69.9-44.45A107.3 107.3 0 0 1 206.67 64c22.59 0 40 10 46.26 15.67a89.5 89.5 0 0 1 10.28 11.64 79 79 0 0 0-9.21-2.77 68.8 68.8 0 0 0-20-1.26c-13.33 1.09-29.41 7.26-38 14-13.9 11-19.87 25.72-20.81 44.71-.68 14.12 2.72 22.1 36.1 55.49a6.6 6.6 0 0 1-.34 9.16l-18.22 18a6.88 6.88 0 0 1-9.54.09c-21.94-21.94-36.65-33.09-45-38.16s-15.07-6.5-18.3-6.85a30.85 30.85 0 0 0-18.27 3.87 11.4 11.4 0 0 0-2.64 2 14.14 14.14 0 0 0 .42 20.08l1.71 1.6a4.63 4.63 0 0 1 0 6.64L71.73 246.6a4.7 4.7 0 0 1-3.41 1.4 4.86 4.86 0 0 1-3.41-1.35l-47.57-46.43a4.88 4.88 0 0 1 0-6.72\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><circle cx=\"256\" cy=\"256\" r=\"208\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M256 464c-114.88 0-208-93.12-208-208S141.12 48 256 48Z\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><circle cx=\"256\" cy=\"256\" r=\"192\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M320 176v-40a40 40 0 0 0-40-40H88a40 40 0 0 0-40 40v240a40 40 0 0 0 40 40h192a40 40 0 0 0 40-40v-40M384 176l80 80-80 80M191 256h273\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M176 48h160M118 304h276M208 48v93.48a64.1 64.1 0 0 1-9.88 34.18L73.21 373.49C48.4 412.78 76.63 464 123.08 464h265.84c46.45 0 74.68-51.22 49.87-90.51L313.87 175.66a64.1 64.1 0 0 1-9.87-34.18V48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><rect width=\"176\" height=\"176\" x=\"48\" y=\"48\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"176\" height=\"176\" x=\"288\" y=\"48\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"176\" height=\"176\" x=\"48\" y=\"288\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"176\" height=\"176\" x=\"288\" y=\"288\" rx=\"20\" ry=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M145.61 464h220.78c19.8 0 35.55-16.29 33.42-35.06C386.06 308 304 310 304 256s83.11-51 95.8-172.94c2-18.78-13.61-35.06-33.41-35.06H145.61c-19.8 0-35.37 16.28-33.41 35.06C124.89 205 208 201 208 256s-82.06 52-95.8 172.94c-2.14 18.77 13.61 35.06 33.41 35.06\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M343.3 432H169.13c-15.6 0-20-18-9.06-29.16C186.55 376 240 356.78 240 326V224c0-19.85-38-35-61.51-67.2-3.88-5.31-3.49-12.8 6.37-12.8h142.73c8.41 0 10.23 7.43 6.4 12.75C310.82 189 272 204.05 272 224v102c0 30.53 55.71 47 80.4 76.87 9.95 12.04 6.47 29.13-9.1 29.13\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><rect width=\"416\" height=\"352\" x=\"48\" y=\"80\" rx=\"48\" ry=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"336\" cy=\"176\" r=\"32\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"m304 335.79-90.66-90.49a32 32 0 0 0-43.87-1.3L48 352M224 432l123.34-123.34a32 32 0 0 1 43.11-2L464 368\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M432 112V96a48.14 48.14 0 0 0-48-48H64a48.14 48.14 0 0 0-48 48v256a48.14 48.14 0 0 0 48 48h16\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"400\" height=\"336\" x=\"96\" y=\"128\" rx=\"45.99\" ry=\"45.99\" fill=\"none\" stroke=\"currentColor\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><ellipse cx=\"372.92\" cy=\"219.64\" rx=\"30.77\" ry=\"30.55\" fill=\"none\" stroke=\"currentColor\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M342.15 372.17 255 285.78a30.93 30.93 0 0 0-42.18-1.21L96 387.64M265.23 464l118.59-117.73a31 31 0 0 1 41.46-1.87L496 402.91\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M160 144h288M160 256h288M160 368h288\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"80\" cy=\"144\" r=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"80\" cy=\"256\" r=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"80\" cy=\"368\" r=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M336 208v-95a80 80 0 0 0-160 0v95\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><rect width=\"320\" height=\"272\" x=\"96\" y=\"208\" rx=\"48\" ry=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><circle cx=\"129\" cy=\"96\" r=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"129\" cy=\"416\" r=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M129 144v224\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><circle cx=\"385\" cy=\"288\" r=\"48\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M129 144c0 96 112 144 208 144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M384 224v184a40 40 0 0 1-40 40H104a40 40 0 0 1-40-40V168a40 40 0 0 1 40-40h167.48M336 64h112v112M224 288 440 72\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M336 448h56a56 56 0 0 0 56-56v-56M448 176v-56a56 56 0 0 0-56-56h-56M176 448h-56a56 56 0 0 1-56-56v-56M64 176v-56a56 56 0 0 1 56-56h56\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M464 208 352 96 240 208M352 113.13V416M48 304l112 112 112-112M160 398V96\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"m112 112 20 320c.95 18.49 14.4 32 32 32h184c17.67 0 30.87-13.51 32-32l20-320\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"M80 112h352\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-miterlimit=\"10\" stroke-width=\"32px\"/><path d=\"M192 112V72h0a23.93 23.93 0 0 1 24-24h80a23.93 23.93 0 0 1 24 24h0v40M256 176v224M184 176l8 224M328 176l-8 224\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/></svg>","<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\" class=\"ionicon\"><path d=\"M85.57 446.25h340.86a32 32 0 0 0 28.17-47.17L284.18 82.58c-12.09-22.44-44.27-22.44-56.36 0L57.4 399.08a32 32 0 0 0 28.17 47.17\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path d=\"m250.26 195.39 5.74 122 5.73-121.95a5.74 5.74 0 0 0-5.79-6h0a5.74 5.74 0 0 0-5.68 5.95\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"32px\"/><path fill=\"currentColor\" d=\"M256 397.25a20 20 0 1 1 20-20 20 20 0 0 1-20 20\"/></svg>","import type { ContextInput, KnownIssueCard, PatternFinding } from '@innspel/core';\nimport React, { useMemo, useState } from 'react';\nimport { Pressable, ScrollView, Text, TextInput, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, H, Hint } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\n/**\n * 2d + 2e — feltet og kontekstlinja. Ett felt, ingenting annet.\n *\n * DD-44: send er inaktiv under `minTextLength` (standard 10), og det er det\n * ENESTE kravet. Ingen kategori, ingen alvorlighet, ingen reproduksjonsfelt.\n * 2h i wireframen er ikke en skjerm — den er fraværet av felter her.\n *\n * DD-45: placeholderen stiller to spørsmål i feilsporet.\n *\n * DD-46: mønstervarselet vises FØR sending og fjerner aldri noe selv.\n * «Fjern» og «Behold» er innsenderens valg; teksten endres bare ved «Fjern».\n *\n * DD-05: konteksten er synlig og kan fjernes linje for linje. Den er en lukket\n * hviteliste (K5) — det som ikke står der, finnes ikke å fjerne.\n */\nexport function Felt({\n spor,\n verdi,\n onEndre,\n minTextLength,\n textMaxLength,\n kontekst,\n fjernedeFelter,\n onFjernKontekst,\n lenketTil,\n onFjernLenke,\n funn,\n onSend,\n sender,\n harFeil,\n offline,\n onSkjermbilde,\n onVelgBilde,\n bildeNotat,\n harVedlegg,\n onFjernVedlegg,\n}: {\n spor: 'feil' | 'onske';\n verdi: string;\n onEndre: (v: string) => void;\n minTextLength: number;\n textMaxLength: number;\n kontekst: ContextInput & { sdkVersion: string };\n fjernedeFelter: string[];\n onFjernKontekst: (felt: string) => void;\n lenketTil?: KnownIssueCard;\n onFjernLenke?: () => void;\n funn: PatternFinding[];\n onSend: () => void;\n sender?: boolean;\n /** Forrige sending feilet: knappen heter «Prøv igjen» til neste forsøk (C7). */\n harFeil?: boolean;\n /** Verten har meldt at nettet er nede (`init({ connectivity })`): knappen heter «Lagre — sendes når du er på nett». */\n offline?: boolean;\n /**\n * «Legg ved skjermbilde» (2f, K4). Utelatt = steget finnes ikke (DD-26): leietakeren\n * har skjermbilde av, eller verten ga ingen adapter. Aldri en deaktivert knapp.\n */\n onSkjermbilde?: () => void;\n /** «Velg bilde» fra galleriet. Utelatt = valget finnes ikke; samme regel som over. */\n onVelgBilde?: () => void;\n /** Vertens setning ved bildesteget (`imageStepNote`). Leietakeren eier den, ikke plattformen. */\n bildeNotat?: string;\n /** Et maskert skjermbilde ligger klart og sendes etter teksten (DD-42). */\n harVedlegg?: boolean;\n onFjernVedlegg?: () => void;\n}) {\n const tema = useTema();\n const [apen, setApen] = useState(false);\n const [beholdt, setBeholdt] = useState<string[]>([]);\n\n const brukt = verdi.length;\n const forKort = brukt < minTextLength;\n const full = brukt >= textMaxLength;\n // Telleren dukker opp ved 80 % — ikke før. En teller fra første tegn gjør\n // lengden til oppgaven i stedet for innholdet.\n const visTeller = brukt >= textMaxLength * 0.8;\n\n const uavklart = funn.find((f) => !beholdt.includes(f.match));\n\n const linjer = useMemo(() => {\n const etiketter: Record<string, string> = {\n screen: 'Skjerm',\n appVersion: 'Appversjon',\n platform: 'Plattform',\n os: 'OS',\n build: 'Bygg',\n locale: 'Språk',\n };\n return Object.entries(etiketter)\n .map(([felt, etikett]) => {\n const verdi = (kontekst as unknown as Record<string, string | undefined>)[felt];\n return verdi && !fjernedeFelter.includes(felt) ? { felt, etikett, verdi } : null;\n })\n .filter((x): x is { felt: string; etikett: string; verdi: string } => x !== null);\n }, [kontekst, fjernedeFelter]);\n\n // Kroppen scroller og Send står fast under den. Arket har bare maxHeight, så\n // uten scrollflate tegnet et høyt skjema (utvidet kontekst) forbi bunnpaddingen\n // og Send havnet under navigasjonslinja. Roten er flexGrow/flexShrink, ikke\n // flex: 1 — den gir flexBasis 0, og arket ville aldri vokst forbi minHeight.\n return (\n <View testID=\"skjema\" style={{ flexGrow: 1, flexShrink: 1, gap: tema.space.md }}>\n <ScrollView\n testID=\"skjema-kropp\"\n style={{ flexGrow: 0, flexShrink: 1 }}\n contentContainerStyle={{ gap: tema.space.md }}\n keyboardShouldPersistTaps=\"handled\"\n >\n {lenketTil ? (\n <View\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n minHeight: tema.touch,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderInteractive,\n borderRadius: tema.radius.pill,\n paddingLeft: tema.space.md,\n paddingRight: tema.space.xs,\n }}\n >\n <Text style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }}>\n {tekst.lenketTil(lenketTil.title)}\n </Text>\n <Pressable\n testID=\"fjern-lenke\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.fjernLenke}\n onPress={onFjernLenke}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n ) : null}\n\n {uavklart ? (\n <View\n style={{\n gap: tema.space.sm,\n backgroundColor: tema.color.warningBg,\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n }}\n >\n <Text\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n style={{\n color: tema.color.warning,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n fontWeight: tema.weight.medium,\n }}\n >\n {tekst.monsterSpm[uavklart.kind]}\n </Text>\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n <Btn\n grow\n variant=\"secondary\"\n testID=\"monster-fjern\"\n label={tekst.monsterFjern}\n onPress={() => onEndre(verdi.slice(0, uavklart.start) + verdi.slice(uavklart.end))}\n />\n <Btn\n grow\n variant=\"ghost\"\n testID=\"monster-behold\"\n label={tekst.monsterBehold}\n onPress={() => setBeholdt((b) => [...b, uavklart.match])}\n />\n </View>\n <Hint>{tekst.monsterForklaring}</Hint>\n </View>\n ) : null}\n\n <H>{spor === 'onske' ? tekst.feltLabelOnske : tekst.feltLabelFeil}</H>\n\n <TextInput\n testID=\"innspill-tekst\"\n accessibilityLabel={spor === 'onske' ? tekst.feltLabelOnske : tekst.feltLabelFeil}\n value={verdi}\n onChangeText={onEndre}\n maxLength={textMaxLength}\n multiline\n numberOfLines={4}\n placeholder={spor === 'onske' ? tekst.placeholderOnske : tekst.placeholderFeil}\n placeholderTextColor={tema.color.textMuted}\n style={{\n backgroundColor: tema.color.surfaceRaised,\n borderWidth: tema.hairline,\n borderColor: full ? tema.color.warning : tema.color.borderStrong,\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n minHeight: tema.touch * 2,\n textAlignVertical: 'top',\n }}\n />\n\n {visTeller ? (\n <Text\n testID=\"teller\"\n accessibilityLiveRegion={full ? 'assertive' : 'polite'}\n style={{\n alignSelf: 'flex-end',\n color: full ? tema.color.warning : tema.color.textMuted,\n fontSize: tema.font.small,\n }}\n >\n {brukt} / {textMaxLength}\n {full ? tekst.tellerFull : ''}\n </Text>\n ) : null}\n\n {/* 2f — opt-in per innsending. Bildet tas først ved trykk (K4). */}\n {harVedlegg ? (\n <View\n testID=\"vedlegg-chip\"\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n minHeight: tema.touch,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderInteractive,\n borderRadius: tema.radius.pill,\n paddingLeft: tema.space.md,\n paddingRight: tema.space.xs,\n }}\n >\n <Ikon navn=\"image-outline\" storrelse=\"minste\" farge={tema.color.textPrimary} />\n <Text style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }}>{tekst.bildeLagtVed}</Text>\n <Pressable\n testID=\"fjern-vedlegg\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.fjernSkjermbilde}\n onPress={onFjernVedlegg}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n ) : onSkjermbilde || onVelgBilde ? (\n // F7 (brukerreisene 2026-09-15): knappene har ingen egen hjelpetekst. Web-widgeten\n // har aldri hatt det, og Følget sender sin egen setning som `imageStepNote` — med\n // pakkens hint i tillegg sto det tre tekster under to knapper. Løftet om at bildet\n // tas ved trykk og kan maskeres står i selve steget (Skjermbilde), der det gjelder.\n <View style={{ gap: tema.space.sm }}>\n {onSkjermbilde ? (\n <Btn\n variant=\"secondary\"\n testID=\"legg-ved-skjermbilde\"\n ikon=\"camera-outline\"\n label={tekst.leggVedSkjermbilde}\n onPress={onSkjermbilde}\n />\n ) : null}\n {onVelgBilde ? (\n <Btn\n variant=\"secondary\"\n testID=\"velg-bilde\"\n ikon=\"images-outline\"\n label={tekst.velgBilde}\n onPress={onVelgBilde}\n />\n ) : null}\n {bildeNotat ? (\n <View testID=\"bilde-notat\">\n <Hint>{bildeNotat}</Hint>\n </View>\n ) : null}\n </View>\n ) : null}\n\n {/* 2e — synlig, ikke skjult (DD-05) */}\n <View style={{ borderTopWidth: tema.hairline, borderTopColor: tema.color.border, paddingTop: tema.space.sm }}>\n <Pressable\n testID=\"kontekst-bryter\"\n accessibilityRole=\"button\"\n accessibilityState={{ expanded: apen }}\n accessibilityLabel={`${tekst.kontekstLinje}${apen ? '' : tekst.kontekstVis}`}\n onPress={() => setApen((a) => !a)}\n style={{ minHeight: tema.touch, justifyContent: 'center' }}\n >\n {/* Ikonet er et eget element, ikke et tegn i teksten: en SVG kan ikke\n ligge inne i en `Text` i React Native. */}\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon\n navn={apen ? 'chevron-up-outline' : 'chevron-down-outline'}\n storrelse=\"minste\"\n farge={tema.color.textSecondary}\n />\n <Text style={{ flex: 1, color: tema.color.textSecondary, fontSize: tema.font.small }}>\n {tekst.kontekstLinje}\n {apen ? '' : tekst.kontekstVis}\n </Text>\n </View>\n </Pressable>\n\n {apen ? (\n <View>\n {linjer.map((l) => (\n <View\n key={l.felt}\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n minHeight: tema.touch,\n borderBottomWidth: tema.hairline,\n borderBottomColor: tema.color.border,\n }}\n >\n <Text style={{ color: tema.color.textMuted, fontSize: tema.font.small, minWidth: tema.touch * 2 }}>\n {l.etikett}\n </Text>\n <Text style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }}>{l.verdi}</Text>\n <Pressable\n testID={`fjern-${l.felt}`}\n accessibilityRole=\"button\"\n accessibilityLabel={`${tekst.kontekstFjern} ${l.etikett.toLowerCase()} fra innsendingen`}\n onPress={() => onFjernKontekst(l.felt)}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"close-outline\" storrelse=\"minste\" farge={tema.color.textSecondary} />\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>\n {tekst.kontekstFjern}\n </Text>\n </View>\n </Pressable>\n </View>\n ))}\n <View style={{ paddingTop: tema.space.sm }}>\n <Hint>{tekst.kontekstAldri}</Hint>\n </View>\n </View>\n ) : null}\n </View>\n\n </ScrollView>\n\n <View testID=\"skjema-fot\" style={{ flexGrow: 1, flexShrink: 0, justifyContent: 'flex-end' }}>\n <Btn\n testID=\"send\"\n label={sender ? tekst.sender : harFeil ? tekst.provIgjen : offline ? tekst.offlineLagre : tekst.send}\n disabled={forKort || sender}\n busy={sender}\n hint={forKort ? tekst.forKort(minTextLength) : harVedlegg ? tekst.sendHintMedBilde : undefined}\n onPress={onSend}\n // F10: tastaturet er oppe når Send trykkes. En ScrollView i vertens tre over\n // provideren kan ta første trykk — det skal likevel sende.\n trykkForbiForelder\n />\n </View>\n </View>\n );\n}\n","import React, { useMemo, useRef } from 'react';\nimport { Pressable, Text, View, type GestureResponderEvent, type StyleProp, type ViewStyle } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\n\n/**\n * Primitivene widgeten er bygget av. Alt visuelt kommer fra tema-tokens —\n * ingen hex, ingen px, ingen fontstørrelse skrives her (CLAUDE.md, «Styling»).\n *\n * Minste trykkflate er `skala.touch` (48). Den er ikke en anbefaling: den er\n * grønt-kriterium for widgeten, og en knapp under målet er en feil.\n *\n * `ikon` er alltid et IONICONS-NAVN, aldri en emoji (brand-ui-guidelines,\n * UX-gjennomgangen C3). Navnene står i `src/Ikon.tsx`, og et ukjent navn kaster.\n */\n\ntype Variant = 'primary' | 'secondary' | 'ghost' | 'danger';\n\nexport function Btn({\n label,\n onPress,\n variant = 'primary',\n ikon,\n hint,\n disabled,\n accessibilityLabel,\n grow,\n testID,\n busy,\n trykkForbiForelder,\n}: {\n label: string;\n onPress?: () => void;\n variant?: Variant;\n ikon?: string;\n hint?: string;\n disabled?: boolean;\n accessibilityLabel?: string;\n grow?: boolean;\n testID?: string;\n /** Handlingen pågår: `busy` i tilstanden, så skjermleseren hører at knappen jobber, ikke bare at den er låst. */\n busy?: boolean;\n /**\n * Trykket teller selv om en FORELDER i vertens tre tok responderen (F10). Se\n * {@link useTrykkForbiForelder}. Brukes på Send, der et tapt trykk er et innspill som\n * ikke ble sendt.\n */\n trykkForbiForelder?: boolean;\n}) {\n const tema = useTema();\n const c = tema.color;\n const forbi = useTrykkForbiForelder(onPress, !!disabled, tema.touch / 2);\n\n const bakgrunn =\n variant === 'primary' ? c.actionPrimary : variant === 'secondary' ? c.surfaceRaised : 'transparent';\n const tekstfarge =\n variant === 'primary' ? c.onActionPrimary : variant === 'danger' ? c.danger : c.actionSecondaryText;\n const kant = variant === 'ghost' ? 'transparent' : variant === 'primary' ? c.actionPrimary : c.actionSecondaryBorder;\n\n return (\n <View style={grow ? { flex: 1 } : undefined}>\n <Pressable\n testID={testID}\n accessibilityRole=\"button\"\n // Hintet er synlig tekst OG del av etiketten: en skjermleserbruker skal\n // få vite hvorfor knappen er inaktiv uten å lete etter teksten under.\n accessibilityLabel={accessibilityLabel ?? (hint ? `${label}. ${hint}` : label)}\n accessibilityState={{ disabled: !!disabled, busy: !!busy }}\n disabled={disabled}\n onPress={onPress}\n {...(trykkForbiForelder ? forbi : {})}\n style={{\n minHeight: tema.touch,\n borderRadius: tema.radius.md,\n borderWidth: tema.hairline,\n borderColor: kant,\n backgroundColor: disabled ? c.surface : bakgrunn,\n paddingHorizontal: tema.space.md,\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'row',\n gap: tema.space.sm,\n opacity: disabled ? 0.6 : 1,\n }}\n >\n {ikon ? <Ikon navn={ikon} farge={disabled ? c.textDisabled : tekstfarge} /> : null}\n <Text\n style={{\n color: disabled ? c.textDisabled : tekstfarge,\n fontSize: tema.font.body,\n fontWeight: tema.weight.semibold,\n }}\n >\n {label}\n </Text>\n </Pressable>\n {hint ? <Hint>{hint}</Hint> : null}\n </View>\n );\n}\n\n/**\n * Et trykk som ender på knappen, teller — også når knappen aldri fikk responderen (F10).\n *\n * React Natives responder-system spør forfedrene i REACT-treet, ytterst først, i\n * capture-fasen (`traverseTwoPhase` over `fiber.return` i renderen). Modalen er et eget\n * vindu på Android, men i React-treet står den der verten plasserte provideren. Står den i\n * en `ScrollView` med `keyboardShouldPersistTaps` på `'never'` (standard), tar den\n * ScrollView-en trykket mens tastaturet er oppe og slipper det med `blurTextInput`\n * (`_handleStartShouldSetResponderCapture` i ScrollView.js). Pressable-en får aldri\n * `onResponderGrant`, og `onPress` kalles aldri: første trykk lukker bare tastaturet.\n *\n * Widgeten kan ikke vinne capture-fasen over en forelder. Men `onTouchStart`/`onTouchEnd`\n * sendes av `ReactNativeBridgeEventPlugin` til målet uavhengig av hvem som er responder.\n * Et trykk som endte innenfor `slingring` av der det startet, uten at `onPressIn` kom,\n * kalles derfor som `onPress` — etter at responder-hendelsene for samme trykk er\n * ferdige, så et vanlig trykk aldri teller to ganger. En låst knapp trykkes aldri.\n */\nfunction useTrykkForbiForelder(onPress: (() => void) | undefined, laast: boolean, slingring: number) {\n const start = useRef<{ x: number; y: number } | null>(null);\n const fikkResponder = useRef(false);\n // Siste verdier leses i timeouten, ikke verdiene fra renderen trykket startet i.\n const siste = useRef({ onPress, laast });\n siste.current = { onPress, laast };\n\n return useMemo(\n () => ({\n onPressIn: () => {\n fikkResponder.current = true;\n },\n onTouchStart: (e: GestureResponderEvent) => {\n start.current = { x: e.nativeEvent.pageX, y: e.nativeEvent.pageY };\n },\n onTouchEnd: (e: GestureResponderEvent) => {\n const s = start.current;\n start.current = null;\n const innenfor =\n s !== null &&\n Math.abs(e.nativeEvent.pageX - s.x) <= slingring &&\n Math.abs(e.nativeEvent.pageY - s.y) <= slingring;\n setTimeout(() => {\n const tatt = fikkResponder.current;\n fikkResponder.current = false;\n if (!tatt && innenfor && !siste.current.laast) siste.current.onPress?.();\n }, 0);\n },\n onTouchCancel: () => {\n start.current = null;\n fikkResponder.current = false;\n },\n }),\n [slingring],\n );\n}\n\nexport function H({ children, sub }: { children: string; sub?: string }) {\n const tema = useTema();\n return (\n <View style={{ gap: tema.space.xs }}>\n <Text\n accessibilityRole=\"header\"\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.h2,\n lineHeight: tema.lineHeight.h2,\n fontWeight: tema.weight.semibold,\n }}\n >\n {children}\n </Text>\n {sub ? (\n <Text\n style={{\n color: tema.color.textSecondary,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {sub}\n </Text>\n ) : null}\n </View>\n );\n}\n\nexport function Hint({ children }: { children: React.ReactNode }) {\n const tema = useTema();\n return (\n <Text\n style={{\n color: tema.color.textMuted,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {children}\n </Text>\n );\n}\n\nexport function Card({\n children,\n dashed,\n style,\n}: {\n children: React.ReactNode;\n dashed?: boolean;\n style?: StyleProp<ViewStyle>;\n}) {\n const tema = useTema();\n return (\n <View\n style={[\n {\n backgroundColor: tema.color.surface,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.border,\n borderStyle: dashed ? 'dashed' : 'solid',\n padding: tema.space.md,\n gap: tema.space.sm,\n },\n style,\n ]}\n >\n {children}\n </View>\n );\n}\n\n/**\n * Status som ikon + etikett. Fargen er et TILLEGG, aldri bæreren: to av\n * palettens statusfarger er målt til under 1,5 i innbyrdes kontrast, så\n * etiketten er det som faktisk skiller dem (DD-08).\n */\nexport function StatusPill({ ikon, etikett, fg, bg }: { ikon: string; etikett: string; fg: string; bg: string }) {\n const tema = useTema();\n // `fg`/`bg` er TOKENNAVN fra theme.ts, ikke farger: samme mappe virker i begge\n // paletter og i vertens eget tema (DD-21).\n const farge = (navn: string, reserve: string) => (tema.color as Record<string, string>)[navn] ?? reserve;\n return (\n <View\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.xs,\n alignSelf: 'flex-start',\n paddingHorizontal: tema.space.sm,\n paddingVertical: tema.space.xs,\n borderRadius: tema.radius.pill,\n backgroundColor: farge(bg, tema.color.neutralBg),\n }}\n >\n <Ikon navn={ikon} storrelse=\"minste\" farge={farge(fg, tema.color.textSecondary)} />\n <Text style={{ color: farge(fg, tema.color.textSecondary), fontSize: tema.font.small, fontWeight: tema.weight.medium }}>\n {etikett}\n </Text>\n </View>\n );\n}\n\n/**\n * Varsel. Rollen ligger på `Text`, ikke på containeren: `accessible` på en\n * container sluker barna som egne fokusstopp (`tdd-contract-validation`).\n */\nexport function Banner({\n ikon,\n tone,\n children,\n live,\n testID,\n}: {\n ikon: string;\n tone: 'info' | 'warning' | 'danger' | 'success';\n children: string;\n live?: boolean;\n testID?: string;\n}) {\n const tema = useTema();\n return (\n <View\n testID={testID}\n style={{\n flexDirection: 'row',\n gap: tema.space.sm,\n backgroundColor: tema.color[`${tone}Bg` as keyof typeof tema.color],\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n }}\n >\n <Ikon navn={ikon} farge={tema.color[tone]} />\n <Text\n accessibilityRole=\"alert\"\n accessibilityLiveRegion={live ? 'polite' : 'none'}\n style={{\n flex: 1,\n color: tema.color[tone],\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {children}\n </Text>\n </View>\n );\n}\n","/**\n * Hver streng innsenderen ser, ett sted.\n *\n * Ordlyden er ikke fri: den er tegnet i `design/wireframes/innsending-widget.jsx`\n * og bundet av beslutninger.\n *\n * SETNINGEN innsenderen får for en status (DD-08) står IKKE her lenger — den bor\n * i `submissionStatus` i `theme/theme.ts` og leses fra den genererte mappa\n * (`status.ts`), så appen, portalen og panelet ikke kan love tre ulike ting.\n *\n * Språket er innsenderens, ikke repoets (DD-50, presisert 2026-09-14): aldri\n * «spor», «reproduksjon», «privat view» eller et kontraktfeltnavn.\n *\n * Norsk bokmål. Ingen leietakernavn: strengen som nevner avsenderen tar navnet\n * som parameter, siden pakken skal kunne brukes av hvem som helst.\n */\n\n/**\n * Saksnummeret uten kontraktens id-prefiks. `sub_2041` er databasens nøkkel;\n * innsenderen skal lese «sak 2041» (DD-50). Et id uten prefiks står som det er.\n */\n/**\n * «Sak f8dc» — de fire siste tegnene av id-en, som panelet viser (`#f8dc`, DD-63): innsender\n * og saksbehandler skal peke på samme nummer. Ekte id-er er UUIDv7 (36 tegn); før sto hele\n * strengen i lista. Et kort prefiks-format («sub_2041») beholder resten etter understreken.\n */\nexport function saksnr(id: string): string {\n const i = id.indexOf('_');\n const rest = i >= 0 ? id.slice(i + 1) : id;\n return rest.length > 8 ? rest.slice(-4) : rest;\n}\n\nconst stor = (s: string): string => (s ? s.charAt(0).toUpperCase() + s.slice(1) : s);\n\nexport const tekst = {\n // 2b — første valg\n valgTittel: 'Hva gjelder det?',\n sporFeil: 'Noe virker ikke',\n sporFeilUnder: 'Noe er galt eller virker rart',\n sporOnske: 'Jeg ønsker meg noe',\n sporOnskeUnder: 'Noe du savner eller vil ha annerledes',\n\n // 2c — kjente feil (DD-29, DD-30)\n kjenteFeilTittelFeil: 'Er det dette du ser?',\n kjenteFeilUnderFeil: 'Kjenner du igjen en av disse?',\n kjenteFeilTittelOnske: 'Har noen ønsket dette?',\n kjenteFeilUnderOnske: 'Ett trykk legger deg til på ønsket — ingen ny sak.',\n svarJa: 'Ja, jeg også',\n svarLigner: 'Ligner, men ikke helt',\n svarNei: 'Nei, det er noe annet',\n omvei: 'Omvei:',\n rettesI: (versjon: string) => `Rettes i ${versjon}`,\n rettetI: (versjon: string) => `Rettet i ${versjon}`,\n\n // 2d + 2e — feltet og kontekstlinja\n /**\n * «Ditt innspill», ikke «Din feil» (DD-54). «Din» festet saken til personen, og\n * «feil» karakteriserte den før noen hadde lest den — innsenderen leste det som\n * skyld. Ønskesporet beholder «Ditt ønske»: et ønske er ingen feil, og der finnes\n * ikke problemet. De to står aldri ved siden av hverandre; sporet velges før dette.\n */\n feltLabelFeil: 'Ditt innspill',\n feltLabelOnske: 'Ditt ønske',\n /** DD-45: to spørsmål i feilsporet. Kilde: Sentry «What's the bug? What did you expect?» */\n placeholderFeil: 'Hva skjedde? Hva forventet du?',\n placeholderOnske: 'Hva ønsker du deg?',\n send: 'Send',\n sender: 'Sender …',\n /** DD-44: minimum tegn er det ENESTE kravet. */\n forKort: (min: number) => `Minst ${min} tegn. Ingenting annet er obligatorisk.`,\n tellerFull: ' — kort og konkret holder',\n kontekstLinje: 'Legges ved: skjerm, appversjon, plattform, OS',\n kontekstVis: ' — Vis',\n kontekstFjern: 'Fjern',\n kontekstAldri:\n 'Aldri: navn, e-post, telefon, posisjon eller det som står på skjermen.',\n lenketTil: (tittel: string) => `Lenket til: «${tittel}»`,\n fjernLenke: 'Fjern lenken til den kjente feilen',\n\n // 2f — skjermbilde (K4, DD-39, DD-40, DD-42)\n leggVedSkjermbilde: 'Legg ved skjermbilde',\n velgBilde: 'Velg bilde',\n skjermbildeUnderGalleri: 'Bildet er fra galleriet. Appen maskerer ingenting i det for deg — mal over det som ikke skal med.',\n bildeFeilet: 'kunne ikke hente bildet. Du kan sende uten.',\n skjermbildeTittel: 'Se over bildet',\n skjermbildeUnder: 'Bildet ble tatt da du trykket. Det du maskerer, ser vi aldri.',\n maskering: 'Maskering',\n maskerFelt: 'Masker felt',\n tegnOver: 'Tegn over',\n maskerAllTekst: 'Masker all tekst',\n maskertAvAppen: 'Maskert av appen',\n maskertAvAppenHint: 'Dette feltet er alltid dekket og kan ikke avdekkes.',\n dittStrok: 'Trykk på et dekket felt for å angre.',\n angreSiste: 'Angre siste',\n angreSisteA11y: 'Angre det siste feltet du dekket',\n allTekstHint: 'Hele bildet er gjort uskarpt så tekst ikke kan leses. Layouten er synlig.',\n fjernBildet: 'Fjern bildet',\n leggVed: 'Legg ved',\n bildeLagtVed: 'Bilde lagt ved',\n fjernSkjermbilde: 'Fjern bildet',\n sendHintMedBilde: 'Teksten sendes først; bildet lastes opp for seg.',\n skjermbildeFeilet: 'kunne ikke ta skjermbilde. Du kan sende uten.',\n skjermbildeA11y: (auto: number, egne: number, uskarpt: boolean) =>\n `Forhåndsvisning av skjermbildet. ${auto ? `${auto} felt maskert av appen og kan ikke avmaskeres. ` : ''}${egne ? `${egne} felt maskert av deg. ` : ''}${uskarpt ? 'All tekst er gjort uskarp. ' : ''}Trykk for å maskere et felt, dra for å tegne over.`,\n\n // DD-46 — mønstervarsel. Aldri stille redaksjon.\n monsterSpm: {\n email: 'Dette ser ut som en e-postadresse. Vil du fjerne den?',\n phone: 'Dette ser ut som et telefonnummer. Vil du fjerne det?',\n card: 'Dette ser ut som et kortnummer. Vil du fjerne det?',\n ip: 'Dette ser ut som en IP-adresse. Vil du fjerne den?',\n token: 'Dette ser ut som en tilgangsnøkkel. Vil du fjerne den?',\n },\n monsterFjern: 'Fjern',\n monsterBehold: 'Behold',\n monsterForklaring: 'Teksten endres bare hvis du trykker Fjern. Vi fjerner aldri noe stille.',\n\n // 2g — kvittering\n kvitteringSendt: 'Sendt',\n kvitteringRegistrert: 'Registrert',\n kvitteringFeil: 'Du får beskjed når den er rettet, eller hvis vi trenger mer.',\n kvitteringJaOgsa: 'Du får beskjed når den er rettet.',\n saksnummer: (nr: string) => `Sak ${saksnr(nr)}`,\n tilbakeTilAppen: 'Tilbake til appen',\n /** DD-42: saken er sendt, bildet kom ikke med — aldri en blokkert innsending. */\n kvitteringVedleggFeilet: 'Sendt — skjermbildet kunne ikke legges ved',\n tekstenErLagret: 'Teksten din er lagret.',\n vedleggFeiletBanner: 'Bildet ble ikke lastet opp. Saken er sendt uten det — vil du, kan du sende et nytt innspill med bilde.',\n saksnummerUtenVedlegg: (nr: string) => `Sak ${saksnr(nr)} · uten vedlegg`,\n\n // 2i — tilstander\n koKvitteringTittel: 'Lagret — sendes når du er på nett',\n offlineBanner:\n 'Ingen nett. Lagres og sendes automatisk — du ser det under «Mine innspill» til det er sendt.',\n offlineLagre: 'Lagre — sendes når du er på nett',\n /** DD-41: et skjermbilde køes aldri. */\n offlineUtenBilde: 'Skjermbilde kan ikke legges ved uten nett. Teksten sendes; bildet ble ikke lagret.',\n sendefeilBanner: (arsak: string) => `Kunne ikke sende: ${arsak} Teksten din er beholdt.`,\n provIgjen: 'Prøv igjen',\n\n // 2j — mine innspill\n mineTittel: 'Mine innspill',\n /** Knappen på første steg med innspill fra før (DD-62): tallet er det som gjør den til en inngang. */\n mineMedAntall: (n: number) => `Mine innspill · ${n}`,\n mineEtikett: (n: number) => `Mine innspill, ${n} innspill`,\n mineUnder: 'Status og hva du kan vente deg.',\n mineTom: 'Du har ikke sendt noe ennå.',\n mineIkkeSendt: 'Ikke sendt ennå',\n mineSak: (nr: string) => `Sak ${saksnr(nr)}`,\n /** «Feil · sak 2041» — sporet først, aldri rå id og aldri kontraktens type (DD-50). */\n sakHode: (spor: string, nr: string) => `${stor(spor)} · sak ${saksnr(nr)}`,\n /** F14: svaret kom siden forrige gang denne enheten viste lista. */\n nyttSvar: 'Nytt svar',\n // Leietakeren fjernet vedlegget. Bare AT — aldri hvorfor, av hvem eller når.\n bildeFjernet: 'Bildet er fjernet.',\n svarFra: (leietaker: string) => `Svar fra ${leietaker}`,\n svarFraGenerisk: 'Svar',\n sendNytt: 'Send nytt innspill',\n /** Tom tilstand: det finnes ikke noe «nytt» å sende når ingenting er sendt. */\n sendForste: 'Send innspill',\n\n // 3a — invitasjonsbanneret (DD-12)\n invitasjonRegion: 'Invitasjon til betaprogram',\n invitasjonHva: (navn: string) => `Vil du teste «${navn}»?`,\n invitasjonKontakter: (maks: number) =>\n `Vi tar kontakt maks ${maks} ganger. Du kan gå ut når som helst.`,\n lesMer: 'Les mer og bli med',\n avvisInvitasjon: 'Avvis invitasjonen',\n\n // 3b — aksepten (DD-13, DD-32, DD-37)\n akseptHva: 'Hva testes',\n /** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */\n akseptTall: (oppgaver: number, minutter: number, periode: string, kontakter: number) =>\n `${oppgaver} oppgaver · ca. ${minutter} min hver · ${periode} · maks ${kontakter} kontakter`,\n akseptOppgaver: 'Hva vi ber om',\n akseptOppgaveTid: (minutter: number) => `ca. ${minutter} min`,\n akseptKjenteFeil: (antall: number) => `Kjente feil (${antall})`,\n akseptKjenteFeilUnder: 'Disse trenger du ikke melde — vi vet om dem.',\n akseptInnsamling: 'Hva som samles inn',\n akseptInnsamlingTekst:\n 'Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.',\n akseptVilkar: 'Les vilkårene (åpnes i nettleser)',\n akseptVilkarHint: 'Bare en lenke. Ingen avkryssing, ingen signatur — «Bli med» binder deg ikke til noe.',\n akseptIngenVilkar:\n 'Ingen vilkår, ingen avtale — plattformen kjenner ikke navnet ditt og kan ikke inngå én.',\n akseptUtgang: 'Du kan gå ut når som helst — herfra.',\n bliMed: 'Bli med',\n bliMedHint: 'Samtykket gjelder bare dette programmet.',\n /** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */\n bliMedUtenToken: 'Åpne lenken vi sendte deg for å bli med.',\n akseptFeil: (arsak: string) => `Kunne ikke bli med: ${arsak}`,\n\n // 3c (M3.1-delen) — deltakelsen og «Gå ut» (DD-36)\n deltakelseRegion: 'Ditt betaprogram',\n deltakelsePeriode: (periode: string, brukt: number, maks: number) =>\n `${periode} · Vi tar kontakt maks ${maks} ganger — ${brukt} brukt`,\n deltakelseOppgaverKommer: 'Oppgavene kan gjøres når det passer deg.',\n gaaUt: 'Gå ut av programmet',\n gaaUtTittel: 'Gå ut av programmet?',\n gaaUtTekst: (navn: string) =>\n `Du tas ut av testgruppen med en gang. «${navn}» slås av for deg, og vi tar ikke kontakt igjen. Det du allerede har svart, beholdes.`,\n bliVaerende: 'Bli værende',\n gaaUtBekreft: 'Gå ut',\n\n // 3c (M3.2) — oppgavene og «Hvordan gikk det?»: tre lukkede valg, aldri en skala\n oppgaverTittel: 'Oppgavene',\n oppgaveIkkeBegynt: 'Ikke begynt',\n oppgaveGjort: 'Gjort',\n oppgaveGjortLabel: (tittel: string) => `Gjort: ${tittel}`,\n oppgaveGjortMed: (utfall: string) => `Prøvd · ${utfall}`,\n hvordanGikkDet: 'Hvordan gikk det?',\n utfallFungerte: 'Fungerte',\n utfallDelvis: 'Fungerte delvis',\n utfallIkke: 'Fungerte ikke',\n setningLabel: 'Vil du si én setning om det? (valgfritt)',\n setningPlaceholder: 'Kopien kom, men rullesjefen manglet på torsdag.',\n lagre: 'Lagre',\n lagreHint: 'Ferdig — ingen flere spørsmål nå.',\n /** Etter «Ikke»: feilsporet er vertens — plattformen navigerer aldri selv. */\n meldFeil: 'Meld det som feil',\n meldFeilHint: 'Gikk det ikke? Et innspill hjelper oss å finne ut hvorfor.',\n svarFeil: (arsak: string) => `Kunne ikke lagre svaret: ${arsak}`,\n\n // 3d (M3.2) — oppfølgingskortene (DD-34): arten avgjør knappene\n oppfolgingRegion: 'Oppfølging fra betaprogrammet',\n oppfolgingKontakt: (nr: number, maks: number) => `Kontakt ${nr} av ${maks} · tar under ett minutt`,\n oppfolgingPaaminnelseHint: (nr: number, maks: number) => `Kontakt ${nr} av ${maks} · planlagt påminnelse`,\n oppfolgingUtgangHint: (nr: number, maks: number) => `Kontakt ${nr} av ${maks} · den siste vi sender`,\n senere: 'Senere',\n svarNaa: 'Svar nå',\n aapneOppgavene: 'Åpne oppgavene',\n\n // Felles\n tilbake: 'Tilbake',\n lukk: 'Lukk',\n venterPaaNett: 'Venter på nett — sendes automatisk',\n feil: 'feil',\n onske: 'ønske',\n} as const;\n\n/**\n * Løftene som IKKE hører til en innsendingsstatus. Statusenes løfter står i\n * `submissionStatus` i `theme/theme.ts` og leses gjennom `status.ts` — det var\n * tre kopier av dem før 2026-09-14 (UX-gjennomgangen C5).\n */\nexport const lofte = {\n venterNett: 'Sendes automatisk når du er på nett — kvitteringen kommer da.',\n} as const;\n","import React from 'react';\nimport { Pressable, Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { H } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\n/**\n * 2b — første valg. To flater, hele nedre halvdel, ikon og tekst.\n *\n * DD-02: ALDRI et tredje valg, og aldri spørsmål om kategori eller\n * alvorlighet. Valget her styrer alt etterpå: feilsporet får kjente feil FØR\n * feltet og kan bære koblingsnøkler, ønskesporet får dem etter og kan ikke.\n */\nexport function Valg({ onVelg }: { onVelg: (spor: 'feil' | 'onske') => void }) {\n const tema = useTema();\n\n const flate = (spor: 'feil' | 'onske', ikon: string, label: string, under: string) => (\n <Pressable\n testID={`spor-${spor}`}\n accessibilityRole=\"button\"\n accessibilityLabel={`${label}. ${under}`}\n onPress={() => onVelg(spor)}\n style={{\n flex: 1,\n minHeight: tema.touch * 3,\n backgroundColor: tema.color.surface,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n borderRadius: tema.radius.lg,\n alignItems: 'center',\n justifyContent: 'center',\n gap: tema.space.sm,\n padding: tema.space.md,\n }}\n >\n {/* Ikonet er det som skiller de to flatene på avstand — derfor `stor`, fylt, i merkefargen\n på en rund tonet flate (DD-63). Valget er et produktelement, ikke en status; brand er\n riktig her og målt mot brandBg i temaet. */}\n <View\n testID={`spor-${spor}-ikonflate`}\n style={{\n width: 2 * tema.icon.inline + 2 * tema.space.md,\n height: 2 * tema.icon.inline + 2 * tema.space.md,\n borderRadius: tema.radius.pill,\n backgroundColor: tema.color.brandBg,\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Ikon navn={ikon} storrelse=\"stor\" farge={tema.color.brand} />\n </View>\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.h3,\n fontWeight: tema.weight.semibold,\n textAlign: 'center',\n }}\n >\n {label}\n </Text>\n <Text style={{ color: tema.color.textMuted, fontSize: tema.font.small, textAlign: 'center' }}>\n {under}\n </Text>\n </Pressable>\n );\n\n return (\n <View style={{ flex: 1, gap: tema.space.lg }}>\n <H>{tekst.valgTittel}</H>\n <View style={{ flex: 1, justifyContent: 'flex-end' }}>\n <View style={{ flexDirection: 'row', gap: tema.space.md }}>\n {flate('feil', 'bug', tekst.sporFeil, tekst.sporFeilUnder)}\n {flate('onske', 'bulb', tekst.sporOnske, tekst.sporOnskeUnder)}\n </View>\n </View>\n </View>\n );\n}\n","import type { KnownIssueCard } from '@innspel/core';\nimport React from 'react';\nimport { ActivityIndicator, ScrollView, Text, View } from 'react-native';\nimport { knownIssueStatus } from '../generated/tokens.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Card, H, StatusPill } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\n/** DD-03: maks tre kort. Grensen er klientens — registeret kan ha flere. */\nconst MAKS_KORT = 3;\n\n/**\n * 2c — kjente feil. Differensiatoren: vises FØR feltet i feilsporet, ETTER i\n * ønskesporet.\n *\n * DD-29 gir kortet TRE svar, ikke to: «Ja, jeg også» (Reach +1, ingen ny sak) ·\n * «Ligner, men ikke helt» (eget innspill med lenke, uten tvunget match) · «Nei,\n * det er noe annet» (vanlig innsending). Det midterste er hele poenget — uten\n * det tvinger man et valg mellom å bli talt feil og å ikke bli talt.\n *\n * Tilgjengelighet: kortet er IKKE én knapp. Tre svar må være tre fokusstopp,\n * og `accessible` på kortcontaineren ville slukt dem. I stedet bærer hver\n * knapp kortets tittel i etiketten, så en skjermleserbruker som lander på «Ja,\n * jeg også» vet hvilken feil svaret gjelder. Se `docs/sdk`-notatet i PR-en:\n * `tdd-contract-validation` sa «ett kort = én knapp», skrevet før DD-29.\n *\n * Treffene er et tilbud, aldri en sperre: feiler oppslaget eller er lista tom,\n * hoppes skjermen over uten melding. Det håndteres i Widget, ikke her.\n */\nexport function KjenteFeil({\n kort,\n spor,\n laster,\n sender,\n onJaOgsa,\n onLigner,\n onNei,\n}: {\n kort: KnownIssueCard[];\n spor: 'feil' | 'onske';\n laster?: boolean;\n /** «Ja, jeg også» er underveis: alle svar låses, så ett trykk gir én bekreftelse (C7). */\n sender?: boolean;\n onJaOgsa: (k: KnownIssueCard) => void;\n onLigner: (k: KnownIssueCard) => void;\n onNei: () => void;\n}) {\n const tema = useTema();\n\n if (laster) {\n return (\n <View style={{ flex: 1, gap: tema.space.md }}>\n <H sub={spor === 'onske' ? tekst.kjenteFeilUnderOnske : tekst.kjenteFeilUnderFeil}>\n {spor === 'onske' ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil}\n </H>\n <ActivityIndicator accessibilityLabel=\"Sjekker kjente feil\" color={tema.color.textSecondary} />\n </View>\n );\n }\n\n // Samme form som skjemaet: kortene scroller, «Nei, det er noe annet» står fast.\n // Lista har ingen tak, og med tre kort havnet svaret under navigasjonslinja.\n return (\n <View testID=\"kjente-feil\" style={{ flexGrow: 1, flexShrink: 1, gap: tema.space.md }}>\n <H sub={spor === 'onske' ? tekst.kjenteFeilUnderOnske : tekst.kjenteFeilUnderFeil}>\n {spor === 'onske' ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil}\n </H>\n\n <ScrollView\n testID=\"kjente-feil-liste\"\n style={{ flexGrow: 0, flexShrink: 1 }}\n contentContainerStyle={{ gap: tema.space.md }}\n keyboardShouldPersistTaps=\"handled\"\n >\n {kort.slice(0, MAKS_KORT).map((k) => {\n // Kortet har ALLTID en status (C5/C6): «Aktiv» eller «Rettet», fra\n // knownIssueStatus i temaet. Versjonen er et TILLEGG når den finnes\n // (DD-30: «Rettes i X» når aktiv, «Rettet i X» når fikset) — før\n // 2026-09-14 var pillen borte på et kort uten versjon.\n const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv;\n const versjon = k.fixedIn\n ? k.status === 'fikset'\n ? tekst.rettetI(k.fixedIn)\n : tekst.rettesI(k.fixedIn)\n : undefined;\n const kontekst = versjon ? `${k.title}. ${o.etikett}. ${versjon}` : `${k.title}. ${o.etikett}`;\n\n return (\n <Card key={k.id}>\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n fontWeight: tema.weight.medium,\n }}\n >\n {k.title}\n </Text>\n\n {k.workaround ? (\n <Text\n style={{\n color: tema.color.textSecondary,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {tekst.omvei} {k.workaround}\n </Text>\n ) : null}\n\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.sm, flexWrap: 'wrap' }}>\n <StatusPill ikon={o.ikon} etikett={o.etikett} fg={o.fg} bg={o.bg} />\n {versjon ? (\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>{versjon}</Text>\n ) : null}\n </View>\n\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n <Btn\n grow\n testID={`ja-ogsa-${k.id}`}\n label={tekst.svarJa}\n accessibilityLabel={`${tekst.svarJa}. ${kontekst}`}\n disabled={sender}\n busy={sender}\n onPress={() => onJaOgsa(k)}\n />\n <Btn\n grow\n variant=\"secondary\"\n testID={`ligner-${k.id}`}\n label={tekst.svarLigner}\n accessibilityLabel={`${tekst.svarLigner}. ${kontekst}`}\n disabled={sender}\n onPress={() => onLigner(k)}\n />\n </View>\n </Card>\n );\n })}\n </ScrollView>\n\n <View testID=\"kjente-feil-fot\" style={{ flexShrink: 0 }}>\n <Btn variant=\"secondary\" testID=\"nei-noe-annet\" label={tekst.svarNei} disabled={sender} onPress={onNei} />\n </View>\n </View>\n );\n}\n","import React from 'react';\nimport { Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, H, Hint } from './primitiver.js';\nimport { statusVisning } from './status.js';\nimport { tekst } from './tekster.js';\n\nexport type KvitteringArt = 'feil' | 'onske' | 'jaOgsa' | 'kø';\n\n/**\n * 2g — kvitteringen. Den LOVER noe, per spor (DD-07), og saksnummeret er der\n * så innsenderen kan vise til det hos support.\n *\n * Ingen «vurder appen». Ingen oppfordring til å dele. Innsenderen har nettopp\n * gjort oss en tjeneste — å be om en til er å ta betalt for den.\n *\n * DD-42: feilet vedlegget, er saken likevel sendt. Overskriften sier det rett\n * ut, løftet står, og saksnummeret merkes «uten vedlegg». Køet offline med et\n * skjermbilde: teksten sendes senere, bildet ble aldri køet (DD-41).\n *\n * DD-47: `accessibilityLiveRegion` og rolle `alert` på TEKSTEN, slik at en\n * skjermleser leser kvitteringen når den kommer, uten at brukeren må lete.\n */\nexport function Kvittering({\n art,\n saksnummer,\n vedlegg,\n frist,\n onLukk,\n}: {\n art: KvitteringArt;\n saksnummer?: string;\n /** `feilet`: teksten er lagret, bildet kom ikke med. `forkastet`: køet offline uten bilde. */\n vedlegg?: 'feilet' | 'forkastet';\n /** Svarfristen fra svaret (`deadlineAt`). Tidsløftet er DATOEN, aldri «innen 90 dager» (DD-07, DD-28). */\n frist?: string;\n onLukk: () => void;\n}) {\n const tema = useTema();\n\n const innhold = {\n feil: { h: tekst.kvitteringSendt, p: tekst.kvitteringFeil },\n // Løftet er NØYAKTIG det «Mine innspill» og panelet viser for «Vurderes»:\n // det leses fra temaet, så kvitteringen og statusen ikke kan si to ting.\n onske: { h: tekst.kvitteringSendt, p: statusVisning('vurderes', 'onske', frist).lofte },\n jaOgsa: { h: tekst.kvitteringRegistrert, p: tekst.kvitteringJaOgsa },\n // Køet offline: kvitteringen kan IKKE love svar på noe som ikke er sendt\n // (DD-41 presiserer DD-07). Den lover bare at det sendes.\n kø: { h: tekst.koKvitteringTittel, p: tekst.offlineBanner },\n }[art];\n\n const overskrift = vedlegg === 'feilet' ? tekst.kvitteringVedleggFeilet : innhold.h;\n const brodtekst = vedlegg === 'feilet' ? `${tekst.tekstenErLagret} ${innhold.p}` : innhold.p;\n\n return (\n <View style={{ flex: 1, justifyContent: 'center', gap: tema.space.lg }}>\n <View style={{ alignItems: 'center', gap: tema.space.md }}>\n {/* Det ene stedet ikonet står ALENE og bærer stemningen — derfor `stor`. */}\n <Ikon\n navn={art === 'kø' ? 'swap-vertical-outline' : 'checkmark-circle-outline'}\n storrelse=\"stor\"\n farge={art === 'kø' ? tema.color.neutral : tema.color.success}\n />\n\n <H>{overskrift}</H>\n\n {vedlegg === 'feilet' ? (\n <Banner ikon=\"warning-outline\" tone=\"warning\" children={tekst.vedleggFeiletBanner} />\n ) : null}\n {vedlegg === 'forkastet' ? <Banner ikon=\"image-outline\" tone=\"info\" children={tekst.offlineUtenBilde} /> : null}\n\n <Text\n testID=\"kvittering-tekst\"\n accessibilityRole=\"alert\"\n accessibilityLiveRegion=\"polite\"\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n textAlign: 'center',\n }}\n >\n {brodtekst}\n </Text>\n\n {saksnummer ? (\n <Hint>{vedlegg === 'feilet' ? tekst.saksnummerUtenVedlegg(saksnummer) : tekst.saksnummer(saksnummer)}</Hint>\n ) : null}\n </View>\n\n <Btn testID=\"tilbake-til-appen\" label={tekst.tilbakeTilAppen} onPress={onLukk} />\n </View>\n );\n}\n","import type { SubmissionStatus, SubmissionStatusView, SubmissionType } from '@innspel/core';\nimport { lofteUtenFrist, submissionStatus } from '../generated/tokens.js';\nimport { lofte, tekst } from './tekster.js';\n\n/**\n * Statusen slik innsenderen ser den. ALT kommer fra `submissionStatus` i\n * `theme/theme.ts`, gjennom den genererte mappa: navnet per spor (DD-22),\n * setningen innsenderen får (DD-08), IKONNAVNET og tokennavnene for farge.\n *\n * Navn, farge og løfte sto hardkodet her OG i `@innspel/web` OG i panelet før\n * 2026-09-14 og spriket (UX-gjennomgangen C5). Ikonet sto igjen som emoji til\n * 2026-09-15, fordi Ionicons i React Native krever en peer-avhengighet — se\n * «`react-native-svg` som peer i @innspel/react-native» i `tech-decisions.md`.\n *\n * DD-08 / «Styling» i CLAUDE.md: **farge bærer aldri mening alene.** `brand` og\n * `info`, og `brand` og `danger`, er målt til under 1,5 i innbyrdes kontrast av\n * tema-generatoren, så etiketten er det som faktisk bærer meningen.\n */\nexport interface StatusVisning {\n /** Ionicons-navn fra temaet — aldri en emoji (brand-ui-guidelines). */\n ikon: string;\n etikett: string;\n /** Tokennavn i den aktive paletten, ikke en farge. */\n fg: string;\n bg: string;\n lofte: string;\n}\n\n/** Norsk dato uten klokkeslett — fristen er en dato, ikke et tidspunkt (DD-28). */\nexport function formaterFrist(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n return new Intl.DateTimeFormat('nb-NO', { day: 'numeric', month: 'long' }).format(d);\n}\n\n/**\n * Oversetter en innsending til det innsenderen skal se.\n *\n * @param status Maskinens status fra kontrakten.\n * @param type Sporet — avgjør «Rettet» mot «Levert» (DD-22).\n * @param deadlineAt Svarfristen, satt kun i `vurderes`.\n */\nexport function statusVisning(status: SubmissionStatus, type: SubmissionType, deadlineAt?: string): StatusVisning {\n const o = submissionStatus[status];\n const spor: 'feil' | 'onske' = type === 'onske' ? 'onske' : 'feil';\n return {\n ikon: o.ikon,\n etikett: o.etikett[spor],\n fg: o.fg,\n bg: o.bg,\n lofte: settInnFrist(o.lofte[spor], deadlineAt),\n };\n}\n\n/**\n * `{frist}` byttes med datoen (DD-28). Uten frist finnes ikke tidsløftet, og da\n * står den fristløse setningen i stedet — aldri en tom plassholder på skjermen.\n */\nfunction settInnFrist(mal: string, deadlineAt: string | undefined): string {\n if (!mal.includes('{frist}')) return mal;\n return deadlineAt ? mal.replace('{frist}', formaterFrist(deadlineAt)) : lofteUtenFrist;\n}\n\n/** Raden som venter på nett (DD-41). Den har ingen saksnummer og intet løfte om svar. */\nexport const venterVisning: StatusVisning = {\n ikon: 'cloud-offline-outline',\n etikett: 'Venter på nett',\n fg: 'textSecondary',\n bg: 'neutralBg',\n lofte: lofte.venterNett,\n};\n\n/**\n * Etikett for en hel rad, brukt som skjermleserens sammendrag. Ikonet er\n * `aria-hidden` i UI-et, så etiketten må bære alt.\n */\nexport function radEtikett(rad: SubmissionStatusView): string {\n const v = statusVisning(rad.status, rad.type, rad.deadlineAt);\n const spor = rad.type === 'onske' ? tekst.onske : tekst.feil;\n return `${tekst.sakHode(spor, rad.id)}: ${rad.text}. Status ${v.etikett.toLowerCase()}. ${v.lofte}`;\n}\n","import type { InnspelStorage, MySubmission } from '@innspel/core';\nimport React, { useEffect, useState } from 'react';\nimport { ActivityIndicator, ScrollView, Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Card, H, Hint, StatusPill } from './primitiver.js';\nimport { markerSvarSett, merkNyeSvar } from './nyttSvar.js';\nimport { statusVisning, venterVisning } from './status.js';\nimport { tekst } from './tekster.js';\n\n/**\n * 2j — «Mine innspill» (DD-27).\n *\n * To ting skjer her som ikke skjer noe annet sted:\n *\n * - **Offline-køen er synlig** (DD-41). Raden som venter på nett står øverst,\n * uten saksnummer, med «Venter på nett — sendes automatisk». Shake er den\n * eneste leverandøren som viser dette til brukeren; alle andre skjuler køen,\n * og en usynlig kø er ikke til å skille fra tapt tekst.\n * - **Svaret står under saken**, ordrett som i panelet. Innsenderen skal ikke\n * måtte lete etter svaret i en e-post som aldri kom — plattformen sender\n * ingen e-post (K14).\n */\nexport function MineInnspill({\n rader,\n laster,\n tenantName,\n onNytt,\n storage,\n}: {\n rader: MySubmission[];\n laster?: boolean;\n tenantName?: string;\n onNytt: () => void;\n /** Vertens lagring — «nytt svar» er per enhet, aldri noe plattformen vet (F14). */\n storage: InnspelStorage;\n}) {\n const tema = useTema();\n\n // F14: nye svar først, og merket. «Nytt» er «kommet siden forrige gang denne enheten\n // viste lista» — kjernen eier både definisjonen og lagringen, så widget og portal kan\n // ikke drive fra hverandre. Feiler lagringen, vises lista umerket i serverens rekkefølge.\n const [visning, setVisning] = useState<{ rad: MySubmission; nytt: boolean }[]>(() => rader.map((rad) => ({ rad, nytt: false })));\n useEffect(() => {\n let gjelder = true;\n void merkNyeSvar(rader, storage)\n .then((m) => {\n if (gjelder) setVisning(m);\n })\n .catch(() => {\n if (gjelder) setVisning(rader.map((rad) => ({ rad, nytt: false })));\n });\n return () => {\n gjelder = false;\n };\n }, [storage, rader]);\n\n // Lista er vist. Ved neste åpning er disse svarene ikke nye lenger.\n useEffect(() => {\n if (!laster && rader.length) void markerSvarSett(storage).catch(() => undefined);\n }, [storage, laster, rader]);\n\n return (\n <View style={{ flex: 1, gap: tema.space.md }}>\n <H sub={tekst.mineUnder}>{tekst.mineTittel}</H>\n\n {laster ? (\n <ActivityIndicator accessibilityLabel=\"Henter innspillene dine\" color={tema.color.textSecondary} />\n ) : rader.length === 0 ? (\n <Hint>{tekst.mineTom}</Hint>\n ) : (\n <ScrollView style={{ flex: 1 }} contentContainerStyle={{ gap: tema.space.sm }}>\n {visning.map(({ rad, nytt }) => {\n const venter = rad.pending === true;\n const v = venter ? venterVisning : statusVisning(rad.status, rad.type, rad.deadlineAt);\n const nokkel = venter ? rad.clientRef : rad.id;\n const svar = venter ? undefined : rad.reply;\n\n return (\n <Card key={nokkel} dashed={venter}>\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs, flexWrap: 'wrap' }}>\n <Hint>\n {venter\n ? `${tekst.mineIkkeSendt} · ${rad.type === 'onske' ? tekst.onske : tekst.feil}`\n : tekst.sakHode(rad.type === 'onske' ? tekst.onske : tekst.feil, rad.id)}\n </Hint>\n {nytt ? (\n <Text\n testID=\"nytt-svar\"\n style={{\n color: tema.color.info,\n backgroundColor: tema.color.infoBg,\n fontSize: tema.font.tiny,\n fontWeight: tema.weight.semibold,\n borderRadius: tema.radius.pill,\n paddingHorizontal: tema.space.sm,\n }}\n >\n {tekst.nyttSvar}\n </Text>\n ) : null}\n </View>\n\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n }}\n >\n {rad.text}\n </Text>\n\n <View style={{ gap: tema.space.xs }}>\n <StatusPill ikon={v.ikon} etikett={v.etikett} fg={v.fg} bg={v.bg} />\n <Hint>{v.lofte}</Hint>\n </View>\n\n {!venter && rad.attachmentRemoved ? (\n <View testID={`bilde-fjernet-${rad.id}`} style={{ flexDirection: 'row', gap: tema.space.xs, alignItems: 'center' }}>\n <Ikon navn=\"trash-outline\" storrelse=\"minste\" farge={tema.color.textMuted} />\n <Hint>{tekst.bildeFjernet}</Hint>\n </View>\n ) : null}\n\n {svar ? (\n <View\n style={{\n borderLeftWidth: tema.hairline * 2,\n borderLeftColor: tema.color.brand,\n paddingLeft: tema.space.sm,\n gap: tema.space.xs,\n }}\n >\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>\n {tenantName ? tekst.svarFra(tenantName) : tekst.svarFraGenerisk}\n </Text>\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.small,\n lineHeight: tema.lineHeight.small,\n }}\n >\n {svar.text}\n </Text>\n </View>\n ) : null}\n </Card>\n );\n })}\n </ScrollView>\n )}\n\n <Btn testID=\"send-nytt\" label={rader.length === 0 ? tekst.sendForste : tekst.sendNytt} onPress={onNytt} />\n </View>\n );\n}\n","import type { InnspelStorage, MySubmission } from '@innspel/core';\n\n/**\n * F14 (brukerreisene 2026-09-15) — «Saken med nytt svar ligger ikke øverst og er ikke\n * merket.» Produkteier svarte i panelet; i appen sto feilen nummer to, under et ønske uten\n * nytt svar, og ingenting sa at det var kommet noe.\n *\n * Løftet er at alle får svar. Et svar innsenderen ikke oppdager, er et brutt løfte — og\n * lista er sortert på når saken ble SENDT (serveren: `OrderByDescending(CreatedAt)`), som\n * ikke sier noe om når det skjedde noe med den.\n *\n * **Hva «nytt» betyr her.** Plattformen eier aldri sluttbrukere, og skal ikke vite hva hun\n * har lest. «Nytt» er derfor «kommet siden forrige gang DENNE enheten viste lista»: ett\n * tidspunkt i lagringen verten allerede injiserer, ingen serverstate, ingen pseudonym, og\n * ingenting som forlater enheten. Bytter hun telefon, ser hun svarene som nye én gang til\n * — en ærlig pris for ikke å spore mennesker.\n *\n * **Hvorfor her og ikke i `@innspel/core`.** Kjernen har et hardt tak på 10 kB gzip\n * (CLAUDE.md), og modulen dyttet den til 10273 B. En visningsregel er ikke verdt kjernens\n * budsjett. Skal `@innspel/web` ha det samme, kopieres de femten linjene dit — billigere\n * enn å bryte taket eller å presse koden til den blir uleselig.\n *\n * Forkastet: sortering på svartidspunkt alene, uten merke — da ville et svar fra i fjor\n * ligget øverst for alltid. Forkastet: å la serveren avgjøre — den måtte lagret «sett» per\n * pseudonym, altså nettopp det plattformen ikke skal vite.\n */\n\nconst NØKKEL = 'innspel:svar-sett';\n\n/** En rad med om svaret på den er kommet siden sist enheten viste lista. */\nexport interface MedNyhet {\n rad: MySubmission;\n nytt: boolean;\n}\n\n/**\n * Radene med nye svar først, hver merket. Rekkefølgen ellers er serverens — nyest sendt\n * først, som fortsatt er riktig for alt uten nytt svar. Køede rader har intet svar og er\n * aldri nye. En ødelagt eller uleselig lagring gir «alt er nytt»: heller vise at det finnes\n * svar enn å gjemme dem.\n */\nexport async function merkNyeSvar(rader: readonly MySubmission[], storage: InnspelStorage): Promise<MedNyhet[]> {\n let grense = 0;\n try {\n grense = Number.parseInt((await storage.get(NØKKEL)) ?? '', 10) || 0;\n } catch {\n grense = 0;\n }\n const tid = (r: MySubmission) => (r.pending === true ? NaN : Date.parse(r.reply?.at ?? ''));\n const merket = rader.map((rad) => ({ rad, nytt: tid(rad) > grense }));\n return [...merket.filter((m) => m.nytt), ...merket.filter((m) => !m.nytt)];\n}\n\n/**\n * Setter «sist sett» til nå. Kalles når innsenderen HAR sett lista — ikke når den hentes i\n * bakgrunnen for tellingen på knappen (DD-62), for da har hun ikke sett noe. Feiler\n * lagringen, vises merket én gang for mye; det er ikke verdt å avbryte visningen for.\n */\nexport async function markerSvarSett(storage: InnspelStorage, nå: number = Date.now()): Promise<void> {\n try {\n await storage.set(NØKKEL, String(nå));\n } catch {\n /* vertens lagring — ikke vår å redde */\n }\n}\n","import { skaler, strokTilRekter, treffer, trykkTilRekt, type MaskPoint, type MaskRect } from '@innspel/core';\nimport React, { useCallback, useMemo, useRef, useState, type RefObject } from 'react';\nimport { Image, Pressable, StyleSheet, Text, View, type GestureResponderEvent, type LayoutChangeEvent } from 'react-native';\nimport { screenRules } from '../generated/tokens.js';\nimport { Ikon } from '../Ikon.js';\nimport type { ScreenshotCapture, ViewRef } from '../skjermbilde.js';\nimport { useTema } from '../tema.js';\nimport { Btn, H, Hint } from './primitiver.js';\nimport { tekst } from './tekster.js';\n\nexport type MaskVerktoy = 'felt' | 'pensel';\n\n/**\n * 2f — skjermbildet, tatt ved trykk og forhåndsvist (K4). Tre likestilte\n * maskeringsveier (DD-40): «Masker felt» (ett trykk legger en boks), «Tegn over»\n * (fingerstrøk) og «Masker all tekst» (heldekkende uskarphet — se DD-40,\n * presisert for RN). Private views (DD-39) ligger der FØR innsenderen ser bildet,\n * merket «Maskert av appen», og kan ikke fjernes. Egne masker fjernes med ett\n * trykk på dem.\n *\n * Maskeringen skjer i bitmapen ved komposisjon: bildet vises med maskeringslagene\n * over, og «Legg ved og fortsett» fanger denne viewen på nytt. Det er komposittet\n * som lastes opp — rå-URI-en forlater aldri widgeten.\n *\n * Fargene her er `screenRules`: det ene stedet temaet ikke gjelder, fordi\n * maskene må være synlige uansett hva skjermbildet selv inneholder.\n */\nexport function Skjermbilde({\n bilde,\n automaskerRot,\n rotStorrelse,\n previewRef,\n komponerer,\n kilde = 'skjerm',\n notat,\n onFjern,\n onLeggVed,\n}: {\n bilde: ScreenshotCapture;\n /** Private views i vertsappens punkter (relativt til rot-viewen). */\n automaskerRot: MaskRect[];\n rotStorrelse: { width: number; height: number };\n previewRef: RefObject<ViewRef | null>;\n komponerer: boolean;\n /** Fra galleriet: private views kan ikke gjelde, og forhåndsvisningen sier det. */\n kilde?: 'skjerm' | 'galleri';\n /** Vertens setning ved bildesteget. */\n notat?: string;\n onFjern: () => void;\n onLeggVed: () => void;\n}) {\n const tema = useTema();\n const [verktoy, setVerktoy] = useState<MaskVerktoy>('pensel');\n const [allTekst, setAllTekst] = useState(false);\n const [egne, setEgne] = useState<MaskRect[]>([]);\n const [ramme, setRamme] = useState<{ width: number; height: number } | null>(null);\n const strok = useRef<MaskPoint[]>([]);\n\n // Bildet tilpasses rammen med bevart sideforhold; alt annet regnes i visningens punkter.\n const visning = useMemo(() => {\n if (!ramme) return null;\n const s = Math.min(ramme.width / bilde.width, ramme.height / bilde.height);\n return { width: Math.floor(bilde.width * s), height: Math.floor(bilde.height * s) };\n }, [ramme, bilde.width, bilde.height]);\n\n const automasker = useMemo(\n () => (visning ? automaskerRot.map((r) => skaler(r, rotStorrelse, visning)) : []),\n [automaskerRot, rotStorrelse, visning],\n );\n\n const onLayout = useCallback((e: LayoutChangeEvent) => {\n const { width, height } = e.nativeEvent.layout;\n setRamme({ width, height });\n }, []);\n\n const punkt = (e: GestureResponderEvent): MaskPoint => ({ x: e.nativeEvent.locationX, y: e.nativeEvent.locationY });\n\n const onGrant = (e: GestureResponderEvent) => {\n if (!visning) return;\n const p = punkt(e);\n // Ett trykk på en egen maske angrer den (wireframe 2f). Private views rører den aldri.\n const treff = egne.findIndex((r) => treffer(p, r));\n if (treff >= 0) {\n setEgne((x) => x.filter((_, i) => i !== treff));\n return;\n }\n if (verktoy === 'felt') {\n const r = trykkTilRekt(p, { width: tema.touch * 4, height: tema.touch }, visning);\n if (r) setEgne((x) => [...x, r]);\n return;\n }\n strok.current = [p];\n };\n\n const onMove = (e: GestureResponderEvent) => {\n if (verktoy !== 'pensel' || strok.current.length === 0) return;\n strok.current.push(punkt(e));\n };\n\n const onRelease = () => {\n if (verktoy !== 'pensel' || !visning || strok.current.length === 0) return;\n const rekter = strokTilRekter(strok.current, screenRules.brushWidth, visning);\n strok.current = [];\n if (rekter.length) setEgne((x) => [...x, ...rekter]);\n };\n\n const knapp = (id: MaskVerktoy | 'allTekst', ikon: string, label: string) => {\n const valgt = id === 'allTekst' ? allTekst : verktoy === id && !allTekst;\n return (\n <Pressable\n key={id}\n testID={`verktoy-${id}`}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n accessibilityState={{ selected: valgt }}\n onPress={() => (id === 'allTekst' ? setAllTekst((a) => !a) : setVerktoy(id))}\n style={{\n flex: 1,\n minHeight: tema.touch,\n alignItems: 'center',\n justifyContent: 'center',\n gap: tema.space.xs,\n padding: tema.space.xs,\n borderRadius: tema.radius.md,\n borderWidth: tema.hairline,\n borderColor: tema.color.actionSecondaryBorder,\n borderBottomWidth: valgt ? tema.hairline * 2 : tema.hairline,\n borderBottomColor: valgt ? tema.color.textPrimary : tema.color.actionSecondaryBorder,\n backgroundColor: valgt ? tema.color.surfaceRaised : 'transparent',\n }}\n >\n <Ikon navn={ikon} farge={tema.color.textPrimary} />\n <Text\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.small,\n fontWeight: valgt ? tema.weight.semibold : tema.weight.regular,\n }}\n >\n {label}\n </Text>\n </Pressable>\n );\n };\n\n const a11y = tekst.skjermbildeA11y(automasker.length, egne.length, allTekst);\n\n // Høyden kommer ovenfra: arket har fast høyde i dette steget (Widget.tsx), rammen får det\n // som er igjen etter overskrift, verktøylinje og fot, og forhåndsvisningen ligger OVER rammen\n // i stedet for i flyten. Før vokste rammen med visningen, onLayout ga ny ramme, og et 9:20-\n // bilde endte begrenset av bredden alene — knappene havnet under navigasjonslinja. Ingen\n // scroll: berøring på forhåndsvisningen er maskering.\n return (\n <View testID=\"skjermbilde-steg\" style={{ flexGrow: 1, flexShrink: 1, gap: tema.space.md }}>\n <H sub={kilde === 'galleri' ? tekst.skjermbildeUnderGalleri : tekst.skjermbildeUnder}>{tekst.skjermbildeTittel}</H>\n {notat ? (\n <View testID=\"bilde-notat\">\n <Hint>{notat}</Hint>\n </View>\n ) : null}\n\n <View accessibilityRole=\"toolbar\" accessibilityLabel={tekst.maskering} style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {knapp('felt', 'scan-outline', tekst.maskerFelt)}\n {knapp('pensel', 'brush-outline', tekst.tegnOver)}\n {knapp('allTekst', 'grid-outline', tekst.maskerAllTekst)}\n </View>\n\n <View\n testID=\"skjermbilde-ramme\"\n onLayout={onLayout}\n style={{\n flexGrow: 1,\n flexShrink: 1,\n flexBasis: 0,\n minHeight: tema.touch * 5,\n backgroundColor: screenRules.previewBackdrop,\n borderRadius: tema.radius.md,\n overflow: 'hidden',\n }}\n >\n <View testID=\"skjermbilde-flate\" pointerEvents=\"box-none\" style={[StyleSheet.absoluteFill, { alignItems: 'center', justifyContent: 'center' }]}>\n {visning ? (\n <View\n ref={previewRef}\n collapsable={false}\n testID=\"forhandsvisning\"\n accessibilityRole=\"image\"\n accessibilityLabel={a11y}\n onStartShouldSetResponder={() => !komponerer}\n onMoveShouldSetResponder={() => !komponerer}\n onResponderGrant={onGrant}\n onResponderMove={onMove}\n onResponderRelease={onRelease}\n onResponderTerminate={onRelease}\n style={{ width: visning.width, height: visning.height, backgroundColor: screenRules.previewBackdrop }}\n >\n <Image\n testID=\"skjermbilde-bilde\"\n source={{ uri: bilde.uri }}\n blurRadius={allTekst ? screenRules.textBlurRadius : 0}\n style={{ width: visning.width, height: visning.height }}\n accessibilityIgnoresInvertColors\n />\n\n {automasker.map((r, i) => (\n <View\n key={`auto-${i}`}\n testID={`automask-${i}`}\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: r.x,\n top: r.y,\n width: r.width,\n height: r.height,\n backgroundColor: screenRules.autoMaskFill,\n borderWidth: tema.hairline * 2,\n borderColor: screenRules.autoMaskStroke,\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {!komponerer ? (\n // Etiketten står PÅ den maskerte flaten og måles mot NETTOPP den\n // (skjermKontrastpar i theme.ts). textSecondary var 2,2:1 (C11a).\n // Ikonet arver samme farge: det er unntaket i «Styling» — maskeringen\n // tegnes i faste signalfarger, ikke i palettens.\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"lock-closed-outline\" storrelse=\"minste\" farge={screenRules.autoMaskText} />\n <Text style={{ color: screenRules.autoMaskText, fontSize: tema.font.small }} numberOfLines={1}>\n {tekst.maskertAvAppen}\n </Text>\n </View>\n ) : null}\n </View>\n ))}\n\n {egne.map((r, i) => (\n <View\n key={`egen-${i}`}\n testID={`maske-${i}`}\n pointerEvents=\"none\"\n style={{ position: 'absolute', left: r.x, top: r.y, width: r.width, height: r.height, backgroundColor: screenRules.brushFill }}\n />\n ))}\n </View>\n ) : null}\n </View>\n </View>\n\n {automasker.length ? (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"lock-closed-outline\" storrelse=\"minste\" farge={tema.color.textMuted} />\n <Hint>{tekst.maskertAvAppenHint}</Hint>\n </View>\n ) : null}\n {egne.length ? <Hint>{tekst.dittStrok}</Hint> : null}\n {allTekst ? <Hint>{tekst.allTekstHint}</Hint> : null}\n\n <View testID=\"skjermbilde-fot\" style={{ flexShrink: 0, gap: tema.space.sm }}>\n {/* «Angre siste» som KNAPP: å treffe en maske med fingeren er en motorisk\n oppgave, og angrefunksjonen kan ikke være den eneste veien tilbake — samme\n grunn som DD-40 gir både pensel og knapp (C11d). */}\n <Btn\n variant=\"secondary\"\n testID=\"angre-siste\"\n label={tekst.angreSiste}\n accessibilityLabel={tekst.angreSisteA11y}\n disabled={komponerer || egne.length === 0}\n onPress={() => setEgne((x) => x.slice(0, -1))}\n />\n <Btn\n variant=\"danger\"\n testID=\"fjern-bildet\"\n ikon=\"trash-outline\"\n label={tekst.fjernBildet}\n onPress={onFjern}\n disabled={komponerer}\n />\n <Btn testID=\"legg-ved\" label={tekst.leggVed} onPress={onLeggVed} disabled={komponerer || !visning} />\n </View>\n </View>\n );\n}\n","import React, { useEffect, useRef } from 'react';\nimport { View, type StyleProp, type ViewStyle } from 'react-native';\nimport { useSkjermbilde, type ViewRef } from './skjermbilde.js';\n\n/**\n * Merk det som aldri skal være med på et skjermbilde (DD-39): navn i en liste,\n * et kontonummer, en samtale. Pakk det inn, og widgeten maskerer det FØR\n * innsenderen ser forhåndsvisningen — som «Maskert av appen», og penselen kan\n * ikke oppheve det. Din kode er sannheten, ikke brukerens presisjon.\n *\n * Uten skjermbilde-adapter gjør komponenten ingenting utover å rendre barna.\n *\n * @example\n * ```tsx\n * <InnspelPrivate><Text>{bruker.navn}</Text></InnspelPrivate>\n * ```\n */\nexport function InnspelPrivate({ children, style }: { children?: React.ReactNode; style?: StyleProp<ViewStyle> }) {\n const ref = useRef<ViewRef | null>(null);\n const kontekst = useSkjermbilde();\n const registrer = kontekst?.privat.register;\n\n useEffect(() => {\n if (!registrer) return;\n return registrer(ref);\n }, [registrer]);\n\n // collapsable={false}: Android slår ellers sammen en View uten stil med\n // forelderen, og da finnes det ingenting å måle.\n return (\n <View ref={ref} collapsable={false} style={style} testID=\"innspel-privat\">\n {children}\n </View>\n );\n}\n","import {\n InnspelApiError,\n type FollowUpView,\n type MyPrograms,\n type ParticipationView,\n type ProgramTask,\n type ProgramView,\n type TaskOutcome,\n} from '@innspel/core';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { Modal, Pressable, Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useInnspel } from '../InnspelProvider.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, Card, H, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\nimport { Aksept } from './Aksept.js';\nimport { HvordanGikkDet } from './HvordanGikkDet.js';\nimport { Oppfolging } from './Oppfolging.js';\nimport { Oppgaver } from './Oppgaver.js';\nimport { periode } from './periode.js';\n\ntype Dialog = { type: 'oppgave'; task: ProgramTask } | { type: 'oppfolging'; oppfolging: FollowUpView };\n\n/**\n * Betaprogrammet i vertsappen: 3a banneret, 3b aksepten og deltakelsen med\n * «Gå ut» (DD-36). Sett den der vertsappen vil ha invitasjonen — typisk øverst\n * på hjemskjermen. Uten invitasjon og uten deltakelse rendrer den INGENTING;\n * det er wireframens «tom → fanen skjules helt», ikke en tom tilstand.\n *\n * **Tokenet kommer fra verten** (DD-12). Plattformen sender aldri invitasjonen:\n * leietakeren får `program.invitation_created` med tokenet, løser pseudonymet til\n * sin egen bruker og sender lenken i sin egen kanal. Verten fanger tokenet fra\n * dyplenken og gir det hit. Uten det viser banneret fortsatt invitasjonen — men\n * «Bli med» er inaktiv, med lenken forklart, i stedet for å feile ved trykk.\n *\n * Deltakelsen (3c) viser oppgavene med «Gjort» → «Hvordan gikk det?» (tre lukkede\n * valg og en setning, aldri en skala) og oppfølgingskortene (3d, DD-34), der arten\n * avgjør knappene. «Ikke» tilbyr å melde feilen — til verten via `onMeldFeil`, fordi\n * feilsporet og navigasjonen er vertens.\n *\n * @example\n * ```tsx\n * <InnspelProgram invitationToken={tokenFraDyplenke} />\n * ```\n */\nexport function InnspelProgram({\n invitationToken,\n onEndring,\n onMeldFeil,\n}: {\n /** Engangs-tokenet fra leietakerens egen kanal, typisk fanget fra en dyplenke. */\n invitationToken?: string;\n /** Kalles når testeren blir med eller går ut — for vertens egen navigasjon. */\n onEndring?: (deltakelse: ParticipationView | null) => void;\n /** Kalles når testeren vil melde at en oppgave ikke gikk — verten åpner feilsporet med oppgaven som kontekst. Utelatt = tilbudet vises ikke. */\n onMeldFeil?: (task: ProgramTask) => void;\n}) {\n const { client } = useInnspel();\n const tema = useTema();\n\n const [mine, setMine] = useState<MyPrograms | undefined>();\n const [deltakelse, setDeltakelse] = useState<ParticipationView | undefined>();\n const [viserAksept, setViserAksept] = useState(false);\n const [viserGaaUt, setViserGaaUt] = useState(false);\n const [avvist, setAvvist] = useState(false);\n const [sender, setSender] = useState(false);\n const [feil, setFeil] = useState<string | undefined>();\n const [dialog, setDialog] = useState<Dialog | undefined>();\n const [svarFeil, setSvarFeil] = useState<string | undefined>();\n const [lagtBort, setLagtBort] = useState<ReadonlySet<string>>(new Set());\n const [meldFeilFor, setMeldFeilFor] = useState<ProgramTask | undefined>();\n\n const leggBort = useCallback((id: string) => setLagtBort((s) => new Set([...s, id])), []);\n\n // «Lagre» i «Hvordan gikk det?»: én dialog, to mål. Fullføringen legges på deltakelsen\n // så raden viser svaret straks; et svar på oppfølging tar kortet ut av lista.\n const lagreSvar = useCallback(\n async (outcome: TaskOutcome, text: string | undefined) => {\n if (!dialog || !deltakelse) return;\n setSender(true);\n setSvarFeil(undefined);\n try {\n if (dialog.type === 'oppgave') {\n const ny = await client.programs.completeTask(dialog.task.id, { outcome, ...(text ? { text } : {}) });\n setDeltakelse({ ...deltakelse, completions: [...deltakelse.completions, ny] });\n if (outcome === 'ikke' && onMeldFeil) setMeldFeilFor(dialog.task);\n } else {\n await client.programs.respond(dialog.oppfolging.id, { outcome, ...(text ? { text } : {}) });\n setMine((m) => (m ? { ...m, pendingFollowUps: m.pendingFollowUps.filter((f) => f.id !== dialog.oppfolging.id) } : m));\n }\n setDialog(undefined);\n } catch (e) {\n setSvarFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n },\n [client, deltakelse, dialog, onMeldFeil],\n );\n\n // Anonym modus har ingen programmer, og skal ikke spørre: kallet ville blitt\n // 401 uansett, og et kall som alltid feiler er ikke en tilstand — det er støy.\n useEffect(() => {\n if (client.isAnonymous) return;\n let levende = true;\n void client.programs\n .list()\n .then((svar) => {\n if (!levende) return;\n setMine(svar);\n // Aktiv deltakelse er det som vises; trukket kommer aldri tilbake fra listen.\n setDeltakelse(svar.participations.find((p) => p.status !== 'trukket'));\n })\n // Programmet er et tilbud, aldri en sperre: svarer ikke kallet, finnes\n // banneret ikke — vertsappen står uendret.\n .catch(() => undefined);\n return () => {\n levende = false;\n };\n }, [client]);\n\n const bliMed = useCallback(async () => {\n if (!invitationToken) return;\n setSender(true);\n setFeil(undefined);\n try {\n const ny = await client.programs.accept(invitationToken);\n setDeltakelse(ny);\n setViserAksept(false);\n onEndring?.(ny);\n } catch (e) {\n setFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n }, [client, invitationToken, onEndring]);\n\n const gaaUt = useCallback(async () => {\n if (!deltakelse) return;\n setSender(true);\n try {\n await client.programs.withdraw(deltakelse.id);\n setDeltakelse(undefined);\n setViserGaaUt(false);\n onEndring?.(null);\n } catch (e) {\n setFeil(e instanceof InnspelApiError ? e.message : 'tjeneren svarte ikke.');\n } finally {\n setSender(false);\n }\n }, [client, deltakelse, onEndring]);\n\n // Deltakelsen vinner over invitasjonen: har man sagt ja, er banneret ferdig.\n const invitasjon = deltakelse ? undefined : mine?.invitations[0];\n const program: ProgramView | undefined = deltakelse?.program ?? invitasjon?.program;\n\n if (!program) return null;\n\n if (deltakelse) {\n // 3d: kortene for DETTE programmet, i den rekkefølgen kontaktene kom. Et kort testeren\n // har lagt bort i denne økten vises ikke igjen før neste oppstart.\n const kort = (mine?.pendingFollowUps ?? [])\n .filter((f) => f.programId === program.id && !lagtBort.has(f.id))\n .sort((a, b) => a.emittedAt.localeCompare(b.emittedAt));\n const forsteKontaktNr = Math.max(1, deltakelse.contactsSent - kort.length + 1);\n\n return (\n <View testID=\"program-deltakelse\" accessibilityLabel={tekst.deltakelseRegion} style={{ gap: tema.space.sm }}>\n {kort.map((f, i) => (\n <Oppfolging\n key={f.id}\n oppfolging={f}\n kontaktNr={forsteKontaktNr + i}\n maksKontakter={program.maxContacts}\n onSenere={() => leggBort(f.id)}\n onSvar={() => {\n setSvarFeil(undefined);\n setDialog({ type: 'oppfolging', oppfolging: f });\n }}\n onAapneOppgavene={() => leggBort(f.id)}\n onGaaUt={() => setViserGaaUt(true)}\n />\n ))}\n\n <Card>\n <H sub={tekst.deltakelsePeriode(periode(program.opensAt, program.closesAt), deltakelse.contactsSent, program.maxContacts)}>\n {program.name}\n </H>\n <Oppgaver\n tasks={program.tasks}\n completions={deltakelse.completions}\n onGjort={(task) => {\n setSvarFeil(undefined);\n setDialog({ type: 'oppgave', task });\n }}\n />\n {meldFeilFor && onMeldFeil ? (\n <View style={{ gap: tema.space.xs }}>\n <Hint>{tekst.meldFeilHint}</Hint>\n <Btn\n variant=\"secondary\"\n testID=\"meld-feil\"\n ikon=\"bug-outline\"\n label={tekst.meldFeil}\n onPress={() => {\n const task = meldFeilFor;\n setMeldFeilFor(undefined);\n onMeldFeil(task);\n }}\n />\n </View>\n ) : null}\n {/* DD-36: «Gå ut» er ALLTID synlig — aldri gjemt bak en meny eller under rullefeltet. */}\n <Btn variant=\"ghost\" testID=\"gaa-ut\" ikon=\"exit-outline\" label={tekst.gaaUt} onPress={() => setViserGaaUt(true)} />\n </Card>\n\n {dialog ? (\n <HvordanGikkDet\n under={dialog.type === 'oppgave' ? dialog.task.title : dialog.oppfolging.question}\n sender={sender}\n {...(svarFeil ? { feil: svarFeil } : {})}\n onLagre={(outcome, text) => void lagreSvar(outcome, text)}\n onLukk={() => setDialog(undefined)}\n />\n ) : null}\n\n {viserGaaUt ? (\n <Modal visible transparent animationType=\"fade\" onRequestClose={() => setViserGaaUt(false)} accessibilityViewIsModal>\n <View style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end', padding: tema.space.md }}>\n <View\n testID=\"gaa-ut-dialog\"\n accessibilityViewIsModal\n style={{\n backgroundColor: tema.color.surface,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n padding: tema.space.md,\n gap: tema.space.md,\n }}\n >\n <H>{tekst.gaaUtTittel}</H>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {tekst.gaaUtTekst(program.name)}\n </Text>\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {/* «Bli værende» står først: utgangen er et valg, ikke en felle med en angreknapp. */}\n <Btn grow variant=\"secondary\" testID=\"bli-vaerende\" label={tekst.bliVaerende} onPress={() => setViserGaaUt(false)} />\n <Btn\n grow\n variant=\"danger\"\n testID=\"bekreft-gaa-ut\"\n ikon=\"exit-outline\"\n label={tekst.gaaUtBekreft}\n disabled={sender}\n onPress={() => void gaaUt()}\n />\n </View>\n </View>\n </View>\n </Modal>\n ) : null}\n </View>\n );\n }\n\n if (!invitasjon || avvist) return null;\n\n return (\n <>\n <View\n testID=\"program-banner\"\n accessibilityLabel={tekst.invitasjonRegion}\n style={{\n backgroundColor: tema.color.brandBg,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.brand,\n padding: tema.space.md,\n gap: tema.space.sm,\n }}\n >\n <View style={{ flexDirection: 'row', gap: tema.space.sm, alignItems: 'flex-start' }}>\n <Ikon navn=\"flask-outline\" farge={tema.color.textPrimary} />\n <View style={{ flex: 1, gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {tekst.invitasjonHva(program.name)}\n </Text>\n <Hint>{tekst.invitasjonKontakter(program.maxContacts)}</Hint>\n </View>\n {/* Avvisbart: invitasjonen er et tilbud. Den kommer tilbake ved neste oppstart, aldri som mas i samme økt. */}\n <Pressable\n testID=\"avvis-invitasjon\"\n accessibilityRole=\"button\"\n accessibilityLabel={tekst.avvisInvitasjon}\n onPress={() => setAvvist(true)}\n style={{ minWidth: tema.touch, minHeight: tema.touch, alignItems: 'center', justifyContent: 'center' }}\n >\n <Ikon navn=\"close-outline\" farge={tema.color.textSecondary} />\n </Pressable>\n </View>\n {feil && !viserAksept ? (\n <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.akseptFeil(feil)} />\n ) : null}\n <Btn variant=\"secondary\" testID=\"les-mer\" label={tekst.lesMer} onPress={() => setViserAksept(true)} />\n </View>\n\n {viserAksept ? (\n <Aksept\n program={program}\n harToken={!!invitationToken}\n sender={sender}\n {...(feil ? { feil } : {})}\n onBliMed={() => void bliMed()}\n onLukk={() => setViserAksept(false)}\n />\n ) : null}\n </>\n );\n}\n","import type { ProgramView } from '@innspel/core';\nimport React from 'react';\nimport { Linking, Modal, Pressable, ScrollView, Text, View } from 'react-native';\nimport { knownIssueStatus } from '../generated/tokens.js';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, Card, H, Hint, StatusPill } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\nimport { minutterPerOppgave, periode } from './periode.js';\n\n/**\n * 3b — aksepten. Én skjerm i fast rekkefølge (DD-13) med TALLENE øverst (DD-32):\n * N oppgaver × M minutter, dato til dato, maks K kontakter. Oppgavene står HER,\n * ikke i en e-post etterpå, og kjente feil er hele lista — testeren skal slippe\n * å melde det vi vet om.\n *\n * Vilkår er en LENKE, aldri en avkryssing (DD-37); ved forpliktelsesfri form\n * (tvunget når leietakeren har mindreårige brukere, K37) finnes ingen vilkår ut\n * over at man kan gå ut når som helst.\n *\n * «Bli med» krever tokenet leietakeren sendte i sin egen kanal (DD-12).\n * Plattformen sender aldri, og tokenet finnes ikke i `programs.list()` — uten\n * det verten har fanget fra dyplenken er knappen inaktiv, med lenken forklart.\n */\nexport function Aksept({\n program,\n harToken,\n sender,\n feil,\n onBliMed,\n onLukk,\n}: {\n program: ProgramView;\n harToken: boolean;\n sender: boolean;\n feil?: string;\n onBliMed: () => void;\n onLukk: () => void;\n}) {\n const tema = useTema();\n const tall = tekst.akseptTall(\n program.tasks.length,\n minutterPerOppgave(program.tasks),\n periode(program.opensAt, program.closesAt),\n program.maxContacts,\n );\n\n return (\n <Modal visible transparent animationType=\"slide\" onRequestClose={onLukk} accessibilityViewIsModal>\n <View style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end' }}>\n <View\n testID=\"program-aksept\"\n accessibilityViewIsModal\n style={{\n backgroundColor: tema.color.bg,\n borderTopLeftRadius: tema.radius.lg * 2,\n borderTopRightRadius: tema.radius.lg * 2,\n padding: tema.screenPadding,\n gap: tema.space.md,\n maxHeight: '92%',\n minHeight: '60%',\n }}\n >\n <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>\n <Btn variant=\"ghost\" testID=\"aksept-tilbake\" ikon=\"arrow-back-outline\" label={tekst.tilbake} onPress={onLukk} />\n <View />\n </View>\n\n {feil ? <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.akseptFeil(feil)} /> : null}\n\n <ScrollView contentContainerStyle={{ gap: tema.space.md }}>\n <H sub={tekst.akseptHva}>{program.name}</H>\n\n {/* DD-32: tallene på én linje, før forklaringen. */}\n <Text\n accessibilityRole=\"text\"\n style={{\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n fontWeight: tema.weight.semibold,\n }}\n >\n {tall}\n </Text>\n\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {program.hypothesis}\n </Text>\n\n <Card>\n <H>{tekst.akseptOppgaver}</H>\n {program.tasks.map((o) => (\n <View key={o.id} style={{ gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>\n {o.title}\n </Text>\n <Hint>\n {tekst.akseptOppgaveTid(o.estimatedMinutes)}\n {o.screenHint ? ` · ${o.screenHint}` : ''}\n </Hint>\n </View>\n ))}\n </Card>\n\n {program.knownIssues.length > 0 ? (\n <Card>\n <H sub={tekst.akseptKjenteFeilUnder}>{tekst.akseptKjenteFeil(program.knownIssues.length)}</H>\n {program.knownIssues.map((k) => {\n const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv!;\n return (\n <View key={k.id} style={{ gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }}>\n {k.title}\n </Text>\n {k.workaround ? (\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }}>\n {tekst.omvei} {k.workaround}\n </Text>\n ) : null}\n {/* Ikon og farge kommer fra `knownIssueStatus` i temaet — samme kilde\n som widgetens kort (C5). Etiketten bærer versjonen her. */}\n {k.fixedIn ? (\n <StatusPill\n ikon={o.ikon}\n etikett={k.status === 'fikset' ? tekst.rettetI(k.fixedIn) : tekst.rettesI(k.fixedIn)}\n fg={o.fg}\n bg={o.bg}\n />\n ) : null}\n </View>\n );\n })}\n </Card>\n ) : null}\n\n <Card>\n <H sub={tekst.akseptInnsamlingTekst}>{tekst.akseptInnsamling}</H>\n <Hint>{tekst.kontekstAldri}</Hint>\n </Card>\n\n {/* DD-37: lenke, aldri avkryssing — og ingen vilkår i forpliktelsesfri form. */}\n {program.termsUrl && !program.commitmentFree ? (\n <View style={{ gap: tema.space.xs }}>\n <Pressable\n testID=\"vilkar-lenke\"\n accessibilityRole=\"link\"\n accessibilityLabel={tekst.akseptVilkar}\n onPress={() => void Linking.openURL(String(program.termsUrl))}\n style={{ minHeight: tema.touch, justifyContent: 'center' }}\n >\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: tema.space.xs }}>\n <Ikon navn=\"open-outline\" farge={tema.color.textPrimary} />\n <Text\n style={{ color: tema.color.textPrimary, fontSize: tema.font.body, textDecorationLine: 'underline' }}\n >\n {tekst.akseptVilkar}\n </Text>\n </View>\n </Pressable>\n <Hint>{tekst.akseptVilkarHint}</Hint>\n </View>\n ) : (\n <Hint>{tekst.akseptIngenVilkar}</Hint>\n )}\n\n <View style={{ flexDirection: 'row', alignItems: 'flex-start', gap: tema.space.sm }}>\n <Ikon navn=\"exit-outline\" farge={tema.color.textPrimary} />\n <Text\n style={{ flex: 1, color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}\n >\n {tekst.akseptUtgang}\n </Text>\n </View>\n </ScrollView>\n\n <Btn\n testID=\"bli-med\"\n label={tekst.bliMed}\n disabled={!harToken || sender}\n hint={harToken ? tekst.bliMedHint : tekst.bliMedUtenToken}\n onPress={onBliMed}\n />\n </View>\n </View>\n </Modal>\n );\n}\n","/**\n * Datoene testeren ser i aksepten (DD-32): «10.–24. oktober», eller med begge\n * måneder når perioden krysser et månedsskifte. Norsk bokmål, ingen klokkeslett —\n * et program varer i dager, og et tidspunkt ville lovet en presisjon som ikke finnes.\n */\nconst MANEDER = [\n 'januar',\n 'februar',\n 'mars',\n 'april',\n 'mai',\n 'juni',\n 'juli',\n 'august',\n 'september',\n 'oktober',\n 'november',\n 'desember',\n] as const;\n\nexport function periode(opensAt: string, closesAt: string): string {\n const fra = new Date(opensAt);\n const til = new Date(closesAt);\n if (Number.isNaN(fra.getTime()) || Number.isNaN(til.getTime())) return '';\n\n const sammeManed = fra.getMonth() === til.getMonth() && fra.getFullYear() === til.getFullYear();\n return sammeManed\n ? `${fra.getDate()}.–${til.getDate()}. ${MANEDER[til.getMonth()]}`\n : `${fra.getDate()}. ${MANEDER[fra.getMonth()]} – ${til.getDate()}. ${MANEDER[til.getMonth()]}`;\n}\n\n/** Anslått tid per oppgave, avrundet. Obligatorisk ved opprettelse (DD-32), så lista er aldri tom her. */\nexport function minutterPerOppgave(tasks: ReadonlyArray<{ estimatedMinutes: number }>): number {\n if (tasks.length === 0) return 0;\n return Math.round(tasks.reduce((sum, t) => sum + t.estimatedMinutes, 0) / tasks.length);\n}\n","import type { TaskOutcome } from '@innspel/core';\nimport React, { useState } from 'react';\nimport { Modal, Pressable, Text, TextInput, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Banner, Btn, H, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\n\n/** Ionicons-navn fra ikonkartet i `design/wireframes/betaprogram-tester.jsx`, aldri en emoji. */\nexport const UTFALL: ReadonlyArray<{ verdi: TaskOutcome; ikon: string; etikett: string }> = [\n { verdi: 'fungerte', ikon: 'checkmark-circle-outline', etikett: tekst.utfallFungerte },\n { verdi: 'delvis', ikon: 'contrast-outline', etikett: tekst.utfallDelvis },\n { verdi: 'ikke', ikon: 'close-circle-outline', etikett: tekst.utfallIkke },\n];\n\nexport const SETNING_MAKS = 140;\n\nexport function utfallEtikett(verdi: TaskOutcome): string {\n return UTFALL.find((u) => u.verdi === verdi)?.etikett ?? verdi;\n}\n\n/**\n * 3c — «Hvordan gikk det?». ETT spørsmål med tre lukkede valg og en valgfri\n * setning ≤ 140 — aldri en skala (tech-decisions «M3.2 (forts.)»). Samme dialog\n * for «Gjort» på en oppgave og for «Svar nå» på en oppfølging (3d): det er det\n * samme spørsmålet, og testeren skal kjenne det igjen.\n *\n * NN/G «task, then ask»: rett etter handlingen, under ett minutt, og «Lagre» er\n * slutten — ingen flere spørsmål etterpå. Push-spørsmålet fra wireframen (7c) er\n * vertens: plattformen holder aldri push-tokens.\n */\nexport function HvordanGikkDet({\n under,\n sender,\n feil,\n onLagre,\n onLukk,\n}: {\n /** Hva spørsmålet gjelder — oppgavens tittel eller oppfølgingens spørsmål. */\n under: string;\n sender: boolean;\n feil?: string;\n onLagre: (outcome: TaskOutcome, text: string | undefined) => void;\n onLukk: () => void;\n}) {\n const tema = useTema();\n const [valgt, setValgt] = useState<TaskOutcome | undefined>();\n const [setning, setSetning] = useState('');\n\n return (\n <Modal visible transparent animationType=\"fade\" onRequestClose={onLukk} accessibilityViewIsModal>\n <View style={{ flex: 1, backgroundColor: tema.color.scrim, justifyContent: 'flex-end', padding: tema.space.md }}>\n <View\n testID=\"hvordan-gikk-det\"\n accessibilityViewIsModal\n style={{\n backgroundColor: tema.color.surface,\n borderRadius: tema.radius.lg,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n padding: tema.space.md,\n gap: tema.space.md,\n }}\n >\n <Btn variant=\"ghost\" testID=\"hvordan-tilbake\" ikon=\"arrow-back-outline\" label={tekst.tilbake} onPress={onLukk} />\n <Hint>{under}</Hint>\n <H>{tekst.hvordanGikkDet}</H>\n\n <View testID=\"utfall-gruppe\" accessibilityRole=\"radiogroup\" accessibilityLabel={tekst.hvordanGikkDet} style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {UTFALL.map((u) => {\n const aktiv = valgt === u.verdi;\n return (\n <Pressable\n key={u.verdi}\n testID={`utfall-${u.verdi}`}\n accessibilityRole=\"radio\"\n accessibilityLabel={u.etikett}\n accessibilityState={{ checked: aktiv }}\n onPress={() => setValgt(u.verdi)}\n style={{\n flex: 1,\n minHeight: tema.touch,\n alignItems: 'center',\n justifyContent: 'center',\n gap: tema.space.xs,\n padding: tema.space.sm,\n borderRadius: tema.radius.md,\n borderWidth: tema.hairline,\n borderColor: aktiv ? tema.color.brand : tema.color.borderStrong,\n backgroundColor: aktiv ? tema.color.brandBg : tema.color.surfaceRaised,\n }}\n >\n <Ikon navn={u.ikon} farge={tema.color.textPrimary} />\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.small, fontWeight: aktiv ? tema.weight.semibold : tema.weight.regular }}>\n {u.etikett}\n </Text>\n </Pressable>\n );\n })}\n </View>\n\n <View style={{ gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textSecondary, fontSize: tema.font.small }}>{tekst.setningLabel}</Text>\n <TextInput\n testID=\"hvordan-setning\"\n accessibilityLabel={tekst.setningLabel}\n value={setning}\n onChangeText={setSetning}\n maxLength={SETNING_MAKS}\n multiline\n numberOfLines={3}\n placeholder={tekst.setningPlaceholder}\n placeholderTextColor={tema.color.textMuted}\n style={{\n backgroundColor: tema.color.surfaceRaised,\n borderWidth: tema.hairline,\n borderColor: tema.color.borderStrong,\n borderRadius: tema.radius.md,\n padding: tema.space.md,\n color: tema.color.textPrimary,\n fontSize: tema.font.body,\n lineHeight: tema.lineHeight.body,\n minHeight: tema.touch * 2,\n textAlignVertical: 'top',\n }}\n />\n </View>\n\n {feil ? <Banner live ikon=\"warning-outline\" tone=\"danger\" children={tekst.svarFeil(feil)} /> : null}\n\n <Btn\n testID=\"hvordan-lagre\"\n label={tekst.lagre}\n hint={tekst.lagreHint}\n disabled={valgt === undefined || sender}\n onPress={() => {\n if (valgt === undefined) return;\n const trimmet = setning.trim();\n onLagre(valgt, trimmet.length > 0 ? trimmet : undefined);\n }}\n />\n </View>\n </View>\n </Modal>\n );\n}\n","import type { FollowUpView } from '@innspel/core';\nimport React from 'react';\nimport { Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\n\n/** Kontakter med spørsmål tar svar; de andre er handlinger (tech-decisions «M3.2 (forts.)»). */\nexport function tarSvar(kind: FollowUpView['kind']): boolean {\n return kind === 'hvordan_gikk_det' || kind === 'sjekkpunkt';\n}\n\n/**\n * 3d — oppfølgingskortene i appen (DD-34). Hvert kort er én av de maks tre\n * kontaktene, og arten avgjør knappene: et spørsmål får «Svar nå», en påminnelse\n * «Åpne oppgavene» (fristen står i teksten fra produkteier), og tilbudet om utgang\n * «Gå ut» — invertert fra press: utgangen er svaret som tilbys. «Senere» legger\n * kortet bort i denne økten; det kommer tilbake ved neste oppstart, aldri som\n * push — plattformen holder ingen push-tokens.\n */\nexport function Oppfolging({\n oppfolging,\n kontaktNr,\n maksKontakter,\n onSenere,\n onSvar,\n onAapneOppgavene,\n onGaaUt,\n}: {\n oppfolging: FollowUpView;\n kontaktNr: number;\n maksKontakter: number;\n onSenere: () => void;\n onSvar: () => void;\n onAapneOppgavene: () => void;\n onGaaUt: () => void;\n}) {\n const tema = useTema();\n const art = tarSvar(oppfolging.kind) ? 'spoersmaal' : oppfolging.kind === 'tilbud_om_utgang' ? 'utgang' : 'paaminnelse';\n const ikon = art === 'spoersmaal' ? 'flask-outline' : art === 'utgang' ? 'exit-outline' : 'calendar-outline';\n const hint =\n art === 'spoersmaal'\n ? tekst.oppfolgingKontakt(kontaktNr, maksKontakter)\n : art === 'utgang'\n ? tekst.oppfolgingUtgangHint(kontaktNr, maksKontakter)\n : tekst.oppfolgingPaaminnelseHint(kontaktNr, maksKontakter);\n\n return (\n <View\n testID={`oppfolging-${oppfolging.id}`}\n accessibilityLabel={tekst.oppfolgingRegion}\n style={{\n backgroundColor: tema.color.brandBg,\n borderWidth: tema.hairline,\n borderColor: tema.color.brand,\n borderRadius: tema.radius.lg,\n padding: tema.space.md,\n gap: tema.space.sm,\n }}\n >\n <View style={{ flexDirection: 'row', gap: tema.space.sm, alignItems: 'flex-start' }}>\n <Ikon navn={ikon} farge={tema.color.textPrimary} />\n <View style={{ flex: 1, gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>{oppfolging.question}</Text>\n <Hint>{hint}</Hint>\n </View>\n </View>\n <View style={{ flexDirection: 'row', gap: tema.space.sm }}>\n {art === 'utgang' ? (\n <>\n {/* «Bli værende» står først: utgangen er et valg, ikke en felle. */}\n <Btn grow variant=\"secondary\" testID={`bli-vaerende-${oppfolging.id}`} label={tekst.bliVaerende} onPress={onSenere} />\n <Btn\n grow\n variant=\"danger\"\n testID={`gaa-ut-${oppfolging.id}`}\n ikon=\"exit-outline\"\n label={tekst.gaaUtBekreft}\n onPress={onGaaUt}\n />\n </>\n ) : (\n <>\n <Btn grow variant=\"secondary\" testID={`senere-${oppfolging.id}`} label={tekst.senere} onPress={onSenere} />\n {art === 'spoersmaal' ? (\n <Btn grow testID={`svar-naa-${oppfolging.id}`} label={tekst.svarNaa} onPress={onSvar} />\n ) : (\n <Btn grow testID={`aapne-oppgavene-${oppfolging.id}`} label={tekst.aapneOppgavene} onPress={onAapneOppgavene} />\n )}\n </>\n )}\n </View>\n </View>\n );\n}\n","import type { ParticipationView, ProgramTask, TaskCompletionView } from '@innspel/core';\nimport React from 'react';\nimport { Text, View } from 'react-native';\nimport { Ikon } from '../Ikon.js';\nimport { useTema } from '../tema.js';\nimport { Btn, Hint } from '../widget/primitiver.js';\nimport { tekst } from '../widget/tekster.js';\nimport { utfallEtikett } from './HvordanGikkDet.js';\n\n/**\n * 3c — oppgavelista i deltakelseskortet. Hver oppgave er én rad: tittel, anslag og\n * status «Ikke begynt» eller «Gjort · utfall». «Gjort» åpner «Hvordan gikk det?»\n * (én gang per oppgave — fullføringen er engangs, og raden viser svaret etterpå).\n * Fritt innspill er alltid mulig utenom oppgavene; det er widgetens sak, ikke denne.\n */\nexport function Oppgaver({\n tasks,\n completions,\n onGjort,\n}: {\n tasks: ProgramTask[];\n completions: ParticipationView['completions'];\n onGjort: (task: ProgramTask) => void;\n}) {\n const tema = useTema();\n const ferdig = new Map<string, TaskCompletionView>(completions.map((c) => [c.taskId, c]));\n\n return (\n <View testID=\"oppgaver\" accessibilityLabel={tekst.oppgaverTittel} style={{ gap: tema.space.sm }}>\n {[...tasks]\n .sort((a, b) => a.order - b.order)\n .map((o) => {\n const c = ferdig.get(o.id);\n return (\n <View\n key={o.id}\n testID={`oppgave-${o.id}`}\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: tema.space.sm,\n paddingVertical: tema.space.xs,\n borderBottomWidth: tema.hairline,\n borderBottomColor: tema.color.border,\n }}\n >\n <View style={{ flex: 1, gap: tema.space.xs }}>\n <Text style={{ color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }}>{o.title}</Text>\n <Hint>\n {c ? tekst.oppgaveGjortMed(utfallEtikett(c.outcome)) : `${tekst.oppgaveIkkeBegynt} · ${tekst.akseptOppgaveTid(o.estimatedMinutes)}`}\n {c?.text ? ` · «${c.text}»` : ''}\n </Hint>\n </View>\n {c ? (\n // Merket er den eneste flaten der ikonet står alene, så etiketten\n // ligger på containeren: skjermleseren hører utfallet, ikke «hake».\n <View accessibilityLabel={tekst.oppgaveGjortMed(utfallEtikett(c.outcome))} accessible>\n <Ikon navn=\"checkmark-circle-outline\" farge={tema.color.success} />\n </View>\n ) : (\n <Btn\n variant=\"secondary\"\n testID={`gjort-${o.id}`}\n ikon=\"checkmark-circle-outline\"\n label={tekst.oppgaveGjort}\n accessibilityLabel={tekst.oppgaveGjortLabel(o.title)}\n onPress={() => onGjort(o)}\n />\n )}\n </View>\n );\n })}\n </View>\n );\n}\n","import type { InnspelStorage } from '@innspel/core';\n\n/**\n * Formen på lagringspakkene i React Native-økosystemet: AsyncStorage, MMKV med\n * async-fasade, expo-secure-store. Alle tre har disse tre metodene.\n */\nexport interface AsyncStorageLike {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n}\n\n/**\n * Lager en {@link InnspelStorage} av vertens egen lagringspakke.\n *\n * Pakken tar ingen avhengighet på AsyncStorage eller MMKV med vilje: verten har\n * som regel én av dem allerede, og to kopier av samme lagring i én app er verre\n * enn litt oppsett. Send inn den du bruker:\n *\n * @example\n * ```ts\n * import AsyncStorage from '@react-native-async-storage/async-storage';\n * const storage = createStorage(AsyncStorage);\n * ```\n *\n * Det eneste som lagres er offline-køen (DD-41) — aldri feedback-tokenet, aldri\n * en install- eller enhets-ID (K20). Lagringen trenger derfor ikke være kryptert.\n */\nexport function createStorage(pakke: AsyncStorageLike): InnspelStorage {\n return {\n get: (key) => pakke.getItem(key),\n set: (key, value) => pakke.setItem(key, value),\n remove: (key) => pakke.removeItem(key),\n };\n}\n\n/**\n * Lagring i minne. Køen overlever da ikke at appen lukkes, så den er til\n * utvikling og test — ikke til produksjon. `InnspelProvider` sier fra i\n * konsollen hvis den brukes uten at det er sagt eksplisitt.\n */\nexport function createMemoryStorage(): InnspelStorage {\n const rader = new Map<string, string>();\n return {\n get: async (key) => rader.get(key) ?? null,\n set: async (key, value) => {\n rader.set(key, value);\n },\n remove: async (key) => {\n rader.delete(key);\n },\n };\n}\n"],"mappings":"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","names":["import_react","import_react_native","import_react","import_core","import_react","import_react_native","import_react","storrelse","import_react","import_react_native","import_react","import_react_native","import_jsx_runtime","periode","import_jsx_runtime","verdi","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_core","import_react","import_react_native","import_react","import_react_native","t","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","import_jsx_runtime"]}
|