<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/bootstrap.php';

$uiLang   = dbnToolsCurrentLanguage();
$isAuthed = dbnToolsIsAuthenticated();
$langPath = '/timeline-tech.php';
$toolsLogin  = 'https://dobetternorge.no/tools-login.php?return=' . urlencode('/timeline.php');
$registerUrl = 'https://dobetternorge.no/register.php';

$_pt = require __DIR__ . '/translations/timeline-tech.php';
$t   = $_pt[$uiLang] ?? $_pt['en'];
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>How Timeline works — 3-pass extraction, Norwegian date recognition, fine-tuned LLM</title>
    <meta name="description" content="Technical deep-dive: how Timeline uses a 3-pass pipeline to extract and classify temporal events from Norwegian legal documents, with 12+ date format recognition and confidence scoring.">
    <meta name="robots" content="index, follow">
    <link rel="canonical" href="https://tools.dobetternorge.no/timeline-tech.php">
    <meta property="og:title" content="How Timeline works — AI date extraction pipeline">
    <meta property="og:description" content="Rule-based pre-pass, LLM extraction, and post-processing. Norwegian date format recognition, event classification schema, multi-engine support.">
    <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=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap">
    <link rel="stylesheet" href="assets/css/tools.css">
</head>
<body class="kdoc-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="<?= htmlspecialchars($langPath . '?lang=' . $langCode) ?>" class="<?= $langCode === $uiLang ? 'is-active' : '' ?>"><?= htmlspecialchars(dbnToolsLanguageLabel($langCode)) ?></a>
<?php endforeach; ?>
        </nav>
<?php if ($isAuthed): ?>
        <a href="/timeline.php" class="lt-nav__cta lt-nav__cta--enter"><?= htmlspecialchars($t['nav_open']) ?></a>
<?php else: ?>
        <a href="<?= htmlspecialchars($toolsLogin) ?>" class="lt-nav__cta"><?= htmlspecialchars($t['nav_signin']) ?></a>
<?php endif; ?>
    </div>
</header>

<nav class="kdoc-doc-nav" aria-label="Timeline documentation">
    <div class="kdoc-doc-nav__inner">
        <a href="/timeline-about.php"><?= htmlspecialchars($t['nav_about']) ?></a>
        <a href="/timeline-guide.php"><?= htmlspecialchars($t['nav_guide']) ?></a>
        <a href="/timeline-tech.php" class="is-active"><?= htmlspecialchars($t['nav_howit']) ?></a>
        <?php if ($isAuthed): ?><a href="/timeline.php"><?= htmlspecialchars($t['nav_opentool']) ?></a><?php endif; ?>
    </div>
</nav>

<!-- Hero -->
<section class="kdoc-hero" style="background: linear-gradient(rgba(5,15,40,0.85),rgba(5,15,40,0.92)), url('assets/images/timeline/hero-tech.png') center/cover no-repeat;">
    <div class="kdoc-hero__inner">
        <p class="kdoc-hero__kicker"><?= htmlspecialchars($t['hero_kicker']) ?></p>
        <h1 class="kdoc-hero__title"><?= htmlspecialchars($t['hero_title']) ?></h1>
        <p class="kdoc-hero__sub"><?= htmlspecialchars($t['hero_sub']) ?></p>

        <div class="kdoc-hero__stats">
            <div class="kdoc-hero__stat">
                <strong>12+</strong>
                <span><?= htmlspecialchars($t['stat1']) ?></span>
            </div>
            <div class="kdoc-hero__stat">
                <strong>5</strong>
                <span><?= htmlspecialchars($t['stat2']) ?></span>
            </div>
            <div class="kdoc-hero__stat">
                <strong>3</strong>
                <span><?= htmlspecialchars($t['stat3']) ?></span>
            </div>
            <div class="kdoc-hero__stat">
                <strong>3</strong>
                <span><?= htmlspecialchars($t['stat4']) ?></span>
            </div>
        </div>
    </div>
</section>

