{{- define "main" }}
<div class="not-found-page">
    {{/* Draggable low-poly easter egg — sits behind the content, purely
         decorative. Empty (no canvas) on phones / reduced-motion / no-WebGL. */}}
    <div class="not-found-field" id="not-found-field" aria-hidden="true"></div>
    <div class="not-found-content">
        <div class="not-found-code">404</div>
        {{- $isZh := eq site.Language.Lang "zh" }}
        <h1 class="not-found-title">{{ if $isZh }}页面未找到{{ else }}Page Not Found{{ end }}</h1>
        <p class="not-found-desc">{{ if $isZh }}这个页面好像去冒险了，找不回来了。让我们重新出发。{{ else }}Looks like this page went exploring without a map. Let's get you back on track.{{ end }}</p>
        <div class="not-found-actions">
            <a href="{{ "/" | relLangURL }}" class="not-found-btn not-found-btn--primary">← {{ if $isZh }}返回主页{{ else }}Go Home{{ end }}</a>
            <a href="{{ "/articles/" | relLangURL }}" class="not-found-btn not-found-btn--secondary">{{ if $isZh }}浏览所有文章{{ else }}Browse All Articles{{ end }}</a>
        </div>
        {{- $allPages := where site.RegularPages "Lang" site.Language.Lang }}
        {{- $recent := first 3 ($allPages.ByDate.Reverse) }}
        {{- if $recent }}
        <div class="not-found-recent">
            <p class="not-found-recent-label">{{ if $isZh }}你可能感兴趣的文章：{{ else }}Recent posts you might like:{{ end }}</p>
            <ul>
                {{- range $recent }}
                <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
                {{- end }}
            </ul>
        </div>
        {{- end }}
    </div>
</div>
<style>
.not-found-page {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    padding: 40px 20px;
    text-align: center;
}
/* Decorative 3D field behind the content. Pointer-events stay ON so the
   object can be grabbed/spun, but it's z-ordered below the content; the
   buttons/links sit above it (z-index:1) and remain fully clickable. */
.not-found-field {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
}
.not-found-field canvas { display: block; }
.not-found-content {
    position: relative;
    z-index: 1;
    max-width: 520px;
    /* Let pointer events fall through the empty margins to the 3D object,
       while the actual content (text/buttons) still captures its own. */
    pointer-events: none;
}
.not-found-content a,
.not-found-content button {
    pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
    .not-found-field { display: none; }
}
.not-found-code {
    font-family: var(--font-display, Georgia, serif);
    font-size: clamp(6rem, 20vw, 10rem);
    font-weight: 700;
    line-height: 1;
    color: var(--color-accent, #2e352e);
    margin-bottom: 16px;
}
.not-found-title {
    font-family: var(--font-display, Georgia, serif);
    font-size: 1.8rem;
    font-weight: 700;
    margin: 0 0 12px;
    color: var(--color-ink, var(--primary));
}
.not-found-desc {
    color: var(--secondary);
    font-size: 1rem;
    line-height: 1.6;
    margin: 0 0 32px;
}
.not-found-actions {
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
    margin-bottom: 40px;
}
.not-found-btn {
    display: inline-block;
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    transition: all 0.2s ease;
}
.not-found-btn--primary {
    background: var(--color-accent, #2e352e);
    color: var(--color-paper, #fff);
}
.not-found-btn--primary:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md, 0 4px 16px rgba(15, 23, 42, 0.12));
    color: var(--color-paper, #fff);
}
.not-found-btn--secondary {
    border: 1px solid var(--color-rule, var(--border));
    color: var(--color-ink, var(--primary));
    background: transparent;
}
.not-found-btn--secondary:hover {
    border-color: var(--color-accent, #2e352e);
    color: var(--color-accent, #2e352e);
}
.not-found-recent {
    text-align: left;
    padding: 20px 24px;
    background: var(--entry);
    border-radius: 12px;
    border: 1px solid var(--border);
}
.not-found-recent-label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--secondary);
    margin: 0 0 12px;
    font-weight: 600;
}
.not-found-recent ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.not-found-recent ul a {
    color: var(--primary);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
}
.not-found-recent ul a:hover {
    color: var(--color-accent, #2e352e);
}
</style>

{{/* ── 404 draggable low-poly easter egg ─────────────────────────
     three.js + OrbitControls + the float module, all fingerprinted and
     locally hosted (same pattern as knowledge-galaxy). The module self-
     gates: on phones / reduced-motion / no-WebGL it mounts nothing, so
     this costs only a tiny deferred import there. three/addons resolve
     via the importmap; the bare ./webgl-guard import is bundled in. */}}
{{- $three := resources.Get "js/vendor/three.module.min.js" | resources.Fingerprint "sha384" -}}
{{- $orbit := resources.Get "js/vendor/addons/controls/OrbitControls.js" | resources.Fingerprint "sha384" -}}
{{- $nf := resources.Get "js/three/not-found-float.js"
      | js.Build (dict "format" "esm" "minify" hugo.IsProduction "externals" (slice "three" "three/addons/controls/OrbitControls.js")) -}}
{{- if not site.Params.assets.disableFingerprinting -}}
  {{- $nf = $nf | fingerprint -}}
{{- end -}}
<script type="importmap">
{
  "imports": {
    "three": "{{ $three.RelPermalink }}",
    "three/addons/controls/OrbitControls.js": "{{ $orbit.RelPermalink }}"
  }
}
</script>
<script type="module">
  import { mountNotFoundFloat } from "{{ $nf.RelPermalink }}";
  const host = document.getElementById('not-found-field');
  if (host) mountNotFoundFloat(host);
</script>
{{- end }}
