93b28b8783
- 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>
526 lines
30 KiB
PHP
526 lines
30 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
require_once __DIR__ . '/includes/bootstrap.php';
|
||
require_once __DIR__ . '/includes/tool-svgs.php';
|
||
|
||
$uiLang = dbnToolsCurrentLanguage();
|
||
$tools = dbnToolsLaunchedTools($uiLang);
|
||
$slug = $_GET['tool'] ?? '';
|
||
|
||
if (!array_key_exists($slug, $tools)) {
|
||
header('Location: index.php');
|
||
exit;
|
||
}
|
||
|
||
$tool = $tools[$slug];
|
||
$returnPath = '/';
|
||
$toolsLogin = 'https://dobetternorge.no/tools-login.php?return=' . urlencode($returnPath);
|
||
|
||
// ── Localized pitch + feature content (en / no; uk/pl fall back to en) ────────
|
||
$localizedContent = [
|
||
|
||
'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 3–5 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 3–5 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',
|
||
],
|
||
],
|
||
],
|
||
|
||
'no' => [
|
||
|
||
'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',
|
||
],
|
||
],
|
||
|
||
'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',
|
||
],
|
||
],
|
||
|
||
'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',
|
||
],
|
||
],
|
||
|
||
'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',
|
||
],
|
||
],
|
||
|
||
'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 3–5 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 3–5 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',
|
||
],
|
||
],
|
||
],
|
||
];
|
||
|
||
// 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 — 23:47 — 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øm, f. 14.07.2017, og hennes mor Ingrid Mari Lindstrøm (fnr. 14095678234), bosatt Torggata 14B, 0181 Oslo, ble kontaktet av saksbehandler Morten Aas den 6. 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 — 6 sider — §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 5–6 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 — 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 2020–2025 → 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 (¶¶68–71).',
|
||
'',
|
||
'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» — 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) ?>">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title><?= htmlspecialchars($tool['label']) ?> — Do Better Norge Legal Tools</title>
|
||
<meta name="description" content="<?= htmlspecialchars($tool['description']) ?>">
|
||
<meta name="robots" content="index, follow">
|
||
<meta name="theme-color" content="#00205B">
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700&family=Roboto:wght@300;400;500;700&family=IBM+Plex+Mono:wght@400;700&display=swap">
|
||
<link rel="stylesheet" href="assets/css/tools.css">
|
||
</head>
|
||
<body class="lt-landing lt-preview-page">
|
||
|
||
<header class="lt-nav">
|
||
<a href="https://dobetternorge.no" class="lt-nav__brand">
|
||
<picture>
|
||
<source srcset="assets/images/logo-header.webp" type="image/webp">
|
||
<img class="lt-nav__logo" src="assets/images/logo-header.png" alt="Do Better Norge" width="140" height="36" loading="eager">
|
||
</picture>
|
||
<span class="lt-nav__badge">Legal Tools</span>
|
||
</a>
|
||
<div class="lt-nav__right">
|
||
<nav class="shell-lang-switcher" aria-label="Language">
|
||
<?php foreach (dbnToolsSupportedLanguages() as $langCode): ?>
|
||
<a href="?tool=<?= htmlspecialchars($slug) ?>&lang=<?= htmlspecialchars($langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
|
||
<?php endforeach; ?>
|
||
</nav>
|
||
<a href="index.php#access" class="lt-nav__cta"><?= htmlspecialchars(dbnToolsT('preview_get_access', $uiLang)) ?></a>
|
||
</div>
|
||
</header>
|
||
|
||
<main>
|
||
|
||
<section class="lt-preview-hero">
|
||
<div class="lt-preview-hero__inner">
|
||
<div class="lt-preview-hero__art" aria-hidden="true">
|
||
<?= $toolSvgs[$slug] ?? '' ?>
|
||
</div>
|
||
<div class="lt-preview-hero__text">
|
||
<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($localContent['pitch']) ?></p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="lt-preview-features">
|
||
<div class="lt-preview-features__inner">
|
||
<h2 class="lt-preview-features__heading"><?= htmlspecialchars(dbnToolsT('preview_what_it_does', $uiLang)) ?></h2>
|
||
<ul class="lt-preview-features__list">
|
||
<?php foreach ($localContent['features'] as $feat): ?>
|
||
<li class="lt-preview-features__item">
|
||
<span class="lt-preview-features__dot" aria-hidden="true"></span>
|
||
<?= htmlspecialchars($feat) ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="lt-preview-sample">
|
||
<div class="lt-preview-sample__inner">
|
||
<div class="lt-preview-sample__col">
|
||
<p class="lt-preview-sample__label">
|
||
<span class="lt-preview-sample__icon" aria-hidden="true">→</span>
|
||
<?= htmlspecialchars($sample['scenario_label']) ?>
|
||
</p>
|
||
<div class="lt-preview-sample__input">
|
||
<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">✓</span>
|
||
<?= htmlspecialchars($sample['output_label']) ?>
|
||
</p>
|
||
<div class="lt-preview-sample__output lt-preview-output">
|
||
<pre><?= htmlspecialchars($sample['output']) ?></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<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"><?= 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)) ?> →</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"><?= 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">
|
||
<?= htmlspecialchars($otherTool['label']) ?>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||
|
||
</body>
|
||
</html>
|