<!-- Architecture overview -->
<div class="kdoc-section">
    <p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['arch_eyebrow']) ?></p>
    <h2 class="kdoc-section__title"><?= htmlspecialchars($t['arch_title']) ?></h2>
    <p class="kdoc-section__sub"><?= htmlspecialchars($t['arch_sub']) ?></p>

    <div class="kdoc-pipeline">
        <div class="kdoc-pipeline__pass">
            <span class="kdoc-pipeline__pass-badge kdoc-pipeline__pass-badge--mini">Pass 1 &middot; PHP / regex</span>
            <h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass1_title']) ?></h3>
            <p class="kdoc-pipeline__pass-body"><?= $t['pass1_p1_html'] ?></p>
            <ul>
                <li><?= $t['pass1_li1_html'] ?></li>
                <li><?= htmlspecialchars($t['pass1_li2']) ?></li>
                <li><?= htmlspecialchars($t['pass1_li3']) ?></li>
                <li><?= htmlspecialchars($t['pass1_li4']) ?></li>
            </ul>
            <p class="kdoc-pipeline__pass-body" style="margin-top:0.7rem;"><?= htmlspecialchars($t['pass1_p2']) ?></p>
        </div>
        <div class="kdoc-pipeline__arrow-down" aria-hidden="true">&rarr;</div>
        <div class="kdoc-pipeline__pass">
            <span class="kdoc-pipeline__pass-badge">Pass 2 &middot; gpt-4o-mini / gpt-4o / dbn-legal-agent</span>
            <h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass2_title']) ?></h3>
            <p class="kdoc-pipeline__pass-body"><?= $t['pass2_p1_html'] ?></p>
            <ul>
                <li><code>date</code> — resolved ISO date, or verbatim string if unresolvable</li>
                <li><code>date_type</code> — <code>absolute</code> | <code>relative</code> | <code>recurring</code> | <code>conditional</code> | <code>period</code></li>
                <li><code>confidence</code> — <code>high</code> | <code>medium</code> | <code>low</code></li>
                <li><code>actor</code> — attributed entity (from source text, not inferred)</li>
                <li><code>description</code> — one-sentence event summary</li>
                <li><code>source_excerpt</code> — verbatim text fragment (max 200 chars)</li>
            </ul>
            <p class="kdoc-pipeline__pass-body" style="margin-top:0.7rem;"><?= htmlspecialchars($t['pass2_p2']) ?></p>
        </div>
        <div class="kdoc-pipeline__arrow-down" aria-hidden="true">&rarr;</div>
        <div class="kdoc-pipeline__pass">
            <span class="kdoc-pipeline__pass-badge kdoc-pipeline__pass-badge--optional">Pass 3 &middot; PHP post-processor</span>
            <h3 class="kdoc-pipeline__pass-title"><?= htmlspecialchars($t['pass3_title']) ?></h3>
            <p class="kdoc-pipeline__pass-body"><?= $t['pass3_p1_html'] ?></p>
            <ul>
                <li><?= $t['pass3_f1_html'] ?></li>
                <li><?= $t['pass3_f2_html'] ?></li>
                <li><?= $t['pass3_f3_html'] ?></li>
                <li><?= $t['pass3_f4_html'] ?></li>
            </ul>
            <p class="kdoc-pipeline__pass-body" style="margin-top:0.7rem;"><?= $t['pass3_p2_html'] ?></p>
        </div>
    </div>
</div>

<!-- Date recognition -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
    <p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['date_eyebrow']) ?></p>
    <h2 class="kdoc-section__title"><?= htmlspecialchars($t['date_title']) ?></h2>
    <p class="kdoc-section__sub"><?= htmlspecialchars($t['date_sub']) ?></p>

    <table class="kdoc-table">
        <thead>
            <tr>
                <th><?= htmlspecialchars($t['th_format']) ?></th>
                <th><?= htmlspecialchars($t['th_example']) ?></th>
                <th><?= htmlspecialchars($t['th_notes']) ?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td><code>dd.mm.yyyy</code></td>
                <td>30.07.2015</td>
                <td><?= htmlspecialchars($t['dn1']) ?></td>
            </tr>
            <tr>
                <td><code>dd.mm.yy</code></td>
                <td>09.04.25</td>
                <td><?= htmlspecialchars($t['dn2']) ?></td>
            </tr>
            <tr>
                <td><code>d. månedsnavn yyyy</code></td>
                <td>3. mars 2024</td>
                <td><?= htmlspecialchars($t['dn3']) ?></td>
            </tr>
            <tr>
                <td><code>d. månedsnavn</code></td>
                <td>15. januar</td>
                <td><?= htmlspecialchars($t['dn4']) ?></td>
            </tr>
            <tr>
                <td><code>yyyy-mm-dd</code></td>
                <td>2024-03-12</td>
                <td><?= htmlspecialchars($t['dn5']) ?></td>
            </tr>
            <tr>
                <td><code>månedsnavn yyyy</code></td>
                <td>mars 2024</td>
                <td><?= htmlspecialchars($t['dn6']) ?></td>
            </tr>
            <tr>
                <td><code>yyyy</code></td>
                <td>2024</td>
                <td><?= htmlspecialchars($t['dn7']) ?></td>
            </tr>
            <tr>
                <td>Season + year</td>
                <td>høsten 2023</td>
                <td><?= htmlspecialchars($t['dn8']) ?></td>
            </tr>
            <tr>
                <td>Diary-format line</td>
                <td>18.09.2025: Møte avholdt</td>
                <td><?= htmlspecialchars($t['dn9']) ?></td>
            </tr>
            <tr>
                <td>Relative reference</td>
                <td>tre uker etter vedtaket</td>
                <td><?= htmlspecialchars($t['dn10']) ?></td>
            </tr>
            <tr>
                <td>Recurring pattern</td>
                <td>hver mandag</td>
                <td><?= htmlspecialchars($t['dn11']) ?></td>
            </tr>
            <tr>
                <td>Period / range</td>
                <td>fra mars til juni 2024</td>
                <td><?= htmlspecialchars($t['dn12']) ?></td>
            </tr>
        </tbody>
    </table>
