feat: rebuild preview pages with real API content and full i18n

- preview.php: localized pitch + features for en/no (uk/pl fall back to en)
- Sample outputs now match actual API response format: streaming pipeline
  steps, confidence fields, entity counts, corpus slice names, speaker roles
- i18n.php: add 10 preview-specific keys across all 4 languages (en/no/uk/pl)
- Transcribe: shows 3-engine cascade + real speaker roles (saksbehandler/dommer/advokat)
- Timeline: shows date_type, confidence, what_remains_uncertain, next_practical_step
- Redact: shows two-pass pipeline (regex Nordic pack + LLM NER) + contextual tags
- Barnevernet: shows 7-step streaming trace + procedural flag severity levels
- Advocate: shows partisan brief with advocate_role + citation confidence
- Deep Research: shows corpus slices + sub-questions + contradiction-aware synthesis
- Corpus: shows real Qdrant + Azure AI Search config, hybrid search result

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 14:39:12 +02:00
parent 849a7cf434
commit 93b28b8783
2 changed files with 424 additions and 100 deletions
+36
View File
@@ -110,6 +110,15 @@ function dbnToolsTranslations(): array
'source_title' => 'Sources stay visible',
'source_text' => 'Research tools keep citations, sections, source excerpts, and uncertainty notes next to the answer.',
'tools_title' => 'Launched tools',
'preview_back' => '← All tools',
'preview_what_it_does' => 'What it does',
'preview_get_access' => 'Get access',
'preview_ready_title' => 'Ready to use',
'preview_free_note' => 'Free for Do Better Norge members. Documents are processed in memory and never stored.',
'preview_other_tools' => 'Other tools',
'preview_join' => 'Not a member? Join Do Better Norge',
'preview_input_label' => 'Sample input',
'preview_output_label' => 'Sample output',
],
'no' => [
'meta_title' => 'Do Better Norge - juridiske AI-verktøy',
@@ -153,6 +162,15 @@ function dbnToolsTranslations(): array
'source_title' => 'Kildene er synlige',
'source_text' => 'Forskningsverktøyene holder sitater, paragrafer, kildeutdrag og usikkerhet ved siden av svaret.',
'tools_title' => 'Lanserte verktøy',
'preview_back' => '← Alle verktøy',
'preview_what_it_does' => 'Hva det gjør',
'preview_get_access' => 'Få tilgang',
'preview_ready_title' => 'Klar til å bruke',
'preview_free_note' => 'Gratis for Do Better Norge-medlemmer. Dokumenter behandles i minnet og lagres aldri.',
'preview_other_tools' => 'Andre verktøy',
'preview_join' => 'Ikke medlem? Bli med i Do Better Norge',
'preview_input_label' => 'Eksempel — inndata',
'preview_output_label' => 'Eksempel — utdata',
],
'uk' => [
'meta_title' => 'Do Better Norge - юридичні AI інструменти',
@@ -196,6 +214,15 @@ function dbnToolsTranslations(): array
'source_title' => 'Джерела залишаються видимими',
'source_text' => 'Дослідницькі інструменти показують цитати, розділи, уривки джерел і примітки про невизначеність поруч із відповіддю.',
'tools_title' => 'Запущені інструменти',
'preview_back' => '← Усі інструменти',
'preview_what_it_does' => 'Що робить',
'preview_get_access' => 'Отримати доступ',
'preview_ready_title' => 'Готові до використання',
'preview_free_note' => 'Безкоштовно для членів Do Better Norge. Документи обробляються в пам\'яті і ніколи не зберігаються.',
'preview_other_tools' => 'Інші інструменти',
'preview_join' => 'Не член? Приєднайтесь до Do Better Norge',
'preview_input_label' => 'Приклад — вхідні дані',
'preview_output_label' => 'Приклад — вихідні дані',
],
'pl' => [
'meta_title' => 'Do Better Norge - prawne narzędzia AI',
@@ -239,6 +266,15 @@ function dbnToolsTranslations(): array
'source_title' => 'Źródła pozostają widoczne',
'source_text' => 'Narzędzia badawcze pokazują cytaty, sekcje, fragmenty źródeł i notatki o niepewności obok odpowiedzi.',
'tools_title' => 'Uruchomione narzędzia',
'preview_back' => '← Wszystkie narzędzia',
'preview_what_it_does' => 'Co robi',
'preview_get_access' => 'Uzyskaj dostęp',
'preview_ready_title' => 'Gotowe do użycia',
'preview_free_note' => 'Bezpłatnie dla członków Do Better Norge. Dokumenty są przetwarzane w pamięci i nigdy nie są przechowywane.',
'preview_other_tools' => 'Inne narzędzia',
'preview_join' => 'Nie jesteś członkiem? Dołącz do Do Better Norge',
'preview_input_label' => 'Przykład — dane wejściowe',
'preview_output_label' => 'Przykład — dane wyjściowe',
],
];
}
+388 -100
View File
@@ -17,109 +17,397 @@ $tool = $tools[$slug];
$returnPath = '/';
$toolsLogin = 'https://dobetternorge.no/tools-login.php?return=' . urlencode($returnPath);
// ── Per-tool preview content ──────────────────────────────────────────────────
$previews = [
// ── Localized pitch + feature content (en / no; uk/pl fall back to en) ────────
$localizedContent = [
'transcribe' => [
'pitch' => 'Upload any recording of a meeting, phone call, or court hearing. The AI transcribes with Norwegian legal vocabulary, separates speakers automatically, and delivers timestamped text you can search, quote, and submit as evidence.',
'features' => [
'Speaker diarization — Saksbehandler, Forelder, Advokat',
'Norwegian legal vocabulary and statute citations',
'Sentence-level timestamps with export to PDF or plain text',
'Processes entirely in memory — audio is never stored',
'en' => [
'transcribe' => [
'pitch' => 'Upload any recording — a meeting with caseworkers, a court hearing, or a phone call — and the AI transcribes it with Norwegian legal vocabulary, identifies each speaker automatically (saksbehandler, advokat, forelder, dommer), and returns timestamped text you can search, cite, and submit as evidence.',
'features' => [
'Three-engine cascade: Azure Speech → Google Cloud Speech v2 → Whisper GPU (large-v3)',
'Automatic speaker role labelling: dommer · saksbehandler · forelder · advokat · barn · sakkyndig',
'Sentence-level timestamps · 20 languages · diarization up to 20 speakers',
'Audio processed in memory then immediately discarded — never written to disk',
],
],
'timeline' => [
'pitch' => 'Paste case notes or upload decision letters and Timeline extracts every date, deadline, and procedural milestone into a sortable chronology. The AI flags overdue response windows, identifies date type (absolute, relative, or recurring), and tells you the next concrete step.',
'features' => [
'Detects absolute, relative ("tre uker etter"), and recurring dates in Norwegian legal prose',
'Confidence scoring per event: high · medium · low',
'Missed statutory deadlines flagged with source excerpt and actor',
'Returns what_remains_uncertain + next_practical_step in every response',
],
],
'redact' => [
'pitch' => 'Two-pass redaction: a deterministic Nordic pattern pack removes fødselsnumre, phone numbers, and addresses instantly; then Azure gpt-4o-mini scans for names, organisations, and contextual identifiers the regex cannot catch. Contextual tags preserve document meaning.',
'features' => [
'Pass 1 — Nordic pattern pack: fødselsnummer (11-digit), phone, IBAN, postcodes, email',
'Pass 2 — LLM semantic NER: names, orgs, places, contextual references',
'Output modes: contextual tags [FORELDER] / [SAKSBEHANDLER: Aas] · generic · pseudonym',
'Redaction audit log — entity type, count, and redaction method per field',
],
],
'barnevernet' => [
'pitch' => 'Upload any Barnevernet document — omsorgsovertakelse, tiltaksplan, or akuttplassering letter — and a 7-step streaming pipeline reads it from your chosen perspective, cross-referencing against 1,731 indexed FNV tribunal decisions and ECHR judgments to surface procedural violations you can challenge.',
'features' => [
'7-step streaming pipeline: classify → parties → timeline → sub-questions → corpus → synthesis → confidence',
'Corpus: 1,731 FNV decisions · 23 ECHR Norwegian cases · Høyesterett precedents',
'§4-12 / §4-6(2) / §4-21 procedural analysis with paragraph-level citations',
'Three severity levels — 🔴 critical / 🟡 caution / 🟢 compliant',
],
],
'advocate' => [
'pitch' => 'Select who you represent — biologisk mor, biologisk far, barnet, fosterforeldre, or barnevernet itself — and Advocate generates a partisan legal brief grounded in statutes, ECHR Grand Chamber rulings, and tribunal decisions that support your position and identify weaknesses in the opposing argument.',
'features' => [
'Eight selectable roles including biological parents, foster carer, child representative, and municipality',
'Sub-questions framed adversarially from the selected party\'s perspective',
'ECHR Grand Chamber citations with paragraph numbers · Lovdata statute cross-refs',
'Citation confidence score based on retrieved source count (low · medium · high)',
],
],
'deep-research' => [
'pitch' => 'Ask any complex legal question and the research agent expands it into 35 adversarial search angles, queries up to eight corpus slices in parallel (family law, child welfare, ECHR, Høyesterett, Bufdir guidance, and more), then synthesizes a fully cited brief with uncertainty notes.',
'features' => [
'Auto-expansion into 35 research sub-questions per query',
'8 corpus slices: family_core · child_welfare · echr · hague · norwegian_courts · bufdir_guidance · broader_legal · dbn_resources',
'Parallel retrieval with hybrid dense + BM25 search across slices',
'Contradiction detection between sources · evidence_trail with title, citation, excerpt',
],
],
'corpus' => [
'pitch' => 'Browse the legal knowledge base that powers all other tools. Inspect indexed sources by corpus slice, run test queries against individual categories, check retrieval latency, and verify which precedents are available before launching a full research session.',
'features' => [
'219,847 indexed passages across 8 corpus slices',
'Four search modes: hybrid (dense + BM25) · BM25 · vector (Qdrant) · Azure AI Search',
'Retrieval health dashboard: p95 latency, embedding model, Azure index name',
'Per-slice document browser with source count and last-indexed date',
],
],
'scenario_label' => 'Sample input',
'scenario' => 'familiesamtale_barnevernet_14mar2025.mp3 &mdash; 23:47 &mdash; Statutory review meeting',
'output_label' => 'Transcript output',
'output' => "[00:00 — Saksbehandler] Jeg vil informere om at dette møtet dokumenteres jf.\n forvaltningsloven § 11d. Formålet er å gjennomgå tiltaksplanen.\n\n[00:18 — Forelder] Vi ønsker å forstå hva som er grunnlaget for bekymringene\n dere fremdeles har, og hva som skal til for å avslutte saken.\n\n[00:31 — Saksbehandler] Bekymringsmeldingen kom inn 14. mars. Vi gjennomførte\n hjemmebesøk 2. april. Tiltaksplanen løper til 30. juni.\n\n[00:48 — Advokat] For protokollen: klienten fikk ikke skriftlig varsel innen\n fristen i forvaltningsloven § 16.",
],
'timeline' => [
'pitch' => 'Paste case notes or upload documents and Timeline extracts every date, hearing, and procedural deadline into a sortable chronology. Flag gaps in due process and see your entire case at a glance.',
'features' => [
'Detects absolute and relative dates ("tre uker etter vedtaket")',
'Category tags: klage, rettsak, hjemmebesøk, frist',
'Missed statutory deadlines highlighted in red',
'Export to CSV or printable table',
],
'scenario_label' => 'Sample input',
'scenario' => 'Four case documents pasted — 3,200 words of notes, letters, and decision excerpts',
'output_label' => 'Timeline output',
'output' => "DATE EVENT SOURCE FLAG\n─────────────────────────────────────────────────────────────────────────────\n14.03.2025 Bekymringsmelding mottatt Barnevernets brev\n02.04.2025 Hjemmebesøk gjennomført Tiltaksplan\n16.04.2025 Klagefrist utløpt Fvl. § 29 ⚠ Svar\n (Klage innsendt 23.04 — 3 dager for sent\n etter frist)\n15.05.2025 Fylkesnemnda berammet Vedtak 2025-882\n30.06.2025 Tiltaksplan utløper Tiltaksplan → Ny\n vurdering",
],
'no' => [
'redact' => [
'pitch' => 'Before sharing documents with courts, advocates, or public forums, Redact removes all personal identifiers automatically. Nothing is sent to third-party AI — redaction runs locally on our servers.',
'features' => [
'Fødselsnummer (11-digit national ID) detection',
'NER-based name and organisation removal',
'Addresses, postcodes, phone numbers, and email addresses',
'Reversible audit log — restore original on request',
'transcribe' => [
'pitch' => 'Last opp opptak fra møter med saksbehandlere, rettsmøter eller telefonsamtaler. AI-en transkriberer med norsk juridisk vokabular, identifiserer automatisk hvem som sier hva (saksbehandler, advokat, forelder, dommer), og leverer tidsstemplet tekst du kan søke i, sitere og legge ved som bevis.',
'features' => [
'Tre-trinns pipeline: Azure Speech → Google Cloud Speech v2 → Whisper GPU (large-v3)',
'Talerrollen identifisert automatisk: dommer · saksbehandler · forelder · advokat · barn · sakkyndig',
'Tidsstempler per setning · 20 språk · diarisering opptil 20 talere',
'Lydfilen behandles i minnet og slettes umiddelbart — skrives aldri til disk',
],
],
'scenario_label' => 'Document excerpt (before)',
'scenario' => 'Barnet Sofie Kristine Lindstr&oslash;m, f.&nbsp;14.07.2017, og hennes mor Ingrid Mari Lindstr&oslash;m (fnr.&nbsp;14095678234), bosatt Torggata&nbsp;14B,&nbsp;0181&nbsp;Oslo, ble kontaktet av saksbehandler Morten Aas den 6.&nbsp;mai.',
'output_label' => 'After redaction',
'output' => "Barnet [NAVN], f. [DATO], og hennes mor [NAVN]\n(fnr. [FNR]), bosatt [ADRESSE], ble kontaktet\nav saksbehandler [NAVN] den 6. mai.\n\n─────────────────────────────────────\nRedacted: 5 names · 1 fødselsnummer\n 1 address · 1 date of birth",
],
'barnevernet' => [
'pitch' => 'Upload any Barnevernet document — decision letter, tiltaksplan, or omsorgsovertakelse — and the analyzer reads it from your perspective, cross-referencing against 1,731 indexed tribunal decisions to surface procedural violations you can challenge.',
'features' => [
'§4-12 / §4-6(2) / §4-21 procedural analysis',
'Cross-reference against FNV tribunal corpus (1,731 decisions)',
'ECHR Article 8 pattern matching and citation',
'Exportable flagged report with paragraph references',
'timeline' => [
'pitch' => 'Lim inn saksdokumenter eller last opp vedtaksbrev, og Tidslinje henter ut alle datoer, frister og prosessuelle milepæler i en sorterbar kronologi. AI-en flagger overskredne svarfrister, klassifiserer datoer (absolutt, relativ eller gjentagende) og foreslår neste konkrete steg.',
'features' => [
'Finner absolutte, relative («tre uker etter») og gjentagende datoer i juridisk prosa',
'Konfidensnivå per hendelse: høy · middels · lav',
'Overskredne lovpålagte frister flagges med kildeutdrag og aktørnavn',
'Returnerer hva_er_usikkert + neste_praktiske_steg i hvert svar',
],
],
'scenario_label' => 'Document uploaded',
'scenario' => 'Vedtak om omsorgsovertakelse — Bydel&nbsp;&Aring;rstad, 14.&nbsp;januar&nbsp;2025 &mdash; 6 pages',
'output_label' => 'Analysis output',
'output' => "ANALYSE — Omsorgsovertakelse §4-12\nRøde flagg funnet: 3\n\n🔴 Utilstrekkelig begrunnelse\n Vedtaket påberoper §4-12(1)(c) uten å spesifisere\n terskelen for \"alvorlige mangler\" — jf. FNV-2023-192-OSL\n der identisk formulering ble opphevet av Høyesterett.\n\n🟡 Tilbakeføring ikke vurdert\n Ingen §4-21-vurdering er inkludert. Strand Lobben v.\n Norway (klagenr. 37283/13 ¶206) krever at staten\n treffer aktive tiltak mot gjenforening fra dag én.\n\n🟡 Foreldrehøring mangler\n Ingen dokumentasjon på at foreldrene ble hørt\n i forkant av vedtaket, jf. forvaltningsloven §17.",
],
'advocate' => [
'pitch' => 'Choose whether you represent a parent, child, foster carer, or municipality, describe the facts, and Advocate drafts a source-grounded legal brief — citing directly from Norwegian law, ECHR rulings, and indexed tribunal decisions.',
'features' => [
'Four representable roles: parent, child, foster carer, municipality',
'ECHR Grand Chamber citations with paragraph references',
'Lovdata statute cross-references (Barneloven, Barnevernloven)',
'Adjustable argument weight and brief length',
'redact' => [
'pitch' => 'To-trinns sladdering: en deterministisk nordisk mønsterpakke fjerner fødselsnumre, telefonnumre og adresser umiddelbart, deretter skanner Azure gpt-4o-mini etter navn, organisasjoner og kontekstuelle identifikatorer som regex ikke fanger. Kontekstuelle merkelapper bevarer dokumentets mening.',
'features' => [
'Trinn 1 — Nordisk mønsterpakke: fødselsnummer (11-siffer), telefon, IBAN, postnummer, e-post',
'Trinn 2 — LLM semantisk NER: navn, organisasjoner, steder, kontekstuelle referanser',
'Utgangsmodus: kontekstuelle merkelapper [FORELDER] / [SAKSBEHANDLER: Aas] · generisk · pseudonym',
'Sladdringslogg — enhetstype, antall og metode per felt',
],
],
'scenario_label' => 'Role and facts',
'scenario' => 'Role: Forelderens representant &mdash; Facts: Akuttplassering etter §4-6(2) iverksatt 14. januar 2025 uten forutgående varsel. Barnet er 7 år. Kommunen anfører §4-12(1)(d).',
'output_label' => 'Draft brief excerpt',
'output' => "PARTSINLEGG — Forelderens perspektiv\nSak: Akuttplassering §4-6(2), januar 2025\n\nSøkeren anfører at akuttplasseringen av 14. januar 2025\nutgjørde en krenkelse av EMK artikkel 8, slik storkammeret\nfastla i Strand Lobben v. Norway (klagenr. 37283/13, ¶206).\n\nProporsjonalitetskravet forutsetter at myndighetene\ndokumenterer: (i) at risikoen var umiddelbar og konkret;\n(ii) at mindre inngripende tiltak ble reelt vurdert; og\n(iii) at vedtaket inneholdt en konkret gjenforeningsplan.\n\nKommunen har ikke fremlagt slik dokumentasjon.",
],
'deep-research' => [
'pitch' => 'Ask a complex legal question and the research agent expands it into parallel search angles, queries three slices of the legal corpus simultaneously, then synthesizes a fully cited brief — more thorough than any single keyword search.',
'features' => [
'Auto-expands your question into 35 research angles',
'Parallel corpus queries across statutes, ECHR, and tribunal decisions',
'Contradiction detection between sources',
'Cited synthesis with clickable source links',
'barnevernet' => [
'pitch' => 'Last opp et barnevernsdokument — omsorgsovertakelse, tiltaksplan eller akuttplasseringsbrev — og en 7-trinns strømmende pipeline leser det fra ditt valgte perspektiv, krysser mot 1 731 indekserte FNV-vedtak og EMD-dommer, og løfter frem prosessuelle feil du kan bestride.',
'features' => [
'7-trinns pipeline: klassifiser → parter → tidslinje → søkevinkler → korpus → syntese → konfidensgrad',
'Korpus: 1 731 FNV-vedtak · 23 EMD-saker (Norge) · Høyesterett-presedenser',
'§4-12 / §4-6(2) / §4-21 prosessanalyse med avsnittsnivå-referanser',
'Tre alvorlighetsnivåer — 🔴 kritisk / 🟡 forsiktighet / 🟢 i orden',
],
],
'scenario_label' => 'Research query',
'scenario' => 'Kan midlertidig fosterhjemsplassering bli permanent uten ny saksbehandling?',
'output_label' => 'Synthesis excerpt (3 of 5 angles completed)',
'output' => "RESEARCH ANGLES\n ① §4-21 vilkår for opphør av omsorgsovertakelse\n ② ECHR art. 8 — statens gjenforeningsplikt\n ③ Fylkesnemnda-praksis 20202025 ✓ 14 relevante avgjørelser\n\nSYNTHESIS\nEtter §4-21 første ledd kan omsorgsovertakelse bare\nopprettholdes dersom tilbakeføring vil utsette barnet for\nreell risiko for skadevirkninger av betydning.\n\nStorkammeret presiserte i K.O. og V.M. v. Norway\n(klagenr. 64808/16, ¶67) at langvarig plassering ikke i seg\nselv legitimerer varig omsorgsovertakelse — ny og selvstendig\nvurdering er påkrevet.",
],
'corpus' => [
'pitch' => 'Browse the legal knowledge base that powers all other tools. Inspect indexed sources by category, check retrieval health, run test queries against specific legal slices, and verify what precedents are available before launching a full research session.',
'features' => [
'219,847 indexed passages across 5 source categories',
'Source browser with document count and last-indexed date',
'Retrieval health dashboard with latency and recall metrics',
'Test-query interface against individual corpus slices',
'advocate' => [
'pitch' => 'Velg hvem du representerer — biologisk mor, biologisk far, barnet, fosterforeldre eller barnevernet — og Advokatmodus genererer et partsinlegg forankret i lovverk, EMD storkammeravgjørelser og nemndsvedtak som støtter din posisjon og identifiserer svakheter i motpartens argumentasjon.',
'features' => [
'Åtte valgbare roller: begge foreldre, fosterforelder, barnets representant, utvidet familie, kommune',
'Søkevinkler utformet som motstander fra valgt parts perspektiv',
'EMD storkammer-sitater med avsnittsnumre · lovhenvisninger via Lovdata',
'Kildekonfidensgrad basert på antall hentede dokumenter (lav · middels · høy)',
],
],
'deep-research' => [
'pitch' => 'Still et komplekst juridisk spørsmål og forskningsagenten utvider det til 35 søkevinkler, søker opptil åtte korpusutsnitt parallelt (familierett, barnevern, EMD, Høyesterett, Bufdir-veiledning og mer), og syntetiserer et kildebelagt notat med usikkerhetsmerknad.',
'features' => [
'Automatisk utvidelse til 35 sub-spørsmål per søk',
'8 korpusutsnitt: family_core · child_welfare · echr · hague · norwegian_courts · bufdir_guidance · broader_legal · dbn_resources',
'Parallell henting med hybrid dense + BM25-søk på tvers av utsnitt',
'Motsigelsedeteksjon mellom kilder · evidensspor med tittel, sitering og utdrag',
],
],
'corpus' => [
'pitch' => 'Se den juridiske kunnskapsbasen som driver alle andre verktøy. Undersøk indekserte kilder per korpusutsnitt, kjør testspørsmål mot enkeltkilder, sjekk hentehelse, og bekreft hvilke presedenser som er tilgjengelige før du starter en full forskningsøkt.',
'features' => [
'219 847 indekserte passasjer fordelt på 8 korpusutsnitt',
'Fire søkemodi: hybrid (dense + BM25) · BM25 · vektor (Qdrant) · Azure AI Search',
'Hentehelse-dashboard: p95-latens, innbyggingsmodell, Azure-indeksnavn',
'Utsnittleser med dokumentantall og sist-indeksert-dato',
],
],
'scenario_label' => 'Corpus snapshot',
'scenario' => 'Full corpus status &mdash; last updated 16 May 2026',
'output_label' => 'Corpus dashboard',
'output' => "Korpusstatus: Frisk ✔ — sist oppdatert 16. mai 2026\n\nKILDE DOKUMENTER PASSASJER\n──────────────────────────────────────────────────────────\nBarnevernet-avgjørelser (FNV) 1 731 87 420\nECHR (norske saker) 23 9 204\nBarneloven + Barnevernloven 4 lover 6 112\nHøyesterett 142 18 903\nAkademiske kommentarer 38 4 208\n──────────────────────────────────────────────────────────\nTotalt 219 847\n\nEmbedding model : nomic-embed-text (768-dim)\nVector store : Qdrant v1.17.0 @ 10.0.2.10:6333\nAvg query p95 : 142 ms",
],
];
$preview = $previews[$slug];
// uk/pl fall back to 'en' — sample documents are Norwegian regardless
$contentLang = array_key_exists($uiLang, $localizedContent) ? $uiLang : 'en';
$localContent = $localizedContent[$contentLang][$slug];
// ── Sample inputs/outputs (always Norwegian — legal domain is Norway) ─────────
$samples = [
'transcribe' => [
'scenario_label' => ($uiLang === 'no') ? 'Lydfil' : 'Audio file',
'scenario' => 'familiesamtale_barnevernet_14mar2025.mp3 &mdash; 23:47 &mdash; Tiltaksplangjenopmgang',
'output_label' => ($uiLang === 'no') ? 'Transkripsjon' : 'Transcript',
'output' => implode("\n", [
'ENGINE : Google Cloud Speech v2 + Whisper GPU (large-v3)',
'TALERE : 3 identifisert → roller tilordnet automatisk',
'',
'[00:00 — saksbehandler] "Jeg vil informere om at dette møtet dokumenteres',
' jf. forvaltningsloven § 11d. Formålet er å gjennomgå',
' tiltaksplanen for perioden frem til 30. juni."',
'',
'[00:18 — forelder] "Vi ønsker å forstå grunnlaget for de gjenværende',
' bekymringene, og hva som konkret kreves for å avslutte',
' saken og få barnet hjem."',
'',
'[00:31 — saksbehandler] "Bekymringsmeldingen kom inn 14. mars. Hjemmebesøk',
' ble gjennomført 2. april. Tiltaksplanen løper til',
' 30. juni og krever ny vurdering deretter."',
'',
'[00:48 — advokat] "For protokollen: min klient mottok ikke skriftlig',
' varsel innen fristen i forvaltningsloven § 16."',
'',
'─────────────────────────────────────────────────────',
'Varighet: 23:47 · Språk: no · Modell: large-v3',
'Behandlingstid: 48 sek · Eksporter: PDF TXT',
]),
],
'timeline' => [
'scenario_label' => ($uiLang === 'no') ? 'Limt inn tekst' : 'Pasted text',
'scenario' => '4 saksdokumenter · 3 200 ord · notater, brev og vedtaksutdrag',
'output_label' => ($uiLang === 'no') ? 'Tidslinjeresultat' : 'Timeline result',
'output' => implode("\n", [
'TIDSLINJE — 5 hendelser · Høykonfidensandel: 80 %',
'',
'DATO HENDELSE TYPE KONFIDENSAKTØR',
'─────────────────────────────────────────────────────────────────────',
'14.03.2025 Bekymringsmelding mottatt absolutt høy',
' Aktør: Ukjent melder',
' Kilde: «mottok melding 14. mars» (s.1)',
'',
'02.04.2025 Hjemmebesøk gjennomført absolutt høy',
' Aktør: Saksbehandler Morten Aas',
'',
'16.04.2025 Klagefrist utløpt absolutt høy',
' ⚠ OVERSKREDET — Svar innsendt 23.04 (7 dager etter frist)',
' Hjemmel: forvaltningsloven § 29',
'',
'15.05.2025 Fylkesnemnda berammet absolutt høy',
' Aktør: Fylkesnemnda for barnevern og sosiale saker',
' Ref: Vedtak 2025-882',
'',
'30.06.2025 Tiltaksplan utløper absolutt middels',
' → Ny §4-5-vurdering påkrevet',
'',
'USIKKERT: Dato for første hjemmebesøk etter bekymringsmelding',
' er ikke eksplisitt angitt i kildedokumentene.',
'',
'NESTE STEG: Dokumenter klagefristoverskridelsen skriftlig og',
' send formell protest til kommunen, ref. fvl. § 29.',
]),
],
'redact' => [
'scenario_label' => ($uiLang === 'no') ? 'Dokumentutdrag (original)' : 'Document excerpt (before)',
'scenario' => 'Barnet Sofie Kristine Lindstr&oslash;m, f.&nbsp;14.07.2017, og hennes mor Ingrid Mari Lindstr&oslash;m (fnr.&nbsp;14095678234), bosatt Torggata&nbsp;14B,&nbsp;0181&nbsp;Oslo, ble kontaktet av saksbehandler Morten Aas den 6.&nbsp;mai.',
'output_label' => ($uiLang === 'no') ? 'Etter sladdering' : 'After redaction',
'output' => implode("\n", [
'TO-TRINNS SLADDERING',
' Trinn 1: Nordisk mønsterpakke (regex) ✓ 3 treff',
' Trinn 2: Azure semantisk NER-skanning ✓ 5 treff',
'',
'RESULTAT (kontekstuell modus)',
'─────────────────────────────────────────────────────',
'Barnet [BARN], f. [FØDSELSDATO], og hennes mor [FORELDER]',
'(fnr. [FNR]), bosatt [ADRESSE], ble kontaktet av',
'saksbehandler [SAKSBEHANDLER: Aas] den 6. mai.',
'',
'─────────────────────────────────────────────────────',
'Sladdringslogg:',
' 2 personnavn → [BARN], [FORELDER]',
' 1 fødselsnummer → [FNR] (11-siffer, nordisk mønster)',
' 1 adresse → [ADRESSE]',
' 1 fødselsdato → [FØDSELSDATO]',
' 1 funksjonsnavn → [SAKSBEHANDLER: Aas] (kontekstuell)',
'',
'Motor: Azure gpt-4o-mini + nordisk regex-pakke',
]),
],
'barnevernet' => [
'scenario_label' => ($uiLang === 'no') ? 'Opplastet dokument' : 'Document uploaded',
'scenario' => 'vedtak_omsorgsovertakelse_bydel_aarstad_14jan2025.pdf &mdash; 6 sider &mdash; §4-12',
'output_label' => ($uiLang === 'no') ? 'Analyseresultat (strøm)' : 'Analysis output (stream)',
'output' => implode("\n", [
'BVJ-ANALYSE — Omsorgsovertakelse §4-12',
'Fil: vedtak_bydel_aarstad_14jan2025.pdf · 6 sider',
'',
'✓ Steg 1 Dokumentklassifisering',
' Type: Omsorgsovertakelse · Ref: 2025-BV-00147',
' Myndighet: Bydel Årstad · Dato: 14.01.2025',
'',
'✓ Steg 2 Partsregistrering',
' Barnet (f. 2017) · Biologisk mor · Bydel Årstad',
'',
'✓ Steg 3 Tidslinjeekstraksjon → 8 hendelser (tidligste: 02.2024)',
'',
'✓ Steg 4 Søkevinkler generert (4) — fra forelderens perspektiv',
'',
'✓ Steg 56 Korpushenting + Syntese',
' FNV-korpuset: 14 relevante vedtak · ECHR: 3 saker',
'',
'RØDE FLAGG FUNNET: 3',
'',
'🔴 Utilstrekkelig proporsjonalitetsvurdering',
' Vedtaket påberoper §4-12(1)(c) men dokumenterer ikke at',
' lempeligere tiltak ble reelt vurdert — krav etter',
' FNV-2023-192-OSL og EMK art. 8 ¶206 (Strand Lobben).',
'',
'🟡 §4-21-vurdering mangler',
' Ingen gjenforeningsplan vedlagt — jf. K.O. og V.M. v. Norge',
' (klagenr. 64808/16, ¶67).',
'',
'🟡 Manglende forutgående varsel',
' Ingen dokumentasjon på at foreldrene ble hørt i forkant,',
' jf. forvaltningsloven § 17.',
'',
'Kildekonfidensgrad: MIDDELS · 14 FNV-vedtak · 3 ECHR-dommer',
]),
],
'advocate' => [
'scenario_label' => ($uiLang === 'no') ? 'Rolle og faktagrunnlag' : 'Role and facts',
'scenario' => 'Rolle: Biologisk mor &mdash; Fakta: Akuttplassering etter §4-6(2) iverksatt 14. januar 2025 uten forutgående varsel. Barnet er 7 år. Kommunen anfører §4-12(1)(d) som videre hjemmel.',
'output_label' => ($uiLang === 'no') ? 'Utkast til partsinlegg' : 'Draft brief excerpt',
'output' => implode("\n", [
'PARTSINLEGG — biologisk mor',
'Sak: Akuttplassering etter §4-6(2), 14. januar 2025',
'',
'Søkeren anfører at akuttplasseringen av 14. januar 2025',
'utgjorde en krenkelse av EMK artikkel 8, slik storkammeret',
'fastla i Strand Lobben v. Norway (klagenr. 37283/13, ¶206).',
'',
'Proporsjonalitetskravet forutsetter at myndighetene',
'dokumenterer: (i) at risikoen var umiddelbar og konkret;',
'(ii) at mindre inngripende tiltak ble reelt vurdert; og',
'(iii) at vedtaket inneholdt en konkret gjenforeningsplan',
'fra plasseringstidspunktet.',
'',
'Kommunen har ikke fremlagt slik dokumentasjon.',
'Plasseringen fremstår dermed som uforholdsmessig og i',
'strid med statens positive forpliktelser etter EMK.',
'',
'Konklusjon: Vedtaket bør kjennes ugyldig og barnet',
'tilbakeføres jf. §4-21(1) og FNV-2024-041-TRO.',
'',
'Kildekonfidensgrad: HØY · 23 FNV-vedtak · 5 ECHR-dommer',
]),
],
'deep-research' => [
'scenario_label' => ($uiLang === 'no') ? 'Forskningsspørsmål' : 'Research query',
'scenario' => 'Kan midlertidig fosterhjemsplassering bli permanent uten ny saksbehandling?',
'output_label' => ($uiLang === 'no') ? 'Synteseutdrag' : 'Synthesis excerpt',
'output' => implode("\n", [
'DYPDYKK-FORSKNING',
'Spørsmål: Kan midlertidig fosterhjemsplassering bli',
' permanent uten ny saksbehandling?',
'',
'Korpusutsnitt aktivert:',
' ✓ family_core ✓ child_welfare ✓ echr',
' ✓ norwegian_courts ✓ bufdir_guidance',
'',
'SØKEVINKLER (4 generert)',
' ① §4-21 vilkår for opphør — hva krever loven?',
' ② ECHR art. 8 — statens aktive gjenforeningsplikt',
' ③ Fylkesnemnda-praksis 20202025 → 14 relevante vedtak',
' ④ Høyesterett-presedenser om varig plassering',
'',
'SYNTESE',
'Etter §4-21 første ledd kan omsorgsovertakelse bare',
'opprettholdes dersom tilbakeføring vil utsette barnet for',
'risiko for skadevirkninger av «vesentlig» betydning. En',
'midlertidig plassering kan ikke automatisk bli varig —',
'ny og selvstendig §4-21-vurdering er alltid påkrevet.',
'',
'Storkammeret presiserte i K.O. og V.M. v. Norway',
'(klagenr. 64808/16, ¶67) at langvarig plassering ikke',
'i seg selv legitimerer varig omsorgsovertakelse.',
'',
'FNV-2023-441-TRO: Nemnda fastslo at kommunen hadde brutt',
'sin plikt til å legge til rette for tilbakeføring.',
'',
'USIKKERT: Praksis er ikke entydig der barnet selv',
' motsetter seg tilbakeføring (¶¶6871).',
'',
'Kildekonfidensgrad: HØY · 48 passasjer · 12 dokumenter',
]),
],
'corpus' => [
'scenario_label' => ($uiLang === 'no') ? 'Testspørsmål + korpusstatus' : 'Test query + corpus status',
'scenario' => 'Spørsmål: «§4-12 proporsjonalitet» &mdash; Modus: hybrid (dense + BM25)',
'output_label' => ($uiLang === 'no') ? 'Søkeresultat + helsestatus' : 'Search result + health',
'output' => implode("\n", [
'KORPUSSTATUS: Frisk ✔ — sist oppdatert 16. mai 2026',
'',
'UTSNITT DOKUMENTER PASSASJER',
'──────────────────────────────────────────────────────────',
'family_core (Barneloven, samvær) 4 lover 6 112',
'child_welfare (FNV-vedtak) 1 731 dok. 87 420',
'echr (norske EMD-saker) 23 dok. 9 204',
'norwegian_courts (Høyesterett) 142 dommer 18 903',
'bufdir_guidance (Bufdir, Barneombudet) 38 kilder 4 208',
'──────────────────────────────────────────────────────────',
'Totalt 219 847',
'',
'TESTSPØRSMÅL: «§4-12 proporsjonalitet»',
' ① FNV-2023-192-OSL score 0.941',
' «...proporsjonalitetskravet forutsetter...»',
' ② Strand Lobben v. Norway score 0.887',
' «...EMK art. 8 ¶206 — positive forpliktelser...»',
' ③ Barnevernloven § 4-12 score 0.831',
' «...alvorlige mangler ved den daglige omsorg...»',
'',
'Embedding : nomic-embed-text 768-dim (LiteLLM/Qdrant)',
'Azure Search: bnl-legal-v2 (hybrid + semantisk reranking)',
'p95 latency : 142 ms',
]),
],
];
$sample = $samples[$slug];
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
@@ -151,7 +439,7 @@ $preview = $previews[$slug];
<a href="?tool=<?= htmlspecialchars($slug) ?>&amp;lang=<?= htmlspecialchars($langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
<?php endforeach; ?>
</nav>
<a href="index.php#access" class="lt-nav__cta">Get access</a>
<a href="index.php#access" class="lt-nav__cta"><?= htmlspecialchars(dbnToolsT('preview_get_access', $uiLang)) ?></a>
</div>
</header>
@@ -163,20 +451,20 @@ $preview = $previews[$slug];
<?= $toolSvgs[$slug] ?? '' ?>
</div>
<div class="lt-preview-hero__text">
<a href="index.php#tools" class="lt-preview-back">&larr; All tools</a>
<a href="index.php#tools" class="lt-preview-back"><?= htmlspecialchars(dbnToolsT('preview_back', $uiLang)) ?></a>
<span class="lt-preview-badge"><?= htmlspecialchars($tool['badge']) ?></span>
<h1 class="lt-preview-title"><?= htmlspecialchars($tool['label']) ?></h1>
<p class="lt-preview-sub"><?= htmlspecialchars($tool['description']) ?></p>
<p class="lt-preview-pitch"><?= htmlspecialchars($preview['pitch']) ?></p>
<p class="lt-preview-pitch"><?= htmlspecialchars($localContent['pitch']) ?></p>
</div>
</div>
</section>
<section class="lt-preview-features">
<div class="lt-preview-features__inner">
<h2 class="lt-preview-features__heading">What it does</h2>
<h2 class="lt-preview-features__heading"><?= htmlspecialchars(dbnToolsT('preview_what_it_does', $uiLang)) ?></h2>
<ul class="lt-preview-features__list">
<?php foreach ($preview['features'] as $feat): ?>
<?php foreach ($localContent['features'] as $feat): ?>
<li class="lt-preview-features__item">
<span class="lt-preview-features__dot" aria-hidden="true"></span>
<?= htmlspecialchars($feat) ?>
@@ -191,19 +479,19 @@ $preview = $previews[$slug];
<div class="lt-preview-sample__col">
<p class="lt-preview-sample__label">
<span class="lt-preview-sample__icon" aria-hidden="true">&#x2192;</span>
<?= htmlspecialchars($preview['scenario_label']) ?>
<?= htmlspecialchars($sample['scenario_label']) ?>
</p>
<div class="lt-preview-sample__input">
<p><?= $preview['scenario'] ?></p>
<p><?= $sample['scenario'] ?></p>
</div>
</div>
<div class="lt-preview-sample__col">
<p class="lt-preview-sample__label lt-preview-sample__label--out">
<span class="lt-preview-sample__icon" aria-hidden="true">&#x2713;</span>
<?= htmlspecialchars($preview['output_label']) ?>
<?= htmlspecialchars($sample['output_label']) ?>
</p>
<div class="lt-preview-sample__output lt-preview-output">
<pre><?= htmlspecialchars($preview['output']) ?></pre>
<pre><?= htmlspecialchars($sample['output']) ?></pre>
</div>
</div>
</div>
@@ -212,13 +500,13 @@ $preview = $previews[$slug];
<section class="lt-preview-cta">
<div class="lt-preview-cta__inner">
<p class="lt-preview-cta__eyebrow">Do Better Norge members</p>
<h2 class="lt-preview-cta__title">Ready to use <?= htmlspecialchars($tool['label']) ?>?</h2>
<p class="lt-preview-cta__note">Free for Do Better Norge members. Documents are processed in memory and never stored.</p>
<a class="lt-preview-cta__btn" href="<?= htmlspecialchars($toolsLogin) ?>">Get access &rarr;</a>
<p class="lt-preview-cta__register">Not a member? <a href="https://dobetternorge.no/register.php">Join Do Better Norge</a></p>
<h2 class="lt-preview-cta__title"><?= htmlspecialchars(dbnToolsT('preview_ready_title', $uiLang)) ?> <?= htmlspecialchars($tool['label']) ?>?</h2>
<p class="lt-preview-cta__note"><?= htmlspecialchars(dbnToolsT('preview_free_note', $uiLang)) ?></p>
<a class="lt-preview-cta__btn" href="<?= htmlspecialchars($toolsLogin) ?>"><?= htmlspecialchars(dbnToolsT('preview_get_access', $uiLang)) ?> &rarr;</a>
<p class="lt-preview-cta__register"><a href="https://dobetternorge.no/register.php"><?= htmlspecialchars(dbnToolsT('preview_join', $uiLang)) ?></a></p>
</div>
<div class="lt-preview-cta__tools">
<p class="lt-preview-cta__tools-label">Other tools</p>
<p class="lt-preview-cta__tools-label"><?= htmlspecialchars(dbnToolsT('preview_other_tools', $uiLang)) ?></p>
<div class="lt-preview-cta__tool-links">
<?php foreach ($tools as $otherSlug => $otherTool): if ($otherSlug === $slug) continue; ?>
<a href="preview.php?tool=<?= htmlspecialchars($otherSlug) ?>" class="lt-preview-cta__tool-link">