feat: add Prettier with go-template and toml plugins, format all files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-08 13:18:05 +02:00
parent b78bc26322
commit 436223913e
36 changed files with 1765 additions and 1178 deletions
+24 -9
View File
@@ -1,24 +1,39 @@
{{- /* Inline author byline for post single pages.
Expects the author page as context (.).
*/ -}}
Expects the author page as context (.).
*/
-}}
<div class="flex items-center gap-4 py-6 border-t border-b border-zinc my-8 max-w-2xl">
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
{{- if $avatarRes -}}
{{- $av := $avatarRes.Resize "96x webp" -}}
<a href="{{ $.RelPermalink }}" class="flex-shrink-0">
<img src="{{ $av.RelPermalink }}" alt="{{ $.Params.name | default $.Title }}" class="w-16 h-16 object-cover border border-zinc hover:border-heat transition-colors" loading="lazy" decoding="async">
<img
src="{{ $av.RelPermalink }}"
alt="{{ $.Params.name | default $.Title }}"
class="w-16 h-16 object-cover border border-zinc hover:border-heat transition-colors"
loading="lazy"
decoding="async"
/>
</a>
{{- else -}}{{- with .Params.avatar -}}
<a href="{{ $.RelPermalink }}" class="flex-shrink-0">
<img src="{{ . }}" alt="{{ $.Params.name | default $.Title }}" class="w-16 h-16 object-cover border border-zinc hover:border-heat transition-colors" loading="lazy" decoding="async">
</a>
{{- end -}}{{- end -}}
{{- else -}}
{{- with .Params.avatar -}}
<a href="{{ $.RelPermalink }}" class="flex-shrink-0">
<img
src="{{ . }}"
alt="{{ $.Params.name | default $.Title }}"
class="w-16 h-16 object-cover border border-zinc hover:border-heat transition-colors"
loading="lazy"
decoding="async"
/>
</a>
{{- end -}}
{{- end -}}
<div class="min-w-0">
<a href="{{ .RelPermalink }}" class="text-base font-display text-heat hover:text-frost transition-colors block">
{{ .Params.name | default .Title }}
</a>
{{- with .Params.bio -}}
<p class="text-fog text-sm leading-relaxed line-clamp-2 font-body">{{ . }}</p>
<p class="text-fog text-sm leading-relaxed line-clamp-2 font-body">{{ . }}</p>
{{- end -}}
</div>
</div>
+17 -11
View File
@@ -1,15 +1,15 @@
<footer class="relative overflow-hidden border-t border-zinc gutter-x py-14 mt-auto bg-ink speed-lines">
<!-- Decorative background text -->
<div
class="graffiti-tag absolute -bottom-6 -right-4 select-none pointer-events-none"
style="-webkit-text-stroke-color: rgba(255,26,140,0.07); opacity: 1;"
aria-hidden="true"
>PIVOINE</div>
>
PIVOINE
</div>
<div class="gradient-line mb-10 relative z-10"></div>
<div class="relative z-10 flex flex-col md:flex-row md:items-start justify-between gap-10">
<!-- Brand -->
<div>
<a href="/" class="block mb-4 hover:opacity-90 transition-opacity w-fit" aria-label="{{ .Site.Title }} Home">
@@ -22,17 +22,23 @@
<nav aria-label="Footer navigation">
<ul class="flex flex-wrap gap-x-8 gap-y-4">
{{- range .Site.Menus.footer -}}
<li>
<a href="{{ .URL }}" class="label text-fog hover:text-heat transition-colors">{{ .Name }}</a>
</li>
<li>
<a href="{{ .URL }}" class="label text-fog hover:text-heat transition-colors">{{ .Name }}</a>
</li>
{{- end -}}
{{- with .Site.Params.social -}}
{{- range $platform, $url := . -}}
<li>
<a href="{{ $url }}" target="_blank" rel="noopener noreferrer" class="label text-fog hover:text-frost transition-colors">
{{- $platform | upper -}} {{ partial "icon.html" "arrow-external" }}
</a>
</li>
<li>
<a
href="{{ $url }}"
target="_blank"
rel="noopener noreferrer"
class="label text-fog hover:text-frost transition-colors"
>
{{- $platform | upper -}}
{{ partial "icon.html" "arrow-external" }}
</a>
</li>
{{- end -}}
{{- end -}}
</ul>
+96 -44
View File
@@ -1,81 +1,133 @@
<meta charset="utf-8">
<meta name="htmx-config" content='{"globalViewTransitions":true,"scrollBehavior":"smooth"}'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#FF1A8C">
<meta charset="utf-8" />
<meta name="htmx-config" content='{"globalViewTransitions":true,"scrollBehavior":"smooth"}' />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#FF1A8C" />
<title>
{{- if .IsHome -}}
{{- .Site.Title }} — {{ .Site.Params.tagline -}}
{{- .Site.Title }} —
{{ .Site.Params.tagline -}}
{{- else -}}
{{- .Title }} — {{ .Site.Title -}}
{{- .Title }} —
{{ .Site.Title -}}
{{- end -}}
</title>
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
<meta name="author" content="{{ with .Params.author }}{{ . }}{{ else }}{{ .Site.Params.author }}{{ end }}">
{{- if .Site.Params.robots }}<meta name="robots" content="{{ .Site.Params.robots }}">{{ end }}
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}" />
<meta name="author" content="{{ with .Params.author }}{{ . }}{{ else }}{{ .Site.Params.author }}{{ end }}" />
{{- if .Site.Params.robots }}<meta name="robots" content="{{ .Site.Params.robots }}" />{{ end }}
<!-- Open Graph -->
<meta property="og:site_name" content="{{ .Site.Title }}">
<meta property="og:title" content="{{ if .IsHome }}{{ .Site.Title }} — {{ .Site.Params.tagline }}{{ else }}{{ .Title }}{{ end }}">
<meta property="og:description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
<meta property="og:url" content="{{ .Permalink }}">
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
<meta property="og:locale" content="{{ .Site.LanguageCode | default "en_US" | replaceRE "-" "_" }}">
<meta property="og:site_name" content="{{ .Site.Title }}" />
<meta
property="og:title"
content="{{ if .IsHome }}
{{ .Site.Title }} —
{{ .Site.Params.tagline }}
{{ else }}
{{ .Title }}
{{ end }}"
/>
<meta
property="og:description"
content="{{ with .Description }}
{{ . }}
{{ else }}
{{ .Site.Params.description }}
{{ end }}"
/>
<meta property="og:url" content="{{ .Permalink }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:locale" content="{{ .Site.LanguageCode | default "en_US" | replaceRE "-" "_" }}" />
{{- $ogImage := .Site.Params.ogImage -}}
{{- $ogImageAlt := .Site.Title -}}
{{- with .Params.banner -}}
{{- $ogImage = .src -}}
{{- $ogImageAlt = $.Title -}}
{{- end -}}
<meta property="og:image" content="{{ $ogImage | absURL }}">
<meta property="og:image:alt" content="{{ $ogImageAlt }}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image" content="{{ $ogImage | absURL }}" />
<meta property="og:image:alt" content="{{ $ogImageAlt }}" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
{{- if .IsPage }}
<meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
<meta property="article:modified_time" content="{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}">
{{- with .Params.author }}<meta property="article:author" content="{{ . }}">{{ end }}
{{- range .Params.categories }}<meta property="article:section" content="{{ . }}">{{ end }}
{{- range .Params.tags }}<meta property="article:tag" content="{{ . }}">{{ end }}
<meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}" />
<meta property="article:modified_time" content="{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}" />
{{- with .Params.author }}<meta property="article:author" content="{{ . }}" />{{ end }}
{{- range .Params.categories }}<meta property="article:section" content="{{ . }}" />{{ end }}
{{- range .Params.tags }}<meta property="article:tag" content="{{ . }}" />{{ end }}
{{- end }}
<!-- Twitter / X Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:card" content="summary_large_image" />
{{- with .Site.Params.twitterHandle }}
<meta name="twitter:site" content="@{{ . }}">
<meta name="twitter:site" content="@{{ . }}" />
{{- end }}
<meta name="twitter:title" content="{{ if .IsHome }}{{ .Site.Title }} — {{ .Site.Params.tagline }}{{ else }}{{ .Title }}{{ end }}">
<meta name="twitter:description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
<meta name="twitter:image" content="{{ $ogImage | absURL }}">
<meta name="twitter:image:alt" content="{{ $ogImageAlt }}">
<meta
name="twitter:title"
content="{{ if .IsHome }}
{{ .Site.Title }} —
{{ .Site.Params.tagline }}
{{ else }}
{{ .Title }}
{{ end }}"
/>
<meta
name="twitter:description"
content="{{ with .Description }}
{{ . }}
{{ else }}
{{ .Site.Params.description }}
{{ end }}"
/>
<meta name="twitter:image" content="{{ $ogImage | absURL }}" />
<meta name="twitter:image:alt" content="{{ $ogImageAlt }}" />
<!-- Canonical -->
<link rel="canonical" href="{{ .Permalink }}">
<link rel="canonical" href="{{ .Permalink }}" />
<!-- JSON-LD structured data -->
{{- partial "schema.html" . -}}
<!-- Fonts — Bebas Neue + Barlow + Share Tech Mono (non-render-blocking) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Barlow:ital,wght@0,300;0,400;0,500;0,600;1,400&family=Share+Tech+Mono&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Barlow:ital,wght@0,300;0,400;0,500;0,600;1,400&family=Share+Tech+Mono&display=swap" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Barlow:ital,wght@0,300;0,400;0,500;0,600;1,400&family=Share+Tech+Mono&display=swap"></noscript>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="preload"
as="style"
href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Barlow:ital,wght@0,300;0,400;0,500;0,600;1,400&family=Share+Tech+Mono&display=swap"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Barlow:ital,wght@0,300;0,400;0,500;0,600;1,400&family=Share+Tech+Mono&display=swap"
media="print"
onload="this.media='all'"
/>
<noscript
><link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Barlow:ital,wght@0,300;0,400;0,500;0,600;1,400&family=Share+Tech+Mono&display=swap"
/></noscript>
<!-- CSS via Hugo Pipes + PostCSS + Tailwind v4 -->
{{- $css := resources.Get "css/main.css" | css.PostCSS -}}
{{- if eq hugo.Environment "production" -}}
{{- $css = $css | minify | fingerprint "sha256" -}}
{{- end -}}
<link rel="stylesheet" href="{{ $css.RelPermalink }}"{{ if eq hugo.Environment "production" }} integrity="{{ $css.Data.Integrity }}"{{ end }}>
<link
rel="stylesheet"
href="{{ $css.RelPermalink }}"
{{ if eq hugo.Environment "production" }}integrity="{{ $css.Data.Integrity }}"{{ end }}
/>
<!-- Favicon & PWA -->
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="manifest" href="/site.webmanifest">
<meta name="msapplication-TileColor" content="#050510">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="manifest" href="/site.webmanifest" />
<meta name="msapplication-TileColor" content="#050510" />
+49 -5
View File
@@ -1,11 +1,55 @@
{{- /* Inline SVG icon. Usage: {{ partial "icon.html" "arrow-right" }}
Renders at 1em × 1em, inherits currentColor, aria-hidden.
*/ -}}
Renders at 1em × 1em, inherits currentColor, aria-hidden. */ -}}
{{- $name := . -}}
{{- if eq $name "arrow-right" -}}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="1em" height="1em" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:inline-block;vertical-align:-0.1em"><path d="M2 8h12"/><path d="M9 3l5 5-5 5"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="1em"
height="1em"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
style="display:inline-block;vertical-align:-0.1em"
>
<path d="M2 8h12" />
<path d="M9 3l5 5-5 5" />
</svg>
{{- else if eq $name "arrow-left" -}}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="1em" height="1em" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:inline-block;vertical-align:-0.1em"><path d="M14 8H2"/><path d="M7 3L2 8l5 5"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="1em"
height="1em"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
style="display:inline-block;vertical-align:-0.1em"
>
<path d="M14 8H2" />
<path d="M7 3L2 8l5 5" />
</svg>
{{- else if eq $name "arrow-external" -}}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="1em" height="1em" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="display:inline-block;vertical-align:-0.1em"><path d="M4 12L12 4"/><path d="M6 4h6v6"/></svg>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="1em"
height="1em"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
style="display:inline-block;vertical-align:-0.1em"
>
<path d="M4 12L12 4" />
<path d="M6 4h6v6" />
</svg>
{{- end -}}
+11 -10
View File
@@ -2,15 +2,16 @@
Renders a Hugo image resource as an optimised WebP <img> with responsive srcset.
Parameters:
res — Hugo image resource (required)
widths — slice of pixel widths to generate, e.g. (slice 600 1200)
default: (slice 800 1600)
sizes — value for the <img sizes> attribute
default: "100vw"
class — CSS classes applied to <img>
alt — alt text (default "")
loading — "lazy" or "eager" (default "lazy")
*/ -}}
res — Hugo image resource (required)
widths — slice of pixel widths to generate, e.g. (slice 600 1200)
default: (slice 800 1600)
sizes — value for the <img sizes> attribute
default: "100vw"
class — CSS classes applied to <img>
alt — alt text (default "")
loading — "lazy" or "eager" (default "lazy")
*/
-}}
{{- $res := .res -}}
{{- $widths := .widths | default (slice 800 1600) -}}
{{- $sizes := .sizes | default "100vw" -}}
@@ -35,4 +36,4 @@
height="{{ $primary.Height }}"
loading="{{ $loading }}"
decoding="async"
>
/>
+4 -5
View File
@@ -1,8 +1,7 @@
{{- /*
Logo image.
Usage: {{ partial "logo.html" (dict "class" "h-8 w-auto") }}
Params:
class — CSS classes on the <img> element (default: "h-9 w-auto")
*/ -}}
Usage: {{ partial "logo.html" (dict "class" "h-8 w-auto")
}}
Params: class — CSS classes on the <img /> element (default: "h-9 w-auto") */ -}}
{{- $class := .class | default "h-9 w-auto" -}}
<img src="/logo.svg" class="{{ $class }} logo-img" alt="{{ site.Title }}" width="512" height="512">
<img src="/logo.svg" class="{{ $class }} logo-img" alt="{{ site.Title }}" width="512" height="512" />
+19 -22
View File
@@ -2,35 +2,32 @@
Renders an image or video from a front matter map.
Usage:
{{ partial "media.html" (dict "media" .Params.banner "class" "w-full h-full object-cover") }}
Parameters:
media — map with keys: type (image|video), src, alt
class — CSS classes applied to the img/video element
lazy — set to false to disable lazy loading (default true)
*/ -}}
{{ partial "media.html" (dict "media" .Params.banner "class" "w-full h-full object-cover")
}}
Parameters: media — map with keys: type (image|video), src, alt class — CSS classes applied to the img/video element
lazy — set to false to disable lazy loading (default true) */ -}}
{{- $media := .media -}}
{{- $class := .class | default "" -}}
{{- $lazy := .lazy | default true -}}
{{- with $media -}}
{{- if eq .type "video" -}}
<video
class="{{ $class }}"
src="{{ .src }}"
autoplay
loop
muted
playsinline
{{- with .alt }} aria-label="{{ . }}"{{ end }}
></video>
<video
class="{{ $class }}"
src="{{ .src }}"
autoplay
loop
muted
playsinline
{{- with .alt }}aria-label="{{ . }}"{{ end }}
></video>
{{- else -}}
<img
class="{{ $class }}"
src="{{ .src }}"
alt="{{ .alt | default "" }}"
{{- if $lazy }} loading="lazy" decoding="async"{{ end }}
>
<img
class="{{ $class }}"
src="{{ .src }}"
alt="{{ .alt | default "" }}"
{{- if $lazy }}loading="lazy" decoding="async"{{ end }}
/>
{{- end -}}
{{- end -}}
+88 -53
View File
@@ -10,7 +10,11 @@
:class="$store.nav.open || scrolled ? 'bg-ink/95 backdrop-blur-md shadow-[0_1px_0_var(--color-zinc)]' : ''"
>
<!-- Logotype -->
<a href="/" class="flex items-center gap-3 hover:opacity-90 transition-opacity" aria-label="{{ .Site.Params.logoText }} Home">
<a
href="/"
class="flex items-center gap-3 hover:opacity-90 transition-opacity"
aria-label="{{ .Site.Params.logoText }} Home"
>
{{- partial "logo.html" (dict "id" "nav" "class" "h-12 w-auto flex-shrink-0") -}}
<span class="logo-glitch font-display text-2xl md:text-3xl leading-none tracking-wide">
{{- .Site.Params.logoText -}}
@@ -20,19 +24,19 @@
<!-- Desktop navigation -->
<nav class="hidden md:flex items-center gap-8" aria-label="Primary navigation">
{{- range .Site.Menus.main -}}
{{- $href := .URL -}}
<a
href="{{ $href }}"
class="label relative transition-colors"
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-heat' : 'text-fog hover:text-chalk'"
>
{{ .Name }}
<span
class="absolute -bottom-0.5 left-0 h-px bg-heat transition-all duration-300 ease-out"
:style="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'width: 100%' : 'width: 0'"
style="width: 0"
></span>
</a>
{{- $href := .URL -}}
<a
href="{{ $href }}"
class="label relative transition-colors"
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-heat' : 'text-fog hover:text-chalk'"
>
{{ .Name }}
<span
class="absolute -bottom-0.5 left-0 h-px bg-heat transition-all duration-300 ease-out"
:style="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'width: 100%' : 'width: 0'"
style="width: 0"
></span>
</a>
{{- end -}}
</nav>
@@ -45,12 +49,18 @@
aria-controls="mobile-menu"
aria-label="Toggle navigation"
>
<span class="block h-px w-6 bg-current transition-all duration-300 origin-center"
:class="$store.nav.open ? 'rotate-45 translate-y-[7px]' : ''"></span>
<span class="block h-px w-4 bg-current transition-all duration-200"
:class="$store.nav.open ? 'opacity-0' : 'opacity-100'"></span>
<span class="block h-px w-6 bg-current transition-all duration-300 origin-center"
:class="$store.nav.open ? '-rotate-45 -translate-y-[7px]' : ''"></span>
<span
class="block h-px w-6 bg-current transition-all duration-300 origin-center"
:class="$store.nav.open ? 'rotate-45 translate-y-[7px]' : ''"
></span>
<span
class="block h-px w-4 bg-current transition-all duration-200"
:class="$store.nav.open ? 'opacity-0' : 'opacity-100'"
></span>
<span
class="block h-px w-6 bg-current transition-all duration-300 origin-center"
:class="$store.nav.open ? '-rotate-45 -translate-y-[7px]' : ''"
></span>
</button>
</div>
@@ -73,51 +83,70 @@
<div class="gradient-line flex-none"></div>
<!-- Decorative background text -->
<div class="graffiti-tag absolute -bottom-4 -right-4 select-none pointer-events-none"
style="-webkit-text-stroke-color: rgba(155,0,255,0.07);" aria-hidden="true">MENU</div>
<div
class="graffiti-tag absolute -bottom-4 -right-4 select-none pointer-events-none"
style="-webkit-text-stroke-color: rgba(155,0,255,0.07);"
aria-hidden="true"
>
MENU
</div>
<!-- Main nav links -->
<nav class="flex-1 flex flex-col justify-center gutter-x py-10" aria-label="Mobile navigation">
<div class="flex flex-col gap-0">
{{- $i := 0 -}}
{{- range .Site.Menus.main -}}
{{- $href := .URL -}}
<a
href="{{ $href }}"
class="group relative leading-none py-3 overflow-hidden"
style="font-family: var(--font-display); font-size: clamp(2.8rem, 11vw, 6.5rem); animation: mob-link-in 0.5s var(--ease-out-expo) {{ mul $i 70 }}ms both"
@click="$store.nav.open = false"
>
<!-- Hover sweep -->
<span class="absolute inset-y-0 left-0 w-0 group-hover:w-full transition-all duration-300 ease-out"
style="background: linear-gradient(90deg, rgba(255,26,140,0.07), transparent);"></span>
<!-- Link text -->
<span class="relative transition-colors duration-200 text-paper group-hover:text-heat uppercase"
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-gradient' : ''"
>{{ .Name }}</span>
<!-- Index number -->
<span class="absolute right-0 top-1/2 -translate-y-1/2 label text-smoke group-hover:text-heat transition-colors duration-200"
style="animation: mob-link-in 0.4s var(--ease-out-expo) {{ add (mul $i 70) 100 }}ms both"
>0{{ add $i 1 }}</span>
</a>
{{- $i = add $i 1 -}}
{{- $href := .URL -}}
<a
href="{{ $href }}"
class="group relative leading-none py-3 overflow-hidden"
style="font-family: var(--font-display); font-size: clamp(2.8rem, 11vw, 6.5rem); animation: mob-link-in 0.5s var(--ease-out-expo) {{ mul $i 70 }}ms both"
@click="$store.nav.open = false"
>
<!-- Hover sweep -->
<span
class="absolute inset-y-0 left-0 w-0 group-hover:w-full transition-all duration-300 ease-out"
style="background: linear-gradient(90deg, rgba(255,26,140,0.07), transparent);"
></span>
<!-- Link text -->
<span
class="relative transition-colors duration-200 text-paper group-hover:text-heat uppercase"
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-gradient' : ''"
>{{ .Name }}</span
>
<!-- Index number -->
<span
class="absolute right-0 top-1/2 -translate-y-1/2 label text-smoke group-hover:text-heat transition-colors duration-200"
style="animation: mob-link-in 0.4s var(--ease-out-expo) {{ add (mul $i 70) 100 }}ms both"
>0{{ add $i 1 }}</span
>
</a>
{{- $i = add $i 1 -}}
{{- end -}}
</div>
<div class="gradient-line my-8"
style="animation: mob-link-in 0.4s ease {{ mul $i 70 }}ms both"></div>
<div class="gradient-line my-8" style="animation: mob-link-in 0.4s ease {{ mul $i 70 }}ms both"></div>
<div class="flex flex-wrap gap-x-8 gap-y-3"
style="animation: mob-link-in 0.4s ease {{ add (mul $i 70) 40 }}ms both">
<div
class="flex flex-wrap gap-x-8 gap-y-3"
style="animation: mob-link-in 0.4s ease {{ add (mul $i 70) 40 }}ms both"
>
{{- range .Site.Menus.footer -}}
<a href="{{ .URL }}" class="label text-fog hover:text-heat transition-colors" @click="$store.nav.open = false">{{ .Name }}</a>
<a
href="{{ .URL }}"
class="label text-fog hover:text-heat transition-colors"
@click="$store.nav.open = false"
>{{ .Name }}</a
>
{{- end -}}
</div>
</nav>
<!-- Bottom bar -->
<div class="flex-none gutter-x pb-8 pt-4 border-t border-zinc"
style="animation: mob-link-in 0.4s ease 420ms both">
<div
class="flex-none gutter-x pb-8 pt-4 border-t border-zinc"
style="animation: mob-link-in 0.4s ease 420ms both"
>
<p class="label text-smoke">{{ .Site.Params.tagline }}</p>
</div>
</div>
@@ -125,8 +154,14 @@
</header>
<style>
@keyframes mob-link-in {
from { opacity: 0; transform: translateY(14px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes mob-link-in {
from {
opacity: 0;
transform: translateY(14px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
+32 -25
View File
@@ -1,33 +1,40 @@
{{- /* Custom pagination component.
Call as: {{ partial "pagination.html" . }}
Call as: {{ partial "pagination.html" .
}}
*/ -}}
{{- $paginator := .Paginator -}}
{{- if gt $paginator.TotalPages 1 -}}
<nav class="flex items-center justify-center gap-2 py-16" aria-label="Pagination">
<nav class="flex items-center justify-center gap-2 py-16" aria-label="Pagination">
{{- if $paginator.HasPrev -}}
<a
href="{{ $paginator.Prev.URL }}"
class="label border border-mist text-ash px-5 py-3 hover:border-gold hover:text-gold transition-all duration-300"
aria-label="Previous page"
>{{ partial "icon.html" "arrow-left" }} Prev</a
>
{{- end -}}
{{- if $paginator.HasPrev -}}
<a
href="{{ $paginator.Prev.URL }}"
class="label border border-mist text-ash px-5 py-3 hover:border-gold hover:text-gold transition-all duration-300"
aria-label="Previous page"
>{{ partial "icon.html" "arrow-left" }} Prev</a>
{{- end -}}
{{- range $paginator.Pagers -}}
<a
href="{{ .URL }}"
class="label border px-4 py-3 transition-all duration-300 {{ if eq . $paginator }}
border-gold text-gold
{{ else }}
border-mist text-ash hover:border-gold hover:text-gold
{{ end }}"
{{- if eq . $paginator }}aria-current="page"{{ end }}
>{{ .PageNumber }}</a
>
{{- end -}}
{{- range $paginator.Pagers -}}
<a
href="{{ .URL }}"
class="label border px-4 py-3 transition-all duration-300 {{ if eq . $paginator }}border-gold text-gold{{ else }}border-mist text-ash hover:border-gold hover:text-gold{{ end }}"
{{- if eq . $paginator }} aria-current="page"{{ end }}
>{{ .PageNumber }}</a>
{{- end -}}
{{- if $paginator.HasNext -}}
<a
href="{{ $paginator.Next.URL }}"
class="label border border-mist text-ash px-5 py-3 hover:border-gold hover:text-gold transition-all duration-300"
aria-label="Next page"
>Next {{ partial "icon.html" "arrow-right" }}</a
>
{{- end -}}
{{- if $paginator.HasNext -}}
<a
href="{{ $paginator.Next.URL }}"
class="label border border-mist text-ash px-5 py-3 hover:border-gold hover:text-gold transition-all duration-300"
aria-label="Next page"
>Next {{ partial "icon.html" "arrow-right" }}</a>
{{- end -}}
</nav>
</nav>
{{- end -}}
+25 -20
View File
@@ -1,50 +1,56 @@
{{- /* Large overlay card for featured/secondary slots.
Expects a post page as context (.).
*/ -}}
Expects a post page as context (.).
*/
-}}
{{- $post := . -}}
<article class="group relative overflow-hidden aspect-[3/4] md:aspect-[4/5] card-comic">
<a href="{{ $post.RelPermalink }}" class="block w-full h-full" aria-label="{{ $post.Title }}">
<!-- Background media — bundle banner.png → 01.png → .Params.banner -->
{{- $thumb := $post.Resources.GetMatch "banner.png" -}}
{{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
<div class="card-media w-full h-full absolute inset-0">
{{- if $thumb -}}
{{- partial "img.html" (dict "res" $thumb "widths" (slice 800 1200) "sizes" "(max-width: 768px) 100vw, 50vw" "class" "w-full h-full object-cover" "alt" $post.Title) -}}
{{- else -}}{{- with $post.Params.banner -}}
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}}
{{- else -}}
<div class="w-full h-full bg-concrete flex items-center justify-center halftone">
<span class="label text-smoke">PIVOINE</span>
</div>
{{- end -}}{{- end -}}
{{- with $post.Params.banner -}}
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}}
{{- else -}}
<div class="w-full h-full bg-concrete flex items-center justify-center halftone">
<span class="label text-smoke">PIVOINE</span>
</div>
{{- end -}}
{{- end -}}
</div>
<!-- Gradient overlay -->
<div class="absolute inset-0 overlay-gradient transition-opacity duration-500 group-hover:opacity-90"></div>
<!-- Diagonal heat accent -->
<div class="absolute bottom-16 left-0 w-28 h-[3px] opacity-0 group-hover:opacity-90 transition-opacity duration-300"
style="background: linear-gradient(90deg, var(--color-heat), var(--color-pulse)); transform: skewX(-20deg) translateX(-4px);"></div>
<div
class="absolute bottom-16 left-0 w-28 h-[3px] opacity-0 group-hover:opacity-90 transition-opacity duration-300"
style="background: linear-gradient(90deg, var(--color-heat), var(--color-pulse)); transform: skewX(-20deg) translateX(-4px);"
></div>
<!-- Content -->
<div class="absolute bottom-0 left-0 right-0 p-5 md:p-6">
{{- with $post.Params.categories -}}
<div class="flex flex-wrap gap-2 mb-3">
{{- range first 1 . -}}
<span class="badge badge-outline">{{ . }}</span>
{{- end -}}
</div>
<div class="flex flex-wrap gap-2 mb-3">
{{- range first 1 . -}}
<span class="badge badge-outline">{{ . }}</span>
{{- end -}}
</div>
{{- end -}}
<h3 class="font-display text-xl md:text-2xl text-paper text-balance leading-none group-hover:text-heat transition-colors mb-3">
<h3
class="font-display text-xl md:text-2xl text-paper text-balance leading-none group-hover:text-heat transition-colors mb-3"
>
{{- $post.Title -}}
</h3>
<div class="flex items-center gap-2">
{{- with $post.Params.author -}}
{{- $authorPage := site.GetPage (printf "authors/%s" .) -}}
{{- with $authorPage -}}
<span class="label text-chalk opacity-70">{{ .Params.name | default .Title }}</span>
<span class="text-smoke opacity-60" aria-hidden="true">/</span>
<span class="label text-chalk opacity-70">{{ .Params.name | default .Title }}</span>
<span class="text-smoke opacity-60" aria-hidden="true">/</span>
{{- end -}}
{{- end -}}
<time class="label text-chalk opacity-70" datetime="{{ $post.Date.Format "2006-01-02" }}">
@@ -52,6 +58,5 @@
</time>
</div>
</div>
</a>
</article>
+40 -20
View File
@@ -1,36 +1,41 @@
{{- /* Compact post card for grids.
Expects a post page as context (.).
*/ -}}
Expects a post page as context (.).
*/
-}}
{{- $post := . -}}
<article class="group card-comic flex flex-col bg-concrete">
<a href="{{ $post.RelPermalink }}" class="block flex-1 flex flex-col">
<!-- Thumbnail — bundle banner.png → 01.png → .Params.banner -->
{{- $thumb := $post.Resources.GetMatch "banner.png" -}}
{{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
<div class="card-media aspect-editorial">
{{- if $thumb -}}
{{- partial "img.html" (dict "res" $thumb "widths" (slice 600 1000) "sizes" "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw" "class" "w-full h-full object-cover" "alt" $post.Title) -}}
{{- else -}}{{- with $post.Params.banner -}}
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}}
{{- else -}}
<div class="w-full h-full flex items-center justify-center halftone">
<span class="label text-smoke text-xs">PIVOINE</span>
</div>
{{- end -}}{{- end -}}
{{- with $post.Params.banner -}}
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}}
{{- else -}}
<div class="w-full h-full flex items-center justify-center halftone">
<span class="label text-smoke text-xs">PIVOINE</span>
</div>
{{- end -}}
{{- end -}}
</div>
<!-- Category badge — parallelogram -->
{{- with $post.Params.categories -}}
<div class="flex flex-wrap gap-2 px-4 pt-4">
{{- range first 1 . -}}
<span class="badge">{{ . }}</span>
{{- end -}}
</div>
<div class="flex flex-wrap gap-2 px-4 pt-4">
{{- range first 1 . -}}
<span class="badge">{{ . }}</span>
{{- end -}}
</div>
{{- end -}}
<!-- Title -->
<h3 class="font-display text-base md:text-lg text-paper text-balance leading-none group-hover:text-heat transition-colors px-4 pt-3 pb-2 flex-1">
<h3
class="font-display text-base md:text-lg text-paper text-balance leading-none group-hover:text-heat transition-colors px-4 pt-3 pb-2 flex-1"
>
{{- $post.Title -}}
</h3>
@@ -42,10 +47,26 @@
{{- $avRes := .Resources.GetMatch "avatar.*" -}}
{{- if $avRes -}}
{{- $av := $avRes.Resize "64x webp" -}}
<img src="{{ $av.RelPermalink }}" alt="{{ $authorPage.Params.name | default $authorPage.Title }}" class="w-5 h-5 object-cover border border-smoke flex-shrink-0" width="{{ $av.Width }}" height="{{ $av.Height }}" loading="lazy" decoding="async">
{{- else -}}{{- with .Params.avatar -}}
<img src="{{ . }}" alt="{{ $authorPage.Params.name | default $authorPage.Title }}" class="w-5 h-5 object-cover border border-smoke flex-shrink-0" loading="lazy" decoding="async">
{{- end -}}{{- end -}}
<img
src="{{ $av.RelPermalink }}"
alt="{{ $authorPage.Params.name | default $authorPage.Title }}"
class="w-5 h-5 object-cover border border-smoke flex-shrink-0"
width="{{ $av.Width }}"
height="{{ $av.Height }}"
loading="lazy"
decoding="async"
/>
{{- else -}}
{{- with .Params.avatar -}}
<img
src="{{ . }}"
alt="{{ $authorPage.Params.name | default $authorPage.Title }}"
class="w-5 h-5 object-cover border border-smoke flex-shrink-0"
loading="lazy"
decoding="async"
/>
{{- end -}}
{{- end -}}
<span class="label text-fog">{{ .Params.name | default .Title }}</span>
<span class="text-smoke" aria-hidden="true">/</span>
{{- end -}}
@@ -54,6 +75,5 @@
{{- $post.Date.Format "Jan 2006" -}}
</time>
</div>
</a>
</article>
+4 -4
View File
@@ -20,10 +20,10 @@
}
</script>
{{- else if and .IsPage (eq .Section "posts") -}}
{{- $authorPage := "" -}}
{{- with .Params.author -}}
{{- $authorPage = site.GetPage (printf "authors/%s" .) -}}
{{- end -}}
{{- $authorPage := "" -}}
{{- with .Params.author -}}
{{- $authorPage = site.GetPage (printf "authors/%s" .) -}}
{{- end -}}
<script type="application/ld+json">
{
"@context": "https://schema.org",