</div>
</section>

<!-- Classification schema -->
<div class="kdoc-section">
    <p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['class_eyebrow']) ?></p>
    <h2 class="kdoc-section__title"><?= htmlspecialchars($t['class_title']) ?></h2>

    <h3 style="font-family:'Crimson Pro',serif; font-size:1.15rem; font-weight:700; margin:0 0 0.8rem; color:var(--dbn-blue);"><?= htmlspecialchars($t['class_h1']) ?></h3>
    <table class="kdoc-table">
        <thead>
            <tr>
                <th><?= htmlspecialchars($t['th_datetype']) ?></th>
                <th><?= htmlspecialchars($t['th_definition']) ?></th>
                <th><?= htmlspecialchars($t['th_example']) ?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td><code>absolute</code></td>
                <td><?= htmlspecialchars($t['dt1_def']) ?></td>
                <td><em>30.07.2015</em> → 2015-07-30</td>
            </tr>
            <tr>
                <td><code>relative</code></td>
                <td><?= htmlspecialchars($t['dt2_def']) ?></td>
                <td><em>tre uker etter vedtaket</em></td>
            </tr>
            <tr>
                <td><code>recurring</code></td>
                <td><?= htmlspecialchars($t['dt3_def']) ?></td>
                <td><em>each Monday</em>, <em>every 6 months</em></td>
            </tr>
            <tr>
                <td><code>conditional</code></td>
                <td><?= htmlspecialchars($t['dt4_def']) ?></td>
                <td><em>if no response within 14 days</em></td>
            </tr>
            <tr>
                <td><code>period</code></td>
                <td><?= htmlspecialchars($t['dt5_def']) ?></td>
                <td><em>fra mars til juni 2024</em></td>
            </tr>
        </tbody>
    </table>

    <h3 style="font-family:'Crimson Pro',serif; font-size:1.15rem; font-weight:700; margin:2rem 0 0.8rem; color:var(--dbn-blue);"><?= htmlspecialchars($t['class_h2']) ?></h3>
    <table class="kdoc-table">
        <thead>
            <tr>
                <th><?= htmlspecialchars($t['th_conf']) ?></th>
                <th><?= htmlspecialchars($t['th_meaning']) ?></th>
                <th><?= htmlspecialchars($t['th_visual']) ?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td><code>high</code></td>
                <td><?= htmlspecialchars($t['conf1_meaning']) ?></td>
                <td><?= htmlspecialchars($t['conf1_visual']) ?></td>
            </tr>
            <tr>
                <td><code>medium</code></td>
                <td><?= htmlspecialchars($t['conf2_meaning']) ?></td>
                <td><?= htmlspecialchars($t['conf2_visual']) ?></td>
            </tr>
            <tr>
                <td><code>low</code></td>
                <td><?= htmlspecialchars($t['conf3_meaning']) ?></td>
                <td><?= htmlspecialchars($t['conf3_visual']) ?></td>
            </tr>
        </tbody>
    </table>

    <h3 style="font-family:'Crimson Pro',serif; font-size:1.15rem; font-weight:700; margin:2rem 0 0.8rem; color:var(--dbn-blue);"><?= htmlspecialchars($t['class_h3']) ?></h3>
    <table class="kdoc-table">
        <thead>
            <tr>
                <th><?= htmlspecialchars($t['th_rule']) ?></th>
                <th><?= htmlspecialchars($t['th_example']) ?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td><?= htmlspecialchars($t['act1_rule']) ?></td>
                <td><em>&ldquo;Trude [saksbehandler] ringte 14. mars&rdquo;</em> → actor: Trude</td>
            </tr>
            <tr>
                <td><?= htmlspecialchars($t['act2_rule']) ?></td>
                <td><em>&ldquo;Barnevernet fattet vedtak&rdquo;</em> → actor: Barnevernet</td>
            </tr>
            <tr>
                <td><?= htmlspecialchars($t['act3_rule']) ?></td>
                <td>actor: <code>[unattributed]</code></td>
            </tr>
            <tr>
                <td><?= htmlspecialchars($t['act4_rule']) ?></td>
                <td><?= htmlspecialchars($t['act4_example']) ?></td>
            </tr>
        </tbody>
    </table>
</div>

<!-- Multi-engine -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
    <p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['eng_eyebrow']) ?></p>
    <h2 class="kdoc-section__title"><?= htmlspecialchars($t['eng_title']) ?></h2>
    <p class="kdoc-section__sub"><?= htmlspecialchars($t['eng_sub']) ?></p>

    <table class="kdoc-table">
        <thead>
            <tr>
                <th><?= htmlspecialchars($t['th_engine'] ?? 'Engine') ?></th>
                <th><?= htmlspecialchars($t['th_model']) ?></th>
                <th><?= htmlspecialchars($t['th_latency']) ?></th>
                <th><?= htmlspecialchars($t['th_best']) ?></th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Azure gpt-4o-mini &#9733;</td>
                <td><code>gpt-4o-mini</code> (Azure West Europe)</td>
                <td>~15 s</td>
                <td><?= htmlspecialchars($t['eng1_best']) ?></td>
            </tr>
            <tr>
                <td>Azure gpt-4o</td>
                <td><code>gpt-4o</code> (Azure West Europe)</td>
                <td>~45 s</td>
                <td><?= htmlspecialchars($t['eng2_best']) ?></td>
            </tr>
            <tr>
                <td>GPU / cuttlefish</td>
                <td><code>dbn-legal-agent</code> via LiteLLM proxy</td>
                <td>~25 s</td>
                <td><?= htmlspecialchars($t['eng3_best']) ?></td>
            </tr>
        </tbody>
    </table>
</div>
</section>

<!-- Fine-tuned LLM -->
<div class="kdoc-section">
    <p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['ft_eyebrow']) ?></p>
    <h2 class="kdoc-section__title"><?= htmlspecialchars($t['ft_title']) ?></h2>

    <div class="kdoc-finetune">
        <span class="kdoc-finetune__badge"><?= htmlspecialchars($t['ft_badge']) ?></span>
        <h3 class="kdoc-finetune__title">dbn-legal-agent</h3>
        <p class="kdoc-finetune__body"><?= htmlspecialchars($t['ft_p1']) ?></p>
        <p class="kdoc-finetune__body" style="margin-top:0.8rem;"><?= htmlspecialchars($t['ft_p2']) ?></p>
        <div class="kdoc-finetune__chips">
            <span class="kdoc-finetune__chip">QLoRA</span>
            <span class="kdoc-finetune__chip">Norwegian legal corpus</span>
            <span class="kdoc-finetune__chip">case notes</span>
            <span class="kdoc-finetune__chip">court decisions</span>
            <span class="kdoc-finetune__chip">Barnevernet</span>
            <span class="kdoc-finetune__chip">Fylkesnemnda</span>
            <span class="kdoc-finetune__chip">LiteLLM proxy</span>
        </div>
    </div>
</div>

<!-- Privacy by design -->
<section class="kdoc-section--alt">
<div class="kdoc-section">
    <p class="kdoc-section__eyebrow"><?= htmlspecialchars($t['priv_eyebrow']) ?></p>
    <h2 class="kdoc-section__title"><?= htmlspecialchars($t['priv_title']) ?></h2>

    <div class="kdoc-privacy">
        <p class="kdoc-privacy__title"><?= htmlspecialchars($t['priv_badge']) ?></p>
        <ul>
            <li><?= $t['priv_1_html'] ?></li>
            <li><?= htmlspecialchars($t['priv_2']) ?></li>
            <li><?= $t['priv_3_html'] ?></li>
            <li><?= $t['priv_4_html'] ?></li>
            <li><?= $t['priv_5_html'] ?></li>
        </ul>
    </div>
</div>
</section>

<!-- CTA -->
<section class="kdoc-cta-strip">
    <h2 class="kdoc-cta-strip__title"><?= htmlspecialchars($t['cta_title']) ?></h2>
    <p class="kdoc-cta-strip__sub"><?= htmlspecialchars($t['cta_sub']) ?></p>
    <div class="kdoc-hero__ctas">
<?php if ($isAuthed): ?>
        <a href="/timeline.php" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_open']) ?></a>
<?php else: ?>
        <a href="<?= htmlspecialchars($toolsLogin) ?>" class="kdoc-btn-primary"><?= htmlspecialchars($t['btn_signin_cta']) ?></a>
        <a href="<?= htmlspecialchars($registerUrl) ?>" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_register']) ?></a>
<?php endif; ?>
        <a href="/timeline-guide.php" class="kdoc-btn-secondary"><?= htmlspecialchars($t['btn_guide']) ?></a>
    </div>
</section>

<?php require_once __DIR__ . '/includes/footer.php'; ?>
<script src="assets/js/tools.js" defer></script>
</body>
</html>
